Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional TOC implementations #2944

Merged
merged 21 commits into from
Mar 5, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3f3d5dd
Show Visible-Icon for all ranges in tree that contain visible canvases
lutzhelm Jan 21, 2020
167e107
Add selector for ids of visible ranges
lutzhelm Feb 5, 2020
23613a1
Track manually opened TOC node ids in store
lutzhelm Feb 6, 2020
367daa5
Scroll to current range in TOC
lutzhelm Feb 7, 2020
ae462f3
Use actual range ids in companion window TOC state
lutzhelm Feb 12, 2020
bdece1a
Toggle nodes with keyboard interaction
lutzhelm Feb 13, 2020
cfdfc13
Take URL fragments in Range.canvases into account
lutzhelm Feb 14, 2020
4645fc2
Have only one Range to scroll to
lutzhelm Feb 14, 2020
0a081c4
Add manifests for TOC examples in M3 wiki
lutzhelm Feb 14, 2020
2804901
Use node ids instead of Range ids for TOC
lutzhelm Feb 18, 2020
0ec146f
Allow automatically opened TOC nodes to be closed
lutzhelm Feb 18, 2020
bff67bd
Make sure to scroll to first treenode that contains a canvas
lutzhelm Feb 19, 2020
d5b41a2
Remove unnecessary props in SidebarIndexTableOfContents
lutzhelm Feb 28, 2020
074668e
Add tests for SidebarIndexTableOfContents
lutzhelm Feb 28, 2020
4bffcce
Fix code style
lutzhelm Mar 2, 2020
0351f31
Run test with explicit WindowSideBarCanvasPanel variant
lutzhelm Mar 2, 2020
63f4639
Add more SidebarIndexTableOfContents component tests, fix Component
lutzhelm Mar 2, 2020
6071801
Add TOC related tests for companionWindow reducer
lutzhelm Mar 2, 2020
50d93fc
Refactor toggle toc node action
lutzhelm Mar 3, 2020
1b5c396
Add tests for toc nodes selectors
lutzhelm Mar 4, 2020
8950dce
Add tests for companionWindow action 'toggleNode'
lutzhelm Mar 5, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions __tests__/fixtures/version-2/structures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@type": "sc:Manifest",
"@id": "http://foo.test/1/manifest",
"label": "Manifest to be used for SidebarIndexTableOfContents.test.js",
"sequences" : [
{
"@type": "sc:Sequence",
"canvases": [
{
"@id": "http://foo.test/1/canvas/c1",
"@type": "sc:Canvas",
"label": "Canvas: 1"
},
{
"@id": "http://foo.test/1/canvas/c2",
"@type": "sc:Canvas",
"label": "Canvas: 2"
},
{
"@id": "http://foo.test/1/canvas/c3",
"@type": "sc:Canvas",
"label": "Canvas: 3"
},
{
"@id": "http://foo.test/1/canvas/c4",
"@type": "sc:Canvas",
"label": "Canvas: 4"
},
{
"@id": "http://foo.test/1/canvas/c5",
"@type": "sc:Canvas",
"label": "Canvas: 5"
},
{
"@id": "http://foo.test/1/canvas/c6",
"@type": "sc:Canvas",
"label": "Canvas: 6"
},
{
"@id": "http://foo.test/1/canvas/c7",
"@type": "sc:Canvas",
"label": "Canvas: 7"
},
{
"@id": "http://foo.test/1/canvas/c8",
"@type": "sc:Canvas",
"label": "Canvas: 8"
},
{
"@id": "http://foo.test/1/canvas/c9",
"@type": "sc:Canvas",
"label": "Canvas: 9"
}
]
}
],
"structures": [
{
"@id": "http://foo.test/1/range/root",
"@type": "sc:Range",
"viewingHint": "top",
"ranges": [
"http://foo.test/1/range/1",
"http://foo.test/1/range/2"
],
"canvases": []
},
{
"@id": "http://foo.test/1/range/1",
"@type": "sc:Range",
"ranges": [
"http://foo.test/1/range/1-1",
"http://foo.test/1/range/1-2",
"http://foo.test/1/range/1-3"
],
"canvases": [
"http://foo.test/1/canvas/c1",
"http://foo.test/1/canvas/c2",
"http://foo.test/1/canvas/c3",
"http://foo.test/1/canvas/c4"
]
},
{
"@id": "http://foo.test/1/range/1-1",
"@type": "sc:Range",
"ranges": [],
"canvases": [
"http://foo.test/1/canvas/c1",
"http://foo.test/1/canvas/c2"
]
},
{
"@id": "http://foo.test/1/range/1-2",
"@type": "sc:Range",
"ranges": [],
"canvases": [
"http://foo.test/1/canvas/c2",
"http://foo.test/1/canvas/c3"
]
},
{
"@id": "http://foo.test/1/range/1-3",
"@type": "sc:Range",
"ranges": [],
"canvases": [
"http://foo.test/1/canvas/c4"
]
},
{
"@id": "http://foo.test/1/range/2",
"@type": "sc:Range",
"ranges": [
"http://foo.test/1/range/2-1",
"http://foo.test/1/range/2-2",
"http://foo.test/1/range/2-3"
],
"canvases": []
},
{
"@id": "http://foo.test/1/range/2-1",
"@type": "sc:Range",
"ranges": [],
"canvases": []
},
{
"@id": "http://foo.test/1/range/2-2",
"@type": "sc:Range",
"ranges": [
"http://foo.test/1/range/2-2-1",
"http://foo.test/1/range/2-2-2"
]
},
{
"@id": "http://foo.test/1/range/2-2-1",
"@type": "sc:Range",
"ranges": [],
"canvases": [
"http://foo.test/1/canvas/c5",
"http://foo.test/1/canvas/c6"
]
},
{
"@id": "http://foo.test/1/range/2-2-2",
"@type": "sc:Range",
"ranges": [],
"canvases": [
"http://foo.test/1/canvas/c7",
"http://foo.test/1/canvas/c8"
]
},
{
"@id": "http://foo.test/1/range/2-3",
"@type": "sc:Range",
"ranges": [],
"canvases": []
}
]
}
7 changes: 7 additions & 0 deletions __tests__/integration/mirador/toc.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
defaultSideBarPanel: 'canvas'
},
manifests: {
'https://iiif.bodleian.ox.ac.uk/iiif/manifest/390fd0e8-9eae-475d-9564-ed916ab9035c.json': { provider: 'Bodleian Libraries' },
'http://dams.llgc.org.uk/iiif/newspaper/issue/3100021/manifest.json': { provider: 'The National Library of Wales' },
'https://iiif.lib.harvard.edu/manifests/drs:5981093': { provider: 'Houghton Library (Harvard University)' },
'https://cudl.lib.cam.ac.uk/iiif/MS-ADD-03965' : {},
'https://iiif.bodleian.ox.ac.uk/iiif/manifest/ca3dc326-4a7b-479f-a754-5aed9d2f2cb4.json': {},
// 'https://gist.githubusercontent.com/jeffreycwitt/90b33c1c4e119e7a48b7a66ea41a48c1/raw/522b132409d6c67a78f8f26b0ceb7346a52cfe62/test-manifest-with-complicated-toc.json': {},
// 'https://gist.githubusercontent.com/jeffreycwitt/1a75fdb4a97e1c2a98bd35797aad263d/raw/859104cb6cd7bd99f3be668f064066f4b3ba2b29/manifest-with-three-level-deep-toc.json': {},
}
});
</script>
Expand Down
194 changes: 194 additions & 0 deletions __tests__/src/components/SidebarIndexTableOfContents.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import React from 'react';
import { shallow } from 'enzyme';
import manifesto from 'manifesto.js';
import TreeItem from '@material-ui/lab/TreeItem';
import TreeView from '@material-ui/lab/TreeView';
import { SidebarIndexTableOfContents } from '../../../src/components/SidebarIndexTableOfContents';
import manifestJson from '../../fixtures/version-2/structures.json';

