Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
a185d1ee
Commit
a185d1ee
authored
Jan 30, 2024
by
Alejandro Celaya
Committed by
Alejandro Celaya
Jan 30, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove deprecated copyText function
parent
1645a344
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
40 additions
and
126 deletions
+40
-126
AnnotationShareControl.tsx
src/sidebar/components/Annotation/AnnotationShareControl.tsx
+3
-3
AnnotationShareControl-test.js
...components/Annotation/test/AnnotationShareControl-test.js
+5
-5
GroupListItem.tsx
src/sidebar/components/GroupList/GroupListItem.tsx
+3
-3
GroupListItem-test.js
src/sidebar/components/GroupList/test/GroupListItem-test.js
+12
-12
ShareAnnotations.tsx
src/sidebar/components/ShareDialog/ShareAnnotations.tsx
+3
-3
ShareAnnotations-test.js
...ebar/components/ShareDialog/test/ShareAnnotations-test.js
+5
-5
VersionInfo.tsx
src/sidebar/components/VersionInfo.tsx
+3
-3
VersionInfo-test.js
src/sidebar/components/test/VersionInfo-test.js
+5
-5
copy-to-clipboard.ts
src/sidebar/util/copy-to-clipboard.ts
+0
-35
copy-to-clipboard-test.js
src/sidebar/util/test/copy-to-clipboard-test.js
+1
-52
No files found.
src/sidebar/components/Annotation/AnnotationShareControl.tsx
View file @
a185d1ee
...
...
@@ -17,7 +17,7 @@ import { isPrivate } from '../../helpers/permissions';
import
{
withServices
}
from
'../../service-context'
;
import
type
{
ToastMessengerService
}
from
'../../services/toast-messenger'
;
import
{
useSidebarStore
}
from
'../../store'
;
import
{
copyText
}
from
'../../util/copy-to-clipboard'
;
import
{
copy
Plain
Text
}
from
'../../util/copy-to-clipboard'
;
import
MenuArrow
from
'../MenuArrow'
;
import
ShareLinks
from
'../ShareLinks'
;
...
...
@@ -94,9 +94,9 @@ function AnnotationShareControl({
// bears further discussion.
const
showShareLinks
=
inContextAvailable
;
const
copyShareLink
=
()
=>
{
const
copyShareLink
=
async
()
=>
{
try
{
copy
Text
(
shareUri
);
await
copyPlain
Text
(
shareUri
);
toastMessenger
.
success
(
'Copied share link to clipboard'
);
}
catch
(
err
)
{
toastMessenger
.
error
(
'Unable to copy link'
);
...
...
src/sidebar/components/Annotation/test/AnnotationShareControl-test.js
View file @
a185d1ee
...
...
@@ -66,7 +66,7 @@ describe('AnnotationShareControl', () => {
};
fakeCopyToClipboard
=
{
copyText
:
sinon
.
stub
(),
copy
Plain
Text
:
sinon
.
stub
(),
};
fakeToastMessenger
=
{
success
:
sinon
.
stub
(),
...
...
@@ -147,16 +147,16 @@ describe('AnnotationShareControl', () => {
getIconButton
(
wrapper
,
'CopyIcon'
).
props
().
onClick
();
assert
.
calledWith
(
fakeCopyToClipboard
.
copyText
,
fakeCopyToClipboard
.
copy
Plain
Text
,
'https://www.example.com'
,
);
});
it
(
'confirms link copy when successful'
,
()
=>
{
it
(
'confirms link copy when successful'
,
async
()
=>
{
const
wrapper
=
createComponent
();
openElement
(
wrapper
);
getIconButton
(
wrapper
,
'CopyIcon'
).
props
().
onClick
();
await
getIconButton
(
wrapper
,
'CopyIcon'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
success
,
...
...
@@ -165,7 +165,7 @@ describe('AnnotationShareControl', () => {
});
it
(
'flashes an error if link copying unsuccessful'
,
()
=>
{
fakeCopyToClipboard
.
copyText
.
throws
();
fakeCopyToClipboard
.
copy
Plain
Text
.
throws
();
const
wrapper
=
createComponent
();
openElement
(
wrapper
);
...
...
src/sidebar/components/GroupList/GroupListItem.tsx
View file @
a185d1ee
...
...
@@ -8,7 +8,7 @@ import { withServices } from '../../service-context';
import
type
{
GroupsService
}
from
'../../services/groups'
;
import
type
{
ToastMessengerService
}
from
'../../services/toast-messenger'
;
import
{
useSidebarStore
}
from
'../../store'
;
import
{
copyText
}
from
'../../util/copy-to-clipboard'
;
import
{
copy
Plain
Text
}
from
'../../util/copy-to-clipboard'
;
import
MenuItem
from
'../MenuItem'
;
export
type
GroupListItemProps
=
{
...
...
@@ -75,9 +75,9 @@ function GroupListItem({
onExpand
(
!
isExpanded
);
};
const
copyLink
=
(
url
:
string
)
=>
{
const
copyLink
=
async
(
url
:
string
)
=>
{
try
{
copy
Text
(
url
);
await
copyPlain
Text
(
url
);
toastMessenger
.
success
(
`Copied link for "
${
group
.
name
}
"`
);
}
catch
(
err
)
{
toastMessenger
.
error
(
'Unable to copy link'
);
...
...
src/sidebar/components/GroupList/test/GroupListItem-test.js
View file @
a185d1ee
...
...
@@ -6,7 +6,7 @@ import GroupListItem, { $imports } from '../GroupListItem';
describe
(
'GroupListItem'
,
()
=>
{
let
fakeConfirm
;
let
fakeCopyText
;
let
fakeCopy
Plain
Text
;
let
fakeToastMessenger
;
let
fakeGroupsService
;
let
fakeStore
;
...
...
@@ -47,7 +47,7 @@ describe('GroupListItem', () => {
leave
:
sinon
.
stub
(),
};
fakeCopyText
=
sinon
.
stub
();
fakeCopy
Plain
Text
=
sinon
.
stub
();
function
FakeMenuItem
()
{
return
null
;
...
...
@@ -64,7 +64,7 @@ describe('GroupListItem', () => {
$imports
.
$mock
({
'../MenuItem'
:
FakeMenuItem
,
'../../util/copy-to-clipboard'
:
{
copy
Text
:
fakeCopy
Text
,
copy
PlainText
:
fakeCopyPlain
Text
,
},
'../../helpers/group-list-item-common'
:
fakeGroupListItemCommon
,
'../../store'
:
{
useSidebarStore
:
()
=>
fakeStore
},
...
...
@@ -87,10 +87,10 @@ describe('GroupListItem', () => {
);
};
function
clickMenuItem
(
wrapper
,
label
)
{
a
ct
(()
=>
{
wrapper
.
find
(
`MenuItem[label="
${
label
}
"]`
).
props
().
onClick
()
;
}
);
async
function
clickMenuItem
(
wrapper
,
label
)
{
a
wait
act
(()
=>
wrapper
.
find
(
`MenuItem[label="
${
label
}
"]`
).
props
().
onClick
()
,
);
wrapper
.
update
();
}
...
...
@@ -359,22 +359,22 @@ describe('GroupListItem', () => {
});
});
it
(
'copies activity URL if "Copy link" action is clicked'
,
()
=>
{
it
(
'copies activity URL if "Copy link" action is clicked'
,
async
()
=>
{
const
wrapper
=
createGroupListItem
(
fakeGroup
,
{
isExpanded
:
true
,
});
clickMenuItem
(
getSubmenu
(
wrapper
),
'Copy invite link'
);
assert
.
calledWith
(
fakeCopyText
,
'https://annotate.com/groups/groupid'
);
await
clickMenuItem
(
getSubmenu
(
wrapper
),
'Copy invite link'
);
assert
.
calledWith
(
fakeCopy
Plain
Text
,
'https://annotate.com/groups/groupid'
);
assert
.
calledWith
(
fakeToastMessenger
.
success
,
'Copied link for "Test"'
);
});
it
(
'reports an error if "Copy link" action fails'
,
()
=>
{
fakeCopyText
.
throws
(
new
Error
(
'Something went wrong'
));
fakeCopy
Plain
Text
.
throws
(
new
Error
(
'Something went wrong'
));
const
wrapper
=
createGroupListItem
(
fakeGroup
,
{
isExpanded
:
true
,
});
clickMenuItem
(
getSubmenu
(
wrapper
),
'Copy invite link'
);
assert
.
calledWith
(
fakeCopyText
,
'https://annotate.com/groups/groupid'
);
assert
.
calledWith
(
fakeCopy
Plain
Text
,
'https://annotate.com/groups/groupid'
);
assert
.
calledWith
(
fakeToastMessenger
.
error
,
'Unable to copy link'
);
});
});
src/sidebar/components/ShareDialog/ShareAnnotations.tsx
View file @
a185d1ee
...
...
@@ -11,7 +11,7 @@ import { pageSharingLink } from '../../helpers/annotation-sharing';
import
{
withServices
}
from
'../../service-context'
;
import
type
{
ToastMessengerService
}
from
'../../services/toast-messenger'
;
import
{
useSidebarStore
}
from
'../../store'
;
import
{
copyText
}
from
'../../util/copy-to-clipboard'
;
import
{
copy
Plain
Text
}
from
'../../util/copy-to-clipboard'
;
import
ShareLinks
from
'../ShareLinks'
;
import
LoadingSpinner
from
'./LoadingSpinner'
;
...
...
@@ -32,10 +32,10 @@ function ShareAnnotations({ toastMessenger }: ShareAnnotationsProps) {
const
shareURI
=
sharingReady
&&
pageSharingLink
(
mainFrame
.
uri
,
focusedGroup
.
id
);
const
copyShareLink
=
useCallback
(()
=>
{
const
copyShareLink
=
useCallback
(
async
()
=>
{
try
{
if
(
shareURI
)
{
copy
Text
(
shareURI
);
await
copyPlain
Text
(
shareURI
);
toastMessenger
.
success
(
'Copied share link to clipboard'
);
}
}
catch
(
err
)
{
...
...
src/sidebar/components/ShareDialog/test/ShareAnnotations-test.js
View file @
a185d1ee
...
...
@@ -26,7 +26,7 @@ describe('ShareAnnotations', () => {
beforeEach
(()
=>
{
fakeBouncerLink
=
'http://hyp.is/go?url=http%3A%2F%2Fwww.example.com'
;
fakeCopyToClipboard
=
{
copyText
:
sinon
.
stub
(),
copy
Plain
Text
:
sinon
.
stub
(),
};
fakePageSharingLink
=
sinon
.
stub
().
returns
(
fakeBouncerLink
);
...
...
@@ -148,13 +148,13 @@ describe('ShareAnnotations', () => {
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeCopyToClipboard
.
copyText
,
fakeBouncerLink
);
assert
.
calledWith
(
fakeCopyToClipboard
.
copy
Plain
Text
,
fakeBouncerLink
);
});
it
(
'confirms link copy when successful'
,
()
=>
{
it
(
'confirms link copy when successful'
,
async
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
await
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
success
,
...
...
@@ -163,7 +163,7 @@ describe('ShareAnnotations', () => {
});
it
(
'flashes an error if link copying unsuccessful'
,
()
=>
{
fakeCopyToClipboard
.
copyText
.
throws
();
fakeCopyToClipboard
.
copy
Plain
Text
.
throws
();
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
...
...
src/sidebar/components/VersionInfo.tsx
View file @
a185d1ee
...
...
@@ -5,7 +5,7 @@ import type { ComponentChildren } from 'preact';
import
type
{
VersionData
}
from
'../helpers/version-data'
;
import
{
withServices
}
from
'../service-context'
;
import
type
{
ToastMessengerService
}
from
'../services/toast-messenger'
;
import
{
copyText
}
from
'../util/copy-to-clipboard'
;
import
{
copy
Plain
Text
}
from
'../util/copy-to-clipboard'
;
type
VersionInfoItemProps
=
{
label
:
string
;
...
...
@@ -37,9 +37,9 @@ export type VersionInfoProps = {
};
function
VersionInfo
({
toastMessenger
,
versionData
}:
VersionInfoProps
)
{
const
copyVersionData
=
()
=>
{
const
copyVersionData
=
async
()
=>
{
try
{
copy
Text
(
versionData
.
asFormattedString
());
await
copyPlain
Text
(
versionData
.
asFormattedString
());
toastMessenger
.
success
(
'Copied version info to clipboard'
);
}
catch
(
err
)
{
toastMessenger
.
error
(
'Unable to copy version info'
);
...
...
src/sidebar/components/test/VersionInfo-test.js
View file @
a185d1ee
...
...
@@ -31,7 +31,7 @@ describe('VersionInfo', () => {
beforeEach
(()
=>
{
fakeCopyToClipboard
=
{
copyText
:
sinon
.
stub
(),
copy
Plain
Text
:
sinon
.
stub
(),
};
$imports
.
$mock
(
mockImportedComponents
());
$imports
.
$mock
({
...
...
@@ -82,13 +82,13 @@ describe('VersionInfo', () => {
wrapper
.
find
(
'Button'
).
props
().
onClick
();
assert
.
calledWith
(
fakeCopyToClipboard
.
copyText
,
'fakeString'
);
assert
.
calledWith
(
fakeCopyToClipboard
.
copy
Plain
Text
,
'fakeString'
);
});
it
(
'confirms info copy when successful'
,
()
=>
{
it
(
'confirms info copy when successful'
,
async
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'Button'
).
props
().
onClick
();
await
wrapper
.
find
(
'Button'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
success
,
...
...
@@ -97,7 +97,7 @@ describe('VersionInfo', () => {
});
it
(
'flashes an error if info copying unsuccessful'
,
()
=>
{
fakeCopyToClipboard
.
copyText
.
throws
();
fakeCopyToClipboard
.
copy
Plain
Text
.
throws
();
const
wrapper
=
createComponent
();
wrapper
.
find
(
'Button'
).
props
().
onClick
();
...
...
src/sidebar/util/copy-to-clipboard.ts
View file @
a185d1ee
/**
* Copy the string `text` to the clipboard.
*
* In most browsers, this function can only be called in response to a user
* gesture. For example in response to a "click" event.
*
* @throws {Error}
* This function may throw an exception if the browser rejects the attempt
* to copy text.
*
* @deprecated Use copyPlainText instead
*/
export
function
copyText
(
text
:
string
)
{
const
temp
=
document
.
createElement
(
'textarea'
);
// use textarea instead of input to preserve line breaks
temp
.
value
=
text
;
temp
.
setAttribute
(
'data-testid'
,
'copy-text'
);
// Recipe from https://stackoverflow.com/a/34046084/14463679
temp
.
contentEditable
=
'true'
;
document
.
body
.
appendChild
(
temp
);
temp
.
focus
();
try
{
const
range
=
document
.
createRange
();
const
selection
=
document
.
getSelection
()
!
;
selection
.
removeAllRanges
();
range
.
selectNodeContents
(
temp
);
selection
.
addRange
(
range
);
temp
.
setSelectionRange
(
0
,
temp
.
value
.
length
);
document
.
execCommand
(
'copy'
);
}
finally
{
temp
.
remove
();
}
}
/**
* Copy the string `text` to the clipboard verbatim.
*
...
...
src/sidebar/util/test/copy-to-clipboard-test.js
View file @
a185d1ee
import
{
copyPlainText
,
copyHTML
,
copyText
}
from
'../copy-to-clipboard'
;
import
{
copyPlainText
,
copyHTML
}
from
'../copy-to-clipboard'
;
describe
(
'copy-to-clipboard'
,
()
=>
{
const
createFakeNavigator
=
clipboard
=>
({
clipboard
});
describe
(
'copyText'
,
()
=>
{
beforeEach
(()
=>
{
sinon
.
stub
(
document
,
'execCommand'
);
});
afterEach
(()
=>
{
document
.
execCommand
.
restore
();
});
/**
* Returns the temporary element used to hold text being copied.
*/
function
tempSpan
()
{
return
document
.
querySelector
(
'[data-testid=copy-text]'
);
}
beforeEach
(()
=>
{
// Make no hidden element created for copying text has been left over
// from a previous test.
assert
.
isNull
(
tempSpan
());
// Make sure there is nothing already selected to copy.
window
.
getSelection
().
removeAllRanges
();
});
it
(
'copies the passed text to the clipboard'
,
()
=>
{
// We can't actually copy to the clipboard due to security restrictions,
// but we can verify that `execCommand("copy")` was called and that the
// passed text was selected at the time.
document
.
execCommand
.
callsFake
(()
=>
{
assert
.
equal
(
document
.
getSelection
().
toString
(),
'test string'
);
});
copyText
(
'test string'
);
assert
.
calledWith
(
document
.
execCommand
,
'copy'
);
assert
.
isNull
(
tempSpan
());
});
it
(
'removes temporary span if copying fails'
,
()
=>
{
document
.
execCommand
.
callsFake
(()
=>
{
assert
.
ok
(
tempSpan
());
throw
new
Error
(
'No clipboard access for you!'
);
});
try
{
copyText
(
'fibble-wobble'
);
}
catch
(
e
)
{
assert
.
equal
(
e
.
message
,
'No clipboard access for you!'
);
}
assert
.
isNull
(
tempSpan
());
});
});
describe
(
'copyPlainText'
,
()
=>
{
it
(
'writes provided text to clipboard'
,
async
()
=>
{
const
text
=
'Lorem ipsum dolor sit amet'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment