Select Git revision
windows.test.js
windows.test.js 15.27 KiB
import { call, select } from 'redux-saga/effects';
import { expectSaga } from 'redux-saga-test-plan';
import { Utils } from 'manifesto.js/dist-esmodule/Utils';
import ActionTypes from '../../../src/state/actions/action-types';
import { setCanvas } from '../../../src/state/actions';
import {
getManifests, getManifestoInstance,
getManifestSearchService, getCompanionWindowIdsForPosition,
getSearchForWindow,
getWorkspace, getElasticLayout,
getWindow, getCanvasGrouping,
getSelectedContentSearchAnnotationIds,
getSortedSearchAnnotationsForCompanionWindow,
getVisibleCanvasIds, getCanvasForAnnotation,
getCanvases, selectInfoResponses,
} from '../../../src/state/selectors';
import { fetchManifests } from '../../../src/state/sagas/iiif';
import {
determineAndShowCollectionDialog,
fetchWindowManifest,
setWindowDefaultSearchQuery,
setWindowStartingCanvas,
getAnnotationsBySearch,
updateVisibleCanvases,
setCanvasOfFirstSearchResult,
setCanvasforSelectedAnnotation,
panToFocusedWindow,
setCurrentAnnotationsOnCurrentCanvas,
fetchInfoResponses,
setCollectionPath,
} from '../../../src/state/sagas/windows';
import fixture from '../../fixtures/version-2/019.json';
import collectionFixture from '../../fixtures/version-2/collection.json';
describe('window-level sagas', () => {
describe('fetchWindowManifest', () => {
it('calls into fetchManifests for each window', () => {
const action = {
window: {
id: 'x',
manifestId: 'manifest.json',
},
};
const manifest = Utils.parseManifest(fixture);
return expectSaga(fetchWindowManifest, action)
.provide([
[select(getManifests), {}],
[select(getManifestoInstance, { manifestId: 'manifest.json' }), manifest],
[call(fetchManifests, 'manifest.json'), {}],
[call(setWindowStartingCanvas, action)],
[call(setWindowDefaultSearchQuery, action)],
[call(setCollectionPath, { manifestId: 'manifest.json', windowId: 'x' })],
])
.call(fetchManifests, 'manifest.json')
.run();
});
it('calls additional methods after ensuring we have a manifest', () => {
const action = {
window: {
id: 'x',
manifestId: 'manifest.json',
},
};
return expectSaga(fetchWindowManifest, action)
.provide([
[select(getManifests), { 'manifest.json': {} }],
[call(setWindowStartingCanvas, action)],
[call(setWindowDefaultSearchQuery, action)],
[call(setCollectionPath, { manifestId: 'manifest.json', windowId: 'x' })],
[call(determineAndShowCollectionDialog, 'manifest.json', 'x')],
])
.call(setWindowStartingCanvas, action)
.call(setWindowDefaultSearchQuery, action)
.call(determineAndShowCollectionDialog, 'manifest.json', 'x')
.run();
});
});
describe('setWindowStartingCanvas', () => {
it('calls setCanvas if the canvas id was provided', () => {
const action = {
window: {
canvasId: '1',
id: 'x',
manifestId: 'manifest.json',
},
};
return expectSaga(setWindowStartingCanvas, action)
.provide([
[select(getManifests), { 'manifest.json': {} }],
[call(setCanvas, 'x', '1', null, { preserveViewport: false }), { type: 'setCanvasThunk' }],
])
.put({ type: 'setCanvasThunk' })
.run();
});
it('calls setCanvas if the canvas id was provided via the payload and preserves viewport', () => {
const action = {
id: 'x',
payload: {
canvasId: '1',
manifestId: 'manifest.json',
},
};
return expectSaga(setWindowStartingCanvas, action)
.provide([
[select(getManifests), { 'manifest.json': {} }],
[call(setCanvas, 'x', '1', null, { preserveViewport: true }), { type: 'setCanvasThunk' }],
])
.put({ type: 'setCanvasThunk' })
.run();
});
it('calculates the starting canvas and calls setCanvas', () => {
const action = {
window: {
id: 'x',
manifestId: 'manifest.json',
},
};
const manifest = Utils.parseManifest({ ...fixture, start: { id: 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1' } });
return expectSaga(fetchWindowManifest, action)
.provide([
[select(getManifests), { 'manifest.json': {} }],
[select(getManifestoInstance, { manifestId: 'manifest.json' }), manifest],
[call(setCanvas, 'x', 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1'), { type: 'setCanvasThunk' }],
])
.put({ type: 'setCanvasThunk' })
.run();
});
});
describe('setWindowDefaultSearchQuery', () => {
it('does nothing if there was no default query', () => {
const action = {
window: {
id: 'x',
manifestId: 'manifest.json',
},
};
return expectSaga(setWindowDefaultSearchQuery, action)
.run().then(({ allEffects }) => allEffects.length === 0);
});
it('initiates a search', () => {
const action = {
window: {
defaultSearchQuery: 'xyz',
id: 'x',
manifestId: 'manifest.json',
},
};
return expectSaga(setWindowDefaultSearchQuery, action)
.provide([
[select(getManifestSearchService, { windowId: 'x' }), { id: 'http://search/' }],
[select(getCompanionWindowIdsForPosition, { position: 'left', windowId: 'x' }), ['left']],
])
.put({
companionWindowId: 'left',
query: 'xyz',
searchId: 'http://search/?q=xyz',
type: ActionTypes.REQUEST_SEARCH,
windowId: 'x',
})
.run()
.then(({ allEffects }) => allEffects.length === 1);
});
});
describe('setCurrentAnnotationsOnCurrentCanvas', () => {
it('short circuits if there is no active search', () => {
const action = {
type: ActionTypes.SET_CANVAS,
visibleCanvases: ['a'],
windowId: 'abc123',
};
return expectSaga(setCurrentAnnotationsOnCurrentCanvas, action)
.provide([
[select(getSearchForWindow,
{ windowId: 'abc123' }), {}],
])
.run()
.then(({ allEffects }) => allEffects.length === 0);
});
it('does nothing when there are no annotations targeting the current canvas', () => {
const action = {
type: ActionTypes.SET_CANVAS,
visibleCanvases: ['a', 'b'],
windowId: 'abc123',
};
return expectSaga(setCurrentAnnotationsOnCurrentCanvas, action)
.provide([
[select(getSearchForWindow,
{ windowId: 'abc123' }), { cwid: { } }],
[select(getAnnotationsBySearch, { canvasIds: ['a', 'b'], companionWindowIds: ['cwid'], windowId: 'abc123' }),
{ }],
])
.run()
// Assert that nothing did happen, see https://github.com/jfairbank/redux-saga-test-plan/issues/137
.then(({ effects }) => {
expect(effects.select.length).toEqual(2);
expect(effects.put).toBeUndefined();
});
});
it('selects content search annotations for the current searches', () => {
const action = {
type: ActionTypes.SET_CANVAS,
visibleCanvases: ['a', 'b'],
windowId: 'abc123',
};
return expectSaga(setCurrentAnnotationsOnCurrentCanvas, action)
.provide([
[select(getSearchForWindow,
{ windowId: 'abc123' }), { cwid: { } }],
[select(getAnnotationsBySearch, { canvasIds: ['a', 'b'], companionWindowIds: ['cwid'], windowId: 'abc123' }),
{ cwid: ['annoId'] }],
])
.put({
annotationIds: ['annoId'], companionWindowId: 'cwid', type: ActionTypes.SET_CONTENT_SEARCH_CURRENT_ANNOTATIONS, windowId: 'abc123',
})
.put({
annotationId: 'annoId', type: ActionTypes.SELECT_ANNOTATION, windowId: 'abc123',
})
.run();
});
});
describe('panToFocusedWindow', () => {
it('does nothing if pan was disabled', () => {
const action = {
pan: false,
windowId: 'x',
};
return expectSaga(panToFocusedWindow, action)
.run().then(({ allEffects }) => allEffects.length === 0);
});
it('sets the viewport position to the newly focused window', () => {
const action = {
pan: true,
windowId: 'x',
};
return expectSaga(panToFocusedWindow, action)
.provide([
[select(getWorkspace), {
viewportPosition: { height: 100, width: 100 },
}],
[select(getElasticLayout), {
x: {
height: 50, width: 50, x: 50, y: 12,
},
}],
])
.put({
payload: {
position: {
x: 25,
y: -13,
},
},
type: ActionTypes.SET_WORKSPACE_VIEWPORT_POSITION,
})
.run();
});
});
describe('updateVisibleCanvases', () => {
it('recalculates the visible canvases', () => {
const windowId = 'x';
const action = {
windowId,
};
return expectSaga(updateVisibleCanvases, action)
.provide([
[select(getWindow, { windowId }), { canvasId: 'y' }],
[select(getCanvasGrouping, { canvasId: 'y', windowId }), [{ id: 'y' }, { id: 'z' }]],
])
.put({
id: windowId,
payload: { visibleCanvases: ['y', 'z'] },
type: ActionTypes.UPDATE_WINDOW,
})
.run();
});
});
describe('setCanvasOfFirstSearchResult', () => {
it('updates the current canvas', () => {
const companionWindowId = 'x';
const windowId = 'y';
const action = {
companionWindowId,
type: ActionTypes.RECEIVE_SEARCH,
windowId,
};
return expectSaga(setCanvasOfFirstSearchResult, action)
.provide([
[select(getSelectedContentSearchAnnotationIds, { companionWindowId, windowId }), []],
[select(getSortedSearchAnnotationsForCompanionWindow, { companionWindowId, windowId }), [{ id: 'a' }, { id: 'b' }]],
])
.put({
annotationId: 'a',
type: 'mirador/SELECT_ANNOTATION',
windowId: 'y',
})
.run();
});
it('does nothing if a search annotation is already selected', () => {
const companionWindowId = 'x';
const windowId = 'y';
const action = {
companionWindowId,
type: ActionTypes.RECEIVE_SEARCH,
windowId,
};
return expectSaga(setCanvasOfFirstSearchResult, action)
.provide([
[select(getSelectedContentSearchAnnotationIds, { companionWindowId, windowId }), ['y']],
])
.run().then(({ allEffects }) => allEffects.length === 0);
});
});
describe('setCanvasforSelectedAnnotation', () => {
it('changes the canvas to that of the selected annotation', () => {
const annotationId = ['a'];
const windowId = 'y';
const action = {
annotationId,
type: ActionTypes.SELECT_ANNOTATION,
windowId,
};
return expectSaga(setCanvasforSelectedAnnotation, action)
.provide([
[select(getVisibleCanvasIds, { windowId }), ['q']],
[select(getCanvasForAnnotation, { annotationId, windowId }), { id: 'z' }],
[call(setCanvas, windowId, 'z'), { type: 'expectedThunk' }],
])
.put({ type: 'expectedThunk' })
.run();
});
it('does nothing if the canvas is already visible', () => {
const annotationId = 'a';
const windowId = 'y';
const action = {
annotationId,
type: ActionTypes.SELECT_ANNOTATION,
windowId,
};
return expectSaga(setCanvasforSelectedAnnotation, action)
.provide([
[select(getVisibleCanvasIds, { windowId }), ['z']],
[select(getCanvasForAnnotation, { annotationId, windowId }), { id: 'z' }],
])
.run().then(({ allEffects }) => allEffects.length === 0);
});
it('does nothing if the annotation is not on one of our canvases', () => {
const annotationId = 'a';
const windowId = 'y';
const action = {
annotationId,
type: ActionTypes.SELECT_ANNOTATION,
windowId,
};
return expectSaga(setCanvasforSelectedAnnotation, action)
.provide([
[select(getVisibleCanvasIds, { windowId }), ['z']],
[select(getCanvasForAnnotation, { annotationId, windowId }), null],
])
.run().then(({ allEffects }) => allEffects.length === 0);
});
});
describe('fetchInfoResponses', () => {
it('requests info responses for each visible canvas', () => {
const action = {
visibleCanvases: ['http://iiif.io/api/presentation/2.0/example/fixtures/canvas/24/c1.json'],
windowId: 'foo',
};
const manifest = Utils.parseManifest(fixture);
return expectSaga(fetchInfoResponses, action)
.provide([
[select(getCanvases, { windowId: 'foo' }), manifest.getSequences()[0].getCanvases()],
[select(selectInfoResponses), {}],
])
.put.like({
action: {
infoId: 'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44',
type: 'mirador/REQUEST_INFO_RESPONSE',
},
})
.run();
});
it('requests nothing if the response is already in the store', () => {
const action = {
visibleCanvases: ['http://iiif.io/api/presentation/2.0/example/fixtures/canvas/24/c1.json'],
windowId: 'foo',
};
const manifest = Utils.parseManifest(fixture);
return expectSaga(fetchInfoResponses, action)
.provide([
[select(getCanvases, { windowId: 'foo' }), manifest.getSequences()[0].getCanvases()],
[select(selectInfoResponses), { 'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44': {} }],
])
.not.put.like({
action: {
infoId: 'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44',
type: 'mirador/REQUEST_INFO_RESPONSE',
},
})
.run();
});
});
describe('determineAndShowCollectionDialog', () => {
it('shows the collection dialog if it is a collection', () => {
const manifest = Utils.parseManifest(collectionFixture);
return expectSaga(determineAndShowCollectionDialog, 'manifest.json', 'x')
.provide([
[select(getManifestoInstance, { manifestId: 'manifest.json' }), manifest],
])
.put.like({
action: {
collectionPath: [],
manifestId: 'manifest.json',
type: 'mirador/SHOW_WINDOW_COLLECTION_DIALOG',
windowId: 'x',
},
})
.run();
});
it('does nothing if not a collection', () => {
const manifest = Utils.parseManifest(fixture);
return expectSaga(determineAndShowCollectionDialog, 'manifest.json', 'x')
.provide([
[select(getManifestoInstance, { manifestId: 'manifest.json' }), manifest],
])
.not.put.like({
action: {
collectionPath: [],
manifestId: 'manifest.json',
type: 'mirador/SHOW_WINDOW_COLLECTION_DIALOG',
windowId: 'x',
},
})
.run();
});
});
});