@internetarchive/bookreader 5.0.0-5-multiple-files → 5.0.0-50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. package/.eslintrc.js +17 -15
  2. package/.github/workflows/node.js.yml +77 -6
  3. package/.github/workflows/npm-publish.yml +6 -20
  4. package/.testcaferc.js +10 -0
  5. package/BookReader/BookReader.css +131 -339
  6. package/BookReader/BookReader.js +2 -21564
  7. package/BookReader/BookReader.js.LICENSE.txt +24 -0
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1493 -0
  10. package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +17 -0
  11. package/BookReader/ia-bookreader-bundle.js.map +1 -0
  12. package/BookReader/icons/1up.svg +1 -12
  13. package/BookReader/icons/2up.svg +1 -15
  14. package/BookReader/icons/advance.svg +3 -26
  15. package/BookReader/icons/chevron-right.svg +1 -1
  16. package/BookReader/icons/close-circle-dark.svg +1 -0
  17. package/BookReader/icons/close-circle.svg +1 -1
  18. package/BookReader/icons/fullscreen.svg +1 -17
  19. package/BookReader/icons/fullscreen_exit.svg +1 -17
  20. package/BookReader/icons/hamburger.svg +1 -15
  21. package/BookReader/icons/left-arrow.svg +1 -12
  22. package/BookReader/icons/magnify-minus.svg +1 -16
  23. package/BookReader/icons/magnify-plus.svg +1 -17
  24. package/BookReader/icons/magnify.svg +1 -15
  25. package/BookReader/icons/pause.svg +1 -23
  26. package/BookReader/icons/play.svg +1 -22
  27. package/BookReader/icons/playback-speed.svg +1 -34
  28. package/BookReader/icons/read-aloud.svg +1 -22
  29. package/BookReader/icons/review.svg +3 -22
  30. package/BookReader/icons/thumbnails.svg +1 -17
  31. package/BookReader/icons/voice.svg +1 -0
  32. package/BookReader/icons/volume-full.svg +1 -22
  33. package/BookReader/images/BRicons.svg +5 -94
  34. package/BookReader/images/books_graphic.svg +1 -177
  35. package/BookReader/images/icon_book.svg +1 -12
  36. package/BookReader/images/icon_bookmark.svg +1 -12
  37. package/BookReader/images/icon_gear.svg +1 -14
  38. package/BookReader/images/icon_hamburger.svg +1 -20
  39. package/BookReader/images/icon_home.svg +1 -21
  40. package/BookReader/images/icon_info.svg +1 -11
  41. package/BookReader/images/icon_one_page.svg +1 -8
  42. package/BookReader/images/icon_pause.svg +1 -1
  43. package/BookReader/images/icon_play.svg +1 -1
  44. package/BookReader/images/icon_playback-rate.svg +1 -15
  45. package/BookReader/images/icon_search_button.svg +1 -8
  46. package/BookReader/images/icon_share.svg +1 -9
  47. package/BookReader/images/icon_skip-ahead.svg +1 -6
  48. package/BookReader/images/icon_skip-back.svg +2 -13
  49. package/BookReader/images/icon_speaker.svg +1 -18
  50. package/BookReader/images/icon_speaker_open.svg +1 -10
  51. package/BookReader/images/icon_thumbnails.svg +1 -12
  52. package/BookReader/images/icon_toc.svg +1 -5
  53. package/BookReader/images/icon_two_pages.svg +1 -9
  54. package/BookReader/images/marker_chap-off.svg +1 -11
  55. package/BookReader/images/marker_chap-on.svg +1 -11
  56. package/BookReader/images/marker_srch-on.svg +1 -11
  57. package/BookReader/jquery-3.js +2 -0
  58. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  59. package/BookReader/plugins/plugin.archive_analytics.js +1 -172
  60. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  61. package/BookReader/plugins/plugin.autoplay.js +1 -165
  62. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  63. package/BookReader/plugins/plugin.chapters.js +1 -304
  64. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  65. package/BookReader/plugins/plugin.iframe.js +1 -74
  66. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  67. package/BookReader/plugins/plugin.mobile_nav.js +1 -334
  68. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  69. package/BookReader/plugins/plugin.resume.js +1 -368
  70. package/BookReader/plugins/plugin.resume.js.map +1 -1
  71. package/BookReader/plugins/plugin.search.js +1 -1420
  72. package/BookReader/plugins/plugin.search.js.map +1 -1
  73. package/BookReader/plugins/plugin.text_selection.js +1 -1080
  74. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  75. package/BookReader/plugins/plugin.tts.js +2 -9193
  76. package/BookReader/plugins/plugin.tts.js.map +1 -1
  77. package/BookReader/plugins/plugin.url.js +1 -269
  78. package/BookReader/plugins/plugin.url.js.map +1 -1
  79. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -379
  80. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  81. package/BookReader/webcomponents-bundle.js +3 -0
  82. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  83. package/BookReader/webcomponents-bundle.js.map +1 -0
  84. package/BookReaderDemo/BookReaderDemo.css +14 -1
  85. package/BookReaderDemo/IADemoBr.js +148 -0
  86. package/BookReaderDemo/demo-advanced.html +2 -2
  87. package/BookReaderDemo/demo-autoplay.html +2 -1
  88. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  89. package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
  90. package/BookReaderDemo/demo-fullscreen.html +2 -1
  91. package/BookReaderDemo/demo-iiif.html +2 -1
  92. package/BookReaderDemo/demo-internetarchive.html +84 -17
  93. package/BookReaderDemo/demo-multiple.html +2 -1
  94. package/BookReaderDemo/demo-preview-pages.html +2 -1
  95. package/BookReaderDemo/demo-simple.html +2 -1
  96. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
  97. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  98. package/BookReaderDemo/immersion-1up.html +2 -1
  99. package/BookReaderDemo/immersion-mode.html +2 -1
  100. package/BookReaderDemo/toggle_controls.html +2 -1
  101. package/BookReaderDemo/view_mode.html +2 -1
  102. package/BookReaderDemo/viewmode-cycle.html +2 -3
  103. package/CHANGELOG.md +205 -0
  104. package/README.md +14 -1
  105. package/babel.config.js +18 -0
  106. package/codecov.yml +6 -0
  107. package/index.html +3 -0
  108. package/jsconfig.json +19 -0
  109. package/package.json +66 -56
  110. package/renovate.json +52 -0
  111. package/scripts/preversion.js +4 -1
  112. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  113. package/src/BookNavigator/assets/button-base.js +9 -2
  114. package/src/BookNavigator/assets/ia-logo.js +17 -0
  115. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  116. package/src/BookNavigator/assets/icon_close.js +1 -1
  117. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  118. package/src/BookNavigator/assets/{icon_sort_ascending.js → icon_sort_desc.js} +2 -2
  119. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  120. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  121. package/src/BookNavigator/book-navigator.js +583 -0
  122. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  123. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  124. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  125. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  126. package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
  127. package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
  128. package/src/BookNavigator/delete-modal-actions.js +1 -1
  129. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  130. package/src/BookNavigator/downloads/downloads.js +41 -25
  131. package/src/BookNavigator/search/a-search-result.js +15 -13
  132. package/src/BookNavigator/search/search-provider.js +80 -28
  133. package/src/BookNavigator/search/search-results.js +10 -18
  134. package/src/BookNavigator/sharing.js +27 -0
  135. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  136. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  137. package/src/BookNavigator/volumes/volumes-provider.js +93 -63
  138. package/src/BookNavigator/volumes/volumes.js +40 -46
  139. package/src/BookReader/BookModel.js +0 -29
  140. package/src/BookReader/DebugConsole.js +3 -3
  141. package/src/BookReader/DragScrollable.js +233 -0
  142. package/src/BookReader/Mode1Up.js +51 -351
  143. package/src/BookReader/Mode1UpLit.js +441 -0
  144. package/src/BookReader/Mode2Up.js +120 -105
  145. package/src/BookReader/ModeSmoothZoom.js +179 -0
  146. package/src/BookReader/ModeThumb.js +17 -11
  147. package/src/BookReader/Navbar/Navbar.js +10 -36
  148. package/src/BookReader/PageContainer.js +69 -6
  149. package/src/BookReader/ReduceSet.js +1 -1
  150. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  151. package/src/BookReader/options.js +10 -0
  152. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  153. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  154. package/src/BookReader/utils.js +92 -13
  155. package/src/BookReader.js +431 -620
  156. package/src/assets/icons/close-circle-dark.svg +1 -0
  157. package/src/assets/icons/magnify-minus.svg +3 -7
  158. package/src/assets/icons/magnify-plus.svg +3 -7
  159. package/src/assets/icons/voice.svg +1 -0
  160. package/src/css/BookReader.scss +0 -12
  161. package/src/css/_BRComponent.scss +1 -1
  162. package/src/css/_BRmain.scss +19 -24
  163. package/src/css/_BRnav.scss +4 -26
  164. package/src/css/_BRpages.scss +35 -0
  165. package/src/css/_BRsearch.scss +25 -216
  166. package/src/css/_TextSelection.scss +14 -17
  167. package/src/css/_colorbox.scss +2 -2
  168. package/src/css/_controls.scss +17 -5
  169. package/src/css/_icons.scss +6 -0
  170. package/src/ia-bookreader/ia-bookreader.js +224 -0
  171. package/src/plugins/plugin.autoplay.js +4 -4
  172. package/src/plugins/plugin.chapters.js +28 -35
  173. package/src/plugins/plugin.mobile_nav.js +11 -10
  174. package/src/plugins/plugin.resume.js +3 -3
  175. package/src/plugins/plugin.text_selection.js +26 -39
  176. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  177. package/src/plugins/search/plugin.search.js +174 -116
  178. package/src/plugins/search/view.js +63 -179
  179. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  180. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  181. package/src/plugins/tts/PageChunk.js +15 -21
  182. package/src/plugins/tts/PageChunkIterator.js +8 -12
  183. package/src/plugins/tts/WebTTSEngine.js +66 -69
  184. package/src/plugins/tts/plugin.tts.js +92 -109
  185. package/src/plugins/tts/utils.js +0 -9
  186. package/src/plugins/url/UrlPlugin.js +184 -0
  187. package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
  188. package/src/util/manifestGenerator.js +0 -0
  189. package/tests/e2e/README.md +37 -0
  190. package/tests/e2e/autoplay.test.js +2 -2
  191. package/tests/e2e/base.test.js +7 -7
  192. package/tests/e2e/helpers/base.js +8 -3
  193. package/tests/e2e/helpers/debug.js +1 -1
  194. package/tests/e2e/helpers/desktopSearch.js +14 -13
  195. package/tests/e2e/helpers/mobileSearch.js +3 -3
  196. package/tests/e2e/helpers/params.js +17 -0
  197. package/tests/e2e/models/Navigation.js +13 -4
  198. package/tests/e2e/rightToLeft.test.js +4 -5
  199. package/tests/e2e/viewmode.test.js +38 -33
  200. package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
  201. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  202. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  203. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  204. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  205. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  206. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  207. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  208. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
  209. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  210. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  211. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
  212. package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
  213. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
  214. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  215. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  216. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  217. package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
  218. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
  219. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  220. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  221. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  222. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  223. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  224. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  225. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  226. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  227. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  228. package/tests/jest/BookReader/utils.test.js +186 -0
  229. package/tests/jest/BookReader.keyboard.test.js +190 -0
  230. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  231. package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
  232. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  233. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  234. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
  235. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  236. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  237. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  238. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  239. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  240. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
  241. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
  242. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  243. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  244. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  245. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  246. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  247. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
  248. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  249. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  250. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  251. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  252. package/tests/{util → jest/util}/strings.test.js +1 -1
  253. package/tests/{utils.js → jest/utils.js} +38 -0
  254. package/webpack.config.js +11 -5
  255. package/.babelrc +0 -12
  256. package/.dependabot/config.yml +0 -6
  257. package/.testcaferc.json +0 -5
  258. package/BookReader/bookreader-component-bundle.js +0 -14275
  259. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  260. package/BookReader/bookreader-component-bundle.js.map +0 -1
  261. package/BookReader/icons/sort-ascending.svg +0 -1
  262. package/BookReader/icons/sort-descending.svg +0 -1
  263. package/BookReader/jquery-1.10.1.js +0 -108
  264. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  265. package/BookReader/plugins/plugin.menu_toggle.js +0 -369
  266. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  267. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  268. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  269. package/karma.conf.js +0 -23
  270. package/src/BookNavigator/BookModel.js +0 -14
  271. package/src/BookNavigator/BookNavigator.js +0 -448
  272. package/src/BookNavigator/assets/book-loader.js +0 -27
  273. package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
  274. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  275. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  276. package/src/ItemNavigator/ItemNavigator.js +0 -373
  277. package/src/ItemNavigator/providers/sharing.js +0 -29
  278. package/src/assets/icons/sort-ascending.svg +0 -1
  279. package/src/assets/icons/sort-descending.svg +0 -1
  280. package/src/dragscrollable-br.js +0 -261
  281. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  282. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  283. package/tests/BookReader/Mode1Up.test.js +0 -164
  284. package/tests/BookReader/utils.test.js +0 -109
  285. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  286. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  287. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  288. package/tests/karma/BookNavigator/volumes.test.js +0 -101
  289. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -0,0 +1,634 @@
