@internetarchive/bookreader 5.0.0-6-multiple-files → 5.0.0-60

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 (303) 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 +241 -377
  6. package/BookReader/BookReader.js +2 -21564
  7. package/BookReader/BookReader.js.LICENSE.txt +24 -20
  8. package/BookReader/BookReader.js.map +1 -1
  9. package/BookReader/ia-bookreader-bundle.js +1519 -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/BookReaderJSAutoplay.js +4 -1
  86. package/BookReaderDemo/BookReaderJSSimple.js +1 -0
  87. package/BookReaderDemo/IADemoBr.js +147 -0
  88. package/BookReaderDemo/demo-advanced.html +2 -2
  89. package/BookReaderDemo/demo-autoplay.html +2 -1
  90. package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
  91. package/BookReaderDemo/demo-fullscreen-mobile.html +2 -1
  92. package/BookReaderDemo/demo-fullscreen.html +2 -1
  93. package/BookReaderDemo/demo-iiif.html +2 -1
  94. package/BookReaderDemo/demo-internetarchive.html +84 -17
  95. package/BookReaderDemo/demo-multiple.html +2 -1
  96. package/BookReaderDemo/demo-preview-pages.html +2 -1
  97. package/BookReaderDemo/demo-simple.html +2 -1
  98. package/BookReaderDemo/demo-vendor-fullscreen.html +2 -1
  99. package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
  100. package/BookReaderDemo/immersion-1up.html +2 -1
  101. package/BookReaderDemo/immersion-mode.html +2 -1
  102. package/BookReaderDemo/toggle_controls.html +2 -1
  103. package/BookReaderDemo/view_mode.html +2 -1
  104. package/BookReaderDemo/viewmode-cycle.html +2 -3
  105. package/CHANGELOG.md +246 -0
  106. package/README.md +14 -1
  107. package/babel.config.js +19 -0
  108. package/codecov.yml +6 -0
  109. package/index.html +3 -0
  110. package/jsconfig.json +19 -0
  111. package/netlify.toml +5 -0
  112. package/package.json +70 -59
  113. package/renovate.json +52 -0
  114. package/scripts/preversion.js +4 -1
  115. package/src/BookNavigator/assets/bookmark-colors.js +1 -1
  116. package/src/BookNavigator/assets/button-base.js +9 -2
  117. package/src/BookNavigator/assets/ia-logo.js +17 -0
  118. package/src/BookNavigator/assets/icon_checkmark.js +1 -1
  119. package/src/BookNavigator/assets/icon_close.js +1 -1
  120. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  121. package/src/BookNavigator/assets/{icon_sort_ascending.js → icon_sort_desc.js} +2 -2
  122. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  123. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  124. package/src/BookNavigator/book-navigator.js +585 -0
  125. package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
  126. package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
  127. package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
  128. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
  129. package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
  130. package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
  131. package/src/BookNavigator/delete-modal-actions.js +1 -1
  132. package/src/BookNavigator/downloads/downloads-provider.js +36 -21
  133. package/src/BookNavigator/downloads/downloads.js +41 -25
  134. package/src/BookNavigator/search/search-provider.js +80 -28
  135. package/src/BookNavigator/search/search-results.js +34 -25
  136. package/src/BookNavigator/sharing.js +27 -0
  137. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -10
  138. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +3 -3
  139. package/src/BookNavigator/volumes/volumes-provider.js +88 -53
  140. package/src/BookNavigator/volumes/volumes.js +41 -14
  141. package/src/BookReader/BookModel.js +59 -30
  142. package/src/BookReader/DebugConsole.js +3 -3
  143. package/src/BookReader/DragScrollable.js +233 -0
  144. package/src/BookReader/Mode1Up.js +56 -351
  145. package/src/BookReader/Mode1UpLit.js +391 -0
  146. package/src/BookReader/Mode2Up.js +73 -1318
  147. package/src/BookReader/Mode2UpLit.js +781 -0
  148. package/src/BookReader/ModeCoordinateSpace.js +29 -0
  149. package/src/BookReader/ModeSmoothZoom.js +211 -0
  150. package/src/BookReader/ModeThumb.js +17 -11
  151. package/src/BookReader/Navbar/Navbar.js +10 -36
  152. package/src/BookReader/PageContainer.js +69 -6
  153. package/src/BookReader/ReduceSet.js +1 -1
  154. package/src/BookReader/Toolbar/Toolbar.js +10 -37
  155. package/src/BookReader/events.js +2 -0
  156. package/src/BookReader/options.js +24 -2
  157. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  158. package/src/BookReader/utils/ScrollClassAdder.js +31 -0
  159. package/src/BookReader/utils.js +108 -13
  160. package/src/BookReader.js +480 -825
  161. package/src/assets/icons/close-circle-dark.svg +1 -0
  162. package/src/assets/icons/magnify-minus.svg +3 -7
  163. package/src/assets/icons/magnify-plus.svg +3 -7
  164. package/src/assets/icons/voice.svg +1 -0
  165. package/src/css/BookReader.scss +0 -12
  166. package/src/css/_BRBookmarks.scss +1 -1
  167. package/src/css/_BRComponent.scss +1 -1
  168. package/src/css/_BRmain.scss +33 -24
  169. package/src/css/_BRnav.scss +4 -26
  170. package/src/css/_BRpages.scss +147 -40
  171. package/src/css/_BRsearch.scss +25 -216
  172. package/src/css/_TextSelection.scss +16 -17
  173. package/src/css/_colorbox.scss +2 -2
  174. package/src/css/_controls.scss +17 -5
  175. package/src/css/_icons.scss +7 -1
  176. package/src/ia-bookreader/ia-bookreader.js +224 -0
  177. package/src/plugins/plugin.archive_analytics.js +3 -3
  178. package/src/plugins/plugin.autoplay.js +4 -9
  179. package/src/plugins/plugin.chapters.js +28 -35
  180. package/src/plugins/plugin.mobile_nav.js +11 -10
  181. package/src/plugins/plugin.resume.js +3 -3
  182. package/src/plugins/plugin.text_selection.js +32 -41
  183. package/src/plugins/plugin.vendor-fullscreen.js +4 -4
  184. package/src/plugins/search/plugin.search.js +179 -116
  185. package/src/plugins/search/view.js +63 -179
  186. package/src/plugins/tts/AbstractTTSEngine.js +46 -37
  187. package/src/plugins/tts/FestivalTTSEngine.js +13 -14
  188. package/src/plugins/tts/PageChunk.js +15 -21
  189. package/src/plugins/tts/PageChunkIterator.js +8 -12
  190. package/src/plugins/tts/WebTTSEngine.js +87 -71
  191. package/src/plugins/tts/plugin.tts.js +94 -125
  192. package/src/plugins/tts/utils.js +0 -25
  193. package/src/plugins/url/UrlPlugin.js +193 -0
  194. package/src/plugins/{plugin.url.js → url/plugin.url.js} +45 -16
  195. package/src/util/docCookies.js +21 -2
  196. package/tests/e2e/README.md +37 -0
  197. package/tests/e2e/autoplay.test.js +2 -2
  198. package/tests/e2e/base.test.js +7 -7
  199. package/tests/e2e/helpers/base.js +28 -23
  200. package/tests/e2e/helpers/debug.js +1 -1
  201. package/tests/e2e/helpers/desktopSearch.js +14 -13
  202. package/tests/e2e/helpers/mobileSearch.js +3 -3
  203. package/tests/e2e/helpers/params.js +17 -0
  204. package/tests/e2e/helpers/rightToLeft.js +4 -10
  205. package/tests/e2e/models/Navigation.js +13 -4
  206. package/tests/e2e/rightToLeft.test.js +4 -5
  207. package/tests/e2e/viewmode.test.js +40 -33
  208. package/tests/jest/BookNavigator/book-navigator.test.js +658 -0
  209. package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
  210. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
  211. package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
  212. package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
  213. package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
  214. package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
  215. package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
  216. package/tests/{karma/BookNavigator → jest/BookNavigator/search}/search-results.test.js +104 -60
  217. package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
  218. package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
  219. package/tests/jest/BookNavigator/volumes/volumes-provider.test.js +184 -0
  220. package/tests/jest/BookNavigator/volumes/volumes.test.js +97 -0
  221. package/tests/{BookReader → jest/BookReader}/BookModel.test.js +59 -14
  222. package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +193 -0
  223. package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
  224. package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
  225. package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
  226. package/tests/jest/BookReader/Mode2Up.test.js +98 -0
  227. package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
  228. package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
  229. package/tests/jest/BookReader/ModeSmoothZoom.test.js +175 -0
  230. package/tests/jest/BookReader/ModeThumb.test.js +71 -0
  231. package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +10 -10
  232. package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +88 -6
  233. package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
  234. package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
  235. package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  236. package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
  237. package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
  238. package/tests/jest/BookReader/utils.test.js +217 -0
  239. package/tests/jest/BookReader.keyboard.test.js +190 -0
  240. package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
  241. package/tests/{BookReader.test.js → jest/BookReader.test.js} +26 -37
  242. package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
  243. package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +4 -4
  244. package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +10 -11
  245. package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
  246. package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
  247. package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
  248. package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
  249. package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
  250. package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +63 -47
  251. package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +35 -6
  252. package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +9 -9
  253. package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
  254. package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
  255. package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
  256. package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +47 -1
  257. package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
  258. package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
  259. package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +53 -14
  260. package/tests/jest/setup.js +3 -0
  261. package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
  262. package/tests/jest/util/docCookies.test.js +24 -0
  263. package/tests/{util → jest/util}/strings.test.js +1 -1
  264. package/tests/{utils.js → jest/utils.js} +38 -0
  265. package/webpack.config.js +11 -5
  266. package/.babelrc +0 -12
  267. package/.dependabot/config.yml +0 -6
  268. package/.testcaferc.json +0 -5
  269. package/BookReader/bookreader-component-bundle.js +0 -14312
  270. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
  271. package/BookReader/bookreader-component-bundle.js.map +0 -1
  272. package/BookReader/icons/sort-ascending.svg +0 -1
  273. package/BookReader/icons/sort-descending.svg +0 -1
  274. package/BookReader/jquery-1.10.1.js +0 -108
  275. package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
  276. package/BookReader/plugins/plugin.menu_toggle.js +0 -369
  277. package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
  278. package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
  279. package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
  280. package/karma.conf.js +0 -23
  281. package/src/BookNavigator/BookModel.js +0 -14
  282. package/src/BookNavigator/BookNavigator.js +0 -452
  283. package/src/BookNavigator/assets/book-loader.js +0 -27
  284. package/src/BookNavigator/assets/icon_sort_descending.js +0 -5
  285. package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
  286. package/src/BookNavigator/search/a-search-result.js +0 -55
  287. package/src/BookReaderComponent/BookReaderComponent.js +0 -112
  288. package/src/ItemNavigator/ItemNavigator.js +0 -372
  289. package/src/ItemNavigator/providers/sharing.js +0 -29
  290. package/src/assets/icons/sort-ascending.svg +0 -1
  291. package/src/assets/icons/sort-descending.svg +0 -1
  292. package/src/dragscrollable-br.js +0 -261
  293. package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
  294. package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
  295. package/tests/BookReader/Mode1Up.test.js +0 -164
  296. package/tests/BookReader/Mode2Up.test.js +0 -247
  297. package/tests/BookReader/utils.test.js +0 -109
  298. package/tests/e2e/ia-production/ia-prod-base.js +0 -17
  299. package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
  300. package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
  301. package/tests/karma/BookNavigator/volumes.test.js +0 -101
  302. package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
  303. package/tests/util/docCookies.test.js +0 -15
