@internetarchive/bookreader 5.0.0-5 → 5.0.0-50-a1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) 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 +1 -1
  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/close-circle-dark.svg +1 -0
  13. package/BookReader/icons/magnify-minus.svg +1 -1
  14. package/BookReader/icons/magnify-plus.svg +1 -1
  15. package/BookReader/icons/pause.svg +1 -1
  16. package/BookReader/icons/playback-speed.svg +1 -1
  17. package/BookReader/icons/read-aloud.svg +1 -1
  18. package/BookReader/icons/voice.svg +1 -0
  19. package/BookReader/images/BRicons.svg +2 -2
  20. package/BookReader/images/books_graphic.svg +1 -1
  21. package/BookReader/images/icon_book.svg +1 -1
  22. package/BookReader/images/icon_gear.svg +1 -1
  23. package/BookReader/images/icon_info.svg +1 -1
  24. package/BookReader/images/icon_playback-rate.svg +1 -1
  25. package/BookReader/images/icon_search_button.svg +1 -1
  26. package/BookReader/images/icon_share.svg +1 -1
  27. package/BookReader/images/icon_speaker.svg +1 -1
  28. package/BookReader/images/icon_speaker_open.svg +1 -1
  29. package/BookReader/images/marker_chap-off.svg +1 -1
  30. package/BookReader/images/marker_chap-on.svg +1 -1
  31. package/BookReader/images/marker_srch-on.svg +1 -1
  32. package/BookReader/jquery-3.js +2 -0
  33. package/BookReader/jquery-3.js.LICENSE.txt +24 -0
  34. package/BookReader/plugins/plugin.archive_analytics.js +1 -1
  35. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
  36. package/BookReader/plugins/plugin.autoplay.js +1 -1
  37. package/BookReader/plugins/plugin.autoplay.js.map +1 -1
  38. package/BookReader/plugins/plugin.chapters.js +1 -1
  39. package/BookReader/plugins/plugin.chapters.js.map +1 -1
  40. package/BookReader/plugins/plugin.iframe.js +1 -1
  41. package/BookReader/plugins/plugin.iframe.js.map +1 -1
  42. package/BookReader/plugins/plugin.mobile_nav.js +1 -1
  43. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
  44. package/BookReader/plugins/plugin.resume.js +1 -1
  45. package/BookReader/plugins/plugin.resume.js.map +1 -1
  46. package/BookReader/plugins/plugin.search.js +1 -1
  47. package/BookReader/plugins/plugin.search.js.map +1 -1
  48. package/BookReader/plugins/plugin.text_selection.js +1 -1
  49. package/BookReader/plugins/plugin.text_selection.js.map +1 -1
  50. package/BookReader/plugins/plugin.tts.js +1 -1
  51. package/BookReader/plugins/plugin.tts.js.map +1 -1
  52. package/BookReader/plugins/plugin.url.js +1 -1
  53. package/BookReader/plugins/plugin.url.js.map +1 -1
  54. package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
  55. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
  56. package/BookReader/webcomponents-bundle.js +3 -0
  57. package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
  58. package/BookReader/webcomponents-bundle.js.map +1 -0
  59. package/BookReaderDemo/BookReaderDemo.css +14 -1
  60. package/BookReaderDemo/IADemoBr.js +148 -0
  61. package/BookReaderDemo/demo-advanced.html +2 -2
  62. package/BookReaderDemo/demo-autoplay.html +2 -1
  63. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  64. package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
  65. package/BookReaderDemo/demo-fullscreen.html +2 -1
  66. package/BookReaderDemo/demo-iiif.html +2 -1
  67. package/BookReaderDemo/demo-internetarchive.html +84 -17
  68. package/BookReaderDemo/demo-multiple.html +2 -1
  69. package/BookReaderDemo/demo-preview-pages.html +2 -1
  70. package/BookReaderDemo/demo-simple.html +2 -1
  71. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
  72. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  73. package/BookReaderDemo/immersion-1up.html +2 -1
  74. package/BookReaderDemo/immersion-mode.html +2 -1
  75. package/BookReaderDemo/toggle_controls.html +2 -1
  76. package/BookReaderDemo/view_mode.html +2 -1
  77. package/BookReaderDemo/viewmode-cycle.html +2 -3
  78. package/CHANGELOG.md +202 -0
  79. package/README.md +14 -1
  80. package/babel.config.js +18 -0
  81. package/codecov.yml +6 -0
  82. package/index.html +3 -0
  83. package/jsconfig.json +19 -0
  84. package/package.json +66 -56
  85. package/renovate.json +52 -0
  86. package/scripts/preversion.js +4 -1
  87. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  88. package/src/BookNavigator/assets/button-base.js +9 -2
  89. package/src/BookNavigator/assets/ia-logo.js +17 -0
  90. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  91. package/src/BookNavigator/assets/icon_close.js +1 -1
  92. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  93. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  94. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  95. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  96. package/src/BookNavigator/book-navigator.js +583 -0
  97. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  98. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  99. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  100. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  101. package/src/BookNavigator/bookmarks/bookmarks-provider.js +21 -8
  102. package/src/BookNavigator/bookmarks/ia-bookmarks.js +102 -66
  103. package/src/BookNavigator/delete-modal-actions.js +1 -1
  104. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  105. package/src/BookNavigator/downloads/downloads.js +41 -25
  106. package/src/BookNavigator/search/a-search-result.js +18 -13
  107. package/src/BookNavigator/search/search-provider.js +80 -28
  108. package/src/BookNavigator/search/search-results.js +10 -18
  109. package/src/BookNavigator/sharing.js +27 -0
  110. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  111. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  112. package/src/BookNavigator/volumes/volumes-provider.js +114 -0
  113. package/src/BookNavigator/volumes/volumes.js +188 -0
  114. package/src/BookReader/BookModel.js +0 -29
  115. package/src/BookReader/DebugConsole.js +3 -3
  116. package/src/BookReader/DragScrollable.js +233 -0
  117. package/src/BookReader/Mode1Up.js +51 -351
  118. package/src/BookReader/Mode1UpLit.js +441 -0
  119. package/src/BookReader/Mode2Up.js +120 -105
  120. package/src/BookReader/ModeSmoothZoom.js +179 -0
  121. package/src/BookReader/ModeThumb.js +17 -11
  122. package/src/BookReader/Navbar/Navbar.js +10 -36
  123. package/src/BookReader/PageContainer.js +69 -6
  124. package/src/BookReader/ReduceSet.js +1 -1
  125. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  126. package/src/BookReader/options.js +10 -0
  127. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  128. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  129. package/src/BookReader/utils.js +92 -13
  130. package/src/BookReader.js +431 -620
  131. package/src/assets/icons/close-circle-dark.svg +1 -0
  132. package/src/assets/icons/magnify-minus.svg +3 -7
  133. package/src/assets/icons/magnify-plus.svg +3 -7
  134. package/src/assets/icons/voice.svg +1 -0
  135. package/src/css/BookReader.scss +0 -12
  136. package/src/css/_BRComponent.scss +1 -1
  137. package/src/css/_BRmain.scss +19 -24
  138. package/src/css/_BRnav.scss +4 -26
  139. package/src/css/_BRpages.scss +35 -0
  140. package/src/css/_BRsearch.scss +25 -216
  141. package/src/css/_TextSelection.scss +14 -17
  142. package/src/css/_colorbox.scss +2 -2
  143. package/src/css/_controls.scss +17 -5
  144. package/src/css/_icons.scss +6 -0
  145. package/src/ia-bookreader/ia-bookreader.js +224 -0
  146. package/src/plugins/plugin.autoplay.js +4 -4
  147. package/src/plugins/plugin.chapters.js +28 -35
  148. package/src/plugins/plugin.mobile_nav.js +11 -10
  149. package/src/plugins/plugin.resume.js +3 -3
  150. package/src/plugins/plugin.text_selection.js +26 -39
  151. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  152. package/src/plugins/search/plugin.search.js +174 -116
  153. package/src/plugins/search/view.js +63 -179
  154. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  155. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  156. package/src/plugins/tts/PageChunk.js +15 -21
  157. package/src/plugins/tts/PageChunkIterator.js +8 -12
  158. package/src/plugins/tts/WebTTSEngine.js +66 -69
  159. package/src/plugins/tts/plugin.tts.js +92 -109
  160. package/src/plugins/tts/utils.js +0 -9
  161. package/src/plugins/url/UrlPlugin.js +184 -0
  162. package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
  163. package/src/util/manifestGenerator.js +0 -0
  164. package/tests/e2e/README.md +37 -0
  165. package/tests/e2e/autoplay.test.js +2 -2
  166. package/tests/e2e/base.test.js +7 -7
  167. package/tests/e2e/helpers/base.js +9 -3
  168. package/tests/e2e/helpers/debug.js +1 -1
  169. package/tests/e2e/helpers/desktopSearch.js +14 -13
  170. package/tests/e2e/helpers/mobileSearch.js +3 -3
  171. package/tests/e2e/helpers/params.js +17 -0
  172. package/tests/e2e/models/Navigation.js +13 -4
  173. package/tests/e2e/rightToLeft.test.js +4 -5
  174. package/tests/e2e/viewmode.test.js +38 -33
  175. package/tests/jest/BookNavigator/book-navigator.test.js +634 -0
  176. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  177. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  178. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  179. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  180. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  181. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  182. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  183. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +102 -58
  184. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  185. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  186. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
  187. package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
  188. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +34 -14
  189. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
  190. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  191. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  192. package/tests/jest/BookReader/Mode1UpLit.test.js +92 -0
  193. package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +36 -15
  194. package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
  195. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  196. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
  197. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  198. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  199. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  200. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  201. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  202. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  203. package/tests/jest/BookReader/utils.test.js +186 -0
  204. package/tests/jest/BookReader.keyboard.test.js +190 -0
  205. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  206. package/tests/{BookReader.test.js → jest/BookReader.test.js} +18 -37
  207. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  208. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  209. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
  210. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  211. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  212. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  213. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  214. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  215. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
  216. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
  217. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  218. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  219. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  220. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  221. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +1 -1
  222. package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -28
  223. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  224. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
  225. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  226. package/tests/{util → jest/util}/docCookies.test.js +1 -1
  227. package/tests/{util → jest/util}/strings.test.js +1 -1
  228. package/tests/{utils.js → jest/utils.js} +38 -0
  229. package/webpack.config.js +11 -5
  230. package/.babelrc +0 -12
  231. package/.dependabot/config.yml +0 -6
  232. package/.testcaferc.json +0 -5
  233. package/BookReader/bookreader-component-bundle.js +0 -1450
  234. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  235. package/BookReader/bookreader-component-bundle.js.map +0 -1
  236. package/BookReader/jquery-1.10.1.js +0 -2
  237. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  238. package/BookReader/plugins/plugin.menu_toggle.js +0 -2
  239. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  240. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  241. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  242. package/karma.conf.js +0 -23
  243. package/src/BookNavigator/BookModel.js +0 -14
  244. package/src/BookNavigator/BookNavigator.js +0 -438
  245. package/src/BookNavigator/assets/book-loader.js +0 -27
  246. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  247. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  248. package/src/ItemNavigator/ItemNavigator.js +0 -372
  249. package/src/ItemNavigator/providers/sharing.js +0 -29
  250. package/src/Layers/sharing/sharing-provider.js +0 -22
  251. package/src/dragscrollable-br.js +0 -261
  252. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  253. package/src/plugins/plugin.bookmarks.js +0 -50
  254. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  255. package/tests/BookReader/Mode1Up.test.js +0 -164
  256. package/tests/BookReader/utils.test.js +0 -109
  257. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  258. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  259. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  260. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -1,7 +1,7 @@