1
+ import {
2
+ html,
3
+ elementUpdated,
4
+ fixtureCleanup,
5
+ fixtureSync,
6
+ } from '@open-wc/testing-helpers';
7
+ import sinon from 'sinon';
8
+ import DownloadsProvider from '@/src/BookNavigator/downloads/downloads-provider.js';
9
+ import SearchProvider from '@/src/BookNavigator/search/search-provider.js';
10
+ import SharingProvider from '@/src/BookNavigator/sharing.js';
11
+ import VisualAdjustmentsProvider from '@/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js';
12
+ import VolumesProvider from '@/src/BookNavigator/volumes/volumes-provider.js';
13
+ import { ModalManager } from '@internetarchive/modal-manager';
14
+ import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
15
+ import '@/src/BookNavigator/book-navigator.js';
16
+
17
+ const promise0 = () => new Promise(res => setTimeout(res, 0));
18
+
19
+ const container = (sharedObserver = null) => {
20
+ const itemStub = {
21
+ metadata: {
22
+ identifier: 'foo',
23
+ creator: 'bar',
24
+ title: 'baz',
25
+ }
26
+ };
27
+ const modalMgr = new ModalManager();
28
+ return html`
29
+ <book-navigator
30
+ .itemMD=${itemStub}
31
+ .baseHost=${`https://foo.archive.org`}
32
+ .sharedObserver=${sharedObserver || new SharedResizeObserver()}
33
+ .modal=${modalMgr}
34
+ >
35
+ <div slot="main">
36
+ <div id="BookReader"></div>
37
+ <p class="visible-in-reader">now showing</p>
38
+ <\div>
39
+ </book-navigator>
40
+ `;
41
+ };
42
+
43
+ window.ResizeObserver = class ResizeObserver {
44
+ observe = sinon.fake()
45
+ unobserve = sinon.fake()
46
+ disconnect = sinon.fake()
47
+ };
48
+
49
+ beforeEach(() => {
50
+ window.archive_analytics = {
51
+ send_event_no_sampling: sinon.fake(),
52
+ send_event: sinon.fake()
53
+ };
54
+ });
55
+
56
+ afterEach(() => {
57
+ window.br = null;
58
+ fixtureCleanup();
59
+ const body = document.querySelector('body');
60
+ body.innerHTML = '';
61
+ sinon.restore();
62
+ });
63
+
64
+
65
+ describe('<book-navigator>', () => {
66
+ describe("How it loads", () => {
67
+ describe('Attaches BookReader listeners before `br.init` is called', () => {
68
+ test('binds global event listeners', async () => {
69
+ const el = fixtureSync(container());
70
+ const spy = sinon.spy(el, 'bindEventListeners');
71
+ await elementUpdated(el);
72
+ expect(spy.callCount).toEqual(1);
73
+ });
74
+ test('Listens for Global Event @BookReader:PostInit', async () => {
75
+ const brStub = {
76
+ resize: sinon.fake(),
77
+ currentIndex: sinon.fake(),
78
+ jumpToIndex: sinon.fake(),
79
+ options: { enableMultipleBooks: false }, // for multipleBooks
80
+ el: '#BookReader',
81
+ refs: {}
82
+ };
83
+
84
+ const sharedObserver = new SharedResizeObserver();
85
+ sinon.spy(sharedObserver, 'addObserver');
86
+ const el = fixtureSync(container(sharedObserver));
87
+
88
+ el.initializeBookSubmenus = sinon.fake();
89
+ el.emitLoadingStatusUpdate = sinon.fake();
90
+ el.handleResize = sinon.fake();
91
+ await elementUpdated(el);
92
+
93
+ expect(brStub.resize.callCount).toEqual(0);
94
+
95
+ window.dispatchEvent(new CustomEvent('BookReader:PostInit', {
96
+ detail: { props: brStub }
97
+ }));
98
+ await elementUpdated(el);
99
+
100
+ expect(el.emitLoadingStatusUpdate.callCount).toEqual(1);
101
+ expect(el.bookreader).toEqual(brStub); // sets bookreader
102
+ expect(el.bookReaderLoaded).toBeTruthy(); // notes bookreader is loaded
103
+ expect(el.bookReaderCannotLoad).toBeFalsy();
104
+ expect(sharedObserver.addObserver.callCount).toEqual(1);
105
+
106
+ await promise0();
107
+
108
+ expect(brStub.resize.callCount > 0).toBeTruthy();
109
+ });
110
+ });
111
+ test('Emits a BrBookNav:PostInit event at completion', async () => {
112
+ let initEventFired = false;
113
+ window.addEventListener('BrBookNav:PostInit', (e) => {
114
+ initEventFired = true;
115
+ });
116
+ const el = fixtureSync(container());
117
+ const spy = sinon.spy(el, 'emitPostInit');
118
+
119
+ await elementUpdated(el);
120
+
121
+ expect(initEventFired).toBeTruthy();
122
+ expect(spy.callCount).toEqual(1);
123
+ });
124
+
125
+ test('creates an item image from metadata', async () => {
126
+ const el = fixtureSync(container());
127
+ const itemImage = fixtureSync(el.itemImage);
128
+ expect(itemImage).toBeInstanceOf(HTMLImageElement);
129
+ expect(itemImage.getAttribute('class')).toEqual('cover-img');
130
+ expect(itemImage.getAttribute('src')).toEqual('https://https://foo.archive.org/services/img/foo');
131
+ });
132
+ });
133
+ describe('Menu/Layer Provider', () => {
134
+ describe('Connecting with a provider:', () => {
135
+ // loads Providers with base shared resources
136
+ test('We load 3 Sub Menus by default', async() => {
137
+ const el = fixtureSync(container());
138
+ const $brContainer = document.createElement('div');
139
+ const brStub = {
140
+ resize: sinon.fake(),
141
+ currentIndex: sinon.fake(),
142
+ jumpToIndex: sinon.fake(),
143
+ options: {},
144
+ refs: {
145
+ $brContainer
146
+ }
147
+ };
148
+ el.bookreader = brStub;
149
+ await el.elementUpdated;
150
+
151
+ el.initializeBookSubmenus();
152
+ await el.elementUpdated;
153
+ const defaultMenus = Object.keys(el.menuProviders);
154
+ expect(defaultMenus).toContain('downloads');
155
+ expect(el.menuProviders.downloads).toBeInstanceOf(DownloadsProvider);
156
+
157
+ expect(defaultMenus).toContain('share');
158
+ expect(el.menuProviders.share).toBeInstanceOf(SharingProvider);
159
+
160
+ expect(defaultMenus).toContain('visualAdjustments');
161
+ expect(el.menuProviders.visualAdjustments).toBeInstanceOf(VisualAdjustmentsProvider);
162
+ });
163
+ describe('Loading Sub Menus By Plugin Flags', () => {
164
+ test('Search: uses `enableSearch` flag', async() => {
165
+ const el = fixtureSync(container());
166
+ const $brContainer = document.createElement('div');
167
+ const brStub = {
168
+ resize: sinon.fake(),
169
+ currentIndex: sinon.fake(),
170
+ jumpToIndex: sinon.fake(),
171
+ options: { enableSearch: true },
172
+ refs: {
173
+ $brContainer
174
+ }
175
+ };
176
+ el.bookreader = brStub;
177
+ await el.elementUpdated;
178
+
179
+ el.initializeBookSubmenus();
180
+ await el.elementUpdated;
181
+
182
+ expect(el.menuProviders.search).toBeDefined();
183
+ expect(el.menuProviders.search).toBeInstanceOf(SearchProvider);
184
+
185
+ // also adds a menu shortcut
186
+ expect(el.menuShortcuts.find(m => m.id === 'search')).toBeDefined();
187
+ });
188
+ test('Volumes/Multiple Books: uses `enableMultipleBooks` flag', async() => {
189
+ const el = fixtureSync(container());
190
+ const $brContainer = document.createElement('div');
191
+ const brStub = {
192
+ resize: sinon.fake(),
193
+ currentIndex: sinon.fake(),
194
+ jumpToIndex: sinon.fake(),
195
+ options: {
196
+ enableMultipleBooks: true,
197
+ multipleBooksList: {
198
+ by_subprefix: {
199
+ fooSubprefix: 'beep'
200
+ }
201
+ }
202
+ },
203
+ refs: {
204
+ $brContainer
205
+ }
206
+ };
207
+ el.bookreader = brStub;
208
+ await el.elementUpdated;
209
+
210
+ el.initializeBookSubmenus();
211
+ await el.elementUpdated;
212
+
213
+ expect(el.menuProviders.volumes).toBeDefined();
214
+ expect(el.menuProviders.volumes).toBeInstanceOf(VolumesProvider);
215
+
216
+ // also adds a menu shortcut
217
+ expect(el.menuShortcuts.find(m => m.id === 'volumes')).toBeDefined();
218
+ });
219
+ });
220
+ test('keeps track of base shared resources for providers in: `baseProviderConfig`', () => {
221
+ const el = fixtureSync(container());
222
+ const baseConfigKeys = Object.keys(el.baseProviderConfig);
223
+ expect(baseConfigKeys).toContain('baseHost');
224
+ expect(baseConfigKeys).toContain('modal');
225
+ expect(baseConfigKeys).toContain('sharedObserver');
226
+ expect(baseConfigKeys).toContain('bookreader');
227
+ expect(baseConfigKeys).toContain('item');
228
+ expect(baseConfigKeys).toContain('signedIn');
229
+ expect(baseConfigKeys).toContain('isAdmin');
230
+ expect(baseConfigKeys).toContain('onProviderChange');
231
+ });
232
+ });
233
+
234
+ describe('Controlling Menu Side Panel & Shortcuts', () => {
235
+ describe('Side Menu Panels', () => {
236
+ test('`isWideEnoughToOpenMenu` checks if menu should be open', async () => {
237
+ const el = fixtureSync(container());
238
+ el.brWidth = 300;
239
+ await el.elementUpdated;
240
+
241
+ expect(el.isWideEnoughToOpenMenu).toEqual(false);
242
+
243
+ el.brWidth = 641;
244
+ await el.elementUpdated;
245
+
246
+ expect(el.isWideEnoughToOpenMenu).toEqual(true);
247
+ });
248
+ describe('Control which side menu to toggle open by using: `this.updateSideMenu`', () => {
249
+ test('Emits `@updateSideMenu` to signal which menu gets the update', async () => {
250
+ const el = fixtureSync(container());
251
+ const brStub = {
252
+ resize: sinon.fake(),
253
+ currentIndex: sinon.fake(),
254
+ jumpToIndex: sinon.fake(),
255
+ options: { enableMultipleBooks: true },
256
+ refs: {},
257
+ };
258
+ el.bookreader = brStub;
259
+ await elementUpdated(el);
260
+
261
+ let initEventFired = false;
262
+ let eventDetails = {};
263
+ el.addEventListener('updateSideMenu', (e) => {
264
+ eventDetails = e.detail;
265
+ initEventFired = true;
266
+ });
267
+
268
+ el.updateSideMenu('foo', 'open');
269
+ expect(initEventFired).toEqual(true);
270
+ expect(eventDetails.menuId).toEqual('foo');
271
+ expect(eventDetails.action).toEqual('open');
272
+ });
273
+ test('Will Not Emit `@updateSideMenu` if menu ID is missing', async() => {
274
+ const el = fixtureSync(container());
275
+ const brStub = {
276
+ resize: sinon.fake(),
277
+ currentIndex: sinon.fake(),
278
+ jumpToIndex: sinon.fake(),
279
+ options: { enableMultipleBooks: true },
280
+ refs: {},
281
+ };
282
+ el.bookreader = brStub;
283
+ await elementUpdated(el);
284
+
285
+ let initEventFired = false;
286
+ el.addEventListener('updateSideMenu', (e) => {
287
+ initEventFired = true;
288
+ });
289
+
290
+ el.updateSideMenu('', 'open');
291
+ expect(initEventFired).toEqual(false);
292
+ });
293
+ });
294
+ });
295
+
296
+ describe('Shortcuts', () => {
297
+ test('has specific order of menu shortcuts to show', () => {
298
+ const el = fixtureSync(container());
299
+ expect(el.shortcutOrder[0]).toEqual('fullscreen');
300
+ expect(el.shortcutOrder[1]).toEqual('volumes');
301
+ expect(el.shortcutOrder[2]).toEqual('search');
302
+ expect(el.shortcutOrder[3]).toEqual('bookmarks');
303
+ });
304
+ });
305
+
306
+ describe('Behaviors for specific menus', () => {
307
+ describe('Search menu - ref: plugin.search.js', () => {
308
+ test('Event: listens for `BookReader:ToggleSearchMenu to open search side panel', async () => {
309
+ const el = fixtureSync(container());
310
+ const brStub = {
311
+ resize: sinon.fake(),
312
+ currentIndex: sinon.fake(),
313
+ jumpToIndex: sinon.fake(),
314
+ options: { enableMultipleBooks: true },
315
+ refs: {},
316
+ };
317
+ el.bookreader = brStub;
318
+ await elementUpdated(el);
319
+
320
+ let sidePanelConfig = {};
321
+ el.addEventListener('updateSideMenu', (e) => {
322
+ console.log();
323
+ sidePanelConfig = e.detail;
324
+ });
325
+ const toggleSearchMenuEvent = new Event('BookReader:ToggleSearchMenu');
326
+ window.dispatchEvent(toggleSearchMenuEvent);
327
+
328
+ await elementUpdated(el);
329
+ expect(sidePanelConfig.menuId).toEqual('search');
330
+ expect(sidePanelConfig.action).toEqual('toggle');
331
+ });
332
+ });
333
+ });
334
+ });
335
+ });
336
+
337
+ describe('Resizing',() => {
338
+ test('keeps track of `brWidth` and `brHeight`', async () => {
339
+ const el = fixtureSync(container());
340
+ const brStub = {
341
+ resize: sinon.fake(),
342
+ options: {},
343
+ refs: {
344
+ $brContainer: document.createElement('div')
345
+ }
346
+ };
347
+ el.bookreader = brStub;
348
+ await elementUpdated(el);
349
+ expect(el.brWidth).toEqual(0);
350
+ expect(el.brHeight).toEqual(0);
351
+
352
+ const mockResizeEvent = {
353
+ contentRect: {
354
+ height: 500,
355
+ width: 900
356
+ },
357
+ target: el.mainBRContainer
358
+ };
359
+ el.handleResize(mockResizeEvent);
360
+
361
+ await elementUpdated(el);
362
+ await promise0();
363
+
364
+ expect(el.brHeight).toEqual(500);
365
+ expect(el.brWidth).toEqual(900);
366
+ });
367
+ test('resizes if height/width changes && is not animating', async () => {
368
+ const el = fixtureSync(container());
369
+ const brStub = {
370
+ animating: false,
371
+ resize: sinon.fake(),
372
+ options: {},
373
+ refs: {
374
+ $brContainer: document.createElement('div')
375
+ }
376
+ };
377
+
378
+ el.bookreader = brStub;
379
+ await elementUpdated(el);
380
+ expect(el.brWidth).toEqual(0);
381
+ expect(el.brHeight).toEqual(0);
382
+
383
+ const mockResizeEvent = {
384
+ contentRect: {
385
+ height: 500,
386
+ width: 900
387
+ },
388
+ target: el.mainBRContainer
389
+ };
390
+ el.handleResize(mockResizeEvent);
391
+
392
+ await elementUpdated(el);
393
+ await promise0();
394
+
395
+ expect(brStub.resize.callCount).toEqual(1);
396
+ });
397
+ test('does not resize bookreader if animating', async () => {
398
+ const el = fixtureSync(container());
399
+ const brStub = {
400
+ animating: true, // <-- testing for this
401
+ resize: sinon.fake(),
402
+ currentIndex: sinon.fake(),
403
+ jumpToIndex: sinon.fake(),
404
+ options: { enableMultipleBooks: true },
405
+ refs: {},
406
+ };
407
+
408
+ el.bookreader = brStub;
409
+ await elementUpdated(el);
410
+
411
+ expect(el.bookreader.resize.callCount).toEqual(0);
412
+ expect(el.bookreader.currentIndex.callCount).toEqual(0);
413
+ expect(el.bookreader.jumpToIndex.callCount).toEqual(0);
414
+ });
415
+ });
416
+
417
+ describe('Fullscreen Management', () => {
418
+ test('needs option: `enableFSLogoShortcut` to use FS logo', async () => {
419
+ const el = fixtureSync(container());
420
+ const brStub = {
421
+ isFullscreen: () => true,
422
+ options: {
423
+ enableFSLogoShortcut: false,
424
+ },
425
+ refs: {},
426
+ };
427
+
428
+ el.bookreader = brStub;
429
+ el.emitMenuShortcutsUpdated = sinon.fake();
430
+ await elementUpdated(el);
431
+
432
+ el.manageFullScreenBehavior();
433
+ await elementUpdated(el);
434
+ expect(el.menuShortcuts.length).toEqual(0);
435
+ });
436
+ test('sets fullscreen shortcut when entering Fullscreen', async () => {
437
+ const el = fixtureSync(container());
438
+ const brStub = {
439
+ isFullscreen: () => true,
440
+ options: {
441
+ enableFSLogoShortcut: true,
442
+ },
443
+ refs: {},
444
+ };
445
+
446
+ el.bookreader = brStub;
447
+ el.emitMenuShortcutsUpdated = sinon.fake();
448
+ await elementUpdated(el);
449
+
450
+ el.manageFullScreenBehavior();
451
+ await elementUpdated(el);
452
+ expect(el.menuShortcuts.length).toEqual(1);
453
+ expect(el.menuShortcuts[0].id).toEqual('fullscreen');
454
+ expect(el.menuShortcuts[0].icon).toBeDefined();
455
+ expect(el.emitMenuShortcutsUpdated.callCount).toEqual(1);
456
+ });
457
+ test('clicking Fullscreen shortcut closes fullscreen', async () => {
458
+ const el = fixtureSync(container());
459
+ const brStub = {
460
+ isFullscreen: () => true,
461
+ options: {
462
+ enableFSLogoShortcut: true,
463
+ },
464
+ refs: {},
465
+ };
466
+
467
+ el.bookreader = brStub;
468
+ el.emitMenuShortcutsUpdated = sinon.fake();
469
+ el.closeFullscreen = sinon.fake();
470
+ await elementUpdated(el);
471
+
472
+ el.manageFullScreenBehavior();
473
+ await elementUpdated(el);
474
+
475
+ fixtureSync(el.menuShortcuts[0].icon).click();
476
+ await elementUpdated(el);
477
+
478
+ expect(el.closeFullscreen.callCount).toEqual(1);
479
+ });
480
+ test('removes Fullscreen shortcut when leaving fullscreen', async() => {
481
+ const el = fixtureSync(container());
482
+ const brStub = {
483
+ isFullscreen: () => false,
484
+ options: {
485
+ enableFSLogoShortcut: true,
486
+ },
487
+ refs: {},
488
+ };
489
+
490
+ el.bookreader = brStub;
491
+ el.emitMenuShortcutsUpdated = sinon.fake();
492
+ await elementUpdated(el);
493
+
494
+ el.manageFullScreenBehavior();
495
+ await elementUpdated(el);
496
+ expect(el.menuShortcuts.length).toEqual(0);
497
+ expect(el.emitMenuShortcutsUpdated.callCount).toEqual(1);
498
+ });
499
+ test('Event: Listens for `BookReader:FullscreenToggled', async() => {
500
+ const el = fixtureSync(container());
501
+ const brStub = {
502
+ isFullscreen: () => true,
503
+ resize: sinon.fake(),
504
+ currentIndex: sinon.fake(),
505
+ jumpToIndex: sinon.fake(),
506
+ options: {
507
+ enableFSLogoShortcut: true,
508
+ },
509
+ refs: {},
510
+ };
511
+ el.bookreader = brStub;
512
+ el.manageFullScreenBehavior = sinon.fake();
513
+ await elementUpdated(el);
514
+
515
+ window.dispatchEvent(new CustomEvent('BookReader:fullscreenToggled', {
516
+ detail: { props: brStub }
517
+ }));
518
+ await elementUpdated(el);
519
+
520
+ expect(el.manageFullScreenBehavior.callCount).toEqual(1);
521
+ });
522
+ });
523
+ describe('Handles Restricted Books', () => {
524
+ describe('contextMenu is prevented when book is restricted', () => {
525
+ it('watches on `div.BRscreen`', async () => {
526
+ const el = fixtureSync(container());
527
+ const brStub = {
528
+ options: { restricted: true },
529
+ };
530
+
531
+ el.bookreader = brStub;
532
+ el.bookIsRestricted = true;
533
+
534
+ const elSpy = sinon.spy(el.manageContextMenuVisibility);
535
+ await el.elementUpdated;
536
+
537
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(false);
538
+ expect(window.archive_analytics.send_event.called).toEqual(false);
539
+ expect(elSpy.called).toEqual(false);
540
+
541
+ const body = document.querySelector('body');
542
+
543
+ const divBRscreen = document.createElement('div');
544
+ divBRscreen.classList.add('BRscreen');
545
+ body.appendChild(divBRscreen);
546
+
547
+ const contextMenuEvent = new Event('contextmenu', { bubbles: true });
548
+
549
+ // Set spy on contextMenuEvent to check if `preventDefault` is called
550
+ const preventDefaultSpy = sinon.spy(contextMenuEvent, 'preventDefault');
551
+ expect(preventDefaultSpy.called).toEqual(false);
552
+
553
+ divBRscreen.dispatchEvent(contextMenuEvent);
554
+
555
+ // analytics fires
556
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
557
+ false
558
+ );
559
+ expect(window.archive_analytics.send_event.called).toEqual(true);
560
+ // we prevent default
561
+ expect(preventDefaultSpy.called).toEqual(true);
562
+ });
563
+ it('watches on `img.BRpageimage`', async () => {
564
+ const el = fixtureSync(container());
565
+ const brStub = {
566
+ options: { restricted: true },
567
+ };
568
+
569
+ el.bookreader = brStub;
570
+ el.bookIsRestricted = true;
571
+
572
+ await el.elementUpdated;
573
+
574
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(false);
575
+ expect(window.archive_analytics.send_event.called).toEqual(false);
576
+
577
+ const body = document.querySelector('body');
578
+ // const element stub for img.BRpageimage
579
+ const imgBRpageimage = document.createElement('img');
580
+ imgBRpageimage.classList.add('BRpageimage');
581
+ body.appendChild(imgBRpageimage);
582
+ const contextMenuEvent = new Event('contextmenu', { bubbles: true });
583
+
584
+ // Set spy on contextMenuEvent to check if `preventDefault` is called
585
+ const preventDefaultSpy = sinon.spy(contextMenuEvent, 'preventDefault');
586
+ expect(preventDefaultSpy.called).toEqual(false);
587
+
588
+ imgBRpageimage.dispatchEvent(contextMenuEvent);
589
+
590
+ // analytics fires
591
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(false);
592
+ expect(window.archive_analytics.send_event.called).toEqual(true);
593
+ // we prevent default
594
+ expect(preventDefaultSpy.called).toEqual(true);
595
+ });
596
+ });
597
+ it('Allows unrestricted books access to context menu', async () => {
598
+ const el = fixtureSync(container());
599
+ const brStub = {
600
+ options: { restricted: false },
601
+ };
602
+
603
+ el.bookreader = brStub;
604
+ el.bookIsRestricted = false;
605
+
606
+ await el.elementUpdated;
607
+
608
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
609
+ false
610
+ );
611
+ expect(window.archive_analytics.send_event.called).toEqual(false);
612
+
613
+
614
+ const body = document.querySelector('body');
615
+ // const element stub for img.BRpageimage
616
+ const imgBRpageimage = document.createElement('img');
617
+ imgBRpageimage.classList.add('not-targeted-element');
618
+ body.appendChild(imgBRpageimage);
619
+ const contextMenuEvent = new Event('contextmenu', { bubbles: true });
620
+
621
+ // Set spy on contextMenuEvent to check if `preventDefault` is called
622
+ const preventDefaultSpy = sinon.spy(contextMenuEvent, 'preventDefault');
623
+ expect(preventDefaultSpy.called).toEqual(false);
624
+
625
+ imgBRpageimage.dispatchEvent(contextMenuEvent);
626
+
627
+ // analytics fires
628
+ expect(window.archive_analytics.send_event_no_sampling.called).toEqual(false);
629
+ expect(window.archive_analytics.send_event.called).toEqual(true);
630
+ // we do not prevent default
631
+ expect(preventDefaultSpy.called).toEqual(false);
632
+ });
633
+ });
634
+ });
@@ -0,0 +1,43 @@
1
+ import {
2
+ html,
3
+ fixtureSync,
4
+ fixtureCleanup,
5
+ } from '@open-wc/testing-helpers';
6
+ import '@/src/BookNavigator/bookmarks/bookmark-button.js';
7
+ import sinon from 'sinon';
8
+
9
+ afterEach(() => {
10
+ sinon.restore();
11
+ fixtureCleanup();
12
+ });
13
+
14
+ describe('<bookmark-button>', () => {
15
+ test('sets default properties', async () => {
16
+ const el = fixtureSync(html`<bookmark-button></bookmark-button>`);
17
+
18
+ expect(el.side).toBeUndefined();
19
+ expect(el.state).toEqual('hollow');
20
+ });
21
+ test('Event: fires `@bookmarkButtonClicked on click', async () => {
22
+ const el = fixtureSync(html`<bookmark-button></bookmark-button>`);
23
+ let buttonClicked = false;
24
+ el.addEventListener('bookmarkButtonClicked', () => { buttonClicked = true; });
25
+ const eventStub = { preventDefault: sinon.fake()};
26
+ el.handleClick(eventStub);
27
+ await el.updateComplete;
28
+
29
+ expect(buttonClicked).toBeTruthy();
30
+ expect(eventStub.preventDefault.callCount).toEqual(1);
31
+ });
32
+ test('Title: Toggles title between `Add/Remove bookmark`', async () => {
33
+ const el = fixtureSync(html`<bookmark-button></bookmark-button>`);
34
+ expect(el.title).toEqual('Add bookmark');
35
+ expect(el.state).toEqual('hollow');
36
+
37
+ el.state = 'filled';
38
+ await el.updateComplete;
39
+
40
+ expect(el.title).toEqual('Remove bookmark');
41
+ expect(el.state).not.toEqual('hollow');
42
+ });
43
+ });