@@ -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', () => {
@@ -1,12 +1,12 @@
1
1
  import sinon from 'sinon';
2
2
  import { afterEventLoop } from '../../utils.js';
3
- import AbstractTTSEngine from '../../../src/plugins/tts/AbstractTTSEngine.js';
4
- import PageChunkIterator from '../../../src/plugins/tts/PageChunkIterator.js';
5
- /** @typedef {import('../../../src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
3
+ import AbstractTTSEngine from '@/src/plugins/tts/AbstractTTSEngine.js';
4
+ import PageChunkIterator from '@/src/plugins/tts/PageChunkIterator.js';
5
+ /** @typedef {import('@/src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
6
6
 
7
7
  // Skipping because it's flaky. Fix in #672
8
8
  describe.skip('AbstractTTSEngine', () => {
9
- test('stops playing once done', () => {
9
+ test('stops playing once done', async () => {
10
10
  class DummyEngine extends AbstractTTSEngine {
11
11
  getVoices() { return []; }
12
12
  }
@@ -15,12 +15,12 @@ describe.skip('AbstractTTSEngine', () => {
15
15
  const stopStub = sinon.stub(d, 'stop');
16
16
  expect(stopStub.callCount).toBe(0);
17
17
  d.step();
18
- return afterEventLoop()
19
- .then(() => expect(stopStub.callCount).toBe(1));
18
+ await afterEventLoop();
19
+ expect(stopStub.callCount).toBe(1);
20
20
  });
21
21
  });
22
22
 
23
- for (const dummyVoice of [dummyVoice, dummyVoiceUnderscores]) {
23
+ for (const dummyVoice of [dummyVoiceHyphens, dummyVoiceUnderscores]) {
24
24
  describe(`getBestBookVoice with BCP47 ${dummyVoice == dummyVoiceUnderscores ? '+' : '-'} underscores`, () => {
25
25
  const { getBestBookVoice } = AbstractTTSEngine;
26
26
 
@@ -130,7 +130,7 @@ export const DUMMY_TTS_ENGINE_OPTS = {
130
130
  * @param {SpeechSynthesisVoice}
131
131
  * @return {SpeechSynthesisVoice}
132
132
  **/
