@internetarchive/bookreader 5.0.0-42-a2 → 5.0.0-44-a1
Sign up to get free protection for your applications and to get access to all the features.
- package/.github/workflows/node.js.yml +14 -14
- package/.github/workflows/npm-publish.yml +4 -4
- package/BookReader/BookReader.css +14 -15
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +87 -87
- package/BookReader/ia-bookreader-bundle.js.map +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/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-1.10.1.js +1 -1
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +6 -6
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.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/BookReaderDemo/IADemoBr.js +30 -0
- package/BookReaderDemo/demo-internetarchive.html +3 -0
- package/CHANGELOG.md +9 -0
- package/babel.config.js +1 -1
- package/package.json +22 -27
- package/renovate.json +13 -4
- package/scripts/preversion.js +4 -1
- package/src/BookNavigator/book-navigator.js +4 -0
- package/src/BookNavigator/downloads/downloads-provider.js +14 -5
- package/src/BookNavigator/downloads/downloads.js +23 -1
- package/src/BookNavigator/search/a-search-result.js +4 -6
- package/src/css/_controls.scss +1 -2
- package/src/plugins/search/plugin.search.js +17 -4
- package/src/plugins/search/view.js +1 -3
- package/src/plugins/tts/plugin.tts.js +15 -3
- package/tests/{karma → jest}/BookNavigator/book-navigator.test.js +119 -104
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-button.test.js +13 -14
- 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/{karma → jest}/BookNavigator/downloads/downloads-provider.test.js +18 -18
- package/tests/{karma → jest}/BookNavigator/downloads/downloads.test.js +7 -8
- package/tests/{karma → jest}/BookNavigator/search/search-provider.test.js +29 -29
- package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +57 -56
- package/tests/{karma → jest}/BookNavigator/sharing/sharing-provider.test.js +8 -8
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/{karma → jest}/BookNavigator/volumes/volumes-provider.test.js +38 -38
- package/tests/{karma → jest}/BookNavigator/volumes/volumes.test.js +15 -16
- package/tests/jest/plugins/search/plugin.search.test.js +40 -23
- package/tests/jest/plugins/tts/AbstractTTSEngine.test.js +3 -3
- package/karma.conf.js +0 -23
- package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +0 -57
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
@@ -1,11 +1,10 @@
|
|
1
1
|
import {
|
2
2
|
html,
|
3
3
|
fixture,
|
4
|
-
expect,
|
5
4
|
oneEvent,
|
6
|
-
} from '@open-wc/testing';
|
5
|
+
} from '@open-wc/testing-helpers';
|
7
6
|
import sinon from 'sinon';
|
8
|
-
import { IABookSearchResults } from '
|
7
|
+
import { IABookSearchResults } from '@/src/BookNavigator/search/search-results.js';
|
9
8
|
|
10
9
|
const container = (results = [], query = '') => (
|
11
10
|
html`<ia-book-search-results .results=${results} .query=${query}></ia-book-search-results>`
|
@@ -17,6 +16,7 @@ const results = [{
|
|
17
16
|
text: `In the drawing of caricatures and cartoons\u2014or any other com' mercial art, for that matter\u2014the artist should know something about the processes of reproduction for that particular form of art work. For pen and ink work the engraving is made on a sine printing plate. It is not necessary, however, to know all about these processes of reproduction. The artist should know that all work intended for line rqproducttons should be made on white paper or {{{${searchQuery}}}} Board with black drawing ink. The drawing to be reproduced is photographed on a chemically treated sine plate, which is then treated with acid. This acid eats away the surface of the sine, except the photographed' lines, which are left in relief, somewhat like printing type. Colored inks do not photograph well; neither does black ink on colored paper.`,
|
18
17
|
cover: '//placehold.it/30x44',
|
19
18
|
title: 'Book title',
|
19
|
+
displayPageNumber: 'Page 24',
|
20
20
|
par: [{
|
21
21
|
boxes: [{
|
22
22
|
r: 2672, b: 792, t: 689, page: 24, l: 2424,
|
@@ -31,6 +31,7 @@ const results = [{
|
|
31
31
|
}],
|
32
32
|
}, {
|
33
33
|
text: `Drawings intended for sale should be made on a good grade of {{{${searchQuery}}}} Board, and a margin left all the way around the drawings. They should be mailed flat, and'require first class postage. Enclose postage for the return of the drawings. Only send good drawings of a reason- able quantity. Enclose a neat and terse letter to the one you are sending the drawings to, written with pen and ink or typewriter if possible, on`,
|
34
|
+
displayPageNumber: 'Page 86',
|
34
35
|
par: [{
|
35
36
|
boxes: [{
|
36
37
|
r: 698, b: 4460, t: 4324, page: 86, l: 450,
|
@@ -50,64 +51,64 @@ describe('<ia-book-search-results>', () => {
|
|
50
51
|
sinon.restore();
|
51
52
|
});
|
52
53
|
|
53
|
-
|
54
|
+
test('sets default properties', async () => {
|
54
55
|
const query = 'bristol';
|
55
56
|
const el = await fixture(container(results, query));
|
56
57
|
|
57
|
-
expect(el.results).
|
58
|
-
expect(el.query).
|
58
|
+
expect(el.results).toEqual(results);
|
59
|
+
expect(el.query).toEqual(query);
|
59
60
|
});
|
60
61
|
|
61
|
-
|
62
|
+
test('sets results when passed in via event object', async () => {
|
62
63
|
const el = await fixture(container());
|
63
64
|
|
64
65
|
el.setResults({ detail: { results } });
|
65
|
-
expect(el.results).
|
66
|
+
expect(el.results).toEqual(results);
|
66
67
|
});
|
67
68
|
|
68
|
-
|
69
|
+
test('listens for a custom search callback event on the document', async () => {
|
69
70
|
IABookSearchResults.prototype.setResults = sinon.fake();
|
70
71
|
const el = await fixture(container());
|
71
72
|
const event = new Event('BookReader:SearchCallback');
|
72
73
|
|
73
74
|
event.detail = { results };
|
74
75
|
document.dispatchEvent(event);
|
75
|
-
expect(el.setResults.callCount).
|
76
|
-
expect(el.setResults.firstArg).
|
76
|
+
expect(el.setResults.callCount).toEqual(1);
|
77
|
+
expect(el.setResults.firstArg).toEqual(event);
|
77
78
|
});
|
78
79
|
|
79
|
-
|
80
|
+
test('renders results that contain the book title', async () => {
|
80
81
|
sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
|
81
82
|
const el = await fixture(container(results));
|
82
83
|
|
83
|
-
expect(el.innerHTML).
|
84
|
+
expect(el.innerHTML).toContain(`${results[0].title}`);
|
84
85
|
});
|
85
86
|
|
86
|
-
|
87
|
+
test('renders results that contain a highlighted match', async () => {
|
87
88
|
sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
|
88
89
|
const el = await fixture(container(results));
|
89
90
|
|
90
|
-
expect(el.innerHTML).
|
91
|
+
expect(el.innerHTML).toContain(`<mark>${searchQuery}</mark>`);
|
91
92
|
});
|
92
93
|
|
93
|
-
|
94
|
+
test('renders results that contain an optional cover image', async () => {
|
94
95
|
sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
|
95
96
|
const el = await fixture(container(results));
|
96
97
|
|
97
|
-
expect(el.innerHTML).
|
98
|
+
expect(el.innerHTML).toContain(`<img src="${results[0].cover}">`);
|
98
99
|
});
|
99
100
|
|
100
|
-
|
101
|
+
test('sets a query prop when search input receives input', async () => {
|
101
102
|
const el = await fixture(container(results));
|
102
103
|
const searchInput = el.shadowRoot.querySelector('[name="query"]');
|
103
104
|
|
104
105
|
searchInput.value = searchQuery;
|
105
106
|
searchInput.dispatchEvent(new Event('keyup'));
|
106
107
|
|
107
|
-
expect(el.query).
|
108
|
+
expect(el.query).toEqual(searchQuery);
|
108
109
|
});
|
109
110
|
|
110
|
-
|
111
|
+
test('emits a custom event when search form submitted when input is populated', async () => {
|
111
112
|
const el = await fixture(container(results));
|
112
113
|
|
113
114
|
setTimeout(() => {
|
@@ -117,35 +118,35 @@ describe('<ia-book-search-results>', () => {
|
|
117
118
|
});
|
118
119
|
const response = await oneEvent(el, 'bookSearchInitiated');
|
119
120
|
|
120
|
-
expect(response).
|
121
|
+
expect(response).toBeDefined();
|
121
122
|
});
|
122
123
|
|
123
|
-
|
124
|
+
test('uses a singular noun when one result given', async () => {
|
124
125
|
const el = await fixture(container([results[0]]));
|
125
126
|
const resultsCount = await fixture(el.resultsCount);
|
126
127
|
|
127
|
-
expect(resultsCount.innerHTML).
|
128
|
+
expect(resultsCount.innerHTML).toContain('1 result');
|
128
129
|
});
|
129
130
|
|
130
|
-
|
131
|
+
test('can render header with active options count', async () => {
|
131
132
|
const el = await fixture(container(results));
|
132
133
|
el.renderHeader = true;
|
133
134
|
|
134
135
|
await el.updateComplete;
|
135
136
|
|
136
|
-
expect(el.shadowRoot.querySelector('header p').
|
137
|
+
expect(el.shadowRoot.querySelector('header p').textContent).toContain('2');
|
137
138
|
});
|
138
139
|
|
139
|
-
|
140
|
+
test('renders search all files checkbox when enabled', async () => {
|
140
141
|
const el = await fixture(container(results));
|
141
142
|
el.renderSearchAllFiles = true;
|
142
143
|
|
143
144
|
await el.updateComplete;
|
144
145
|
|
145
|
-
expect(el.shadowRoot.querySelector('[name="all_files"]')).
|
146
|
+
expect(el.shadowRoot.querySelector('[name="all_files"]')).not.toBeNull();
|
146
147
|
});
|
147
148
|
|
148
|
-
|
149
|
+
test('emits a resultSelected event when a search result is clicked', async () => {
|
149
150
|
const el = await fixture(container(results));
|
150
151
|
|
151
152
|
setTimeout(() => (
|
@@ -153,10 +154,10 @@ describe('<ia-book-search-results>', () => {
|
|
153
154
|
));
|
154
155
|
const response = await oneEvent(el, 'resultSelected');
|
155
156
|
|
156
|
-
expect(response).
|
157
|
+
expect(response).toBeDefined();
|
157
158
|
});
|
158
159
|
|
159
|
-
|
160
|
+
test('emits a closeMenu event when a search result is clicked', async () => {
|
160
161
|
const el = await fixture(container(results));
|
161
162
|
|
162
163
|
setTimeout(() => (
|
@@ -164,75 +165,75 @@ describe('<ia-book-search-results>', () => {
|
|
164
165
|
));
|
165
166
|
const response = await oneEvent(el, 'closeMenu');
|
166
167
|
|
167
|
-
expect(response).
|
168
|
+
expect(response).toBeDefined();
|
168
169
|
});
|
169
170
|
|
170
171
|
describe('Search results placeholders', () => {
|
171
|
-
|
172
|
+
test('renders a loading state when queryInProgress is true', async () => {
|
172
173
|
const el = await fixture(container(results));
|
173
174
|
|
174
175
|
el.queryInProgress = true;
|
175
176
|
await el.updateComplete;
|
176
177
|
|
177
|
-
expect(el.shadowRoot.querySelector('.loading')).
|
178
|
+
expect(el.shadowRoot.querySelector('.loading')).not.toBeNull();
|
178
179
|
});
|
179
|
-
|
180
|
+
test('renders an error message when provided', async () => {
|
180
181
|
const el = await fixture(container([]));
|
181
182
|
const message = 'Sample error message';
|
182
183
|
el.errorMessage = message;
|
183
184
|
await el.updateComplete;
|
184
185
|
|
185
|
-
expect(el.shadowRoot.querySelector('.error-message')).
|
186
|
-
expect(el.shadowRoot.querySelector('.search-cta')).
|
186
|
+
expect(el.shadowRoot.querySelector('.error-message')).toBeDefined();
|
187
|
+
expect(el.shadowRoot.querySelector('.search-cta')).toBeNull();
|
187
188
|
});
|
188
|
-
|
189
|
+
test('displays call to search when no results or search errors are showing', async () => {
|
189
190
|
const el = await fixture(container([]));
|
190
191
|
|
191
|
-
expect(el.shadowRoot.querySelector('.search-cta')).
|
192
|
-
expect(el.shadowRoot.querySelector('.error-message')).
|
193
|
-
expect(el.shadowRoot.querySelector('.results')).
|
192
|
+
expect(el.shadowRoot.querySelector('.search-cta')).toBeDefined();
|
193
|
+
expect(el.shadowRoot.querySelector('.error-message')).toBeNull();
|
194
|
+
expect(el.shadowRoot.querySelector('.results')).toBeNull();
|
194
195
|
});
|
195
196
|
});
|
196
197
|
|
197
|
-
|
198
|
+
test('displays results images when told to', async () => {
|
198
199
|
const el = await fixture(container(results));
|
199
200
|
el.displayResultImages = true;
|
200
201
|
await el.updateComplete;
|
201
202
|
|
202
|
-
expect(el.shadowRoot.querySelector('.results.show-image')).
|
203
|
+
expect(el.shadowRoot.querySelector('.results.show-image')).toBeDefined();
|
203
204
|
});
|
204
205
|
|
205
206
|
describe('search input focus', () => {
|
206
|
-
|
207
|
+
test('will always try to re-focus once the component updates', async () => {
|
207
208
|
const el = await fixture(container(results));
|
208
209
|
el.focusOnInputIfNecessary = sinon.fake();
|
209
210
|
// update any property to fire lifecycle
|
210
211
|
el.results = [];
|
211
212
|
await el.updateComplete;
|
212
213
|
|
213
|
-
expect(el.focusOnInputIfNecessary.callCount).
|
214
|
+
expect(el.focusOnInputIfNecessary.callCount).toEqual(1);
|
214
215
|
});
|
215
|
-
|
216
|
+
test('refocuses on input when results are empty', async () => {
|
216
217
|
const el = await fixture(container(results));
|
217
218
|
el.results = [];
|
218
219
|
await el.updateComplete;
|
219
220
|
|
220
221
|
const searchInputField = el.shadowRoot.querySelector('input[type=\'search\']');
|
221
|
-
expect(searchInputField).
|
222
|
+
expect(searchInputField).toEqual(el.shadowRoot.activeElement);
|
222
223
|
});
|
223
224
|
});
|
224
225
|
|
225
|
-
|
226
|
-
|
226
|
+
test("emits a bookSearchCanceled event when loading state's cancel action clicked", async () => {
|
227
|
+
const el = await fixture(container(results));
|
227
228
|
|
228
|
-
|
229
|
-
|
229
|
+
el.queryInProgress = true;
|
230
|
+
await el.updateComplete;
|
230
231
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
232
|
+
setTimeout(() => (
|
233
|
+
el.shadowRoot.querySelector('button').click()
|
234
|
+
));
|
235
|
+
const response = await oneEvent(el, 'bookSearchCanceled');
|
235
236
|
|
236
|
-
|
237
|
-
|
237
|
+
expect(response).toBeDefined();
|
238
|
+
});
|
238
239
|
});
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import {
|
1
|
+
import { fixtureSync } from '@open-wc/testing-helpers';
|
2
2
|
import sinon from 'sinon';
|
3
|
-
import SharingProvider from '
|
3
|
+
import SharingProvider from '@/src/BookNavigator/sharing.js';
|
4
4
|
|
5
5
|
afterEach(() => {
|
6
6
|
sinon.restore();
|
@@ -27,14 +27,14 @@ describe('Sharing Provider', () => {
|
|
27
27
|
}
|
28
28
|
});
|
29
29
|
|
30
|
-
expect(provider.id).
|
31
|
-
expect(provider.icon).
|
32
|
-
expect(provider.label).
|
33
|
-
expect(fixtureSync(provider.component).tagName).
|
30
|
+
expect(provider.id).toEqual('share');
|
31
|
+
expect(provider.icon).toBeDefined();
|
32
|
+
expect(provider.label).toEqual('Share this book');
|
33
|
+
expect(fixtureSync(provider.component).tagName).toContain('IA-SHARING-OPTIONS');
|
34
34
|
});
|
35
35
|
|
36
36
|
describe('Handles being a sub file/volume', () => {
|
37
|
-
|
37
|
+
test('encodes the subprefix if it has one', async () => {
|
38
38
|
const provider = new SharingProvider({
|
39
39
|
item,
|
40
40
|
baseHost,
|
@@ -43,7 +43,7 @@ describe('Sharing Provider', () => {
|
|
43
43
|
}
|
44
44
|
});
|
45
45
|
|
46
|
-
expect(fixtureSync(provider.component).fileSubPrefix).
|
46
|
+
expect(fixtureSync(provider.component).fileSubPrefix).toEqual(subPrefix);
|
47
47
|
});
|
48
48
|
});
|
49
49
|
});
|
@@ -0,0 +1,200 @@
|
|
1
|
+
import {
|
2
|
+
html,
|
3
|
+
fixture,
|
4
|
+
oneEvent,
|
5
|
+
} from '@open-wc/testing-helpers';
|
6
|
+
import sinon from 'sinon';
|
7
|
+
import { IABookVisualAdjustments } from '@/src/BookNavigator/visual-adjustments/visual-adjustments.js';
|
8
|
+
|
9
|
+
const options = [{
|
10
|
+
id: 'contrast',
|
11
|
+
name: 'Adjust contrast',
|
12
|
+
active: true,
|
13
|
+
min: 0,
|
14
|
+
max: 150,
|
15
|
+
step: 1,
|
16
|
+
value: 100,
|
17
|
+
}, {
|
18
|
+
id: 'invert',
|
19
|
+
name: 'Invert colors',
|
20
|
+
active: false,
|
21
|
+
}, {
|
22
|
+
id: 'brightness',
|
23
|
+
name: 'Adjust brightness',
|
24
|
+
active: false,
|
25
|
+
value: 100,
|
26
|
+
}];
|
27
|
+
|
28
|
+
const container = (renderHeader = false) => (
|
29
|
+
html`<ia-book-visual-adjustments .options=${options} ?renderHeader=${renderHeader}></ia-book-visual-adjustments>`
|
30
|
+
);
|
31
|
+
|
32
|
+
describe('<ia-book-visual-adjustments>', () => {
|
33
|
+
afterEach(() => {
|
34
|
+
sinon.restore();
|
35
|
+
});
|
36
|
+
|
37
|
+
test('sets default properties', async () => {
|
38
|
+
const el = await fixture(container());
|
39
|
+
|
40
|
+
expect(el.options).toBeDefined();
|
41
|
+
expect(el.options.length).toEqual(options.length);
|
42
|
+
expect(el.renderHeader).toBeDefined();
|
43
|
+
expect(el.renderHeader).toBeFalsy();
|
44
|
+
expect(el.activeCount).toBeDefined();
|
45
|
+
expect(el.showZoomControls).toBeTruthy();
|
46
|
+
});
|
47
|
+
|
48
|
+
test('renders all properties of a visual adjustment option', async () => {
|
49
|
+
const el = await fixture(container());
|
50
|
+
|
51
|
+
await el.updateComplete;
|
52
|
+
|
53
|
+
const label = el.shadowRoot.querySelector('label');
|
54
|
+
const name = label.querySelector('.name');
|
55
|
+
const checkbox = label.querySelector('input');
|
56
|
+
expect(name.textContent).toEqual(options[0].name);
|
57
|
+
expect(checkbox.checked).toEqual(true);
|
58
|
+
});
|
59
|
+
|
60
|
+
test('can render header with active options count', async () => {
|
61
|
+
const renderHeader = true;
|
62
|
+
const el = await fixture(container(renderHeader));
|
63
|
+
expect(el.shadowRoot.querySelector('header p').textContent).toContain('1');
|
64
|
+
});
|
65
|
+
|
66
|
+
test('does not render active options count element when none are selected', async () => {
|
67
|
+
const el = await fixture(container());
|
68
|
+
|
69
|
+
el.options = [options[1]];
|
70
|
+
await el.updateComplete;
|
71
|
+
|
72
|
+
expect(el.shadowRoot.querySelector('header p')).toBe(null);
|
73
|
+
});
|
74
|
+
|
75
|
+
test('changes option\'s active state when input changed', async () => {
|
76
|
+
const el = await fixture(container());
|
77
|
+
|
78
|
+
el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
|
79
|
+
await el.updateComplete;
|
80
|
+
|
81
|
+
expect(el.options[0].active).toEqual(false);
|
82
|
+
});
|
83
|
+
|
84
|
+
test('renders zoom in and out controls when enabled', async () => {
|
85
|
+
const el = await fixture(container());
|
86
|
+
|
87
|
+
expect(el.shadowRoot.querySelector('.zoom_out')).toBeDefined();
|
88
|
+
expect(el.shadowRoot.querySelector('.zoom_in')).toBeDefined();
|
89
|
+
});
|
90
|
+
|
91
|
+
test('does not render zoom controls when disabled', async () => {
|
92
|
+
const el = await fixture(container());
|
93
|
+
|
94
|
+
el.showZoomControls = false;
|
95
|
+
await el.updateComplete;
|
96
|
+
|
97
|
+
expect(el.shadowRoot.querySelector('.zoom_out')).toBe(null);
|
98
|
+
expect(el.shadowRoot.querySelector('.zoom_in')).toBe(null);
|
99
|
+
});
|
100
|
+
|
101
|
+
describe('Custom events', () => {
|
102
|
+
test('prepareEventDetails returns proper params', async () => {
|
103
|
+
const el = await fixture(container());
|
104
|
+
await el.updateComplete;
|
105
|
+
const params = el.prepareEventDetails();
|
106
|
+
|
107
|
+
expect(params.activeCount).toBeDefined();
|
108
|
+
expect(typeof (params.activeCount)).toEqual('number');
|
109
|
+
expect(params.changedOptionId).toBeDefined();
|
110
|
+
expect(typeof (params.changedOptionId)).toEqual('string');
|
111
|
+
expect(params.options).toBeDefined();
|
112
|
+
expect(params.options.length).toBeDefined();
|
113
|
+
expect(params.options.length).toBeGreaterThan(0);
|
114
|
+
});
|
115
|
+
test('emitOptionChangedEvent calls for the params', async () => {
|
116
|
+
IABookVisualAdjustments.prototype.prepareEventDetails = sinon.fake();
|
117
|
+
const el = await fixture(container());
|
118
|
+
await el.updateComplete;
|
119
|
+
|
120
|
+
expect(el.prepareEventDetails.callCount).toEqual(1);
|
121
|
+
});
|
122
|
+
test('triggers an emitOptionChangedEvent event at firstUpdate', async () => {
|
123
|
+
IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
|
124
|
+
const el = await fixture(container());
|
125
|
+
|
126
|
+
expect(el.emitOptionChangedEvent.callCount).toEqual(1);
|
127
|
+
});
|
128
|
+
|
129
|
+
test('triggers an emitOptionChangedEvent event when a checkbox\'s change event fires', async () => {
|
130
|
+
IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
|
131
|
+
const el = await fixture(container());
|
132
|
+
|
133
|
+
expect(el.emitOptionChangedEvent.callCount).toEqual(1); // firstUpdate fire
|
134
|
+
|
135
|
+
el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
|
136
|
+
expect(el.emitOptionChangedEvent.callCount).toEqual(2);
|
137
|
+
});
|
138
|
+
|
139
|
+
test('triggers an emitOptionChangedEvent event when a range\'s change event fires', async () => {
|
140
|
+
IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
|
141
|
+
|
142
|
+
const el = await fixture(container());
|
143
|
+
expect(el.emitOptionChangedEvent.callCount).toEqual(1); // firstUpdate fire
|
144
|
+
|
145
|
+
el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('change'));
|
146
|
+
expect(el.emitOptionChangedEvent.callCount).toEqual(2);
|
147
|
+
});
|
148
|
+
|
149
|
+
test('emits a zoom out event when zoom out button clicked', async () => {
|
150
|
+
const el = await fixture(container());
|
151
|
+
|
152
|
+
setTimeout(() => (
|
153
|
+
el.shadowRoot.querySelector('.zoom_out').click()
|
154
|
+
));
|
155
|
+
const response = await oneEvent(el, 'visualAdjustmentZoomOut');
|
156
|
+
|
157
|
+
expect(response).toBeDefined();
|
158
|
+
});
|
159
|
+
|
160
|
+
test('emits a zoom in event when zoom in button clicked', async () => {
|
161
|
+
const el = await fixture(container());
|
162
|
+
|
163
|
+
setTimeout(() => (
|
164
|
+
el.shadowRoot.querySelector('.zoom_in').click()
|
165
|
+
));
|
166
|
+
const response = await oneEvent(el, 'visualAdjustmentZoomIn');
|
167
|
+
|
168
|
+
expect(response).toBeDefined();
|
169
|
+
});
|
170
|
+
});
|
171
|
+
|
172
|
+
test('sets range defaults when none supplied', async () => {
|
173
|
+
const el = await fixture(container());
|
174
|
+
const brightnessRange = el.shadowRoot.querySelector('[name="brightness_range"]');
|
175
|
+
|
176
|
+
expect(brightnessRange.getAttribute('min')).toEqual('0');
|
177
|
+
expect(brightnessRange.getAttribute('max')).toEqual('100');
|
178
|
+
expect(brightnessRange.getAttribute('step')).toEqual('1');
|
179
|
+
});
|
180
|
+
|
181
|
+
test('sets the updated range value on the options prop', async () => {
|
182
|
+
const el = await fixture(container());
|
183
|
+
const { id } = options[0];
|
184
|
+
const newValue = 120;
|
185
|
+
|
186
|
+
el.setRangeValue(id, newValue);
|
187
|
+
await el.updateComplete;
|
188
|
+
|
189
|
+
expect(el.options[0].value).toEqual(newValue);
|
190
|
+
});
|
191
|
+
|
192
|
+
test('triggers a setRangeValue event when a range\'s input event fires', async () => {
|
193
|
+
IABookVisualAdjustments.prototype.setRangeValue = sinon.fake();
|
194
|
+
|
195
|
+
const el = await fixture(container());
|
196
|
+
|
197
|
+
el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('input'));
|
198
|
+
expect(el.setRangeValue.callCount).toEqual(1);
|
199
|
+
});
|
200
|
+
});
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import {
|
1
|
+
import { fixture, fixtureCleanup, fixtureSync } from '@open-wc/testing-helpers';
|
2
2
|
import sinon from 'sinon';
|
3
|
-
import volumesProvider from '
|
3
|
+
import volumesProvider from '@/src/BookNavigator/volumes/volumes-provider';
|
4
4
|
|
5
5
|
const brOptions = {
|
6
6
|
"options": {
|
@@ -39,7 +39,7 @@ afterEach(() => {
|
|
39
39
|
});
|
40
40
|
|
41
41
|
describe('Volumes Provider', () => {
|
42
|
-
|
42
|
+
test('constructor', () => {
|
43
43
|
const onProviderChange = sinon.fake();
|
44
44
|
const baseHost = "https://archive.org";
|
45
45
|
const provider = new volumesProvider({
|
@@ -51,20 +51,20 @@ describe('Volumes Provider', () => {
|
|
51
51
|
const files = brOptions.options.multipleBooksList.by_subprefix;
|
52
52
|
const volumeCount = Object.keys(files).length;
|
53
53
|
|
54
|
-
expect(provider.onProviderChange).
|
55
|
-
expect(provider.id).
|
56
|
-
expect(provider.icon).
|
57
|
-
expect(fixtureSync(provider.icon).tagName).
|
58
|
-
expect(provider.label).
|
59
|
-
expect(provider.viewableFiles).
|
60
|
-
expect(provider.viewableFiles.length).
|
61
|
-
|
62
|
-
expect(provider.component.hostUrl).
|
63
|
-
expect(provider.component.hostUrl).
|
64
|
-
expect(provider.component).
|
54
|
+
expect(provider.onProviderChange).toEqual(onProviderChange);
|
55
|
+
expect(provider.id).toEqual('volumes');
|
56
|
+
expect(provider.icon).toBeDefined();
|
57
|
+
expect(fixtureSync(provider.icon).tagName).toEqual('svg');
|
58
|
+
expect(provider.label).toEqual(`Viewable files (${volumeCount})`);
|
59
|
+
expect(provider.viewableFiles).toBeDefined();
|
60
|
+
expect(provider.viewableFiles.length).toEqual(3);
|
61
|
+
|
62
|
+
expect(provider.component.hostUrl).toBeDefined();
|
63
|
+
expect(provider.component.hostUrl).toEqual(baseHost);
|
64
|
+
expect(provider.component).toBeDefined();
|
65
65
|
});
|
66
66
|
|
67
|
-
|
67
|
+
test('sorting cycles - render sort actionButton', async () => {
|
68
68
|
const onProviderChange = sinon.fake();
|
69
69
|
const baseHost = "https://archive.org";
|
70
70
|
const provider = new volumesProvider({
|
@@ -73,22 +73,22 @@ describe('Volumes Provider', () => {
|
|
73
73
|
onProviderChange
|
74
74
|
});
|
75
75
|
|
76
|
-
expect(provider.sortOrderBy).
|
76
|
+
expect(provider.sortOrderBy).toEqual("default");
|
77
77
|
|
78
78
|
provider.sortVolumes("title_asc");
|
79
|
-
expect(provider.sortOrderBy).
|
80
|
-
expect(fixtureSync(provider.sortButton).outerHTML).
|
79
|
+
expect(provider.sortOrderBy).toEqual("title_asc");
|
80
|
+
expect(fixtureSync(provider.sortButton).outerHTML).toContain("sort-by asc-icon");
|
81
81
|
|
82
82
|
provider.sortVolumes("title_desc");
|
83
|
-
expect(provider.sortOrderBy).
|
84
|
-
expect(fixtureSync(provider.sortButton).outerHTML).
|
83
|
+
expect(provider.sortOrderBy).toEqual("title_desc");
|
84
|
+
expect(fixtureSync(provider.sortButton).outerHTML).toContain("sort-by desc-icon");
|
85
85
|
|
86
86
|
provider.sortVolumes("default");
|
87
|
-
expect(provider.sortOrderBy).
|
88
|
-
expect(fixtureSync(provider.sortButton).outerHTML).
|
87
|
+
expect(provider.sortOrderBy).toEqual("default");
|
88
|
+
expect(fixtureSync(provider.sortButton).outerHTML).toContain("sort-by neutral-icon");
|
89
89
|
});
|
90
90
|
|
91
|
-
|
91
|
+
test('sort volumes in initial order', async () => {
|
92
92
|
const onProviderChange = sinon.fake();
|
93
93
|
const baseHost = "https://archive.org";
|
94
94
|
const provider = new volumesProvider({
|
@@ -103,15 +103,15 @@ describe('Volumes Provider', () => {
|
|
103
103
|
|
104
104
|
provider.sortVolumes("default");
|
105
105
|
|
106
|
-
expect(provider.sortOrderBy).
|
107
|
-
expect(provider.actionButton).
|
106
|
+
expect(provider.sortOrderBy).toEqual("default");
|
107
|
+
expect(provider.actionButton).toBeDefined();
|
108
108
|
|
109
109
|
const providerFileTitles = provider.viewableFiles.map(item => item.title);
|
110
110
|
// use `.eql` for "lose equality" in order to deeply compare values.
|
111
|
-
expect(providerFileTitles).
|
111
|
+
expect(providerFileTitles).toEqual([...origSortTitles]);
|
112
112
|
});
|
113
113
|
|
114
|
-
|
114
|
+
test('sort volumes in ascending title order', async () => {
|
115
115
|
const onProviderChange = sinon.fake();
|
116
116
|
const baseHost = "https://archive.org";
|
117
117
|
const provider = new volumesProvider({
|
@@ -126,15 +126,15 @@ describe('Volumes Provider', () => {
|
|
126
126
|
|
127
127
|
provider.sortVolumes("title_asc");
|
128
128
|
|
129
|
-
expect(provider.sortOrderBy).
|
130
|
-
expect(provider.actionButton).
|
129
|
+
expect(provider.sortOrderBy).toEqual("title_asc");
|
130
|
+
expect(provider.actionButton).toBeDefined();
|
131
131
|
|
132
132
|
const providerFileTitles = provider.viewableFiles.map(item => item.title);
|
133
133
|
// use `.eql` for "lose equality" in order to deeply compare values.
|
134
|
-
expect(providerFileTitles).
|
134
|
+
expect(providerFileTitles).toEqual([...ascendingTitles]);
|
135
135
|
});
|
136
136
|
|
137
|
-
|
137
|
+
test('sort volumes in descending title order', async () => {
|
138
138
|
const onProviderChange = sinon.fake();
|
139
139
|
const baseHost = "https://archive.org";
|
140
140
|
const provider = new volumesProvider({
|
@@ -150,16 +150,16 @@ describe('Volumes Provider', () => {
|
|
150
150
|
|
151
151
|
provider.sortVolumes("title_desc");
|
152
152
|
|
153
|
-
expect(provider.sortOrderBy).
|
154
|
-
expect(provider.actionButton).
|
153
|
+
expect(provider.sortOrderBy).toEqual("title_desc");
|
154
|
+
expect(provider.actionButton).toBeDefined();
|
155
155
|
|
156
156
|
const providerFileTitles = provider.viewableFiles.map(item => item.title);
|
157
157
|
// use `.eql` for "lose equality" in order to deeply compare values.
|
158
|
-
expect(providerFileTitles).
|
158
|
+
expect(providerFileTitles).toEqual([...descendingTitles]);
|
159
159
|
});
|
160
160
|
|
161
161
|
describe('Sorting icons', () => {
|
162
|
-
|
162
|
+
test('has 3 icons', async () => {
|
163
163
|
const onProviderChange = sinon.fake();
|
164
164
|
const baseHost = "https://archive.org";
|
165
165
|
const provider = new volumesProvider({
|
@@ -170,15 +170,15 @@ describe('Volumes Provider', () => {
|
|
170
170
|
provider.sortOrderBy = 'default';
|
171
171
|
|
172
172
|
const origSortButton = await fixture(provider.sortButton);
|
173
|
-
expect(origSortButton.classList.contains('neutral-icon')).
|
173
|
+
expect(origSortButton.classList.contains('neutral-icon')).toBeTruthy();
|
174
174
|
|
175
175
|
provider.sortOrderBy = 'title_asc';
|
176
176
|
const ascButton = await fixture(provider.sortButton);
|
177
|
-
expect(ascButton.classList.contains('asc-icon')).
|
177
|
+
expect(ascButton.classList.contains('asc-icon')).toBeTruthy();
|
178
178
|
|
179
179
|
provider.sortOrderBy = 'title_desc';
|
180
180
|
const descButton = await fixture(provider.sortButton);
|
181
|
-
expect(descButton.classList.contains('desc-icon')).
|
181
|
+
expect(descButton.classList.contains('desc-icon')).toBeTruthy();
|
182
182
|
});
|
183
183
|
});
|
184
184
|
});
|