/**
* Create shallow enzyme wrapper for SidebarIndexTableOfContents component
* @param {*} props
*/
function createWrapper(props) {
const manifest = manifesto.create(manifestJson);
return shallow(
<SidebarIndexTableOfContents
id="something"
classes={{}}
treeStructure={props.treeStructure ? props.treeStructure : manifest.getDefaultTree()}
visibleNodeIds={props.visibleNodeIds ? props.visibleNodeIds : []}
expandedNodeIds={props.expandedNodeIds ? props.expandedNodeIds : []}
containerRef={props.containerRef}
nodeIdToScrollTo={props.nodeIdToScrollTo}
{...props}
/>,
);
}

/**
* Create necessary props to simulate keydown event with specific key
*/
function createKeydownProps(key) {
return [
'keydown',
{
key,
},
];
}

describe('SidebarIndexTableOfContents', () => {
let toggleNode;
let setCanvas;

beforeEach(() => {
toggleNode = jest.fn();
setCanvas = jest.fn();
});


it('renders a tree item for every node', () => {
const structuresWrapper = createWrapper({});
expect(structuresWrapper.find(TreeItem)).toHaveLength(10);
const simpleTreeWrapper = createWrapper({
treeStructure: {
nodes: [
{
id: '0',
nodes: [
{
id: '0-0',
nodes: [],
},
{
id: '0-1',
nodes: [],
},
],
},
],
},
});
expect(simpleTreeWrapper.find(TreeItem)).toHaveLength(3);
});

it('accepts missing nodes property for tress structure and tree nodes', () => {
const noNodesWrapper = createWrapper({
treeStructure: { nodes: undefined },
});
expect(noNodesWrapper.find(TreeItem)).toHaveLength(0);
const noChildNodesWrapper = createWrapper({
treeStructure: {
nodes: [{ id: '0' }],
},
});
expect(noChildNodesWrapper.find(TreeItem)).toHaveLength(1);
});

it('toggles branch nodes on click, but not leaf nodes', () => {
const wrapper = createWrapper({ setCanvas, toggleNode });
const treeView = wrapper.children(TreeView).at(0);

const node0 = treeView.childAt(0);
expect(node0.prop('nodeId')).toBe('0-0');
node0.simulate('click');
node0.simulate('click');
expect(toggleNode).toHaveBeenCalledTimes(2);

const node00 = node0.children().at(0);
expect(node00.prop('nodeId')).toBe('0-0-0');
node00.simulate('click');
node00.simulate('click');
expect(toggleNode).toHaveBeenCalledTimes(2);

const node1 = treeView.childAt(1);
expect(node1.prop('nodeId')).toBe('0-1');
node1.simulate('click');
expect(toggleNode).toHaveBeenCalledTimes(3);
});

it('collapses branch nodes (i.e. toggles open branch nodes) with left arrow key', () => {
const wrapper = createWrapper({
expandedNodeIds: ['0-0'],
setCanvas,
toggleNode,
});
const treeView = wrapper.children(TreeView).at(0);

const node0 = treeView.childAt(0);
expect(node0.prop('nodeId')).toBe('0-0');
node0.simulate(...createKeydownProps('ArrowLeft'));
expect(toggleNode).toHaveBeenCalledTimes(1);

const node00 = node0.children().at(0);
expect(node00.prop('nodeId')).toBe('0-0-0');
const node1 = treeView.childAt(1);
expect(node1.prop('nodeId')).toBe('0-1');

node00.simulate(...createKeydownProps('ArrowLeft'));
node1.simulate(...createKeydownProps('ArrowLeft'));
expect(toggleNode).toHaveBeenCalledTimes(1);
});

it('expands branch nodes (i.e. toggles closed branch nodes) with right arrow key', () => {
const wrapper = createWrapper({
expandedNodeIds: ['0-0'],
setCanvas,
toggleNode,
});
const treeView = wrapper.children(TreeView).at(0);
const node0 = treeView.childAt(0);
expect(node0.prop('nodeId')).toBe('0-0');
const node00 = node0.children().at(0);
expect(node00.prop('nodeId')).toBe('0-0-0');

node0.simulate(...createKeydownProps('ArrowRight'));
node00.simulate(...createKeydownProps('ArrowRight'));
expect(toggleNode).toHaveBeenCalledTimes(0);

const node1 = treeView.childAt(1);
expect(node1.prop('nodeId')).toBe('0-1');
node1.simulate(...createKeydownProps('ArrowRight'));
expect(toggleNode).toHaveBeenCalledTimes(1);
});

it('toggles branch nodes (but not leaf nodes) with Space or Enter key', () => {
const wrapper = createWrapper({ setCanvas, toggleNode });
const treeView = wrapper.children(TreeView).at(0);
const node0 = treeView.childAt(0);
node0.simulate(...createKeydownProps('Enter'));
expect(toggleNode).toHaveBeenCalledTimes(1);
node0.simulate(...createKeydownProps(' '));
expect(toggleNode).toHaveBeenCalledTimes(2);
node0.simulate(...createKeydownProps('Spacebar'));
expect(toggleNode).toHaveBeenCalledTimes(3);
node0.simulate(...createKeydownProps('Tab'));
node0.children().at(0).simulate(...createKeydownProps('Enter'));
node0.children().at(0).simulate(...createKeydownProps(' '));
expect(toggleNode).toHaveBeenCalledTimes(3);
treeView.childAt(1).simulate(...createKeydownProps('Enter'));
treeView.childAt(1).simulate(...createKeydownProps(' '));
expect(toggleNode).toHaveBeenCalledTimes(5);
});

it('calls setCanvas only on click for ranges with canvases', () => {
const wrapper = createWrapper({ setCanvas, toggleNode });
const treeView = wrapper.children(TreeView).at(0);
const node0 = treeView.childAt(0);
expect(node0.prop('nodeId')).toBe('0-0');
node0.simulate('click');
expect(setCanvas).toHaveBeenCalledTimes(1);
node0.childAt(0).simulate('click');
expect(setCanvas).toHaveBeenCalledTimes(2);
node0.childAt(1).simulate('click');
expect(setCanvas).toHaveBeenCalledTimes(3);
node0.childAt(2).simulate('click');
expect(setCanvas).toHaveBeenCalledTimes(4);

const node1 = treeView.childAt(1);
expect(node1.prop('nodeId')).toBe('0-1');
node1.simulate(...createKeydownProps('ArrowRight'));
expect(setCanvas).toHaveBeenCalledTimes(4);
});
});
1 change: 1 addition & 0 deletions __tests__/src/components/WindowSideBarCanvasPanel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function createWrapper(props) {
config={{ canvasNavigation: { height: 100 } }}
updateVariant={() => {}}
selectedCanvases={[canvases[1]]}
variant="compact"
{...props}
/>,
);
Expand Down
Loading