1
1
 
2
- import BookReader from '../src/BookReader.js';
3
- import '../src/plugins/plugin.resume.js';
4
- import '../src/plugins/plugin.url.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.resume.js';
4
+ import '@/src/plugins/url/plugin.url.js';
5
5
 
6
6
  let br;
7
7
  beforeAll(() => {
@@ -124,7 +124,7 @@ test('has suppressFragmentChange false when init with fragment', () => {
124
124
  test('has suppressFragmentChange false when init with hash fragment', () => {
125
125
  br.getResumeValue = jest.fn(() => null);
126
126
  br.urlReadFragment = jest.fn(() => '');
127
- br.urlReadHashFragment = jest.fn(() => 'mode/1up')
127
+ br.urlReadHashFragment = jest.fn(() => 'mode/1up');
128
128
  br.switchMode = jest.fn();
129
129
  br.options.urlMode = 'history',
130
130
 
@@ -157,39 +157,20 @@ test('does not add q= term to urlMode=hash query string', () => {
157
157
  )).toBe('?name=value');
158
158
  });
159
159
 
160
- test('_getPageURISrcset with 0 page book', () => {
161
- br._models.book.getNumLeafs = jest.fn(() => 0);
162
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
163
- br.init();
164
- expect(br._getPageURISrcset(5, undefined, undefined)).toBe("");
165
- });
166
-
167
- test('_getPageURISrcset with negative index', () => {
168
- br._models.book.getNumLeafs = jest.fn(() => 0);
169
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
170
- br.init();
171
- expect(br._getPageURISrcset(-7, undefined, undefined)).toBe("");
172
- });
173
-
174
- test('_getPageURISrcset with 0 elements in srcset', () => {
175
- br._models.book.getNumLeafs = jest.fn(() => 30);
176
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
177
- br.init();
178
- expect(br._getPageURISrcset(5, 1, undefined)).toBe("");
179
- });
180
-
181
- test('_getPageURISrcset with 2 elements in srcset', () => {
182
- br._models.book.getNumLeafs = jest.fn(() => 30);
183
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
184
- br.init();
185
- expect(br._getPageURISrcset(5, 5, undefined)).toBe("correctURL.png&scale=2 2x, correctURL.png&scale=1 4x");
186
- });
187
-
188
- test('_getPageURISrcset with the most elements in srcset', () => {
189
- br._models.book.getNumLeafs = jest.fn(() => 30);
190
- br._models.book.getPageURI = jest.fn((index, scale, rotate) => "correctURL.png&scale=" + scale);
191
- br.init();
192
- expect(br._getPageURISrcset(5, 35, undefined)).toBe("correctURL.png&scale=16 2x, correctURL.png&scale=8 4x, correctURL.png&scale=4 8x, correctURL.png&scale=2 16x, correctURL.png&scale=1 32x");
160
+ describe('Navigation Bars', () => {
161
+ test('Standard navigation is being used by default', () => {
162
+ br.initNavbar = jest.fn();
163
+ br.options.ui = '';
164
+ br.init();
165
+ expect(br.initNavbar).toHaveBeenCalledTimes(1);
166
+ });
167
+ test('Standard navigation is being used by default - when bookreader is embedded', () => {
168
+ br.initNavbar = jest.fn();
169
+ br.options.ui = 'embed';
170
+ br.init();
171
+ expect(br.initNavbar).toHaveBeenCalledTimes(1);
172
+ expect(br.options.ui).toEqual('embed');
173
+ });
193
174
  });
194
175
 
195
176
  describe('quantizeReduce', () => {
@@ -1,6 +1,6 @@
1
1
  import sinon from 'sinon';
2
- import BookReader from '../../src/BookReader.js';
3
- import '../../src/plugins/plugin.archive_analytics.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.archive_analytics.js';
4
4
 
5
5
  describe('archiveAnalyticsSendEvent', () => {
6
6
  const sendEvent = BookReader.prototype.archiveAnalyticsSendEvent;
@@ -1,6 +1,6 @@
1
1
 
2
- import BookReader from '../../src/BookReader.js';
3
- import '../../src/plugins/plugin.autoplay.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.autoplay.js';
4
4
 
5
5
 
6
6
  let br;
@@ -38,12 +38,12 @@ describe('Plugin: Menu Toggle', () => {
38
38
  });
39
39
  test('autoplay will run without `flipSpeed` parameters', () => {
40
40
  const initialAutoTimer = br.autoTimer;
41
- br.flipFwdToIndex = jest.fn();
41
+ br.next = jest.fn();
42
42
  br.autoStop = jest.fn();
43
43
  br.init();
44
44
  br.autoToggle();
45
45
  // internally referenced functions that fire
46
- expect(br.flipFwdToIndex).toHaveBeenCalledTimes(1);
46
+ expect(br.next).toHaveBeenCalledTimes(1);
47
47
 
48
48
  expect(initialAutoTimer).toBeFalsy();
49
49
  // br.autoTimer changes when autoToggle turns on
@@ -1,8 +1,8 @@
1
1
  import sinon from 'sinon';
2
2
 
3
- import BookReader from '../../src/BookReader.js';
4
- import '../../src/plugins/plugin.mobile_nav.js';
5
- import '../../src/plugins/plugin.chapters.js';
3
+ import BookReader from '@/src/BookReader.js';
4
+ import '@/src/plugins/plugin.mobile_nav.js';
5
+ import '@/src/plugins/plugin.chapters.js';
6
6
 
7
7
  const SAMPLE_TOC = [{
8
8
  "pagenum": "3",
@@ -53,8 +53,9 @@ const SAMPLE_TOC_UNDEF = [
53
53
  "title": "THE COUNTRY AND THE MISSION 2",
54
54
  "pageIndex": undefined,
55
55
  }
56
- ]
56
+ ];
57
57
 
58
+ /** @type {BookReader} */
58
59
  let br;
59
60
  beforeEach(() => {
60
61
  $.ajax = jest.fn().mockImplementation((args) => {
@@ -97,9 +98,7 @@ describe('updateTOCState', () => {
97
98
 
98
99
  beforeEach(() => {
99
100
  window.HTMLElement.prototype.scrollIntoView = sinon.stub();
100
- //Sinon is not used because this function is imported from BookModel with exposeOverrideableMethod()
101
- //which has a getter and setter
102
- br.getPageIndex = (str) => parseFloat(str);
101
+ br.book.getPageIndex = (str) => parseFloat(str);
103
102
  br.init();
104
103
  });
105
104
 
@@ -111,20 +110,20 @@ describe('updateTOCState', () => {
111
110
  test('Only one element has .current-chapter', () => {
112
111
  br.updateTOCState(9, SAMPLE_TOC);
113
112
  expect($('li.BRtable-contents-el.current-chapter').length).toBe(1);
114
- })
113
+ });
115
114
 
116
115
  test('No chapter has .current-chapter if current index is < than any chapter index', () => {
117
116
  br.updateTOCState(1, SAMPLE_TOC);
118
117
  expect($('li.BRtable-contents-el.current-chapter').length).toBe(0);
119
- })
118
+ });
120
119
 
121
120
  test('if current index == chapter index ', () => {
122
121
  br.updateTOCState(17, SAMPLE_TOC);
123
122
  expect($('li.BRtable-contents-el')[1].classList.contains('current-chapter'));
124
- })
123
+ });
125
124
 
126
125
  test('No chapter has .current-chapter if all chapter have undefined pageIndex ', () => {
127
126
  br.updateTOCState(10, SAMPLE_TOC_UNDEF);
128
127
  expect($('li.BRtable-contents-el.current-chapter').length).toBe(0);
129
- })
128
+ });
130
129
  });
@@ -1,7 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
 
3
- import BookReader from '../../src/BookReader.js';
4
- import { _attachEventListeners } from '../../src/plugins/plugin.iframe.js';
3
+ import BookReader from '@/src/BookReader.js';
4
+ import { _attachEventListeners } from '@/src/plugins/plugin.iframe.js';
5
5
 
6
6
  afterEach(() => {
7
7
  sinon.restore();
@@ -1,6 +1,6 @@
1
1
 
2
- import BookReader from '../../src/BookReader.js';
3
- import '../../src/plugins/plugin.mobile_nav.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.mobile_nav.js';
4
4
 
5
5
  /** @type {BookReader} */
6
6
  let br;
@@ -37,7 +37,7 @@ describe('Plugin: Mobile Nav', () => {
37
37
  return function() {
38
38
  callCount++;
39
39
  _super.apply(this, arguments);
40
- }
40
+ };
41
41
  }(BookReader.prototype.initToolbar);
42
42
  const br = new BookReader();
43
43
  br.init();
@@ -47,7 +47,7 @@ describe('Plugin: Mobile Nav', () => {
47
47
  expect($(document.body).hasClass('BRbodyMobileNavEnabled')).toEqual(true);
48
48
  });
49
49
  test('loads the navbar on init', () => {
50
- expect($('#BRmobileMenu')).toHaveLength(1)
50
+ expect($('#BRmobileMenu')).toHaveLength(1);
51
51
  });
52
52
  test('There is a Settings Section', () => {
53
53
  expect($('.BRmobileMenu__settings')).toHaveLength(1);
@@ -60,7 +60,7 @@ describe('Plugin: Mobile Nav', () => {
60
60
  });
61
61
  test('clicking on hamburger opens menu', () => {
62
62
  expect($('html').hasClass('mm-opened')).toEqual(false);
63
- $('.BRmobileHamburger').click();
63
+ $('.BRmobileHamburger').trigger("click");
64
64
  expect($('html').hasClass('mm-opened')).toEqual(true);
65
65
  });
66
66
  });
@@ -1,8 +1,8 @@
1
- import BookReader from '../../src/BookReader.js';
2
- import '../../src/plugins/plugin.resume.js';
1
+ import BookReader from '@/src/BookReader.js';
2
+ import '@/src/plugins/plugin.resume.js';
3
3
 
4
4
  import sinon from 'sinon';
5
- import * as docCookies from '../../src/util/docCookies.js';
5
+ import * as docCookies from '@/src/util/docCookies.js';
6
6
 
7
7
  let br;
8
8
  beforeAll(() => {
@@ -1,7 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
 
3
- import '../../src/BookReader.js';
4
- import { BookreaderWithTextSelection, TextSelectionPlugin, Cache } from '../../src/plugins/plugin.text_selection.js';
3
+ import '@/src/BookReader.js';
4
+ import { BookreaderWithTextSelection, TextSelectionPlugin, Cache } from '@/src/plugins/plugin.text_selection.js';
5
5
 
6
6
 
7
7
  /** @type {BookReader} */
@@ -19,30 +19,32 @@ const FAKE_XML_5COORDS = `<OBJECT data="file://localhost//tmp/derive/goodytwosho
19
19
  const FAKE_XML_EMPTY = '';
20
20
 
21
21
  describe("Generic tests", () => {
22
- let br;
23
- beforeEach(() => {
24
- document.body.innerHTML = '<div id="BookReader">';
25
- br = new BookreaderWithTextSelection({
26
- data: [
27
- [
28
- { width: 800, height: 1200,
29
- uri: '//archive.org/download/BookReader/img/page001.jpg' },
30
- ],
31
- [
32
- { width: 800, height: 1200,
33
- uri: '//archive.org/download/BookReader/img/page002.jpg' },
34
- { width: 800, height: 1200,
35
- uri: '//archive.org/download/BookReader/img/page003.jpg' },
36
- ],
37
- [
38
- { width: 800, height: 1200,
39
- uri: '//archive.org/download/BookReader/img/page004.jpg' },
40
- { width: 800, height: 1200,
41
- uri: '//archive.org/download/BookReader/img/page005.jpg' },
42
- ]
22
+ document.body.innerHTML = '<div id="BookReader">';
23
+ const br = new BookreaderWithTextSelection({
24
+ data: [
25
+ [
26
+ { width: 800, height: 1200,
27
+ uri: '//archive.org/download/BookReader/img/page001.jpg' },
43
28
  ],
44
- });
45
- br.init();
29
+ [
30
+ { width: 800, height: 1200,
31
+ uri: '//archive.org/download/BookReader/img/page002.jpg' },
32
+ { width: 800, height: 1200,
33
+ uri: '//archive.org/download/BookReader/img/page003.jpg' },
34
+ ],
35
+ [
36
+ { width: 800, height: 1200,
37
+ uri: '//archive.org/download/BookReader/img/page004.jpg' },
38
+ { width: 800, height: 1200,
39
+ uri: '//archive.org/download/BookReader/img/page005.jpg' },
40
+ ]
41
+ ],
42
+ });
43
+ br.init();
44
+
45
+ afterEach(() => {
46
+ sinon.restore();
47
+ $('.textSelectionSVG').remove();
46
48
  });
47
49
 
48
50
  test("_createPageContainer overridden function still creates a BRpagecontainer element", () => {
@@ -72,8 +74,8 @@ describe("Generic tests", () => {
72
74
  const $container = br.refs.$brContainer;
73
75
  sinon.stub(br.textSelectionPlugin, "getPageText")
74
76
  .returns($(new DOMParser().parseFromString(FAKE_XML_1WORD, "text/xml")));
75
- const pageIndex = br.data.length - 1
76
- await br.textSelectionPlugin.createTextLayer(pageIndex, $container);
77
+ const pageIndex = br.data.length - 1;
78
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: pageIndex, width: 100, height: 100 }});
77
79
  expect($container.find(".textSelectionSVG").length).toBe(1);
78
80
  expect($container.find(".BRparagElement").length).toBe(1);
79
81
  });
@@ -83,17 +85,7 @@ describe("Generic tests", () => {
83
85
  const xml = FAKE_XML_1WORD.replace(/<WORD.*<\/WORD>/, FAKE_XML_1WORD.match(/<WORD.*<\/WORD>/)[0].repeat(3000));
84
86
  sinon.stub(br.textSelectionPlugin, "getPageText")
85
87
  .returns($(new DOMParser().parseFromString(xml, "text/xml")));
86
- await br.textSelectionPlugin.createTextLayer(0, $container);
87
- expect($container.find(".textSelectionSVG").length).toBe(0);
88
- expect($container.find(".BRparagElement").length).toBe(0);
89
- expect($container.find(".BRwordElement").length).toBe(0);
90
- });
91
-
92
- // GRRRR!!! This is a useful test :( But can't get it working for some reason,
93
- // and the error output is super cryptic.
94
- test.skip("createTextLayer will not create text layer if index is more than total number of book pages", async () => {
95
- const $container = br.refs.$brContainer;
96
- await br.textSelectionPlugin.createTextLayer(150, $container);
88
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: 0, width: 100, height: 100 }});
97
89
  expect($container.find(".textSelectionSVG").length).toBe(0);
98
90
  expect($container.find(".BRparagElement").length).toBe(0);
99
91
  expect($container.find(".BRwordElement").length).toBe(0);
@@ -103,7 +95,7 @@ describe("Generic tests", () => {
103
95
  const $container = br.refs.$brContainer;
104
96
  sinon.stub(br.textSelectionPlugin, "getPageText")
105
97
  .returns($(new DOMParser().parseFromString(FAKE_XML_1WORD, "text/xml")));
106
- await br.textSelectionPlugin.createTextLayer(1, $container);
98
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: 1, width: 100, height: 100 }});
107
99
  expect($container.find(".textSelectionSVG").length).toBe(1);
108
100
  expect($container.find(".BRparagElement").length).toBe(1);
109
101
  expect($container.find(".BRwordElement").length).toBe(1);
@@ -114,7 +106,7 @@ describe("Generic tests", () => {
114
106
  const $container = br.refs.$brContainer;
115
107
  sinon.stub(br.textSelectionPlugin, "getPageText")
116
108
  .returns($(new DOMParser().parseFromString(FAKE_XML_MULT_WORDS, "text/xml")));
117
- await br.textSelectionPlugin.createTextLayer(2, $container);
109
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: 2, width: 100, height: 100 }});
118
110
  expect($container.find(".textSelectionSVG").length).toBe(1);
119
111
  expect($container.find(".BRparagElement").length).toBe(1);
120
112
  expect($container.find(".BRwordElement").length).toBe(5);
@@ -125,7 +117,7 @@ describe("Generic tests", () => {
125
117
  const $container = br.refs.$brContainer;
126
118
  sinon.stub(br.textSelectionPlugin, "getPageText")
127
119
  .returns($(new DOMParser().parseFromString(FAKE_XML_5COORDS, "text/xml")));
128
- await br.textSelectionPlugin.createTextLayer(3, $container);
120
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: 3, width: 100, height: 100 }});
129
121
  expect($container.find(".textSelectionSVG").length).toBe(1);
130
122
  expect($container.find(".BRparagElement").length).toBe(1);
131
123
  expect($container.find(".BRwordElement").length).toBe(1);
@@ -135,7 +127,7 @@ describe("Generic tests", () => {
135
127
  const $container = br.refs.$brContainer;
136
128
  sinon.stub(br.textSelectionPlugin, "getPageText")
137
129
  .returns($(new DOMParser().parseFromString(FAKE_XML_EMPTY, "text/xml")));
138
- await br.textSelectionPlugin.createTextLayer(4, $container);
130
+ await br.textSelectionPlugin.createTextLayer({ $container, page: { index: 4, width: 100, height: 100 }});
139
131
  expect($container.find(".textSelectionSVG").length).toBe(1);
140
132
  expect($container.find(".BRparagElement").length).toBe(0);
141
133
  expect($container.find(".BRwordElement").length).toBe(0);
@@ -146,28 +138,28 @@ describe("Generic tests", () => {
146
138
  const $container = br.refs.$brContainer;
147
139
  br.textSelectionPlugin.stopPageFlip($container);
148
140
  const currIndex = br.currentIndex();
149
- $container.find("BRwordElement").mousedown();
141
+ $container.find("BRwordElement").trigger("mousedown");
150
142
  // Waits for long press
151
143
  setTimeout(() => {
152
- $container.find("BRwordElement").mousedown();
144
+ $container.find("BRwordElement").trigger("mousedown");
153
145
  // Waits for flipping animation
154
146
  setTimeout(() => {
155
147
  expect(br.currentIndex()).toBe(currIndex);
156
148
  }, 2000);
157
149
  }, LONG_PRESS_DURATION);
158
150
  });
159
- })
151
+ });
160
152
 
161
153
  describe("textSelectionPlugin constructor", () => {
162
154
  test("textSelectionPlugin constructor with firefox browser", () => {
163
- const tsp = new TextSelectionPlugin({}, {}, true)
155
+ const tsp = new TextSelectionPlugin({}, {}, true);
164
156
  expect(tsp.djvuPagesPromise).toBe(null);
165
157
  expect(tsp.svgParagraphElement).toBe("g");
166
158
  expect(tsp.svgWordElement).toBe("text");
167
159
  });
168
160
 
169
161
  test("textSelectionPlugin constructor not on firefox browser", () => {
170
- const tsp = new TextSelectionPlugin({}, {}, false)
162
+ const tsp = new TextSelectionPlugin({}, {}, false);
171
163
  expect(tsp.djvuPagesPromise).toBe(null);
172
164
  expect(tsp.svgParagraphElement).toBe("text");
173
165
  expect(tsp.svgWordElement).toBe("tspan");
@@ -1,6 +1,6 @@
1
1
 
2
- import BookReader from '../../src/BookReader.js';
3
- import * as util from '../../src/plugins/plugin.vendor-fullscreen.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import * as util from '@/src/plugins/plugin.vendor-fullscreen.js';
4
4
 
5
5
  let br;
6
6
  beforeEach(() => {
@@ -1,9 +1,9 @@
1
+ import BookReader from '@/src/BookReader.js';
2
+ import '@/src/plugins/plugin.mobile_nav.js';
3
+ import { marshallSearchResults } from '@/src/plugins/search/plugin.search.js';
4
+ import { deepCopy } from '../../utils.js';
1
5
 
2
- import BookReader from '../../../src/BookReader.js';
3
- import '../../../src/plugins/plugin.mobile_nav.js';
4
- import '../../../src/plugins/search/plugin.search.js';
5
-
6
- jest.mock('../../../src/plugins/search/view.js');
6
+ jest.mock('@/src/plugins/search/view.js');
7
7
 
8
8
  let br;
9
9
  const namespace = 'BookReader:';
@@ -14,31 +14,33 @@ const triggeredEvents = () => {
14
14
  });
15
15
  };
16
16
 
17
+ const DUMMY_RESULTS = {
18
+ ia: "adventuresofoli00dick",
19
+ q: "child",
20
+ indexed: true,
21
+ page_count: 644,
22
+ body_length: 666,
23
+ leaf0_missing: false,
24
+ matches: [{
25
+ text: 'For a long; time after it was ushered into this world of sorrow and trouble, by the parish surgeon, it remained a matter of considerable doubt wliether the {{{child}}} Avould survi^ e to bear any name at all; in which case it is somewhat more than probable that these memoirs would never have appeared; or, if they had, that being comprised within a couple of pages, they would have possessed the inestimable meiit of being the most concise and faithful specimen of biography, extant in the literature of any age or country.',
26
+ par: [{
27
+ boxes: [{r: 1221, b: 2121, t: 2075, page: 37, l: 1107}],
28
+ b: 2535,
29
+ t: 1942,
30
+ page_width: 1790,
31
+ r: 1598,
32
+ l: 50,
33
+ page_height: 2940,
34
+ page: 37
35
+ }]
36
+ }]
37
+ };
38
+
17
39
  beforeEach(() => {
18
40
  $.ajax = jest.fn().mockImplementation(() => {
19
41
  // return from:
20
42
  // `https://ia800304.us.archive.org/fulltext/inside.php?item_id=adventuresofoli00dick&doc=adventuresofoli00dick&path=/30/items/adventuresofoli00dick&q=child&callback=<serialized jQ CB>`
21
- return Promise.resolve({
22
- ia: "adventuresofoli00dick",
23
- q: "child",
24
- indexed: true,
25
- page_count: 644,
26
- body_length: 666,
27
- leaf0_missing: false,
28
- matches: [{
29
- text: 'For a long; time after it was ushered into this world of sorrow and trouble, by the parish surgeon, it remained a matter of considerable doubt wliether the {{{child}}} Avould survi^ e to bear any name at all; in which case it is somewhat more than probable that these memoirs would never have appeared; or, if they had, that being comprised within a couple of pages, they would have possessed the inestimable meiit of being the most concise and faithful specimen of biography, extant in the literature of any age or country.',
30
- par: [{
31
- boxes: [{r: 1221, b: 2121, t: 2075, page: 37, l: 1107}],
32
- b: 2535,
33
- t: 1942,
34
- page_width: 1790,
35
- r: 1598,
36
- l: 50,
37
- page_height: 2940,
38
- page: 37
39
- }]
40
- }]
41
- });
43
+ return Promise.resolve(deepCopy(DUMMY_RESULTS));
42
44
  });
43
45
 
44
46
  $.fn.trigger = jest.fn();
@@ -46,6 +48,7 @@ beforeEach(() => {
46
48
  br = new BookReader();
47
49
  br.initToolbar = jest.fn();
48
50
  br.showProgressPopup = jest.fn();
51
+ br.searchXHR = jest.fn();
49
52
  });
50
53
 
51
54
  afterEach(() => {
@@ -101,7 +104,7 @@ describe('Plugin: Search', () => {
101
104
  expect(br.search.mock.calls[0][1])
102
105
  .toHaveProperty('goToFirstResult', true);
103
106
  expect(br.search.mock.calls[0][1])
104
- .toHaveProperty('suppressFragmentChange', true);
107
+ .toHaveProperty('suppressFragmentChange', false);
105
108
  });
106
109
 
107
110
  test('calling `search` fires ajax call`', () => {
@@ -116,28 +119,30 @@ describe('Plugin: Search', () => {
116
119
  expect(triggeredEvents()).toContain(`${namespace}SearchStarted`);
117
120
  });
118
121
 
119
- test('SearchCallback event fires when AJAX search returns results', () => {
122
+ test('SearchStarted event fires and should go to first result', () => {
120
123
  br.init();
121
- const dfd = br.search('foo');
122
- return dfd.then(() => {
123
- expect(triggeredEvents()).toContain(`${namespace}SearchCallback`);
124
- });
124
+ br.search('foo', { goToFirstResult: true});
125
+ expect(br.options.goToFirstResult).toBeTruthy();
126
+ });
127
+
128
+ test('SearchCallback event fires when AJAX search returns results', async () => {
129
+ br.init();
130
+ await br.search('foo');
131
+ expect(triggeredEvents()).toContain(`${namespace}SearchCallback`);
125
132
  });
126
133
 
127
- test('SearchCallbackError event fires when AJAX search returns error', () => {
134
+ test('SearchCallbackError event fires when AJAX search returns error', async () => {
128
135
  $.ajax = jest.fn().mockImplementation(() => {
129
136
  return Promise.resolve({
130
137
  error: true,
131
138
  });
132
139
  });
133
140
  br.init();
134
- const dfd = br.search('foo');
135
- return dfd.then(() => {
136
- expect(triggeredEvents()).toContain(`${namespace}SearchCallbackError`);
137
- });
141
+ await br.search('foo');
142
+ expect(triggeredEvents()).toContain(`${namespace}SearchCallbackError`);
138
143
  });
139
144
 
140
- test('SearchCallbackNotIndexed event fires when AJAX search returns false indexed value', () => {
145
+ test('SearchCallbackNotIndexed event fires when AJAX search returns false indexed value', async () => {
141
146
  $.ajax = jest.fn().mockImplementation(() => {
142
147
  return Promise.resolve({
143
148
  matches: [],
@@ -145,22 +150,33 @@ describe('Plugin: Search', () => {
145
150
  });
146
151
  });
147
152
  br.init();
148
- const dfd = br.search('foo');
149
- return dfd.then(() => {
150
- expect(triggeredEvents()).toContain(`${namespace}SearchCallbackBookNotIndexed`);
151
- });
153
+ await br.search('foo');
154
+ expect(triggeredEvents()).toContain(`${namespace}SearchCallbackBookNotIndexed`);
152
155
  });
153
156
 
154
- test('SearchCallbackEmpty event fires when AJAX search returns no matches', () => {
157
+ test('SearchCallbackEmpty event fires when AJAX search returns no matches', async () => {
155
158
  $.ajax = jest.fn().mockImplementation(() => {
156
159
  return Promise.resolve({
157
160
  matches: [],
158
161
  });
159
162
  });
160
163
  br.init();
161
- const dfd = br.search('foo');
162
- return dfd.then(() => {
163
- expect(triggeredEvents()).toContain(`${namespace}SearchCallbackEmpty`);
164
- });
164
+ await br.search('foo');
165
+ expect(triggeredEvents()).toContain(`${namespace}SearchCallbackEmpty`);
166
+ });
167
+ });
168
+
169
+ describe('marshallSearchResults', () => {
170
+ test('Adds match index', () => {
171
+ const results = deepCopy(DUMMY_RESULTS);
172
+ marshallSearchResults(results, x => x.toString());
173
+ expect(results.matches[0]).toHaveProperty('matchIndex', 0);
174
+ expect(results.matches[0].par[0].boxes[0]).toHaveProperty('matchIndex', 0);
175
+ });
176
+
177
+ test('Adds display page number', () => {
178
+ const results = deepCopy(DUMMY_RESULTS);
179
+ marshallSearchResults(results, x => `n${x}`);
180
+ expect(results.matches[0]).toHaveProperty('displayPageNumber', 'n37');
165
181
  });
166
182
  });
@@ -1,8 +1,8 @@
1
1
 
2
- import BookReader from '../../../src/BookReader.js';
3
- import '../../../src/plugins/plugin.mobile_nav.js';
4
- import '../../../src/plugins/search/plugin.search.js';
5
- import '../../../src/plugins/search/view.js';
2
+ import BookReader from '@/src/BookReader.js';
3
+ import '@/src/plugins/plugin.mobile_nav.js';
4
+ import '@/src/plugins/search/plugin.search.js';
5
+ import '@/src/plugins/search/view.js';
6
6
 
7
7
  let br;
8
8
  const namespace = 'BookReader:';
@@ -27,6 +27,27 @@ const results = {
27
27
  }]
28
28
  }]
29
29
  };
30
+ const resultWithScript = {
31
+ ia: "adventuresofoli00dick",
32
+ q: "child",
33
+ indexed: true,
34
+ page_count: 644,
35
+ body_length: 666,
36
+ leaf0_missing: false,
37
+ matches: [{
38
+ text: 'foo bar <script>alert(1);</script> {{{keyword}}} baz',
39
+ par: [{
40
+ boxes: [{r: 1221, b: 2121, t: 2075, page: 37, l: 1107}],
41
+ b: 2535,
42
+ t: 1942,
43
+ page_width: 1790,
44
+ r: 1598,
45
+ l: 50,
46
+ page_height: 2940,
47
+ page: 37
48
+ }]
49
+ }]
50
+ };
30
51
  beforeEach(() => {
31
52
  $.ajax = jest.fn().mockImplementation(() => {
32
53
  // return from:
@@ -63,14 +84,14 @@ describe('View: Plugin: Search', () => {
63
84
 
64
85
  expect(br.searchView.dom.searchNavigation).toBeUndefined();
65
86
 
66
- br.searchView.handleSearchCallback(event, { results, options})
87
+ br.searchView.handleSearchCallback(event, { results, options});
67
88
  expect(br.searchView.dom.searchNavigation).toBeDefined();
68
89
  });
69
90
  test('has controls', () => {
70
91
  br.init();
71
92
  const event = new CustomEvent(`${namespace}SearchCallback`);
72
93
  const options = { goToFirstResult: false };
73
- br.searchView.handleSearchCallback(event, { results, options})
94
+ br.searchView.handleSearchCallback(event, { results, options});
74
95
 
75
96
  const searchResultsNav = document.querySelector('.BRsearch-navigation');
76
97
  expect(searchResultsNav).toBeDefined();
@@ -81,6 +102,14 @@ describe('View: Plugin: Search', () => {
81
102
  expect(searchResultsNav.querySelector('.prev')).toBeDefined();
82
103
  expect(searchResultsNav.querySelector('.next')).toBeDefined();
83
104
  });
105
+ test('disallows xss from search results', () => {
106
+ br.init();
107
+ const event = new CustomEvent(`${namespace}SearchCallback`);
108
+ const options = { goToFirstResult: false };
109
+ br.searchView.handleSearchCallback(event, { results: resultWithScript, options });
110
+
111
+ expect(br.searchView.dom.searchNavigation.parent().html()).not.toContain('<script>alert(1);</script>');
112
+ });
84
113
 
85
114
  describe('Click events handlers', () => {
86
115
  it('triggers custom event when toggling side menu', () => {