@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-a1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +17 -15
- package/.github/workflows/node.js.yml +77 -6
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +131 -339
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +24 -0
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1493 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/images/BRicons.svg +2 -2
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -1
- package/BookReader/images/icon_search_button.svg +1 -1
- package/BookReader/images/icon_share.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/marker_chap-off.svg +1 -1
- package/BookReader/images/marker_chap-on.svg +1 -1
- package/BookReader/images/marker_srch-on.svg +1 -1
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +1 -1
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -1
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +14 -1
- package/BookReaderDemo/IADemoBr.js +148 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-autoplay.html +2 -1
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
- package/BookReaderDemo/demo-fullscreen.html +2 -1
- package/BookReaderDemo/demo-iiif.html +2 -1
- package/BookReaderDemo/demo-internetarchive.html +84 -17
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +2 -1
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -1
- package/BookReaderDemo/immersion-mode.html +2 -1
- package/BookReaderDemo/toggle_controls.html +2 -1
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +202 -0
- package/README.md +14 -1
- package/babel.config.js +18 -0
- package/codecov.yml +6 -0
- package/index.html +3 -0
- package/jsconfig.json +19 -0
- package/package.json +66 -56
- package/renovate.json +52 -0
- package/scripts/preversion.js +4 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +9 -2
- package/src/BookNavigator/assets/ia-logo.js +17 -0
- package/src/BookNavigator/assets/icon_checkmark.js +1 -1
- package/src/BookNavigator/assets/icon_close.js +1 -1
- package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/book-navigator.js +583 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +41 -25
- package/src/BookNavigator/search/a-search-result.js +18 -13
- package/src/BookNavigator/search/search-provider.js +80 -28
- package/src/BookNavigator/search/search-results.js +10 -18
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/BookModel.js +0 -29
- package/src/BookReader/DebugConsole.js +3 -3
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +51 -351
- package/src/BookReader/Mode1UpLit.js +441 -0
- package/src/BookReader/Mode2Up.js +120 -105
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +17 -11
- package/src/BookReader/Navbar/Navbar.js +10 -36
- package/src/BookReader/PageContainer.js +69 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +10 -37
- package/src/BookReader/options.js +10 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils.js +92 -13
- package/src/BookReader.js +431 -620
- package/src/assets/icons/close-circle-dark.svg +1 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/assets/icons/voice.svg +1 -0
- package/src/css/BookReader.scss +0 -12
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +19 -24
- package/src/css/_BRnav.scss +4 -26
- package/src/css/_BRpages.scss +35 -0
- package/src/css/_BRsearch.scss +25 -216
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +17 -5
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.autoplay.js +4 -4
- package/src/plugins/plugin.chapters.js +28 -35
- package/src/plugins/plugin.mobile_nav.js +11 -10
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +26 -39
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +174 -116
- package/src/plugins/search/view.js +63 -179
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +13 -14
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +66 -69
- package/src/plugins/tts/plugin.tts.js +92 -109
- package/src/plugins/tts/utils.js +0 -9
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/src/util/manifestGenerator.js +0 -0
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +7 -7
- package/tests/e2e/helpers/base.js +9 -3
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/desktopSearch.js +14 -13
- package/tests/e2e/helpers/mobileSearch.js +3 -3
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/models/Navigation.js +13 -4
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
- package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
- package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
- package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
- package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
- package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
- package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
- package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +186 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
- package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
- package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
- package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
- package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/{util → jest/util}/docCookies.test.js +1 -1
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/webpack.config.js +11 -5
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -1450
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/jquery-1.10.1.js +0 -2
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/karma.conf.js +0 -23
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -438
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/Layers/sharing/sharing-provider.js +0 -22
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.bookmarks.js +0 -50
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -0,0 +1,184 @@
|
|
1
|
+
export class UrlPlugin {
|
2
|
+
constructor(options = {}) {
|
3
|
+
this.bookReaderOptions = options;
|
4
|
+
|
5
|
+
// the canonical order of elements is important in the path and query string
|
6
|
+
this.urlSchema = [
|
7
|
+
{ name: 'page', position: 'path', default: 'n0' },
|
8
|
+
{ name: 'mode', position: 'path', default: '2up' },
|
9
|
+
{ name: 'search', position: 'path', deprecated_for: 'q' },
|
10
|
+
{ name: 'q', position: 'query_param' },
|
11
|
+
{ name: 'sort', position: 'query_param' },
|
12
|
+
{ name: 'view', position: 'query_param' },
|
13
|
+
{ name: 'admin', position: 'query_param' },
|
14
|
+
];
|
15
|
+
|
16
|
+
this.urlState = {};
|
17
|
+
this.urlMode = this.bookReaderOptions.urlMode || 'hash';
|
18
|
+
this.urlHistoryBasePath = this.bookReaderOptions.urlHistoryBasePath || '/';
|
19
|
+
this.urlLocationPollId = null;
|
20
|
+
this.oldLocationHash = null;
|
21
|
+
this.oldUserHash = null;
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Parse JSON object URL state to string format
|
26
|
+
* Arrange path names in an order that it is positioned on the urlSchema
|
27
|
+
* @param {Object} urlState
|
28
|
+
* @returns {string}
|
29
|
+
*/
|
30
|
+
urlStateToUrlString(urlState) {
|
31
|
+
const searchParams = new URLSearchParams();
|
32
|
+
const pathParams = {};
|
33
|
+
|
34
|
+
Object.keys(urlState).forEach(key => {
|
35
|
+
let schema = this.urlSchema.find(schema => schema.name === key);
|
36
|
+
if (schema?.deprecated_for) {
|
37
|
+
schema = this.urlSchema.find(schemaKey => schemaKey.name === schema.deprecated_for);
|
38
|
+
}
|
39
|
+
if (schema?.position == 'path') {
|
40
|
+
pathParams[schema?.name] = urlState[key];
|
41
|
+
} else {
|
42
|
+
searchParams.append(schema?.name || key, urlState[key]);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
|
46
|
+
const strPathParams = this.urlSchema
|
47
|
+
.filter(s => s.position == 'path')
|
48
|
+
.map(schema => pathParams[schema.name] ? `${schema.name}/${pathParams[schema.name]}` : '')
|
49
|
+
.join('/');
|
50
|
+
|
51
|
+
// replace consecutive slashes with a single slash + remove trailing slashes
|
52
|
+
const strStrippedTrailingSlash = `${strPathParams.replace(/\/+/g, '/').replace(/\/+$/, '')}`;
|
53
|
+
const concatenatedPath = `${strStrippedTrailingSlash}?${searchParams.toString()}`;
|
54
|
+
return searchParams.toString() ? concatenatedPath : `${strStrippedTrailingSlash}`;
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Parse string URL and add it in the current urlState
|
59
|
+
* Example:
|
60
|
+
* /page/n7/mode/2up => {page: 'n7', mode: '2up'}
|
61
|
+
* /page/n7/mode/2up/search/hello => {page: 'n7', mode: '2up', q: 'hello'}
|
62
|
+
* @param {string} urlString
|
63
|
+
* @returns {object}
|
64
|
+
*/
|
65
|
+
urlStringToUrlState(urlString) {
|
66
|
+
const urlState = {};
|
67
|
+
|
68
|
+
// Fetch searchParams from given {str}
|
69
|
+
// Note: whole URL path is needed for URL parsing
|
70
|
+
const urlPath = new URL(urlString, 'http://example.com');
|
71
|
+
const urlSearchParamsObj = Object.fromEntries(urlPath.searchParams.entries());
|
72
|
+
const splitUrlMatches = urlPath.pathname.match(/[^\\/]+\/[^\\/]+/g);
|
73
|
+
const urlStrSplitSlashObj = splitUrlMatches ? Object.fromEntries(splitUrlMatches.map(x => x.split('/'))) : {};
|
74
|
+
|
75
|
+
const doesKeyExists = (_object, _key) => {
|
76
|
+
return Object.keys(_object).some(value => value == _key);
|
77
|
+
};
|
78
|
+
|
79
|
+
// Add path objects to urlState
|
80
|
+
this.urlSchema
|
81
|
+
.filter(schema => schema.position == 'path')
|
82
|
+
.forEach(schema => {
|
83
|
+
const hasPropertyKey = doesKeyExists(urlStrSplitSlashObj, schema.name);
|
84
|
+
const hasDeprecatedKey = doesKeyExists(schema, 'deprecated_for') && hasPropertyKey;
|
85
|
+
|
86
|
+
if (hasDeprecatedKey) {
|
87
|
+
urlState[schema.deprecated_for] = urlStrSplitSlashObj[schema.name];
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
|
91
|
+
if (hasPropertyKey) {
|
92
|
+
urlState[schema.name] = urlStrSplitSlashObj[schema.name];
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
// Add searchParams to urlState
|
98
|
+
Object.entries(urlSearchParamsObj).forEach(([key, value]) => {
|
99
|
+
urlState[key] = value;
|
100
|
+
});
|
101
|
+
|
102
|
+
return urlState;
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Add or update key-value to the urlState
|
107
|
+
* @param {string} key
|
108
|
+
* @param {string} val
|
109
|
+
*/
|
110
|
+
setUrlParam(key, value) {
|
111
|
+
this.urlState[key] = value;
|
112
|
+
|
113
|
+
this.pushToAddressBar();
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* Delete key-value to the urlState
|
118
|
+
* @param {string} key
|
119
|
+
*/
|
120
|
+
removeUrlParam(key) {
|
121
|
+
delete this.urlState[key];
|
122
|
+
|
123
|
+
this.pushToAddressBar();
|
124
|
+
}
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Get key-value from the urlState
|
128
|
+
* @param {string} key
|
129
|
+
* @return {string}
|
130
|
+
*/
|
131
|
+
getUrlParam(key) {
|
132
|
+
return this.urlState[key];
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Push URL params to addressbar
|
137
|
+
*/
|
138
|
+
pushToAddressBar() {
|
139
|
+
const urlStrPath = this.urlStateToUrlString(this.urlState);
|
140
|
+
const concatenatedPath = urlStrPath !== '/' ? urlStrPath : '';
|
141
|
+
if (this.urlMode == 'history') {
|
142
|
+
if (window.history && window.history.replaceState) {
|
143
|
+
const newUrlPath = `${this.urlHistoryBasePath}${concatenatedPath}`.trim().replace(/(\/+)/g, '/');
|
144
|
+
window.history.replaceState({}, null, newUrlPath);
|
145
|
+
}
|
146
|
+
} else {
|
147
|
+
window.location.replace('#' + concatenatedPath);
|
148
|
+
}
|
149
|
+
this.oldLocationHash = urlStrPath;
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Get the url and check if it has changed
|
154
|
+
* If it was changeed, update the urlState
|
155
|
+
*/
|
156
|
+
listenForHashChanges() {
|
157
|
+
this.oldLocationHash = window.location.hash.substr(1);
|
158
|
+
if (this.urlLocationPollId) {
|
159
|
+
clearInterval(this.urlLocationPollId);
|
160
|
+
this.urlLocationPollId = null;
|
161
|
+
}
|
162
|
+
|
163
|
+
// check if the URL changes
|
164
|
+
const updateHash = () => {
|
165
|
+
const newFragment = window.location.hash.substr(1);
|
166
|
+
const hasFragmentChange = newFragment != this.oldLocationHash;
|
167
|
+
|
168
|
+
if (!hasFragmentChange) { return; }
|
169
|
+
|
170
|
+
this.urlState = this.urlStringToUrlState(newFragment);
|
171
|
+
};
|
172
|
+
this.urlLocationPollId = setInterval(updateHash, 500);
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Will read either the hash or URL and return the bookreader fragment
|
177
|
+
*/
|
178
|
+
pullFromAddressBar (location = window.location) {
|
179
|
+
const path = this.urlMode === 'history'
|
180
|
+
? (location.pathname.substr(this.urlHistoryBasePath.length) + location.search)
|
181
|
+
: location.hash.substr(1);
|
182
|
+
this.urlState = this.urlStringToUrlState(path);
|
183
|
+
}
|
184
|
+
}
|
@@ -1,4 +1,7 @@
|
|
1
1
|
/* global BookReader */
|
2
|
+
|
3
|
+
import { UrlPlugin } from "./UrlPlugin";
|
4
|
+
|
2
5
|
/**
|
3
6
|
* Plugin for URL management in BookReader
|
4
7
|
* Note read more about the url "fragment" here:
|
@@ -22,7 +25,7 @@ jQuery.extend(BookReader.defaultOptions, {
|
|
22
25
|
urlHistoryBasePath: '/',
|
23
26
|
|
24
27
|
/** Only these params will be reflected onto the URL */
|
25
|
-
urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight'],
|
28
|
+
urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight', 'view'],
|
26
29
|
|
27
30
|
/** If true, don't update the URL when `page == n0 (eg "/page/n0")` */
|
28
31
|
urlTrackIndex0: false,
|
@@ -50,7 +53,7 @@ BookReader.prototype.init = (function(super_) {
|
|
50
53
|
this.bind(BookReader.eventNames.PostInit, () => {
|
51
54
|
const { updateWindowTitle, urlMode } = this.options;
|
52
55
|
if (updateWindowTitle) {
|
53
|
-
document.title = this.shortTitle(50);
|
56
|
+
document.title = this.shortTitle(this.bookTitle, 50);
|
54
57
|
}
|
55
58
|
if (urlMode === 'hash') {
|
56
59
|
this.urlStartLocationPolling();
|
@@ -86,7 +89,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
|
|
86
89
|
this.oldLocationHash = this.urlReadFragment();
|
87
90
|
|
88
91
|
if (this.locationPollId) {
|
89
|
-
clearInterval(this.
|
92
|
+
clearInterval(this.locationPollId);
|
90
93
|
this.locationPollId = null;
|
91
94
|
}
|
92
95
|
|
@@ -110,7 +113,7 @@ BookReader.prototype.urlStartLocationPolling = function() {
|
|
110
113
|
updateParams();
|
111
114
|
}
|
112
115
|
this.oldUserHash = newFragment;
|
113
|
-
}
|
116
|
+
};
|
114
117
|
|
115
118
|
this.locationPollId = setInterval(updateHash, 500);
|
116
119
|
};
|
@@ -134,7 +137,7 @@ BookReader.prototype.urlUpdateFragment = function() {
|
|
134
137
|
if (paramName in allParams) {
|
135
138
|
validParams[paramName] = allParams[paramName];
|
136
139
|
}
|
137
|
-
return validParams
|
140
|
+
return validParams;
|
138
141
|
}, {});
|
139
142
|
|
140
143
|
const newFragment = this.fragmentFromParams(params, urlMode);
|
@@ -173,7 +176,7 @@ BookReader.prototype.urlUpdateFragment = function() {
|
|
173
176
|
BookReader.prototype.urlParamsFiltersOnlySearch = function(url) {
|
174
177
|
const params = new URLSearchParams(url);
|
175
178
|
return params.has('q') ? `?${new URLSearchParams({ q: params.get('q') })}` : '';
|
176
|
-
}
|
179
|
+
};
|
177
180
|
|
178
181
|
|
179
182
|
/**
|
@@ -196,3 +199,22 @@ BookReader.prototype.urlReadFragment = function() {
|
|
196
199
|
BookReader.prototype.urlReadHashFragment = function() {
|
197
200
|
return window.location.hash.substr(1);
|
198
201
|
};
|
202
|
+
export class BookreaderUrlPlugin extends BookReader {
|
203
|
+
init() {
|
204
|
+
if (this.options.enableUrlPlugin) {
|
205
|
+
this.urlPlugin = new UrlPlugin(this.options);
|
206
|
+
this.bind(BookReader.eventNames.PostInit, () => {
|
207
|
+
const { urlMode } = this.options;
|
208
|
+
|
209
|
+
if (urlMode === 'hash') {
|
210
|
+
this.urlPlugin.listenForHashChanges();
|
211
|
+
}
|
212
|
+
});
|
213
|
+
}
|
214
|
+
|
215
|
+
super.init();
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
window.BookReader = BookreaderUrlPlugin;
|
220
|
+
export default BookreaderUrlPlugin;
|
File without changes
|
package/tests/e2e/README.md
CHANGED
@@ -48,6 +48,43 @@ To run a particular fixture, add the path to the file at the end of your argumen
|
|
48
48
|
|
49
49
|
`npm run test:e2e chrome tests/e2e/example.test.js`
|
50
50
|
|
51
|
+
### Testing netlify or archive.org
|
52
|
+
|
53
|
+
```sh
|
54
|
+
BASE_URL='https://lucid-poitras-9a1249.netlify.app' npx testcafe
|
55
|
+
BASE_URL='https://archive.org' npx testcafe
|
56
|
+
```
|
57
|
+
|
58
|
+
### Testing any OCAID
|
59
|
+
|
60
|
+
For OCAIDs you should pick the specific test file to run, since things like autoplay tests won't work. The main tests are in `base.test.js`.
|
61
|
+
|
62
|
+
```sh
|
63
|
+
OCAIDS='goody,goodytwoshoes00newyiala' npx testcafe tests/e2e/base.test.js
|
64
|
+
OCAIDS='goody,goodytwoshoes00newyiala' BASE_URL='https://archive.org' npx testcafe tests/e2e/base.test.js
|
65
|
+
|
66
|
+
# right to left book; note this also runs the base tests
|
67
|
+
OCAIDS='gendaitankashu00meijuoft' BASE_URL='https://archive.org' npx testcafe tests/e2e/rightToLeft.test.js
|
68
|
+
```
|
69
|
+
|
70
|
+
### Running tests with browserstack
|
71
|
+
|
72
|
+
Note these can only test a public url, so you either need to create a draft PR and use the netlify link, or use ngrok to publish your dev server's port.
|
73
|
+
|
74
|
+
Note: Windows users, there is a bug that prevents spaces in the browser field when using `npx`, so you'll need to have `testcafe` globally installed, and run it without `npx`. (See https://github.com/DevExpress/testcafe/issues/6600 ). Or, you can add browserstack browsers the `.testcaferc.js` file.
|
75
|
+
|
76
|
+
```sh
|
77
|
+
# Set auth; find yours at https://www.browserstack.com/accounts/settings
|
78
|
+
export BROWSERSTACK_USERNAME="YOUR_USERNAME"
|
79
|
+
export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY"
|
80
|
+
|
81
|
+
BASE_URL='https://archive.org' OCAIDS='goody,goodytwoshoes00newyiala' npx testcafe 'browserstack:iPad Pro 12.9 2018@15' tests/e2e/base.test.js
|
82
|
+
```
|
83
|
+
|
84
|
+
See a list of available browsers with `npx testcafe -b browserstack`. Note there are some browsers which appear to not work for some reason (eg `browserstack:iPad Mini 4@9.3`).
|
85
|
+
|
86
|
+
Read more about other options/etc at the browserstack docs: https://www.browserstack.com/docs/automate/selenium/getting-started/nodejs/testcafe .
|
87
|
+
|
51
88
|
## Pending (skip) tests
|
52
89
|
|
53
90
|
You can skip any tests by calling the method `.skip` on the test object rather
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import { ClientFunction } from 'testcafe';
|
2
|
+
import params from './helpers/params';
|
2
3
|
|
3
|
-
const { BASE_URL } = process.env;
|
4
4
|
const getLocationHref = ClientFunction(() => window.location.href.toString());
|
5
5
|
const FLIP_SPEED = 1000;
|
6
6
|
const FIRST_PAGE_DELAY = 2000;
|
7
7
|
|
8
|
-
fixture `Autoplay plugin`.page `${
|
8
|
+
fixture `Autoplay plugin`.page `${params.baseUrl}/BookReaderDemo/demo-autoplay.html`;
|
9
9
|
|
10
10
|
test('page auto-advances after allotted flip speed and delay', async t => {
|
11
11
|
await t.wait(2 * FLIP_SPEED + FIRST_PAGE_DELAY);
|
package/tests/e2e/base.test.js
CHANGED
@@ -2,10 +2,9 @@ import { runBaseTests } from './helpers/base';
|
|
2
2
|
import BookReader from './models/BookReader';
|
3
3
|
import { runDesktopSearchTests } from './helpers/desktopSearch';
|
4
4
|
// import { runMobileSearchTests } from './helpers/mobileSearch';
|
5
|
+
import params from './helpers/params';
|
5
6
|
|
6
|
-
|
7
|
-
const { BASE_URL } = process.env;
|
8
|
-
const OCAIDS = [
|
7
|
+
const ocaids = params.ocaids || [
|
9
8
|
'theworksofplato01platiala',
|
10
9
|
// Removed because failing test 'Canonical URL with cookie shows paramters'
|
11
10
|
// in tests/e2e/helpers/base.js
|
@@ -15,18 +14,19 @@ const OCAIDS = [
|
|
15
14
|
// /BookReaderDemo/demo-ia-olivertwist.html/page/n13/mode/2up
|
16
15
|
// 'demo-ia-olivertwist.html',
|
17
16
|
];
|
18
|
-
const DEMO_PATH = 'demo-internetarchive.html?ocaid='
|
19
17
|
|
20
|
-
|
21
|
-
const url =
|
18
|
+
ocaids.forEach(ocaid => {
|
19
|
+
const url = params.getArchiveUrl(ocaid);
|
22
20
|
|
23
21
|
fixture `Base Tests for: ${ocaid}`.page `${url}`;
|
24
22
|
runBaseTests(new BookReader());
|
25
23
|
|
24
|
+
|
26
25
|
fixture `Desktop Search Tests for: ${ocaid}`
|
27
|
-
.page `${url}
|
26
|
+
.page `${url}`;
|
28
27
|
runDesktopSearchTests(new BookReader());
|
29
28
|
|
29
|
+
// Todo: deprecated, will remove once mmenu is removed.
|
30
30
|
// fixture `Mobile Search Tests for: ${ocaid}`
|
31
31
|
// .page `${url}`
|
32
32
|
// runMobileSearchTests(new BookReader());
|
@@ -38,6 +38,7 @@ const isModeInUrl = ClientFunction((mode) => {
|
|
38
38
|
*/
|
39
39
|
export function runBaseTests (br) {
|
40
40
|
test('On load, pages fit fully inside of the BookReader™', async t => {
|
41
|
+
await t.wait(1000); // for load
|
41
42
|
await t.expect(br.shell.visible).ok();
|
42
43
|
await t.expect(br.BRcontainer.visible).ok();
|
43
44
|
|
@@ -96,7 +97,7 @@ export function runBaseTests (br) {
|
|
96
97
|
|
97
98
|
if (await usesResume()) {
|
98
99
|
await t.expect(isPageInUrl()).eql(true, initialUrl);
|
99
|
-
await t.expect(isModeInUrl('2up')).eql(true, initialUrl)
|
100
|
+
await t.expect(isModeInUrl('2up')).eql(true, initialUrl);
|
100
101
|
} else {
|
101
102
|
// No plugin, no br-resume cookie
|
102
103
|
await t.expect(getUrl()).notContains('#page/');
|
@@ -138,7 +139,7 @@ export function runBaseTests (br) {
|
|
138
139
|
|
139
140
|
// we aren't showing the same image in the new pages
|
140
141
|
await t.expect(prevImg1Src).notEql(prevImg2Src);
|
141
|
-
})
|
142
|
+
});
|
142
143
|
|
143
144
|
test('2up mode - Clicking `Next page` changes the page', async t => {
|
144
145
|
// Note: this will fail on a R to L book if at front cover
|
@@ -168,7 +169,7 @@ export function runBaseTests (br) {
|
|
168
169
|
|
169
170
|
// we aren't showing the same image in the new pages
|
170
171
|
await t.expect(nextImg1Src).notEql(nextImg2Src);
|
171
|
-
})
|
172
|
+
});
|
172
173
|
|
173
174
|
test('Clicking `page flip buttons` updates location', async t => {
|
174
175
|
const { nav } = br;
|
@@ -191,6 +192,11 @@ export function runBaseTests (br) {
|
|
191
192
|
test('Clicking `1 page view` brings up 1 at a time', async t => {
|
192
193
|
const { nav } = br;
|
193
194
|
await t.click(nav.desktop.mode1Up);
|
195
|
+
|
196
|
+
// Flip away from cover
|
197
|
+
await t.click(nav.desktop.goNext);
|
198
|
+
await t.wait(PAGE_FLIP_WAIT_TIME);
|
199
|
+
|
194
200
|
// we usually pre-fetch the page in question & the 2 after it
|
195
201
|
await t.expect(Selector('.BRpagecontainer').count).gte(3);
|
196
202
|
});
|
@@ -19,14 +19,15 @@ export function runDesktopSearchTests(br) {
|
|
19
19
|
const nav = br.nav;
|
20
20
|
|
21
21
|
//assuring that the search bar is enabled
|
22
|
-
await t.expect(nav.desktop.
|
22
|
+
await t.expect(nav.desktop.searchIcon.visible).ok();
|
23
|
+
await t.click(nav.desktop.searchIcon);
|
23
24
|
|
24
25
|
//testing search for a word found in the book
|
25
|
-
await t
|
26
|
-
|
27
|
-
|
28
|
-
await t.
|
29
|
-
|
26
|
+
await t.selectText(nav.desktop.searchBox).pressKey('delete');
|
27
|
+
// FIXME: Why is it only typing every other letter?!?!
|
28
|
+
await t.typeText(nav.desktop.searchBox, TEST_TEXT_FOUND.split('').join('_'));
|
29
|
+
await t.pressKey('enter');
|
30
|
+
|
30
31
|
await t.expect(nav.desktop.searchPin.exists).ok();
|
31
32
|
await t.expect(nav.desktop.searchPin.child('.BRquery').child('div').exists).ok();
|
32
33
|
await t.expect(nav.desktop.searchPin.child('.BRquery').child('div').innerText).contains(TEST_TEXT_FOUND);
|
@@ -43,7 +44,7 @@ export function runDesktopSearchTests(br) {
|
|
43
44
|
await t.expect(getPageUrl()).contains(PAGE_FIRST_RESULT);
|
44
45
|
|
45
46
|
//checks highlight on result page is visible
|
46
|
-
const highlight = br.shell.find(".
|
47
|
+
const highlight = br.shell.find(".searchHiliteLayer rect");
|
47
48
|
await t.expect(highlight.visible).ok();
|
48
49
|
|
49
50
|
});
|
@@ -54,14 +55,14 @@ export function runDesktopSearchTests(br) {
|
|
54
55
|
const nav = br.nav;
|
55
56
|
|
56
57
|
//assuring that the search bar is enabled
|
57
|
-
await t.expect(nav.desktop.
|
58
|
+
await t.expect(nav.desktop.searchIcon.visible).ok();
|
59
|
+
await t.click(nav.desktop.searchIcon);
|
58
60
|
|
59
61
|
//testing search for a word not found in the book
|
60
|
-
await t
|
61
|
-
|
62
|
-
|
63
|
-
await t.
|
64
|
-
await t.click((nav.desktop.searchBox).child('.BRsearchSubmit'));
|
62
|
+
await t.selectText(nav.desktop.searchBox).pressKey('delete');
|
63
|
+
// FIXME: Why is it only typing every other letter?!?!
|
64
|
+
await t.typeText(nav.desktop.searchBox, TEST_TEXT_NOT_FOUND.split('').join('_'));
|
65
|
+
await t.pressKey('enter');
|
65
66
|
await t.expect(nav.desktop.searchPin.child('.BRquery').child('div').withText(TEST_TEXT_NOT_FOUND).exists).notOk();
|
66
67
|
|
67
68
|
const getPageUrl = ClientFunction(() => window.location.href.toString());
|
@@ -15,7 +15,7 @@ export function runMobileSearchTests(br) {
|
|
15
15
|
|
16
16
|
test
|
17
17
|
.requestHooks(mockFound)('Mobile search - successful search', async t => {
|
18
|
-
await t.resizeWindowToFitDevice('Sony Xperia Z', {portraitOrientation: true})
|
18
|
+
await t.resizeWindowToFitDevice('Sony Xperia Z', {portraitOrientation: true});
|
19
19
|
const nav = br.nav.mobile;
|
20
20
|
|
21
21
|
//opening side menu and search
|
@@ -47,7 +47,7 @@ export function runMobileSearchTests(br) {
|
|
47
47
|
await t.expect(getPageUrl()).contains(PAGE_FIRST_RESULT);
|
48
48
|
|
49
49
|
//checks highlight on result page is visible
|
50
|
-
const highlight = br.shell.find(".
|
50
|
+
const highlight = br.shell.find(".searchHiliteLayer rect");
|
51
51
|
await t.expect(highlight.visible).ok();
|
52
52
|
|
53
53
|
await t.maximizeWindow();
|
@@ -55,7 +55,7 @@ export function runMobileSearchTests(br) {
|
|
55
55
|
|
56
56
|
test
|
57
57
|
.requestHooks(mockNotFound)('Mobile search - unsuccessful search', async t => {
|
58
|
-
await t.resizeWindowToFitDevice('Sony Xperia Z', {portraitOrientation: true})
|
58
|
+
await t.resizeWindowToFitDevice('Sony Xperia Z', {portraitOrientation: true});
|
59
59
|
const nav = br.nav.mobile;
|
60
60
|
|
61
61
|
//opening side menu and search
|
@@ -0,0 +1,17 @@
|
|
1
|
+
// @ts-check
|
2
|
+
class TestParams {
|
3
|
+
baseUrl = process.env.BASE_URL?.replace(/\/+$/, '') ?? 'http://127.0.0.1:8000'
|
4
|
+
ocaids = process.env.OCAIDS?.split(',') ?? null;
|
5
|
+
/** Whether the url we're testing is a prod (or near prod) IA url, or a demos url */
|
6
|
+
isIA = new URL(this.baseUrl).hostname.endsWith('archive.org');
|
7
|
+
|
8
|
+
/** @param {string} ocaid */
|
9
|
+
getArchiveUrl(ocaid) {
|
10
|
+
return this.isIA ? `${this.baseUrl}/details/${ocaid}`
|
11
|
+
// Otherwise it's a demo page
|
12
|
+
: `${this.baseUrl}/BookReaderDemo/demo-internetarchive.html?ocaid=${ocaid}`;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
const params = new TestParams();
|
17
|
+
export default params;
|
@@ -6,7 +6,8 @@ export default class Navigation {
|
|
6
6
|
this.topNavShell = new Selector('.BRtoolbar');
|
7
7
|
this.bottomNavShell = new Selector('.BRfooter');
|
8
8
|
this.mobileMenu = new Selector('.BRmobileMenu');
|
9
|
-
this.
|
9
|
+
this.itemNav = Selector('ia-bookreader').shadowRoot().find('ia-item-navigator').shadowRoot();
|
10
|
+
this.desktop = new DesktopNav(this.bottomNavShell, this.itemNav);
|
10
11
|
this.mobile = new MobileNav(this.mobileMenu, this.topNavShell);
|
11
12
|
}
|
12
13
|
}
|
@@ -16,8 +17,12 @@ export default class Navigation {
|
|
16
17
|
* @class
|
17
18
|
* @classdesc defines DesktopNav base elements
|
18
19
|
*/
|
19
|
-
class DesktopNav {
|
20
|
-
|
20
|
+
export class DesktopNav {
|
21
|
+
/**
|
22
|
+
* @param {Selector} bottomToolbar
|
23
|
+
* @param {Selector} itemNav
|
24
|
+
*/
|
25
|
+
constructor(bottomToolbar, itemNav) {
|
21
26
|
// flipping
|
22
27
|
this.goLeft = bottomToolbar.find('.BRicon.book_left');
|
23
28
|
this.goRight = bottomToolbar.find('.BRicon.book_right');
|
@@ -35,7 +40,11 @@ class DesktopNav {
|
|
35
40
|
this.zoomOut = bottomToolbar.find('.BRicon.zoom_out');
|
36
41
|
|
37
42
|
// search
|
38
|
-
this.
|
43
|
+
this.searchIcon = itemNav.find('button.shortcut.search');
|
44
|
+
this.searchBox = itemNav
|
45
|
+
.find('ia-menu-slider').shadowRoot()
|
46
|
+
.find('ia-book-search-results').shadowRoot()
|
47
|
+
.find('input[name=query]');
|
39
48
|
this.searchPin = bottomToolbar.find('.BRsearch');
|
40
49
|
this.searchNavigation = bottomToolbar.find('.BRsearch-navigation');
|
41
50
|
|
@@ -1,16 +1,15 @@
|
|
1
1
|
import { runBaseTests } from './helpers/base';
|
2
2
|
import { runRightToLeftTests } from './helpers/rightToLeft';
|
3
|
+
import params from './helpers/params';
|
3
4
|
|
4
5
|
import BookReader from './models/BookReader';
|
5
6
|
|
6
|
-
const
|
7
|
-
const DEMO_PATH = 'demo-internetarchive.html?ocaid=';
|
8
|
-
const OCAIDS = [
|
7
|
+
const ocaids = params.ocaids || [
|
9
8
|
'gendaitankashu00meijuoft', // Right to Left book
|
10
9
|
];
|
11
10
|
|
12
|
-
|
13
|
-
const url = `${
|
11
|
+
ocaids.forEach(ocaid => {
|
12
|
+
const url = `${params.getArchiveUrl(ocaid)}`;
|
14
13
|
|
15
14
|
fixture `Base Tests for right to left book: ${ocaid}`.page `${url}`;
|
16
15
|
runBaseTests(new BookReader({ pageProgression: 'rl' }));
|
@@ -1,37 +1,42 @@
|
|
1
1
|
import { Selector } from 'testcafe';
|
2
2
|
import BookReader from './models/BookReader';
|
3
|
+
import params from './helpers/params';
|
3
4
|
|
4
|
-
const
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
5
|
+
const ocaids = params.ocaids || ['goody'];
|
6
|
+
|
7
|
+
ocaids.forEach(ocaid => {
|
8
|
+
const url = params.getArchiveUrl(ocaid);
|
9
|
+
|
10
|
+
fixture `Viewmode carousel`.page `${url}`;
|
11
|
+
|
12
|
+
test('Clicking `view mode` cycles through view modes', async t => {
|
13
|
+
const { nav } = (new BookReader());
|
14
|
+
|
15
|
+
// viewmode button only appear on mobile devices
|
16
|
+
await t.resizeWindow(400, 800);
|
17
|
+
// Flip forward one
|
18
|
+
await t.pressKey('right');
|
19
|
+
|
20
|
+
// 2up to thumb
|
21
|
+
await t.click(nav.desktop.viewmode);
|
22
|
+
const thumbnailContainer = Selector('.BRmodeThumb');
|
23
|
+
await t.expect(thumbnailContainer.visible).ok();
|
24
|
+
const thumbImages = thumbnailContainer.find('.BRpageview img');
|
25
|
+
await t.expect(thumbImages.count).gt(0);
|
26
|
+
|
27
|
+
// thumb to 1up
|
28
|
+
await t.click(nav.desktop.viewmode);
|
29
|
+
const onePageViewContainer = Selector('br-mode-1up');
|
30
|
+
await t.expect(onePageViewContainer.visible).ok();
|
31
|
+
const onePageImages = onePageViewContainer.find('.BRmode1up .BRpagecontainer');
|
32
|
+
// we usually pre-fetch the page in question & 1 before/after it
|
33
|
+
await t.expect(onePageImages.count).gte(3);
|
34
|
+
|
35
|
+
// 1up to 2up
|
36
|
+
await t.click(nav.desktop.viewmode);
|
37
|
+
const twoPageContainer = Selector('.BRtwopageview');
|
38
|
+
await t.expect(twoPageContainer.visible).ok();
|
39
|
+
const twoPageImages = twoPageContainer.find('img.BRpageimage');
|
40
|
+
await t.expect(twoPageImages.count).gte(2);
|
41
|
+
});
|
37
42
|
});
|