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
c0eb4f61
Commit
c0eb4f61
authored
Jul 25, 2023
by
Lyza Danger Gardner
Committed by
Lyza Gardner
Jul 26, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extract `ShareAnnotations` component
parent
b1ddafbf
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
325 additions
and
304 deletions
+325
-304
ShareAnnotations.tsx
src/sidebar/components/ShareDialog/ShareAnnotations.tsx
+115
-0
ShareDialog.tsx
src/sidebar/components/ShareDialog/ShareDialog.tsx
+10
-154
ShareAnnotations-test.js
...ebar/components/ShareDialog/test/ShareAnnotations-test.js
+181
-0
ShareDialog-test.js
src/sidebar/components/ShareDialog/test/ShareDialog-test.js
+19
-150
No files found.
src/sidebar/components/ShareDialog/ShareAnnotations.tsx
0 → 100644
View file @
c0eb4f61
import
{
CopyIcon
,
Input
,
InputGroup
,
IconButton
,
LockIcon
,
}
from
'@hypothesis/frontend-shared'
;
import
{
useCallback
}
from
'preact/hooks'
;
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
ShareLinks
from
'../ShareLinks'
;
import
LoadingSpinner
from
'./LoadingSpinner'
;
export
type
ShareAnnotationsProps
=
{
// injected
toastMessenger
:
ToastMessengerService
;
};
/**
* Render UI for sharing annotations (by URL) within the currently-focused group
*/
function
ShareAnnotations
({
toastMessenger
}:
ShareAnnotationsProps
)
{
const
store
=
useSidebarStore
();
const
mainFrame
=
store
.
mainFrame
();
const
focusedGroup
=
store
.
focusedGroup
();
const
sharingReady
=
focusedGroup
&&
mainFrame
;
const
shareURI
=
sharingReady
&&
pageSharingLink
(
mainFrame
.
uri
,
focusedGroup
.
id
);
const
copyShareLink
=
useCallback
(()
=>
{
try
{
if
(
shareURI
)
{
copyText
(
shareURI
);
toastMessenger
.
success
(
'Copied share link to clipboard'
);
}
}
catch
(
err
)
{
toastMessenger
.
error
(
'Unable to copy link'
);
}
},
[
shareURI
,
toastMessenger
]);
if
(
!
sharingReady
)
{
return
<
LoadingSpinner
/>;
}
return
(
<
div
className=
"text-color-text-light space-y-3"
>
{
shareURI
?
(
<>
<
div
className=
"text-color-text font-medium"
data
-
testid=
"sharing-intro"
>
{
focusedGroup
.
type
===
'private'
?
(
<
p
>
Use this link to share these annotations with other group
members:
</
p
>
)
:
(
<
p
>
Use this link to share these annotations with anyone:
</
p
>
)
}
</
div
>
<
div
>
<
InputGroup
>
<
Input
aria
-
label=
"Use this URL to share these annotations"
type=
"text"
value=
{
shareURI
}
readOnly
/>
<
IconButton
icon=
{
CopyIcon
}
onClick=
{
copyShareLink
}
title=
"Copy share link"
variant=
"dark"
/>
</
InputGroup
>
</
div
>
<
p
data
-
testid=
"sharing-details"
>
{
focusedGroup
.
type
===
'private'
?
(
<
span
>
Annotations in the private group
<
em
>
{
focusedGroup
.
name
}
</
em
>
{
' '
}
are only visible to group members.
</
span
>
)
:
(
<
span
>
Anyone using this link may view the annotations in the group
{
' '
}
<
em
>
{
focusedGroup
.
name
}
</
em
>
.
</
span
>
)
}{
' '
}
<
span
>
Private (
<
LockIcon
className=
"inline w-em h-em ml-0.5 -mt-0.5"
/>
{
' '
}
<
em
>
Only Me
</
em
>
) annotations are only visible to you.
</
span
>
</
p
>
<
div
className=
"text-[24px]"
>
<
ShareLinks
shareURI=
{
shareURI
}
/>
</
div
>
</>
)
:
(
<
p
data
-
testid=
"no-sharing"
>
These annotations cannot be shared because this document is not
available on the web.
</
p
>
)
}
</
div
>
);
}
export
default
withServices
(
ShareAnnotations
,
[
'toastMessenger'
]);
src/sidebar/components/ShareDialog/ShareDialog.tsx
View file @
c0eb4f61
import
{
import
{
Card
,
Tab
}
from
'@hypothesis/frontend-shared'
;
Card
,
import
{
useState
}
from
'preact/hooks'
;
CopyIcon
,
IconButton
,
Input
,
InputGroup
,
LockIcon
,
Tab
,
}
from
'@hypothesis/frontend-shared'
;
import
{
useCallback
,
useState
}
from
'preact/hooks'
;
import
{
pageSharingLink
}
from
'../../helpers/annotation-sharing'
;
import
{
withServices
}
from
'../../service-context'
;
import
type
{
ToastMessengerService
}
from
'../../services/toast-messenger'
;
import
{
useSidebarStore
}
from
'../../store'
;
import
{
useSidebarStore
}
from
'../../store'
;
import
{
copyText
}
from
'../../util/copy-to-clipboard'
;
import
ShareLinks
from
'../ShareLinks'
;
import
SidebarPanel
from
'../SidebarPanel'
;
import
SidebarPanel
from
'../SidebarPanel'
;
import
ExportAnnotations
from
'./ExportAnnotations'
;
import
ExportAnnotations
from
'./ExportAnnotations'
;
import
LoadingSpinner
from
'./LoadingSpinner
'
;
import
ShareAnnotations
from
'./ShareAnnotations
'
;
import
TabHeader
from
'./TabHeader'
;
import
TabHeader
from
'./TabHeader'
;
import
TabPanel
from
'./TabPanel'
;
import
TabPanel
from
'./TabPanel'
;
type
SharePanelContentProps
=
{
loading
:
boolean
;
shareURI
?:
string
|
null
;
/** Callback for when "copy URL" button is clicked */
onCopyShareLink
:
()
=>
void
;
groupName
?:
string
;
groupType
?:
string
;
};
/**
/**
* Render content for "share" panel or tab.
* Panel with sharing options.
* - If export feature flag is enabled, will show a tabbed interface with
* share and export tabs
* - Else, shows a single "Share annotations" interface
*/
*/
function
SharePanelContent
({
export
default
function
ShareDialog
()
{
groupName
,
groupType
,
loading
,
onCopyShareLink
,
shareURI
,
}:
SharePanelContentProps
)
{
if
(
loading
)
{
return
<
LoadingSpinner
/>;
}
return
(
<
div
className=
"text-color-text-light space-y-3"
>
{
shareURI
?
(
<>
<
div
className=
"text-color-text font-medium"
data
-
testid=
"sharing-intro"
>
{
groupType
===
'private'
?
(
<
p
>
Use this link to share these annotations with other group
members:
</
p
>
)
:
(
<
p
>
Use this link to share these annotations with anyone:
</
p
>
)
}
</
div
>
<
div
>
<
InputGroup
>
<
Input
aria
-
label=
"Use this URL to share these annotations"
type=
"text"
value=
{
shareURI
}
readOnly
/>
<
IconButton
icon=
{
CopyIcon
}
onClick=
{
onCopyShareLink
}
title=
"Copy share link"
variant=
"dark"
/>
</
InputGroup
>
</
div
>
<
p
data
-
testid=
"sharing-details"
>
{
groupType
===
'private'
?
(
<
span
>
Annotations in the private group
<
em
>
{
groupName
}
</
em
>
are only
visible to group members.
</
span
>
)
:
(
<
span
>
Anyone using this link may view the annotations in the group
{
' '
}
<
em
>
{
groupName
}
</
em
>
.
</
span
>
)
}{
' '
}
<
span
>
Private (
<
LockIcon
className=
"inline w-em h-em ml-0.5 -mt-0.5"
/>
{
' '
}
<
em
>
Only Me
</
em
>
) annotations are only visible to you.
</
span
>
</
p
>
<
div
className=
"text-[24px]"
>
<
ShareLinks
shareURI=
{
shareURI
}
/>
</
div
>
</>
)
:
(
<
p
data
-
testid=
"no-sharing"
>
These annotations cannot be shared because this document is not
available on the web.
</
p
>
)
}
</
div
>
);
}
export
type
ShareDialogProps
=
{
// injected
toastMessenger
:
ToastMessengerService
;
};
/**
* A panel for sharing the current group's annotations on the current document.
*
* Links within this component allow a user to share the set of annotations that
* are on the current page (as defined by the main frame's URI) and contained
* within the app's currently-focused group.
*/
function
ShareDialog
({
toastMessenger
}:
ShareDialogProps
)
{
const
store
=
useSidebarStore
();
const
store
=
useSidebarStore
();
const
mainFrame
=
store
.
mainFrame
();
const
focusedGroup
=
store
.
focusedGroup
();
const
focusedGroup
=
store
.
focusedGroup
();
const
groupName
=
(
focusedGroup
&&
focusedGroup
.
name
)
||
'...'
;
const
groupName
=
(
focusedGroup
&&
focusedGroup
.
name
)
||
'...'
;
const
panelTitle
=
`Share Annotations in
${
groupName
}
`
;
const
panelTitle
=
`Share Annotations in
${
groupName
}
`
;
...
@@ -131,26 +23,6 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
...
@@ -131,26 +23,6 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
const
tabbedDialog
=
store
.
isFeatureEnabled
(
'export_annotations'
);
const
tabbedDialog
=
store
.
isFeatureEnabled
(
'export_annotations'
);
const
[
selectedTab
,
setSelectedTab
]
=
useState
<
'share'
|
'export'
>
(
'share'
);
const
[
selectedTab
,
setSelectedTab
]
=
useState
<
'share'
|
'export'
>
(
'share'
);
// To be able to concoct a sharing link, a focused group and frame need to
// be available
const
sharingReady
=
focusedGroup
&&
mainFrame
;
// Show a loading spinner in the export tab if annotations are loading
const
shareURI
=
sharingReady
&&
pageSharingLink
(
mainFrame
.
uri
,
focusedGroup
.
id
);
// TODO: Move into Share-panel-content component once extracted
const
copyShareLink
=
useCallback
(()
=>
{
try
{
if
(
shareURI
)
{
copyText
(
shareURI
);
toastMessenger
.
success
(
'Copied share link to clipboard'
);
}
}
catch
(
err
)
{
toastMessenger
.
error
(
'Unable to copy link'
);
}
},
[
shareURI
,
toastMessenger
]);
return
(
return
(
<
SidebarPanel
<
SidebarPanel
title=
{
panelTitle
}
title=
{
panelTitle
}
...
@@ -188,13 +60,7 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
...
@@ -188,13 +60,7 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
aria
-
labelledby=
"share-panel-tab"
aria
-
labelledby=
"share-panel-tab"
title=
{
panelTitle
}
title=
{
panelTitle
}
>
>
<
SharePanelContent
<
ShareAnnotations
/>
groupName=
{
focusedGroup
?.
name
}
groupType=
{
focusedGroup
?.
type
}
loading=
{
!
sharingReady
}
onCopyShareLink=
{
copyShareLink
}
shareURI=
{
shareURI
}
/>
</
TabPanel
>
</
TabPanel
>
<
TabPanel
<
TabPanel
id=
"export-panel"
id=
"export-panel"
...
@@ -207,17 +73,7 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
...
@@ -207,17 +73,7 @@ function ShareDialog({ toastMessenger }: ShareDialogProps) {
</
Card
>
</
Card
>
</>
</>
)
}
)
}
{
!
tabbedDialog
&&
(
{
!
tabbedDialog
&&
<
ShareAnnotations
/>
}
<
SharePanelContent
groupName=
{
focusedGroup
?.
name
}
groupType=
{
focusedGroup
?.
type
}
loading=
{
!
sharingReady
}
onCopyShareLink=
{
copyShareLink
}
shareURI=
{
shareURI
}
/>
)
}
</
SidebarPanel
>
</
SidebarPanel
>
);
);
}
}
export
default
withServices
(
ShareDialog
,
[
'toastMessenger'
]);
src/sidebar/components/ShareDialog/test/ShareAnnotations-test.js
0 → 100644
View file @
c0eb4f61
import
{
mount
}
from
'enzyme'
;
import
{
checkAccessibility
}
from
'../../../../test-util/accessibility'
;
import
{
mockImportedComponents
}
from
'../../../../test-util/mock-imported-components'
;
import
ShareAnnotations
from
'../ShareAnnotations'
;
import
{
$imports
}
from
'../ShareAnnotations'
;
describe
(
'ShareAnnotations'
,
()
=>
{
let
fakeStore
;
let
fakeBouncerLink
;
let
fakePageSharingLink
;
let
fakeToastMessenger
;
let
fakeCopyToClipboard
;
const
fakePrivateGroup
=
{
type
:
'private'
,
name
:
'Test Private Group'
,
id
:
'testprivate'
,
};
const
createComponent
=
props
=>
mount
(
<
ShareAnnotations
toastMessenger
=
{
fakeToastMessenger
}
{...
props
}
/>
)
;
beforeEach
(()
=>
{
fakeBouncerLink
=
'http://hyp.is/go?url=http%3A%2F%2Fwww.example.com'
;
fakeCopyToClipboard
=
{
copyText
:
sinon
.
stub
(),
};
fakePageSharingLink
=
sinon
.
stub
().
returns
(
fakeBouncerLink
);
fakeToastMessenger
=
{
success
:
sinon
.
stub
(),
error
:
sinon
.
stub
(),
};
fakeStore
=
{
focusedGroup
:
sinon
.
stub
().
returns
(
fakePrivateGroup
),
mainFrame
:
()
=>
({
uri
:
'https://www.example.com'
,
}),
};
$imports
.
$mock
(
mockImportedComponents
());
$imports
.
$mock
({
'../../store'
:
{
useSidebarStore
:
()
=>
fakeStore
},
'../../helpers/annotation-sharing'
:
{
pageSharingLink
:
fakePageSharingLink
,
},
'../../util/copy-to-clipboard'
:
fakeCopyToClipboard
,
});
});
afterEach
(()
=>
{
$imports
.
$restore
();
});
describe
(
'share panel content'
,
()
=>
{
it
(
'renders a spinner if focused group not available yet'
,
()
=>
{
fakeStore
.
focusedGroup
.
returns
(
undefined
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'LoadingSpinner'
).
exists
());
});
it
(
'renders panel content if needed info available'
,
()
=>
{
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'LoadingSpinner'
).
exists
());
});
});
[
{
groupType
:
'private'
,
introPattern
:
/Use this link.*with other group members/
,
visibilityPattern
:
/Annotations in the private group.*are only visible to group members/
,
},
{
groupType
:
'restricted'
,
introPattern
:
/Use this link to share these annotations with anyone/
,
visibilityPattern
:
/Anyone using this link may view the annotations in the group/
,
},
{
groupType
:
'open'
,
introPattern
:
/Use this link to share these annotations with anyone/
,
visibilityPattern
:
/Anyone using this link may view the annotations in the group/
,
},
].
forEach
(
testCase
=>
{
it
(
'it displays appropriate help text depending on group type'
,
()
=>
{
fakeStore
.
focusedGroup
.
returns
({
type
:
testCase
.
groupType
,
name
:
'Test Group'
,
id
:
'testid,'
,
});
const
wrapper
=
createComponent
();
assert
.
match
(
wrapper
.
find
(
'[data-testid="sharing-intro"]'
).
text
(),
testCase
.
introPattern
);
assert
.
match
(
wrapper
.
find
(
'[data-testid="sharing-details"]'
).
text
(),
testCase
.
visibilityPattern
);
});
context
(
'document URI cannot be shared'
,
()
=>
{
it
(
'renders explanatory text about inability to share'
,
()
=>
{
fakePageSharingLink
.
returns
(
null
);
const
wrapper
=
createComponent
();
const
panelEl
=
wrapper
.
find
(
'[data-testid="no-sharing"]'
);
assert
.
include
(
panelEl
.
text
(),
'These annotations cannot be shared'
);
});
});
});
describe
(
'web share link'
,
()
=>
{
it
(
'displays web share link in readonly form input'
,
()
=>
{
const
wrapper
=
createComponent
();
const
inputEl
=
wrapper
.
find
(
'input'
);
assert
.
equal
(
inputEl
.
prop
(
'value'
),
fakeBouncerLink
);
assert
.
equal
(
inputEl
.
prop
(
'readOnly'
),
true
);
});
context
(
'document URI cannot be shared'
,
()
=>
{
it
(
'does not render an input field with share link'
,
()
=>
{
fakePageSharingLink
.
returns
(
null
);
const
wrapper
=
createComponent
();
const
inputEl
=
wrapper
.
find
(
'input'
);
assert
.
isFalse
(
inputEl
.
exists
());
});
});
describe
(
'copy link to clipboard'
,
()
=>
{
it
(
'copies link to clipboard when copy button clicked'
,
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeCopyToClipboard
.
copyText
,
fakeBouncerLink
);
});
it
(
'confirms link copy when successful'
,
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
success
,
'Copied share link to clipboard'
);
});
it
(
'flashes an error if link copying unsuccessful'
,
()
=>
{
fakeCopyToClipboard
.
copyText
.
throws
();
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
error
,
'Unable to copy link'
);
});
});
});
// TODO: Add a11y test for tabbed interface
it
(
'should pass a11y checks'
,
checkAccessibility
({
content
:
()
=>
createComponent
(),
})
);
});
src/sidebar/components/ShareDialog/test/ShareDialog-test.js
View file @
c0eb4f61
...
@@ -8,10 +8,6 @@ import { $imports } from '../ShareDialog';
...
@@ -8,10 +8,6 @@ import { $imports } from '../ShareDialog';
describe
(
'ShareDialog'
,
()
=>
{
describe
(
'ShareDialog'
,
()
=>
{
let
fakeStore
;
let
fakeStore
;
let
fakeBouncerLink
;
let
fakePageSharingLink
;
let
fakeToastMessenger
;
let
fakeCopyToClipboard
;
const
fakePrivateGroup
=
{
const
fakePrivateGroup
=
{
type
:
'private'
,
type
:
'private'
,
...
@@ -19,44 +15,22 @@ describe('ShareDialog', () => {
...
@@ -19,44 +15,22 @@ describe('ShareDialog', () => {
id
:
'testprivate'
,
id
:
'testprivate'
,
};
};
const
createComponent
=
props
=>
const
createComponent
=
()
=>
mount
(
<
ShareDialog
/>
);
mount
(
<
ShareDialog
toastMessenger
=
{
fakeToastMessenger
}
{...
props
}
/>
)
;
beforeEach
(()
=>
{
beforeEach
(()
=>
{
fakeBouncerLink
=
'http://hyp.is/go?url=http%3A%2F%2Fwww.example.com'
;
fakeCopyToClipboard
=
{
copyText
:
sinon
.
stub
(),
};
fakePageSharingLink
=
sinon
.
stub
().
returns
(
fakeBouncerLink
);
fakeToastMessenger
=
{
success
:
sinon
.
stub
(),
error
:
sinon
.
stub
(),
};
fakeStore
=
{
fakeStore
=
{
allAnnotations
:
sinon
.
stub
().
returns
(
0
),
focusedGroup
:
sinon
.
stub
().
returns
(
fakePrivateGroup
),
focusedGroup
:
sinon
.
stub
().
returns
(
fakePrivateGroup
),
isLoading
:
sinon
.
stub
().
returns
(
false
),
isFeatureEnabled
:
sinon
.
stub
().
returns
(
false
),
isFeatureEnabled
:
sinon
.
stub
().
returns
(
false
),
mainFrame
:
()
=>
({
uri
:
'https://www.example.com'
,
}),
};
};
$imports
.
$mock
(
mockImportedComponents
());
$imports
.
$mock
(
mockImportedComponents
());
// Don't mock these related components for now
// Don't mock these related components for now
$imports
.
$restore
({
$imports
.
$restore
({
'./LoadingSpinner'
:
true
,
'./TabHeader'
:
true
,
'./TabHeader'
:
true
,
'./TabPanel'
:
true
,
'./TabPanel'
:
true
,
});
});
$imports
.
$mock
({
$imports
.
$mock
({
'../../store'
:
{
useSidebarStore
:
()
=>
fakeStore
},
'../../store'
:
{
useSidebarStore
:
()
=>
fakeStore
},
'../../helpers/annotation-sharing'
:
{
pageSharingLink
:
fakePageSharingLink
,
},
'../../util/copy-to-clipboard'
:
fakeCopyToClipboard
,
});
});
});
});
...
@@ -85,122 +59,6 @@ describe('ShareDialog', () => {
...
@@ -85,122 +59,6 @@ describe('ShareDialog', () => {
});
});
});
});
describe
(
'share panel content'
,
()
=>
{
it
(
'renders a spinner if focused group not available yet'
,
()
=>
{
fakeStore
.
focusedGroup
.
returns
(
undefined
);
const
wrapper
=
createComponent
();
assert
.
isTrue
(
wrapper
.
find
(
'Spinner'
).
exists
());
});
it
(
'renders panel content if needed info available'
,
()
=>
{
const
wrapper
=
createComponent
();
assert
.
isFalse
(
wrapper
.
find
(
'Spinner'
).
exists
());
});
});
[
{
groupType
:
'private'
,
introPattern
:
/Use this link.*with other group members/
,
visibilityPattern
:
/Annotations in the private group.*are only visible to group members/
,
},
{
groupType
:
'restricted'
,
introPattern
:
/Use this link to share these annotations with anyone/
,
visibilityPattern
:
/Anyone using this link may view the annotations in the group/
,
},
{
groupType
:
'open'
,
introPattern
:
/Use this link to share these annotations with anyone/
,
visibilityPattern
:
/Anyone using this link may view the annotations in the group/
,
},
].
forEach
(
testCase
=>
{
it
(
'it displays appropriate help text depending on group type'
,
()
=>
{
fakeStore
.
focusedGroup
.
returns
({
type
:
testCase
.
groupType
,
name
:
'Test Group'
,
id
:
'testid,'
,
});
const
wrapper
=
createComponent
();
assert
.
match
(
wrapper
.
find
(
'[data-testid="sharing-intro"]'
).
text
(),
testCase
.
introPattern
);
assert
.
match
(
wrapper
.
find
(
'[data-testid="sharing-details"]'
).
text
(),
testCase
.
visibilityPattern
);
});
context
(
'document URI cannot be shared'
,
()
=>
{
it
(
'renders explanatory text about inability to share'
,
()
=>
{
fakePageSharingLink
.
returns
(
null
);
const
wrapper
=
createComponent
();
const
panelEl
=
wrapper
.
find
(
'[data-testid="no-sharing"]'
);
assert
.
include
(
panelEl
.
text
(),
'These annotations cannot be shared'
);
});
});
});
describe
(
'web share link'
,
()
=>
{
it
(
'displays web share link in readonly form input'
,
()
=>
{
const
wrapper
=
createComponent
();
const
inputEl
=
wrapper
.
find
(
'input'
);
assert
.
equal
(
inputEl
.
prop
(
'value'
),
fakeBouncerLink
);
assert
.
equal
(
inputEl
.
prop
(
'readOnly'
),
true
);
});
context
(
'document URI cannot be shared'
,
()
=>
{
it
(
'does not render an input field with share link'
,
()
=>
{
fakePageSharingLink
.
returns
(
null
);
const
wrapper
=
createComponent
();
const
inputEl
=
wrapper
.
find
(
'input'
);
assert
.
isFalse
(
inputEl
.
exists
());
});
});
describe
(
'copy link to clipboard'
,
()
=>
{
it
(
'copies link to clipboard when copy button clicked'
,
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeCopyToClipboard
.
copyText
,
fakeBouncerLink
);
});
it
(
'confirms link copy when successful'
,
()
=>
{
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
success
,
'Copied share link to clipboard'
);
});
it
(
'flashes an error if link copying unsuccessful'
,
()
=>
{
fakeCopyToClipboard
.
copyText
.
throws
();
const
wrapper
=
createComponent
();
wrapper
.
find
(
'IconButton'
).
props
().
onClick
();
assert
.
calledWith
(
fakeToastMessenger
.
error
,
'Unable to copy link'
);
});
});
});
describe
(
'tabbed dialog panel'
,
()
=>
{
describe
(
'tabbed dialog panel'
,
()
=>
{
it
(
'does not render a tabbed dialog if export feature flag is not enabled'
,
()
=>
{
it
(
'does not render a tabbed dialog if export feature flag is not enabled'
,
()
=>
{
const
wrapper
=
createComponent
();
const
wrapper
=
createComponent
();
...
@@ -262,11 +120,22 @@ describe('ShareDialog', () => {
...
@@ -262,11 +120,22 @@ describe('ShareDialog', () => {
});
});
});
});
// TODO: Add a11y test for tabbed interface
describe
(
'a11y'
,
()
=>
{
it
(
beforeEach
(()
=>
{
'should pass a11y checks'
,
fakeStore
.
isFeatureEnabled
.
withArgs
(
'export_annotations'
).
returns
(
true
);
checkAccessibility
({
});
content
:
()
=>
createComponent
(),
})
// TODO: This test is not useful for non-tabbed interfaces because the
);
// ReactWrapper is empty. It is failing currently when the tabbed dialog
// is enabled on a `aria-invalid-attr-value` error on `aria-controls`
// attributes. I believe the rendered component markup is valid, but this
// failing test needs debugging. As the tabbed interface is behind a
// feature flag right now, deferring for followup.
it
.
skip
(
'should pass a11y checks'
,
checkAccessibility
({
content
:
()
=>
createComponent
(),
})
);
});
});
});
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