133
- function dummyVoice(overrides) {
133
+ function dummyVoiceHyphens(overrides) {
134
134
  return Object.assign({
135
135
  default: false,
136
136
  lang: "en-US",
@@ -147,7 +147,7 @@ function dummyVoice(overrides) {
147
147
  * @return {SpeechSynthesisVoice}
148
148
  **/
149
149
  function dummyVoiceUnderscores(overrides) {
150
- const voice = dummyVoice(overrides);
150
+ const voice = dummyVoiceHyphens(overrides);
151
151
  voice.lang = voice.lang.replace('-', '_');
152
152
  return voice;
153
153
  }
@@ -1,10 +1,10 @@
1
- import FestivalTTSEngine from '../../../src/plugins/tts/FestivalTTSEngine.js';
1
+ import FestivalTTSEngine from '@/src/plugins/tts/FestivalTTSEngine.js';
2
2
  import sinon from 'sinon';
3
3
  import { afterEventLoop } from '../../utils.js';
4
4
  import { DUMMY_TTS_ENGINE_OPTS } from './AbstractTTSEngine.test.js';
5
- import PageChunk from '../../../src/plugins/tts/PageChunk.js';
6
- import PageChunkIterator from '../../../src/plugins/tts/PageChunkIterator.js';
7
- /** @typedef {import('../../../src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
5
+ import PageChunk from '@/src/plugins/tts/PageChunk.js';
6
+ import PageChunkIterator from '@/src/plugins/tts/PageChunkIterator.js';
7
+ /** @typedef {import('@/src/plugins/tts/AbstractTTSEngine.js').TTSEngineOptions} TTSEngineOptions */
8
8
 
9
9
  describe('iOSCaptureUserIntentHack', () => {
10
10
  test('synchronously calls createSound/play to capture user intent', () => {
@@ -1,4 +1,4 @@
1
- import PageChunk from '../../../src/plugins/tts/PageChunk.js';
1
+ import PageChunk from '@/src/plugins/tts/PageChunk.js';
2
2
 
3
3
  describe('_fixChunkRects', () => {
4
4
  const { _fixChunkRects } = PageChunk;
@@ -1,6 +1,6 @@
1
1
  import sinon from 'sinon';
2
- import PageChunkIterator from "../../../src/plugins/tts/PageChunkIterator";
3
- import PageChunk from '../../../src/plugins/tts/PageChunk';
2
+ import PageChunkIterator from "@/src/plugins/tts/PageChunkIterator";
3
+ import PageChunk from '@/src/plugins/tts/PageChunk';
4
4
 
5
5
  describe('Buffers pages', () => {
6
6
  test('Does not error if no room for reverse buffer', async () => {
@@ -109,7 +109,7 @@ describe('Iterates pages', () => {
109
109
  expect(iterator._cursor.chunk).toBe(0);
110
110
 
111
111
  for (let i = 2; i >= 0; i--) {
112
- await iterator.decrement()
112
+ await iterator.decrement();
113
113
  expect(iterator._cursor.page).toBe(49);
114
114
  expect(iterator._cursor.chunk).toBe(i);
115
115
  }
@@ -1,5 +1,5 @@
1
1
  import sinon from 'sinon';
2
- import { WebTTSSound } from '../../../src/plugins/tts/WebTTSEngine.js';
2
+ import WebTTSEngine, { WebTTSSound } from '@/src/plugins/tts/WebTTSEngine.js';
3
3
  import { afterEventLoop, eventTargetMixin } from '../../utils.js';
4
4
 
5
5
  beforeEach(() => {
@@ -8,6 +8,7 @@ beforeEach(() => {
8
8
  speak: sinon.stub(),
9
9
  pause: sinon.stub(),
10
10
  resume: sinon.stub(),
11
+
11
12
  ...eventTargetMixin(),
12
13
  };
13
14
  window.SpeechSynthesisUtterance = function (text) {
@@ -21,6 +22,51 @@ afterEach(() => {
21
22
  delete window.SpeechSynthesisUtterance;
22
23
  });
23
24
 
25
+ describe('WebTTSEngine', () => {
26
+ test('getVoices should include default voice when no actual default', () => {
27
+ // iOS devices set all the voices to default -_-
28
+ speechSynthesis.getVoices = () => [
29
+ {
30
+ default: true,
31
+ lang: "ar-001",
32
+ localService: true,
33
+ name: "Majed",
34
+ voiceURI: "com.apple.voice.compact.ar-001.Maged",
35
+ },
36
+ {
37
+ default: true,
38
+ lang: "bg-BG",
39
+ localService: true,
40
+ name: "Daria",
41
+ voiceURI: "com.apple.voice.compact.bg-BG.Daria",
42
+ }
43
+ ];
44
+ const voices = WebTTSEngine.prototype.getVoices();
45
+ expect(voices.length).toBe(3);
46
+ expect(voices[0].voiceURI).toBe('bookreader.SystemDefault');
47
+ });
48
+
49
+ test('getVoices should not include default voice when there is a default', () => {
50
+ speechSynthesis.getVoices = () => [
51
+ {
52
+ default: true,
53
+ lang: "ar-001",
54
+ localService: true,
55
+ name: "Majed",
56
+ voiceURI: "com.apple.voice.compact.ar-001.Maged",
57
+ },
58
+ {
59
+ default: false,
60
+ lang: "bg-BG",
61
+ localService: true,
62
+ name: "Daria",
63
+ voiceURI: "com.apple.voice.compact.bg-BG.Daria",
64
+ }
65
+ ];
66
+ const voices = WebTTSEngine.prototype.getVoices();
67
+ expect(voices.length).toBe(2);
68
+ });
69
+ });
24
70
 
25
71
  describe('WebTTSSound', () => {
26
72
  describe('setPlaybackRate', () => {
@@ -1,38 +1,4 @@
1
- import sinon from 'sinon';
2
- import { afterEventLoop, eventTargetMixin } from '../../utils.js';
3
- import * as utils from '../../../src/plugins/tts/utils.js';
4
-
5
- describe('promisifyEvent', () => {
6
- const { promisifyEvent } = utils;
7
-
8
- test('Resolves once event fires', async () => {
9
- const fakeTarget = eventTargetMixin();
10
- const resolveSpy = sinon.spy();
11
- promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
12
-
13
- await afterEventLoop()
14
- expect(resolveSpy.callCount).toBe(0);
15
- fakeTarget.dispatchEvent('pause', {});
16
- await afterEventLoop();
17
- expect(resolveSpy.callCount).toBe(1);
18
- });
19
-
20
- test('Only resolves once', async () => {
21
- const fakeTarget = eventTargetMixin();
22
- const resolveSpy = sinon.spy();
23
- promisifyEvent(fakeTarget, 'pause').then(resolveSpy);
24
-
25
- await afterEventLoop()
26
- expect(resolveSpy.callCount).toBe(0);
27
- fakeTarget.dispatchEvent('pause', {});
28
- fakeTarget.dispatchEvent('pause', {});
29
- fakeTarget.dispatchEvent('pause', {});
30
- fakeTarget.dispatchEvent('pause', {});
31
-
32
- await afterEventLoop();
33
- expect(resolveSpy.callCount).toBe(1);
34
- });
35
- });
1
+ import * as utils from '@/src/plugins/tts/utils.js';
36
2
 
37
3
  describe('approximateWordCount', () => {
38
4
  const { approximateWordCount } = utils;
@@ -66,31 +32,6 @@ describe('approximateWordCount', () => {
66
32
  });
67
33
  });
68
34
 
69
- describe('sleep', () => {
70
- const { sleep } = utils;
71
-
72
- test('Sleep 0 doest not called immediately', async () => {
73
- const spy = sinon.spy();
74
- sleep(0).then(spy);
75
- expect(spy.callCount).toBe(0);
76
- await afterEventLoop();
77
- expect(spy.callCount).toBe(1);
78
- });
79
-
80
- test('Waits the appropriate ms', async () => {
81
- const clock = sinon.useFakeTimers();
82
- const spy = sinon.spy();
83
- sleep(10).then(spy);
84
- expect(spy.callCount).toBe(0);
85
- clock.tick(10);
86
- expect(spy.callCount).toBe(0);
87
- clock.restore();
88
-
89
- await afterEventLoop();
90
- expect(spy.callCount).toBe(1);
91
- });
92
- });
93
-
94
35
  describe('toISO6391', () => {
95
36
  const { toISO6391 } = utils;
96
37