@internetarchive/bookreader 5.0.0-58 → 5.0.0-59
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/BookReader/BookReader.css +110 -39
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +0 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1 -1
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- 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.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.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/BookReaderDemo/BookReaderJSAutoplay.js +4 -1
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +1 -2
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/BookReader/BookModel.js +59 -1
- package/src/BookReader/Mode1UpLit.js +13 -70
- package/src/BookReader/Mode2Up.js +72 -1332
- package/src/BookReader/Mode2UpLit.js +774 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +32 -0
- package/src/BookReader/options.js +8 -2
- package/src/BookReader/utils.js +16 -0
- package/src/BookReader.js +24 -217
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRmain.scss +14 -0
- package/src/css/_BRpages.scss +113 -41
- package/src/plugins/plugin.autoplay.js +1 -6
- package/src/plugins/tts/WebTTSEngine.js +2 -2
- package/src/plugins/tts/plugin.tts.js +3 -17
- package/src/plugins/tts/utils.js +0 -16
- package/tests/e2e/helpers/base.js +20 -20
- package/tests/e2e/helpers/rightToLeft.js +4 -10
- package/tests/e2e/viewmode.test.js +10 -8
- package/tests/jest/BookReader/BookModel.test.js +25 -0
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +28 -11
- package/tests/jest/BookReader/Mode1UpLit.test.js +0 -19
- package/tests/jest/BookReader/Mode2Up.test.js +55 -225
- package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
- package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +26 -0
- package/tests/jest/BookReader/Navbar/Navbar.test.js +3 -3
- package/tests/jest/BookReader/utils.test.js +32 -1
- package/tests/jest/plugins/tts/utils.test.js +0 -34
@@ -1,7 +1,9 @@
|
|
1
1
|
|
2
2
|
import sinon from 'sinon';
|
3
|
-
import {
|
3
|
+
import { Mode2Up } from '@/src/BookReader/Mode2Up.js';
|
4
4
|
import BookReader from '@/src/BookReader.js';
|
5
|
+
import { BookModel } from '@/src/BookReader/BookModel.js';
|
6
|
+
import { afterEventLoop } from '../utils';
|
5
7
|
/** @typedef {import('@/src/BookReader/options.js').BookReaderOptions} BookReaderOptions */
|
6
8
|
|
7
9
|
beforeAll(() => {
|
@@ -31,238 +33,66 @@ const SAMPLE_DATA = [
|
|
31
33
|
];
|
32
34
|
|
33
35
|
|
34
|
-
describe('
|
35
|
-
|
36
|
-
br
|
36
|
+
describe('Mode2Up', () => {
|
37
|
+
/** @type {BookReader} */
|
38
|
+
let br;
|
39
|
+
/** @type {BookModel} */
|
40
|
+
let bookModel;
|
41
|
+
/** @type {Mode2Up} */
|
42
|
+
let mode2Up;
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
test('stops animations when zooming', () => {
|
43
|
-
expect(stopAnim.callCount).toBe(1);
|
44
|
-
});
|
45
|
-
test('always redraws when zooming', () => {
|
46
|
-
expect(resizeSpread.callCount).toBe(0);
|
47
|
-
});
|
48
|
-
});
|
49
|
-
|
50
|
-
describe('page flip directions', () => {
|
51
|
-
test('animates the left page in the correct direction', () => {
|
52
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
53
|
-
br.init();
|
54
|
-
|
55
|
-
const fake = sinon.fake();
|
56
|
-
const fakeAnimWithCB = sinon.fake.yields();
|
57
|
-
const fakeAnim = sinon.fake((...args) =>
|
58
|
-
typeof args[args.length - 1] === 'function' ? fakeAnimWithCB(...args) : fake
|
59
|
-
);
|
60
|
-
sinon.replace(jQuery.prototype, 'animate', fakeAnim);
|
61
|
-
|
62
|
-
const fakeCSS = sinon.spy(jQuery.prototype, 'css');
|
63
|
-
|
64
|
-
br.next();
|
65
|
-
|
66
|
-
expect(fakeAnimWithCB.callCount).toBe(2);
|
67
|
-
// Find the call to .css() immediately preceding the second animation with a callback (i.e., the left page animation)
|
68
|
-
const preSecondAnimCssCallIndex = fakeCSS.getCalls().findIndex(call => call.calledAfter(fakeAnimWithCB.getCall(1))) - 1;
|
69
|
-
expect(fakeCSS.getCall(preSecondAnimCssCallIndex).args[0].left).toBe('');
|
70
|
-
});
|
71
|
-
});
|
72
|
-
|
73
|
-
describe('prefetch', () => {
|
74
|
-
test('loads nearby pages', () => {
|
75
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
76
|
-
const mode2Up = br._modes.mode2Up;
|
77
|
-
br.init();
|
78
|
-
mode2Up.prefetch();
|
79
|
-
expect(Object.keys(mode2Up.pageContainers).length).toBeGreaterThan(2);
|
80
|
-
});
|
81
|
-
|
82
|
-
test('works when at end of book', () => {
|
83
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
84
|
-
const mode2Up = br._modes.mode2Up;
|
85
|
-
br.init();
|
86
|
-
br.jumpToIndex(-1);
|
87
|
-
mode2Up.prefetch();
|
88
|
-
expect(Object.keys(mode2Up.pageContainers).length).toBeGreaterThan(2);
|
89
|
-
});
|
90
|
-
|
91
|
-
test('skips consecutive unviewables', () => {
|
92
|
-
const data = deepCopy(SAMPLE_DATA);
|
93
|
-
data[1].forEach(page => page.viewable = false);
|
94
|
-
const br = new BookReader({ data });
|
95
|
-
const mode2Up = br._modes.mode2Up;
|
96
|
-
br.init();
|
97
|
-
mode2Up.prefetch();
|
98
|
-
expect(mode2Up.pageContainers).not.toContain(2);
|
99
|
-
});
|
100
|
-
});
|
101
|
-
|
102
|
-
describe('draw 2up leaves', () => {
|
103
|
-
test('calls `drawLeafs` on init as default', () => {
|
104
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
105
|
-
const drawLeafs = sinon.spy(br._modes.mode2Up, 'drawLeafs');
|
106
|
-
|
107
|
-
br.init();
|
108
|
-
expect(drawLeafs.callCount).toBe(1);
|
109
|
-
});
|
110
|
-
|
111
|
-
test('sets `this.displayedIndices`', () => {
|
112
|
-
const extremelyWrongValueForDisplayedIndices = null;
|
113
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
114
|
-
|
115
|
-
br.init();
|
116
|
-
br.displayedIndices = extremelyWrongValueForDisplayedIndices;
|
117
|
-
expect(br.displayedIndices).toBe(extremelyWrongValueForDisplayedIndices);
|
118
|
-
|
119
|
-
br._modes.mode2Up.drawLeafs();
|
120
|
-
|
121
|
-
expect(br.displayedIndices).not.toBe(extremelyWrongValueForDisplayedIndices);
|
122
|
-
expect(br.displayedIndices.length).toBe(2); // is array
|
123
|
-
expect(br.displayedIndices).toEqual([-1, 0]); // default to starting index on right, placeholder for left
|
124
|
-
});
|
125
|
-
});
|
126
|
-
|
127
|
-
describe('resizeSpread', () => {
|
128
|
-
test('only resizes spread', () => {
|
129
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
130
|
-
br.init();
|
131
|
-
const resizeBRcontainer = sinon.spy(br, 'resizeBRcontainer');
|
132
|
-
const calculateSpreadSize = sinon.spy(br._modes.mode2Up, 'calculateSpreadSize');
|
133
|
-
const drawLeafs = sinon.spy(br._modes.mode2Up, 'drawLeafs');
|
134
|
-
const centerView = sinon.spy(br._modes.mode2Up, 'centerView');
|
135
|
-
|
136
|
-
br._modes.mode2Up.resizeSpread();
|
137
|
-
expect(drawLeafs.callCount).toBe(0); // no draw
|
138
|
-
expect(resizeBRcontainer.callCount).toBe(1);
|
139
|
-
expect(calculateSpreadSize.callCount).toBe(1);
|
140
|
-
expect(centerView.callCount).toBe(1);
|
141
|
-
});
|
142
|
-
});
|
143
|
-
|
144
|
-
describe('2up Container sizing', () => {
|
145
|
-
test('baseLeafCss', () => {
|
146
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
147
|
-
br.init();
|
148
|
-
br._modes.mode2Up.calculateSpreadSize();
|
149
|
-
expect(Object.keys(br._modes.mode2Up.baseLeafCss)).toEqual(['position', 'right', 'top', 'zIndex']);
|
150
|
-
});
|
151
|
-
test('heightCss', () => {
|
152
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
153
|
-
br.init();
|
154
|
-
br._modes.mode2Up.calculateSpreadSize();
|
155
|
-
const heightStub = 1000;
|
156
|
-
br.twoPage.height = heightStub;
|
157
|
-
expect(Object.keys(br._modes.mode2Up.heightCss)).toEqual(['height']);
|
158
|
-
expect(br._modes.mode2Up.heightCss).toEqual({height: `${heightStub}px`});
|
159
|
-
});
|
160
|
-
describe('left side', () => {
|
161
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
162
|
-
br.init();
|
163
|
-
br._modes.mode2Up.calculateSpreadSize();
|
164
|
-
|
165
|
-
test('leftLeafCss', () => {
|
166
|
-
expect(Object.keys(br._modes.mode2Up.leftLeafCss)).toEqual([
|
167
|
-
'position',
|
168
|
-
'right',
|
169
|
-
'top',
|
170
|
-
'zIndex',
|
171
|
-
'height',
|
172
|
-
'left',
|
173
|
-
'width',
|
174
|
-
]);
|
44
|
+
beforeEach(() => {
|
45
|
+
br = new BookReader({
|
46
|
+
data: SAMPLE_DATA,
|
47
|
+
el: document.createElement('div'),
|
175
48
|
});
|
176
|
-
test('leafEdgeLCss', () => {
|
177
|
-
expect(Object.keys(br._modes.mode2Up.leafEdgeLCss)).toEqual([
|
178
|
-
'height',
|
179
|
-
'width',
|
180
|
-
'left',
|
181
|
-
'top',
|
182
|
-
'border'
|
183
|
-
]);
|
184
|
-
});
|
185
|
-
});
|
186
|
-
describe('right side', () => {
|
187
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
188
49
|
br.init();
|
189
|
-
br
|
190
|
-
|
191
|
-
test('rightLeafCss', () => {
|
192
|
-
expect(Object.keys(br._modes.mode2Up.rightLeafCss)).toEqual([
|
193
|
-
'position',
|
194
|
-
'right',
|
195
|
-
'top',
|
196
|
-
'zIndex',
|
197
|
-
'height',
|
198
|
-
'left',
|
199
|
-
'width',
|
200
|
-
]);
|
201
|
-
});
|
202
|
-
test('leafEdgeRCss', () => {
|
203
|
-
expect(Object.keys(br._modes.mode2Up.leafEdgeRCss)).toEqual([
|
204
|
-
'height',
|
205
|
-
'width',
|
206
|
-
'left',
|
207
|
-
'top',
|
208
|
-
'border'
|
209
|
-
]);
|
210
|
-
});
|
50
|
+
bookModel = new BookModel(br);
|
51
|
+
mode2Up = new Mode2Up(br, bookModel);
|
211
52
|
});
|
212
|
-
describe('full width container, overlay + spine', () => {
|
213
|
-
test('mainContainerCss', () => {
|
214
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
215
|
-
br.init();
|
216
|
-
br._modes.mode2Up.calculateSpreadSize();
|
217
53
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
const
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
54
|
+
describe('prepare', () => {
|
55
|
+
it('initializes DOM properly', async () => {
|
56
|
+
const spyAppend = sinon.spy(br.refs.$brContainer, 'append');
|
57
|
+
const spyRequestUpdate = sinon.spy(mode2Up.mode2UpLit, 'requestUpdate');
|
58
|
+
const initFirstRenderSpy = sinon.spy(mode2Up.mode2UpLit, 'initFirstRender');
|
59
|
+
const jumpToIndexSpy = sinon.spy(mode2Up.mode2UpLit, 'jumpToIndex');
|
60
|
+
sinon.stub(mode2Up.mode2UpLit, 'updateComplete').get(() => Promise.resolve());
|
61
|
+
mode2Up.prepare();
|
62
|
+
|
63
|
+
expect(br.refs.$brContainer[0].style.overflow).toEqual('hidden');
|
64
|
+
expect(spyAppend.calledWith(mode2Up.$el)).toBe(true);
|
65
|
+
expect(mode2Up.mode2UpLit.style.opacity).toEqual('0');
|
66
|
+
|
67
|
+
await afterEventLoop();
|
68
|
+
|
69
|
+
expect(initFirstRenderSpy.called).toBe(true);
|
70
|
+
expect(jumpToIndexSpy.called).toBe(false);
|
71
|
+
expect(mode2Up.everShown).toBe(true);
|
72
|
+
expect(spyRequestUpdate.called).toBe(true);
|
73
|
+
expect(mode2Up.mode2UpLit.style.opacity).toEqual('1');
|
231
74
|
});
|
232
75
|
});
|
233
|
-
});
|
234
|
-
|
235
|
-
describe('prepareTwoPageView', () => {
|
236
|
-
describe('drawing spread', () => {
|
237
|
-
test('always draws new spread if `drawNewSpread` is true ', () => {
|
238
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
239
|
-
const mode2Up = br._modes.mode2Up;
|
240
|
-
br.init();
|
241
|
-
const drawLeafs = sinon.spy(mode2Up, 'drawLeafs');
|
242
|
-
const resizeSpread = sinon.spy(mode2Up, 'resizeSpread');
|
243
|
-
const calculateSpreadSize = sinon.spy(mode2Up, 'calculateSpreadSize');
|
244
|
-
const prunePageContainers = sinon.spy(mode2Up, 'prunePageContainers');
|
245
|
-
const prefetch = sinon.spy(mode2Up, 'prefetch');
|
246
|
-
const centerView = sinon.spy(mode2Up, 'centerView');
|
247
|
-
const preparePopUp = sinon.spy(mode2Up, 'preparePopUp');
|
248
|
-
const updateBrClasses = sinon.spy(br, 'updateBrClasses');
|
249
76
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
expect(
|
258
|
-
expect(
|
259
|
-
expect(
|
77
|
+
describe('resizePageView', () => {
|
78
|
+
it('updates autoFit when possible', async () => {
|
79
|
+
const updateClientSizesSpy = sinon.stub(mode2Up.mode2UpLit.htmlDimensionsCacher, 'updateClientSizes');
|
80
|
+
const resizeViaAutofitSpy = sinon.spy(mode2Up.mode2UpLit, 'resizeViaAutofit');
|
81
|
+
const recenterStub = sinon.stub(mode2Up.mode2UpLit, 'recenter');
|
82
|
+
|
83
|
+
mode2Up.resizePageView();
|
84
|
+
expect(updateClientSizesSpy.called).toBe(true);
|
85
|
+
expect(resizeViaAutofitSpy.called).toBe(true);
|
86
|
+
expect(recenterStub.called).toBe(true);
|
87
|
+
|
88
|
+
// Test with scale and autoFit as 'none'
|
89
|
+
mode2Up.mode2UpLit.scale = 0.1;
|
90
|
+
mode2Up.mode2UpLit.autoFit = 'none';
|
91
|
+
mode2Up.resizePageView();
|
92
|
+
|
93
|
+
expect(mode2Up.mode2UpLit.autoFit).toEqual('auto');
|
94
|
+
expect(resizeViaAutofitSpy.callCount).toEqual(2);
|
95
|
+
expect(recenterStub.callCount).toEqual(2);
|
260
96
|
});
|
261
97
|
});
|
262
98
|
});
|
263
|
-
|
264
|
-
test('uses ImageCache', () => {
|
265
|
-
const br = new BookReader({ data: SAMPLE_DATA });
|
266
|
-
br.init();
|
267
|
-
expect(Object.keys(br.imageCache.cache).length).toBeGreaterThan(2);
|
268
|
-
});
|
@@ -0,0 +1,190 @@
|
|
1
|
+
import sinon from "sinon";
|
2
|
+
import { BookModel } from "@/src/BookReader/BookModel.js";
|
3
|
+
import { Mode2UpLit } from "@/src/BookReader/Mode2UpLit.js";
|
4
|
+
|
5
|
+
/** @type {import('@/src/BookReader/options.js').BookReaderOptions['data']} */
|
6
|
+
const SAMPLE_DATA = [
|
7
|
+
[
|
8
|
+
{
|
9
|
+
width: 123,
|
10
|
+
height: 123,
|
11
|
+
uri: "https://archive.org/image0.jpg",
|
12
|
+
pageNum: "1",
|
13
|
+
},
|
14
|
+
],
|
15
|
+
[
|
16
|
+
{
|
17
|
+
width: 123,
|
18
|
+
height: 123,
|
19
|
+
uri: "https://archive.org/image1.jpg",
|
20
|
+
pageNum: "2",
|
21
|
+
},
|
22
|
+
{
|
23
|
+
width: 123,
|
24
|
+
height: 123,
|
25
|
+
uri: "https://archive.org/image2.jpg",
|
26
|
+
pageNum: "3",
|
27
|
+
},
|
28
|
+
],
|
29
|
+
[
|
30
|
+
{
|
31
|
+
width: 123,
|
32
|
+
height: 123,
|
33
|
+
uri: "https://archive.org/image3.jpg",
|
34
|
+
pageNum: "4",
|
35
|
+
},
|
36
|
+
{
|
37
|
+
width: 123,
|
38
|
+
height: 123,
|
39
|
+
uri: "https://archive.org/image4.jpg",
|
40
|
+
pageNum: "5",
|
41
|
+
},
|
42
|
+
],
|
43
|
+
[
|
44
|
+
{
|
45
|
+
width: 123,
|
46
|
+
height: 123,
|
47
|
+
uri: "https://archive.org/image5.jpg",
|
48
|
+
pageNum: "6",
|
49
|
+
},
|
50
|
+
],
|
51
|
+
];
|
52
|
+
|
53
|
+
function make_dummy_br(overrides = {}) {
|
54
|
+
return Object.assign({
|
55
|
+
updateFirstIndex() {},
|
56
|
+
_components: {
|
57
|
+
navbar: {
|
58
|
+
updateNavIndexThrottled() {},
|
59
|
+
},
|
60
|
+
},
|
61
|
+
data: [],
|
62
|
+
}, overrides);
|
63
|
+
}
|
64
|
+
|
65
|
+
afterEach(() => {
|
66
|
+
sinon.restore();
|
67
|
+
});
|
68
|
+
|
69
|
+
describe("computePageHeight", () => {
|
70
|
+
test("Always returns the median", () => {
|
71
|
+
const mode = new Mode2UpLit({
|
72
|
+
getMedianPageSizeInches: () => ({ width: 100, height: 200 }),
|
73
|
+
}, null);
|
74
|
+
expect(mode.computePageHeight(null)).toEqual(200);
|
75
|
+
expect(mode.computePageHeight({ widthInches: 300, heightInches: 400 }))
|
76
|
+
.toEqual(200);
|
77
|
+
});
|
78
|
+
});
|
79
|
+
|
80
|
+
describe("computePageWidth", () => {
|
81
|
+
test("returns relative to pageHeight", () => {
|
82
|
+
const mode = new Mode2UpLit(null, null);
|
83
|
+
sinon.stub(mode, "computePageHeight").returns(6);
|
84
|
+
|
85
|
+
expect(mode.computePageWidth({ widthInches: 2, heightInches: 6 })).toEqual(
|
86
|
+
2,
|
87
|
+
);
|
88
|
+
expect(mode.computePageWidth({ widthInches: 3, heightInches: 6 })).toEqual(
|
89
|
+
3,
|
90
|
+
);
|
91
|
+
expect(mode.computePageWidth({ widthInches: 2, heightInches: 4 })).toEqual(
|
92
|
+
2 * 6 / 4,
|
93
|
+
);
|
94
|
+
});
|
95
|
+
});
|
96
|
+
|
97
|
+
describe("computePositions", () => {
|
98
|
+
const LEFT_COVER_EXPECTED = {
|
99
|
+
leafEdgesLeftStart: -0.246,
|
100
|
+
leafEdgesLeftMainWidth: 0,
|
101
|
+
leafEdgesLeftMovingStart: -0.246,
|
102
|
+
leafEdgesLeftMovingWidth: 0,
|
103
|
+
leafEdgesLeftEnd: -0.246,
|
104
|
+
leafEdgesLeftFullWidth: 0,
|
105
|
+
pageLeftStart: -0.246,
|
106
|
+
pageLeftWidth: 0.246,
|
107
|
+
pageLeftEnd: 0,
|
108
|
+
gutter: 0,
|
109
|
+
pageRightStart: 0,
|
110
|
+
pageRightWidth: 0.246,
|
111
|
+
pageRightEnd: 0.246,
|
112
|
+
leafEdgesRightStart: 0.246,
|
113
|
+
leafEdgesRightMovingWidth: 0,
|
114
|
+
leafEdgesRightMainStart: 0.246,
|
115
|
+
leafEdgesRightMainWidth: 0.006,
|
116
|
+
leafEdgesRightEnd: 0.252,
|
117
|
+
leafEdgesRightFullWidth: 0.006,
|
118
|
+
spreadWidth: 0.492,
|
119
|
+
bookWidth: 0.498
|
120
|
+
};
|
121
|
+
const SPREAD_EXPECTED = {
|
122
|
+
leafEdgesLeftStart: -0.246,
|
123
|
+
leafEdgesLeftMainWidth: 0.002,
|
124
|
+
leafEdgesLeftMovingStart: -0.244,
|
125
|
+
leafEdgesLeftMovingWidth: 0,
|
126
|
+
leafEdgesLeftEnd: -0.244,
|
127
|
+
leafEdgesLeftFullWidth: 0.002,
|
128
|
+
pageLeftStart: -0.244,
|
129
|
+
pageLeftWidth: 0.246,
|
130
|
+
pageLeftEnd: 0.002,
|
131
|
+
gutter: 0.002,
|
132
|
+
pageRightStart: 0.002,
|
133
|
+
pageRightWidth: 0.246,
|
134
|
+
pageRightEnd: 0.248,
|
135
|
+
leafEdgesRightStart: 0.248,
|
136
|
+
leafEdgesRightMovingWidth: 0,
|
137
|
+
leafEdgesRightMainStart: 0.248,
|
138
|
+
leafEdgesRightMainWidth: 0.004,
|
139
|
+
leafEdgesRightEnd: 0.252,
|
140
|
+
leafEdgesRightFullWidth: 0.004,
|
141
|
+
spreadWidth: 0.492,
|
142
|
+
bookWidth: 0.498
|
143
|
+
};
|
144
|
+
const RIGHT_COVER_EXPECTED = {
|
145
|
+
leafEdgesLeftStart: -0.242,
|
146
|
+
leafEdgesLeftMainWidth: 0.006,
|
147
|
+
leafEdgesLeftMovingStart: -0.236,
|
148
|
+
leafEdgesLeftMovingWidth: 0,
|
149
|
+
leafEdgesLeftEnd: -0.236,
|
150
|
+
leafEdgesLeftFullWidth: 0.006,
|
151
|
+
pageLeftStart: -0.236,
|
152
|
+
pageLeftWidth: 0.246,
|
153
|
+
pageLeftEnd: 0.01,
|
154
|
+
gutter: 0.01,
|
155
|
+
pageRightStart: 0.01,
|
156
|
+
pageRightWidth: 0,
|
157
|
+
pageRightEnd: 0.01,
|
158
|
+
leafEdgesRightStart: 0.01,
|
159
|
+
leafEdgesRightMovingWidth: 0,
|
160
|
+
leafEdgesRightMainStart: 0.01,
|
161
|
+
leafEdgesRightMainWidth: 0,
|
162
|
+
leafEdgesRightEnd: 0.01,
|
163
|
+
leafEdgesRightFullWidth: 0,
|
164
|
+
spreadWidth: 0.246,
|
165
|
+
bookWidth: 0.252
|
166
|
+
};
|
167
|
+
|
168
|
+
test("left cover page", () => {
|
169
|
+
const br = make_dummy_br({ data: SAMPLE_DATA });
|
170
|
+
const book = new BookModel(br);
|
171
|
+
const mode = new Mode2UpLit(book, br);
|
172
|
+
expect(mode.computePositions(null, book.getPage(0))).toEqual(LEFT_COVER_EXPECTED);
|
173
|
+
});
|
174
|
+
|
175
|
+
test("spread", () => {
|
176
|
+
const br = make_dummy_br({ data: SAMPLE_DATA });
|
177
|
+
const book = new BookModel(br);
|
178
|
+
const mode = new Mode2UpLit(book, br);
|
179
|
+
|
180
|
+
expect(mode.computePositions(book.getPage(1), book.getPage(2))).toEqual(SPREAD_EXPECTED);
|
181
|
+
});
|
182
|
+
|
183
|
+
test("right cover page", () => {
|
184
|
+
const br = make_dummy_br({ data: SAMPLE_DATA });
|
185
|
+
const book = new BookModel(br);
|
186
|
+
const mode = new Mode2UpLit(book, br);
|
187
|
+
|
188
|
+
expect(mode.computePositions(book.getPage(-1), null)).toEqual(RIGHT_COVER_EXPECTED);
|
189
|
+
});
|
190
|
+
});
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { ModeCoordinateSpace } from "@/src/BookReader/ModeCoordinateSpace";
|
2
|
+
|
3
|
+
describe("worldUnitsToRenderedPixels", () => {
|
4
|
+
test("0 case", () => {
|
5
|
+
const mcs = new ModeCoordinateSpace({ scale: 1 });
|
6
|
+
expect(mcs.worldUnitsToRenderedPixels(0)).toBe(0);
|
7
|
+
});
|
8
|
+
|
9
|
+
test("Misc cases", () => {
|
10
|
+
const mcs = new ModeCoordinateSpace({ scale: 1 });
|
11
|
+
mcs.screenDPI = 100;
|
12
|
+
expect(mcs.worldUnitsToRenderedPixels(1)).toBe(100);
|
13
|
+
mcs.screenDPI = 78;
|
14
|
+
expect(mcs.worldUnitsToRenderedPixels(1)).toBe(78);
|
15
|
+
});
|
16
|
+
});
|
@@ -146,4 +146,30 @@ describe('ModeSmoothZoom', () => {
|
|
146
146
|
expect(mode.scale).not.toBe(1);
|
147
147
|
});
|
148
148
|
});
|
149
|
+
|
150
|
+
describe("updateViewportOnZoom", () => {
|
151
|
+
test("adjusts scroll position when zooming in", () => {
|
152
|
+
const mode = dummy_mode();
|
153
|
+
const msz = new ModeSmoothZoom(mode);
|
154
|
+
mode.$container.scrollTop = 100;
|
155
|
+
mode.$container.scrollLeft = 100;
|
156
|
+
|
157
|
+
msz.updateViewportOnZoom(2, 1);
|
158
|
+
|
159
|
+
expect(mode.$container.scrollTop).toBeGreaterThan(100);
|
160
|
+
expect(mode.$container.scrollLeft).toBeGreaterThan(100);
|
161
|
+
});
|
162
|
+
|
163
|
+
test("updates scroll position when zooming out", () => {
|
164
|
+
const mode = dummy_mode();
|
165
|
+
const msz = new ModeSmoothZoom(mode);
|
166
|
+
mode.$container.scrollTop = 100;
|
167
|
+
mode.$container.scrollLeft = 100;
|
168
|
+
|
169
|
+
msz.updateViewportOnZoom(0.5, 1);
|
170
|
+
|
171
|
+
expect(mode.$container.scrollTop).toBeLessThan(100);
|
172
|
+
expect(mode.$container.scrollLeft).toBeLessThan(100);
|
173
|
+
});
|
174
|
+
});
|
149
175
|
});
|
@@ -63,14 +63,14 @@ describe('Navbar slider', () => {
|
|
63
63
|
|
64
64
|
test('on slide change, actual page changes', () => {
|
65
65
|
const $slider = navbar.$root.find('.BRpager');
|
66
|
-
const
|
66
|
+
const jumpToIndexStub = sinon.stub(br, 'jumpToIndex');
|
67
67
|
expect(br.currentIndex()).toBe(0);
|
68
68
|
|
69
69
|
$slider.trigger('slidechange', { value: 3 });
|
70
70
|
|
71
71
|
expect(navbar.$root.find('.BRcurrentpage').text().includes('3'));
|
72
|
-
expect(
|
73
|
-
expect(
|
72
|
+
expect(jumpToIndexStub.callCount).toBe(1);
|
73
|
+
expect(jumpToIndexStub.args[0][0]).toBe(3);
|
74
74
|
});
|
75
75
|
});
|
76
76
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import sinon from 'sinon';
|
2
|
-
import { afterEventLoop } from '../utils.js';
|
2
|
+
import { afterEventLoop, eventTargetMixin } from '../utils.js';
|
3
3
|
import {
|
4
4
|
clamp,
|
5
5
|
cssPercentage,
|
@@ -12,6 +12,7 @@ import {
|
|
12
12
|
poll,
|
13
13
|
polyfillCustomEvent,
|
14
14
|
PolyfilledCustomEvent,
|
15
|
+
promisifyEvent,
|
15
16
|
sleep,
|
16
17
|
} from '@/src/BookReader/utils.js';
|
17
18
|
|
@@ -184,3 +185,33 @@ describe('sleep', () => {
|
|
184
185
|
expect(spy.callCount).toBe(1);
|
185
186
|
});
|
186
187
|
});
|
188
|
+
|
189
|
+
describe('promisifyEvent', () => {
|
190
|
+
test('Resolves once event fires', async () => {
|
191
|
+
const fakeTarget = eventTargetMixin();
|
192
|
+
const resolveSpy = sinon.spy();
|
193
|
+
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
194
|
+
|
195
|
+
await afterEventLoop();
|
196
|
+
expect(resolveSpy.callCount).toBe(0);
|
197
|
+
fakeTarget.dispatchEvent('pause', {});
|
198
|
+
await afterEventLoop();
|
199
|
+
expect(resolveSpy.callCount).toBe(1);
|
200
|
+
});
|
201
|
+
|
202
|
+
test('Only resolves once', async () => {
|
203
|
+
const fakeTarget = eventTargetMixin();
|
204
|
+
const resolveSpy = sinon.spy();
|
205
|
+
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
206
|
+
|
207
|
+
await afterEventLoop();
|
208
|
+
expect(resolveSpy.callCount).toBe(0);
|
209
|
+
fakeTarget.dispatchEvent('pause', {});
|
210
|
+
fakeTarget.dispatchEvent('pause', {});
|
211
|
+
fakeTarget.dispatchEvent('pause', {});
|
212
|
+
fakeTarget.dispatchEvent('pause', {});
|
213
|
+
|
214
|
+
await afterEventLoop();
|
215
|
+
expect(resolveSpy.callCount).toBe(1);
|
216
|
+
});
|
217
|
+
});
|
@@ -1,39 +1,5 @@
|
|
1
|
-
import sinon from 'sinon';
|
2
|
-
import { afterEventLoop, eventTargetMixin } from '../../utils.js';
|
3
1
|
import * as utils from '@/src/plugins/tts/utils.js';
|
4
2
|
|
5
|
-
describe('promisifyEvent', () => {
|
6
|
-
const { promisifyEvent } = utils;
|
7
|
-
|
8
|
-
test('Resolves once event fires', async () => {
|
9
|
-
const fakeTarget = eventTargetMixin();
|
10
|
-
const resolveSpy = sinon.spy();
|
11
|
-
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
12
|
-
|
13
|
-
await afterEventLoop();
|
14
|
-
expect(resolveSpy.callCount).toBe(0);
|
15
|
-
fakeTarget.dispatchEvent('pause', {});
|
16
|
-
await afterEventLoop();
|
17
|
-
expect(resolveSpy.callCount).toBe(1);
|
18
|
-
});
|
19
|
-
|
20
|
-
test('Only resolves once', async () => {
|
21
|
-
const fakeTarget = eventTargetMixin();
|
22
|
-
const resolveSpy = sinon.spy();
|
23
|
-
promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
|
24
|
-
|
25
|
-
await afterEventLoop();
|
26
|
-
expect(resolveSpy.callCount).toBe(0);
|
27
|
-
fakeTarget.dispatchEvent('pause', {});
|
28
|
-
fakeTarget.dispatchEvent('pause', {});
|
29
|
-
fakeTarget.dispatchEvent('pause', {});
|
30
|
-
fakeTarget.dispatchEvent('pause', {});
|
31
|
-
|
32
|
-
await afterEventLoop();
|
33
|
-
expect(resolveSpy.callCount).toBe(1);
|
34
|
-
});
|
35
|
-
});
|
36
|
-
|
37
3
|
describe('approximateWordCount', () => {
|
38
4
|
const { approximateWordCount } = utils;
|
39
5
|
|