@internetarchive/bookreader 5.0.0-37 → 5.0.0-38
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/node.js.yml +66 -4
- package/BookReader/BookReader.js +1 -1
- package/BookReader/ia-bookreader-bundle.js +1 -1
- package/BookReader/ia-bookreader-bundle.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.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/CHANGELOG.md +12 -0
- package/codecov.yml +6 -0
- package/package.json +12 -12
- package/renovate.json +43 -0
- package/src/plugins/search/plugin.search.js +5 -15
- package/src/plugins/search/view.js +2 -0
- package/src/plugins/tts/AbstractTTSEngine.js +9 -4
- package/stat/BookNavigator/BookNavigator.js +42 -0
- package/tests/e2e/base.test.js +4 -5
- package/tests/e2e/helpers/desktopSearch.js +13 -12
- package/tests/e2e/models/Navigation.js +12 -3
- package/tests/e2e/rightToLeft.test.js +1 -1
- package/tests/e2e/viewmode.test.js +37 -31
- package/.github/dependabot.yml +0 -8
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
# 5.0.0-38
|
2
|
+
Dev: Add Renovate Bot @cdrini
|
3
|
+
Dev: Update node-fetch @cdrini
|
4
|
+
Fix: Search request promise err & fix tests @cdrini
|
5
|
+
Dev: Split node workflow into different jobs @cdrini
|
6
|
+
Dev: Give cache steps better names in GHA @cdrini
|
7
|
+
Dev: Update concurrently + Small speedup to build & test @cdrini
|
8
|
+
Dev: Renovate - Auto-update dev dependencies for minor/patch @cdrini
|
9
|
+
Fix: Better MS Edge voice selection @cdrini
|
10
|
+
Dev: Allow small drops in codecov coverage (< 0.5%) @cdrini
|
11
|
+
Dev: Renovate - add `^@internetarchive/icon-` @cdrini
|
12
|
+
|
1
13
|
# 5.0.0-37
|
2
14
|
Fix: Update all `.then()` to async/await @sancodes
|
3
15
|
Fix: Upgrade to Lit 2 @Aadilhassan
|
package/codecov.yml
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@internetarchive/bookreader",
|
3
|
-
"version": "5.0.0-
|
3
|
+
"version": "5.0.0-38",
|
4
4
|
"description": "The Internet Archive BookReader.",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -41,25 +41,25 @@
|
|
41
41
|
"lit": "^2.1.3"
|
42
42
|
},
|
43
43
|
"devDependencies": {
|
44
|
-
"@babel/core": "7.
|
45
|
-
"@babel/eslint-parser": "
|
46
|
-
"@babel/plugin-proposal-class-properties": "
|
47
|
-
"@babel/plugin-proposal-decorators": "
|
48
|
-
"@babel/preset-env": "7.
|
44
|
+
"@babel/core": "7.17.5",
|
45
|
+
"@babel/eslint-parser": "7.17.0",
|
46
|
+
"@babel/plugin-proposal-class-properties": "7.16.7",
|
47
|
+
"@babel/plugin-proposal-decorators": "7.17.2",
|
48
|
+
"@babel/preset-env": "7.16.11",
|
49
49
|
"@open-wc/testing": "^3.0.4",
|
50
50
|
"@open-wc/testing-karma": "^4.0.9",
|
51
51
|
"@types/jest": "^27.4.0",
|
52
52
|
"@webcomponents/webcomponentsjs": "^2.6.0",
|
53
|
-
"babel-loader": "8.2.
|
53
|
+
"babel-loader": "8.2.3",
|
54
54
|
"codecov": "^3.8.3",
|
55
|
-
"concurrently": "
|
55
|
+
"concurrently": "7.0.0",
|
56
56
|
"core-js": "3.16.2",
|
57
57
|
"cpx2": "3.0.0",
|
58
58
|
"eslint": "^7.32.0",
|
59
59
|
"eslint-plugin-no-jquery": "^2.7.0",
|
60
60
|
"eslint-plugin-testcafe": "^0.2.1",
|
61
61
|
"hammerjs": "^2.0.8",
|
62
|
-
"http-server": "
|
62
|
+
"http-server": "14.1.0",
|
63
63
|
"iso-language-codes": "1.1.0",
|
64
64
|
"jest": "^27.4.7",
|
65
65
|
"jquery": "1.11.3",
|
@@ -70,7 +70,7 @@
|
|
70
70
|
"jquery.mmenu": "5.6.5",
|
71
71
|
"karma-coverage": "^2.1.0",
|
72
72
|
"live-server": "1.2.1",
|
73
|
-
"node-fetch": "2.6.
|
73
|
+
"node-fetch": "2.6.7",
|
74
74
|
"regenerator-runtime": "0.13.9",
|
75
75
|
"sass": "1.38.2",
|
76
76
|
"sinon": "^12.0.1",
|
@@ -102,7 +102,7 @@
|
|
102
102
|
"preversion": "npm run test && node scripts/preversion.js",
|
103
103
|
"version": "node scripts/version.js",
|
104
104
|
"postversion": "node scripts/postversion.js",
|
105
|
-
"build": "npm run clean &&
|
105
|
+
"build": "npm run clean && npx concurrently --group npm:build-js npm:build-css npm:build-assets",
|
106
106
|
"build-assets": "npx cpx \"src/assets/**/*\" BookReader && npx svgo -f BookReader/icons && npx svgo -f BookReader/images",
|
107
107
|
"build-assets:watch": "npx cpx --watch --verbose \"src/assets/**/*\" BookReader",
|
108
108
|
"build-js": "npx webpack",
|
@@ -115,7 +115,7 @@
|
|
115
115
|
"serve": "npx http-server . --port 8000",
|
116
116
|
"serve-live": "npx live-server . --port 8000 --watch=index.html,BookReader,BookReaderDemo",
|
117
117
|
"serve-dev": "npm run build-css && npx concurrently --kill-others npm:serve-live npm:build-*:watch",
|
118
|
-
"test": "
|
118
|
+
"test": "npx concurrently --group npm:test-jest npm:test-karma",
|
119
119
|
"test:e2e": "npm run build && npx testcafe",
|
120
120
|
"test:e2e:dev": "npx testcafe --live --dev",
|
121
121
|
"test-jest:watch": "npx jest --watch",
|
package/renovate.json
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
{
|
2
|
+
"extends": [
|
3
|
+
"config:base"
|
4
|
+
],
|
5
|
+
"packageRules": [
|
6
|
+
{
|
7
|
+
"matchPackageNames": [
|
8
|
+
"@babel/eslint-parser",
|
9
|
+
"@open-wc/testing",
|
10
|
+
"@open-wc/testing-karma",
|
11
|
+
"@types/jest",
|
12
|
+
"codecov",
|
13
|
+
"eslint",
|
14
|
+
"eslint-plugin-no-jquery",
|
15
|
+
"eslint-plugin-testcafe",
|
16
|
+
"jest",
|
17
|
+
"karma-coverage",
|
18
|
+
"sinon",
|
19
|
+
"testcafe"
|
20
|
+
],
|
21
|
+
"automerge": true
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"matchPackageNames": [
|
25
|
+
"concurrently",
|
26
|
+
"http-server",
|
27
|
+
"live-server",
|
28
|
+
"node-fetch"
|
29
|
+
],
|
30
|
+
"matchUpdateTypes": ["minor", "patch"],
|
31
|
+
"automerge": true
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"matchPackagePatterns": ["^@internetarchive/icon-"],
|
35
|
+
"groupName": "@internetarchive icons",
|
36
|
+
"rangeStrategy": "bump"
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"matchPackagePatterns": ["^@internetarchive"],
|
40
|
+
"rangeStrategy": "bump"
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
@@ -144,6 +144,7 @@ BookReader.prototype.search = async function(term = '', overrides = {}) {
|
|
144
144
|
};
|
145
145
|
const options = jQuery.extend({}, defaultOptions, overrides);
|
146
146
|
this.suppressFragmentChange = options.suppressFragmentChange;
|
147
|
+
this.searchCancelled = false;
|
147
148
|
|
148
149
|
// strip slashes, since this goes in the url
|
149
150
|
this.searchTerm = term.replace(/\//g, ' ');
|
@@ -179,13 +180,8 @@ BookReader.prototype.search = async function(term = '', overrides = {}) {
|
|
179
180
|
|
180
181
|
const url = `${baseUrl}${paramStr}`;
|
181
182
|
|
182
|
-
const cleanup = () => {
|
183
|
-
this.searchXHR = null;
|
184
|
-
window.BRSearchInProgress = () => {};
|
185
|
-
};
|
186
|
-
|
187
183
|
const processSearchResults = (searchInsideResults) => {
|
188
|
-
if (
|
184
|
+
if (this.searchCancelled) {
|
189
185
|
return;
|
190
186
|
}
|
191
187
|
const responseHasError = searchInsideResults.error || !searchInsideResults.matches.length;
|
@@ -201,12 +197,6 @@ BookReader.prototype.search = async function(term = '', overrides = {}) {
|
|
201
197
|
? options.success.call(this, searchInsideResults, options)
|
202
198
|
: this.BRSearchCallback(searchInsideResults, options);
|
203
199
|
}
|
204
|
-
cleanup();
|
205
|
-
};
|
206
|
-
|
207
|
-
const beforeSend = (xhr) => {
|
208
|
-
this.searchXHR = xhr;
|
209
|
-
window.BRSearchInProgress = processSearchResults;
|
210
200
|
};
|
211
201
|
|
212
202
|
this.trigger('SearchStarted', { term: this.searchTerm, instance: this });
|
@@ -214,8 +204,7 @@ BookReader.prototype.search = async function(term = '', overrides = {}) {
|
|
214
204
|
url: url,
|
215
205
|
dataType: 'jsonp',
|
216
206
|
cache: true,
|
217
|
-
beforeSend,
|
218
|
-
jsonpCallback: 'BRSearchInProgress'
|
207
|
+
beforeSend: xhr => { this.searchXHR = xhr; },
|
219
208
|
}));
|
220
209
|
};
|
221
210
|
|
@@ -228,8 +217,8 @@ BookReader.prototype._cancelSearch = function () {
|
|
228
217
|
this.searchView.clearSearchFieldAndResults(false);
|
229
218
|
this.searchTerm = '';
|
230
219
|
this.searchXHR = null;
|
220
|
+
this.searchCancelled = true;
|
231
221
|
this.searchResults = [];
|
232
|
-
window.BRSearchInProgress = () => {};
|
233
222
|
};
|
234
223
|
|
235
224
|
/**
|
@@ -237,6 +226,7 @@ BookReader.prototype._cancelSearch = function () {
|
|
237
226
|
* checks for term & xhr in flight before running
|
238
227
|
*/
|
239
228
|
BookReader.prototype.cancelSearchRequest = function () {
|
229
|
+
this.searchCancelled = true;
|
240
230
|
if (this.searchXHR !== null) {
|
241
231
|
this._cancelSearch();
|
242
232
|
this.searchView.toggleSearchPending();
|
@@ -149,10 +149,12 @@ class SearchView {
|
|
149
149
|
}
|
150
150
|
|
151
151
|
updateResultsPosition() {
|
152
|
+
if (!this.dom.searchNavigation) return;
|
152
153
|
this.dom.searchNavigation.find('[data-id=resultsCount]').text(this.resultsPosition());
|
153
154
|
}
|
154
155
|
|
155
156
|
updateSearchNavigationButtons() {
|
157
|
+
if (!this.dom.searchNavigation) return;
|
156
158
|
this.dom.searchNavigation.find('.prev').attr('disabled', !this.currentMatchIndex);
|
157
159
|
this.dom.searchNavigation.find('.next').attr('disabled', this.currentMatchIndex + 1 === this.matches.length);
|
158
160
|
}
|
@@ -51,9 +51,7 @@ export default class AbstractTTSEngine {
|
|
51
51
|
/** @type {SpeechSynthesisVoice} */
|
52
52
|
this.voice = null;
|
53
53
|
// Listen for voice changes (fired by subclasses)
|
54
|
-
this.events.on('voiceschanged',
|
55
|
-
this.voice = AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);
|
56
|
-
});
|
54
|
+
this.events.on('voiceschanged', this.updateBestVoice);
|
57
55
|
this.events.trigger('voiceschanged');
|
58
56
|
}
|
59
57
|
|
@@ -72,6 +70,10 @@ export default class AbstractTTSEngine {
|
|
72
70
|
/** @abstract */
|
73
71
|
init() { return null; }
|
74
72
|
|
73
|
+
updateBestVoice = () => {
|
74
|
+
this.voice = AbstractTTSEngine.getBestBookVoice(this.getVoices(), this.opts.bookLanguage);
|
75
|
+
}
|
76
|
+
|
75
77
|
/**
|
76
78
|
* @param {number} leafIndex
|
77
79
|
* @param {number} numLeafs total number of leafs in the current book
|
@@ -134,8 +136,11 @@ export default class AbstractTTSEngine {
|
|
134
136
|
this.step();
|
135
137
|
}
|
136
138
|
|
137
|
-
/** @param {
|
139
|
+
/** @param {string} voiceURI */
|
138
140
|
setVoice(voiceURI) {
|
141
|
+
// if the user actively selects a voice, don't re-choose best voice anymore
|
142
|
+
// MS Edge fires voices changed randomly very often
|
143
|
+
this.events.off('voiceschanged', this.updateBestVoice);
|
139
144
|
this.voice = this.getVoices().find(voice => voice.voiceURI === voiceURI);
|
140
145
|
if (this.activeSound) this.activeSound.setVoice(this.voice);
|
141
146
|
}
|
@@ -1,3 +1,44 @@
|
|
1
|
+
/*
|
2
|
+
<script src="foo-plugin.js"></script>
|
3
|
+
|
4
|
+
foo-plugin.js
|
5
|
+
|
6
|
+
$('#foo-plugin').dataSet('MainController', 'bar');
|
7
|
+
|
8
|
+
<ia-bookreader>
|
9
|
+
<div slot="plugins">
|
10
|
+
<ia-search></ia-search>
|
11
|
+
<book-marks></book-marks>
|
12
|
+
</div>
|
13
|
+
</ia-bookreader>
|
14
|
+
|
15
|
+
iaBookreader.registerPlugin('foo-plugin', Class);
|
16
|
+
|
17
|
+
|
18
|
+
class IABr extends LItElement {
|
19
|
+
|
20
|
+
render() {
|
21
|
+
|
22
|
+
registerPlugins() {
|
23
|
+
this.pluginSlots.map(slot => {
|
24
|
+
.. to slot registry
|
25
|
+
each slot - do handshake
|
26
|
+
|
27
|
+
|
28
|
+
});
|
29
|
+
}
|
30
|
+
|
31
|
+
html`
|
32
|
+
<div slot="plugins" @onslotchange=${() => x}></div>
|
33
|
+
`;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
*/
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
1
42
|
import { css, html, LitElement } from 'lit-element';
|
2
43
|
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
3
44
|
import SearchProvider from './search/search-provider.js';
|
@@ -113,6 +154,7 @@ export class BookNavigator extends LitElement {
|
|
113
154
|
// };
|
114
155
|
|
115
156
|
this.menuProviders = {
|
157
|
+
// if enableSearch ?
|
116
158
|
search: new SearchProvider(
|
117
159
|
/**
|
118
160
|
* Search specific menu updates
|
package/tests/e2e/base.test.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
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
5
|
import params from './helpers/params';
|
6
6
|
|
@@ -22,10 +22,9 @@ ocaids.forEach(ocaid => {
|
|
22
22
|
runBaseTests(new BookReader());
|
23
23
|
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
// runDesktopSearchTests(new BookReader());
|
25
|
+
fixture `Desktop Search Tests for: ${ocaid}`
|
26
|
+
.page `${url}`;
|
27
|
+
runDesktopSearchTests(new BookReader());
|
29
28
|
|
30
29
|
// Todo: deprecated, will remove once mmenu is removed.
|
31
30
|
// fixture `Mobile Search Tests for: ${ocaid}`
|
@@ -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);
|
@@ -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());
|
@@ -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
|
}
|
@@ -17,7 +18,11 @@ export default class Navigation {
|
|
17
18
|
* @classdesc defines DesktopNav base elements
|
18
19
|
*/
|
19
20
|
class DesktopNav {
|
20
|
-
|
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
|
|
@@ -9,7 +9,7 @@ const ocaids = params.ocaids || [
|
|
9
9
|
];
|
10
10
|
|
11
11
|
ocaids.forEach(ocaid => {
|
12
|
-
const url = `${params.
|
12
|
+
const url = `${params.getArchiveUrl(ocaid)}`;
|
13
13
|
|
14
14
|
fixture `Base Tests for right to left book: ${ocaid}`.page `${url}`;
|
15
15
|
runBaseTests(new BookReader({ pageProgression: 'rl' }));
|
@@ -2,35 +2,41 @@ import { Selector } from 'testcafe';
|
|
2
2
|
import BookReader from './models/BookReader';
|
3
3
|
import params from './helpers/params';
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
const
|
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
|
-
|
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
|
+
});
|
36
42
|
});
|