@internetarchive/bookreader 5.0.0-18

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 (428) hide show
  1. package/.eslintrc.js +58 -0
  2. package/.gitattributes +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug.md +32 -0
  4. package/.github/ISSUE_TEMPLATE/feature-request.md +30 -0
  5. package/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +15 -0
  6. package/.github/dependabot.yml +8 -0
  7. package/.github/workflows/node.js.yml +37 -0
  8. package/.github/workflows/npm-publish.yml +47 -0
  9. package/.testcaferc.json +5 -0
  10. package/BookReader/BookReader.css +2983 -0
  11. package/BookReader/BookReader.js +3 -0
  12. package/BookReader/BookReader.js.LICENSE.txt +117 -0
  13. package/BookReader/BookReader.js.map +1 -0
  14. package/BookReader/bookreader-component-bundle.js +1436 -0
  15. package/BookReader/bookreader-component-bundle.js.LICENSE.txt +27 -0
  16. package/BookReader/bookreader-component-bundle.js.map +1 -0
  17. package/BookReader/icons/1up.svg +1 -0
  18. package/BookReader/icons/2up.svg +1 -0
  19. package/BookReader/icons/advance.svg +3 -0
  20. package/BookReader/icons/chevron-right.svg +1 -0
  21. package/BookReader/icons/close-circle-dark.svg +1 -0
  22. package/BookReader/icons/close-circle.svg +1 -0
  23. package/BookReader/icons/fullscreen.svg +1 -0
  24. package/BookReader/icons/fullscreen_exit.svg +1 -0
  25. package/BookReader/icons/hamburger.svg +1 -0
  26. package/BookReader/icons/left-arrow.svg +1 -0
  27. package/BookReader/icons/magnify-minus.svg +1 -0
  28. package/BookReader/icons/magnify-plus.svg +1 -0
  29. package/BookReader/icons/magnify.svg +1 -0
  30. package/BookReader/icons/pause.svg +1 -0
  31. package/BookReader/icons/play.svg +1 -0
  32. package/BookReader/icons/playback-speed.svg +1 -0
  33. package/BookReader/icons/read-aloud.svg +1 -0
  34. package/BookReader/icons/review.svg +3 -0
  35. package/BookReader/icons/thumbnails.svg +1 -0
  36. package/BookReader/icons/volume-full.svg +1 -0
  37. package/BookReader/images/BRicons.png +0 -0
  38. package/BookReader/images/BRicons.svg +5 -0
  39. package/BookReader/images/BRicons_ia.png +0 -0
  40. package/BookReader/images/back_pages.png +0 -0
  41. package/BookReader/images/book_bottom_icon.png +0 -0
  42. package/BookReader/images/book_down_icon.png +0 -0
  43. package/BookReader/images/book_left_icon.png +0 -0
  44. package/BookReader/images/book_leftmost_icon.png +0 -0
  45. package/BookReader/images/book_right_icon.png +0 -0
  46. package/BookReader/images/book_rightmost_icon.png +0 -0
  47. package/BookReader/images/book_top_icon.png +0 -0
  48. package/BookReader/images/book_up_icon.png +0 -0
  49. package/BookReader/images/books_graphic.svg +1 -0
  50. package/BookReader/images/booksplit.png +0 -0
  51. package/BookReader/images/control_pause_icon.png +0 -0
  52. package/BookReader/images/control_play_icon.png +0 -0
  53. package/BookReader/images/embed_icon.png +0 -0
  54. package/BookReader/images/icon-home-ia.png +0 -0
  55. package/BookReader/images/icon_OL-logo-xs.png +0 -0
  56. package/BookReader/images/icon_alert-xs.png +0 -0
  57. package/BookReader/images/icon_book.svg +1 -0
  58. package/BookReader/images/icon_bookmark.svg +1 -0
  59. package/BookReader/images/icon_close-pop.png +0 -0
  60. package/BookReader/images/icon_download.png +0 -0
  61. package/BookReader/images/icon_gear.svg +1 -0
  62. package/BookReader/images/icon_hamburger.svg +1 -0
  63. package/BookReader/images/icon_home.png +0 -0
  64. package/BookReader/images/icon_home.svg +1 -0
  65. package/BookReader/images/icon_home_ia.png +0 -0
  66. package/BookReader/images/icon_indicator.png +0 -0
  67. package/BookReader/images/icon_info.svg +1 -0
  68. package/BookReader/images/icon_one_page.svg +1 -0
  69. package/BookReader/images/icon_pause.svg +1 -0
  70. package/BookReader/images/icon_play.svg +1 -0
  71. package/BookReader/images/icon_playback-rate.svg +1 -0
  72. package/BookReader/images/icon_return.png +0 -0
  73. package/BookReader/images/icon_search_button.svg +1 -0
  74. package/BookReader/images/icon_share.svg +1 -0
  75. package/BookReader/images/icon_skip-ahead.svg +1 -0
  76. package/BookReader/images/icon_skip-back.svg +2 -0
  77. package/BookReader/images/icon_speaker.svg +1 -0
  78. package/BookReader/images/icon_speaker_open.svg +1 -0
  79. package/BookReader/images/icon_thumbnails.svg +1 -0
  80. package/BookReader/images/icon_toc.svg +1 -0
  81. package/BookReader/images/icon_two_pages.svg +1 -0
  82. package/BookReader/images/icon_zoomer.png +0 -0
  83. package/BookReader/images/loading.gif +0 -0
  84. package/BookReader/images/logo_icon.png +0 -0
  85. package/BookReader/images/marker_chap-off.png +0 -0
  86. package/BookReader/images/marker_chap-off.svg +1 -0
  87. package/BookReader/images/marker_chap-off_ia.png +0 -0
  88. package/BookReader/images/marker_chap-on.png +0 -0
  89. package/BookReader/images/marker_chap-on.svg +1 -0
  90. package/BookReader/images/marker_srch-on.svg +1 -0
  91. package/BookReader/images/marker_srchchap-off.png +0 -0
  92. package/BookReader/images/marker_srchchap-on.png +0 -0
  93. package/BookReader/images/nav_control-dn.png +0 -0
  94. package/BookReader/images/nav_control-dn_ia.png +0 -0
  95. package/BookReader/images/nav_control-up.png +0 -0
  96. package/BookReader/images/nav_control-up_ia.png +0 -0
  97. package/BookReader/images/nav_control.png +0 -0
  98. package/BookReader/images/one_page_mode_icon.png +0 -0
  99. package/BookReader/images/paper-badge.png +0 -0
  100. package/BookReader/images/print_icon.png +0 -0
  101. package/BookReader/images/progressbar.gif +0 -0
  102. package/BookReader/images/right_edges.png +0 -0
  103. package/BookReader/images/slider.png +0 -0
  104. package/BookReader/images/slider_ia.png +0 -0
  105. package/BookReader/images/thumbnail_mode_icon.png +0 -0
  106. package/BookReader/images/transparent.png +0 -0
  107. package/BookReader/images/two_page_mode_icon.png +0 -0
  108. package/BookReader/images/zoom_in_icon.png +0 -0
  109. package/BookReader/images/zoom_out_icon.png +0 -0
  110. package/BookReader/jquery-1.10.1.js +2 -0
  111. package/BookReader/jquery-1.10.1.js.LICENSE.txt +24 -0
  112. package/BookReader/plugins/plugin.archive_analytics.js +2 -0
  113. package/BookReader/plugins/plugin.archive_analytics.js.map +1 -0
  114. package/BookReader/plugins/plugin.autoplay.js +2 -0
  115. package/BookReader/plugins/plugin.autoplay.js.map +1 -0
  116. package/BookReader/plugins/plugin.chapters.js +2 -0
  117. package/BookReader/plugins/plugin.chapters.js.map +1 -0
  118. package/BookReader/plugins/plugin.iframe.js +2 -0
  119. package/BookReader/plugins/plugin.iframe.js.map +1 -0
  120. package/BookReader/plugins/plugin.mobile_nav.js +2 -0
  121. package/BookReader/plugins/plugin.mobile_nav.js.map +1 -0
  122. package/BookReader/plugins/plugin.resume.js +2 -0
  123. package/BookReader/plugins/plugin.resume.js.map +1 -0
  124. package/BookReader/plugins/plugin.search.js +2 -0
  125. package/BookReader/plugins/plugin.search.js.map +1 -0
  126. package/BookReader/plugins/plugin.text_selection.js +2 -0
  127. package/BookReader/plugins/plugin.text_selection.js.map +1 -0
  128. package/BookReader/plugins/plugin.tts.js +3 -0
  129. package/BookReader/plugins/plugin.tts.js.LICENSE.txt +27 -0
  130. package/BookReader/plugins/plugin.tts.js.map +1 -0
  131. package/BookReader/plugins/plugin.url.js +2 -0
  132. package/BookReader/plugins/plugin.url.js.map +1 -0
  133. package/BookReader/plugins/plugin.vendor-fullscreen.js +2 -0
  134. package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -0
  135. package/BookReaderDemo/BookReaderDemo.css +41 -0
  136. package/BookReaderDemo/BookReaderJSAdvanced.js +115 -0
  137. package/BookReaderDemo/BookReaderJSAutoplay.js +56 -0
  138. package/BookReaderDemo/BookReaderJSSimple.js +55 -0
  139. package/BookReaderDemo/IIIFBookReader.js +207 -0
  140. package/BookReaderDemo/assets/v5/Bookreader-logo-cool-grad.svg +1 -0
  141. package/BookReaderDemo/assets/v5/Bookreader-logo-flat.svg +1 -0
  142. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-cool-grad.png +0 -0
  143. package/BookReaderDemo/assets/v5/Bookreader-logo-hex-flat.png +0 -0
  144. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.png +0 -0
  145. package/BookReaderDemo/assets/v5/Bookreader-logo-lines.svg +1 -0
  146. package/BookReaderDemo/assets/v5/Bookreader-logo-warm.svg +1 -0
  147. package/BookReaderDemo/assets/v5/bookreader-logo-renders@1x.png +0 -0
  148. package/BookReaderDemo/assets/v5/bookreader-logo-renders@2x.png +0 -0
  149. package/BookReaderDemo/assets/v5/bookreader-v5-screenshot.png +0 -0
  150. package/BookReaderDemo/bookreader-template-bundle.js +7178 -0
  151. package/BookReaderDemo/demo-advanced.html +32 -0
  152. package/BookReaderDemo/demo-autoplay.html +38 -0
  153. package/BookReaderDemo/demo-embed-iframe-src.html +84 -0
  154. package/BookReaderDemo/demo-embed.html +26 -0
  155. package/BookReaderDemo/demo-fullscreen-mobile.html +36 -0
  156. package/BookReaderDemo/demo-fullscreen.html +33 -0
  157. package/BookReaderDemo/demo-iiif.html +34 -0
  158. package/BookReaderDemo/demo-iiif.js +26 -0
  159. package/BookReaderDemo/demo-internetarchive.html +74 -0
  160. package/BookReaderDemo/demo-multiple.html +43 -0
  161. package/BookReaderDemo/demo-preview-pages.html +1092 -0
  162. package/BookReaderDemo/demo-simple.html +34 -0
  163. package/BookReaderDemo/demo-vendor-fullscreen.html +36 -0
  164. package/BookReaderDemo/immersion-1up.html +64 -0
  165. package/BookReaderDemo/immersion-mode.html +35 -0
  166. package/BookReaderDemo/toggle_controls.html +53 -0
  167. package/BookReaderDemo/view_mode.html +39 -0
  168. package/BookReaderDemo/viewmode-cycle.html +41 -0
  169. package/CHANGELOG.md +540 -0
  170. package/CONTRIBUTING.md +7 -0
  171. package/LICENSE +661 -0
  172. package/README.md +205 -0
  173. package/babel.config.js +18 -0
  174. package/codecov.yml +17 -0
  175. package/index.html +31 -0
  176. package/jsconfig.json +14 -0
  177. package/karma.conf.js +23 -0
  178. package/package.json +129 -0
  179. package/screenshot.png +0 -0
  180. package/scripts/postversion.js +10 -0
  181. package/scripts/preversion.js +14 -0
  182. package/scripts/version.js +26 -0
  183. package/src/BookNavigator/BookModel.js +14 -0
  184. package/src/BookNavigator/BookNavigator.js +468 -0
  185. package/src/BookNavigator/assets/book-loader.js +27 -0
  186. package/src/BookNavigator/assets/bookmark-colors.js +15 -0
  187. package/src/BookNavigator/assets/button-base.js +61 -0
  188. package/src/BookNavigator/assets/icon_checkmark.js +6 -0
  189. package/src/BookNavigator/assets/icon_close.js +3 -0
  190. package/src/BookNavigator/assets/icon_sort_asc.js +5 -0
  191. package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
  192. package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
  193. package/src/BookNavigator/assets/icon_volumes.js +11 -0
  194. package/src/BookNavigator/bookmarks/bookmark-button.js +64 -0
  195. package/src/BookNavigator/bookmarks/bookmark-edit.js +215 -0
  196. package/src/BookNavigator/bookmarks/bookmarks-list.js +285 -0
  197. package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +28 -0
  198. package/src/BookNavigator/bookmarks/bookmarks-provider.js +53 -0
  199. package/src/BookNavigator/bookmarks/ia-bookmarks.js +500 -0
  200. package/src/BookNavigator/br-fullscreen-mgr.js +83 -0
  201. package/src/BookNavigator/delete-modal-actions.js +49 -0
  202. package/src/BookNavigator/downloads/downloads-provider.js +76 -0
  203. package/src/BookNavigator/downloads/downloads.js +138 -0
  204. package/src/BookNavigator/search/a-search-result.js +55 -0
  205. package/src/BookNavigator/search/search-provider.js +180 -0
  206. package/src/BookNavigator/search/search-results.js +360 -0
  207. package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +93 -0
  208. package/src/BookNavigator/visual-adjustments/visual-adjustments.js +280 -0
  209. package/src/BookNavigator/volumes/volumes-provider.js +83 -0
  210. package/src/BookNavigator/volumes/volumes.js +178 -0
  211. package/src/BookReader/BookModel.js +518 -0
  212. package/src/BookReader/DebugConsole.js +54 -0
  213. package/src/BookReader/ImageCache.js +116 -0
  214. package/src/BookReader/Mode1Up.js +90 -0
  215. package/src/BookReader/Mode1UpLit.js +434 -0
  216. package/src/BookReader/Mode2Up.js +1372 -0
  217. package/src/BookReader/ModeSmoothZoom.js +177 -0
  218. package/src/BookReader/ModeThumb.js +336 -0
  219. package/src/BookReader/Navbar/Navbar.js +339 -0
  220. package/src/BookReader/PageContainer.js +120 -0
  221. package/src/BookReader/ReduceSet.js +26 -0
  222. package/src/BookReader/Toolbar/Toolbar.js +384 -0
  223. package/src/BookReader/events.js +20 -0
  224. package/src/BookReader/options.js +320 -0
  225. package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
  226. package/src/BookReader/utils/classes.js +36 -0
  227. package/src/BookReader/utils.js +240 -0
  228. package/src/BookReader.js +2546 -0
  229. package/src/BookReaderComponent/BookReaderComponent.js +112 -0
  230. package/src/ItemNavigator/ItemNavigator.js +376 -0
  231. package/src/ItemNavigator/providers/sharing.js +33 -0
  232. package/src/assets/icons/1up.svg +12 -0
  233. package/src/assets/icons/2up.svg +15 -0
  234. package/src/assets/icons/advance.svg +26 -0
  235. package/src/assets/icons/chevron-right.svg +1 -0
  236. package/src/assets/icons/close-circle-dark.svg +1 -0
  237. package/src/assets/icons/close-circle.svg +1 -0
  238. package/src/assets/icons/fullscreen.svg +17 -0
  239. package/src/assets/icons/fullscreen_exit.svg +17 -0
  240. package/src/assets/icons/hamburger.svg +15 -0
  241. package/src/assets/icons/left-arrow.svg +12 -0
  242. package/src/assets/icons/magnify-minus.svg +16 -0
  243. package/src/assets/icons/magnify-plus.svg +17 -0
  244. package/src/assets/icons/magnify.svg +15 -0
  245. package/src/assets/icons/pause.svg +23 -0
  246. package/src/assets/icons/play.svg +22 -0
  247. package/src/assets/icons/playback-speed.svg +34 -0
  248. package/src/assets/icons/read-aloud.svg +22 -0
  249. package/src/assets/icons/review.svg +22 -0
  250. package/src/assets/icons/thumbnails.svg +17 -0
  251. package/src/assets/icons/volume-full.svg +22 -0
  252. package/src/assets/images/BRicons.png +0 -0
  253. package/src/assets/images/BRicons.svg +94 -0
  254. package/src/assets/images/BRicons_ia.png +0 -0
  255. package/src/assets/images/back_pages.png +0 -0
  256. package/src/assets/images/book_bottom_icon.png +0 -0
  257. package/src/assets/images/book_down_icon.png +0 -0
  258. package/src/assets/images/book_left_icon.png +0 -0
  259. package/src/assets/images/book_leftmost_icon.png +0 -0
  260. package/src/assets/images/book_right_icon.png +0 -0
  261. package/src/assets/images/book_rightmost_icon.png +0 -0
  262. package/src/assets/images/book_top_icon.png +0 -0
  263. package/src/assets/images/book_up_icon.png +0 -0
  264. package/src/assets/images/books_graphic.svg +177 -0
  265. package/src/assets/images/booksplit.png +0 -0
  266. package/src/assets/images/control_pause_icon.png +0 -0
  267. package/src/assets/images/control_play_icon.png +0 -0
  268. package/src/assets/images/embed_icon.png +0 -0
  269. package/src/assets/images/icon-home-ia.png +0 -0
  270. package/src/assets/images/icon_OL-logo-xs.png +0 -0
  271. package/src/assets/images/icon_alert-xs.png +0 -0
  272. package/src/assets/images/icon_book.svg +12 -0
  273. package/src/assets/images/icon_bookmark.svg +12 -0
  274. package/src/assets/images/icon_close-pop.png +0 -0
  275. package/src/assets/images/icon_download.png +0 -0
  276. package/src/assets/images/icon_gear.svg +14 -0
  277. package/src/assets/images/icon_hamburger.svg +20 -0
  278. package/src/assets/images/icon_home.png +0 -0
  279. package/src/assets/images/icon_home.svg +21 -0
  280. package/src/assets/images/icon_home_ia.png +0 -0
  281. package/src/assets/images/icon_indicator.png +0 -0
  282. package/src/assets/images/icon_info.svg +11 -0
  283. package/src/assets/images/icon_one_page.svg +8 -0
  284. package/src/assets/images/icon_pause.svg +1 -0
  285. package/src/assets/images/icon_play.svg +1 -0
  286. package/src/assets/images/icon_playback-rate.svg +15 -0
  287. package/src/assets/images/icon_return.png +0 -0
  288. package/src/assets/images/icon_search_button.svg +8 -0
  289. package/src/assets/images/icon_share.svg +9 -0
  290. package/src/assets/images/icon_skip-ahead.svg +6 -0
  291. package/src/assets/images/icon_skip-back.svg +13 -0
  292. package/src/assets/images/icon_speaker.svg +18 -0
  293. package/src/assets/images/icon_speaker_open.svg +10 -0
  294. package/src/assets/images/icon_thumbnails.svg +12 -0
  295. package/src/assets/images/icon_toc.svg +5 -0
  296. package/src/assets/images/icon_two_pages.svg +9 -0
  297. package/src/assets/images/icon_zoomer.png +0 -0
  298. package/src/assets/images/loading.gif +0 -0
  299. package/src/assets/images/logo_icon.png +0 -0
  300. package/src/assets/images/marker_chap-off.png +0 -0
  301. package/src/assets/images/marker_chap-off.svg +11 -0
  302. package/src/assets/images/marker_chap-off_ia.png +0 -0
  303. package/src/assets/images/marker_chap-on.png +0 -0
  304. package/src/assets/images/marker_chap-on.svg +11 -0
  305. package/src/assets/images/marker_srch-on.svg +11 -0
  306. package/src/assets/images/marker_srchchap-off.png +0 -0
  307. package/src/assets/images/marker_srchchap-on.png +0 -0
  308. package/src/assets/images/nav_control-dn.png +0 -0
  309. package/src/assets/images/nav_control-dn_ia.png +0 -0
  310. package/src/assets/images/nav_control-up.png +0 -0
  311. package/src/assets/images/nav_control-up_ia.png +0 -0
  312. package/src/assets/images/nav_control.png +0 -0
  313. package/src/assets/images/one_page_mode_icon.png +0 -0
  314. package/src/assets/images/paper-badge.png +0 -0
  315. package/src/assets/images/print_icon.png +0 -0
  316. package/src/assets/images/progressbar.gif +0 -0
  317. package/src/assets/images/right_edges.png +0 -0
  318. package/src/assets/images/slider.png +0 -0
  319. package/src/assets/images/slider_ia.png +0 -0
  320. package/src/assets/images/thumbnail_mode_icon.png +0 -0
  321. package/src/assets/images/transparent.png +0 -0
  322. package/src/assets/images/two_page_mode_icon.png +0 -0
  323. package/src/assets/images/zoom_in_icon.png +0 -0
  324. package/src/assets/images/zoom_out_icon.png +0 -0
  325. package/src/css/BookReader.scss +89 -0
  326. package/src/css/_BRBookmarks.scss +29 -0
  327. package/src/css/_BRComponent.scss +13 -0
  328. package/src/css/_BRfloat.scss +197 -0
  329. package/src/css/_BRicon.scss +48 -0
  330. package/src/css/_BRmain.scss +251 -0
  331. package/src/css/_BRnav.scss +382 -0
  332. package/src/css/_BRpages.scss +139 -0
  333. package/src/css/_BRsearch.scss +226 -0
  334. package/src/css/_BRtoolbar.scss +84 -0
  335. package/src/css/_BRvendor.scss +5 -0
  336. package/src/css/_MobileNav.scss +194 -0
  337. package/src/css/_TextSelection.scss +32 -0
  338. package/src/css/_colorbox.scss +52 -0
  339. package/src/css/_controls.scss +244 -0
  340. package/src/css/_icons.scss +121 -0
  341. package/src/dragscrollable-br.js +261 -0
  342. package/src/jquery-wrapper.js +4 -0
  343. package/src/plugins/plugin.archive_analytics.js +86 -0
  344. package/src/plugins/plugin.autoplay.js +129 -0
  345. package/src/plugins/plugin.chapters.js +251 -0
  346. package/src/plugins/plugin.iframe.js +48 -0
  347. package/src/plugins/plugin.mobile_nav.js +287 -0
  348. package/src/plugins/plugin.resume.js +68 -0
  349. package/src/plugins/plugin.text_selection.js +291 -0
  350. package/src/plugins/plugin.url.js +198 -0
  351. package/src/plugins/plugin.vendor-fullscreen.js +247 -0
  352. package/src/plugins/search/plugin.search.js +439 -0
  353. package/src/plugins/search/view.js +440 -0
  354. package/src/plugins/tts/AbstractTTSEngine.js +242 -0
  355. package/src/plugins/tts/FestivalTTSEngine.js +169 -0
  356. package/src/plugins/tts/PageChunk.js +107 -0
  357. package/src/plugins/tts/PageChunkIterator.js +163 -0
  358. package/src/plugins/tts/WebTTSEngine.js +352 -0
  359. package/src/plugins/tts/plugin.tts.js +335 -0
  360. package/src/plugins/tts/tooltip_dict.js +15 -0
  361. package/src/plugins/tts/utils.js +91 -0
  362. package/src/util/browserSniffing.js +30 -0
  363. package/src/util/debouncer.js +26 -0
  364. package/src/util/docCookies.js +67 -0
  365. package/src/util/strings.js +34 -0
  366. package/tests/BookReader/BookModel.test.js +312 -0
  367. package/tests/BookReader/BookReaderPublicFunctions.test.js +164 -0
  368. package/tests/BookReader/DebugConsole.test.js +25 -0
  369. package/tests/BookReader/ImageCache.test.js +150 -0
  370. package/tests/BookReader/Mode1UpLit.test.js +87 -0
  371. package/tests/BookReader/Mode2Up.test.js +245 -0
  372. package/tests/BookReader/ModeSmoothZoom.test.js +149 -0
  373. package/tests/BookReader/Navbar/Navbar.test.js +169 -0
  374. package/tests/BookReader/PageContainer.test.js +187 -0
  375. package/tests/BookReader/ReduceSet.test.js +38 -0
  376. package/tests/BookReader/Toolbar/Toolbar.test.js +26 -0
  377. package/tests/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
  378. package/tests/BookReader/utils/classes.test.js +88 -0
  379. package/tests/BookReader/utils.test.js +136 -0
  380. package/tests/BookReader.options.test.js +39 -0
  381. package/tests/BookReader.test.js +301 -0
  382. package/tests/e2e/README.md +75 -0
  383. package/tests/e2e/autoplay.test.js +13 -0
  384. package/tests/e2e/base.test.js +35 -0
  385. package/tests/e2e/helpers/base.js +263 -0
  386. package/tests/e2e/helpers/debug.js +13 -0
  387. package/tests/e2e/helpers/desktopSearch.js +72 -0
  388. package/tests/e2e/helpers/mobileSearch.js +85 -0
  389. package/tests/e2e/helpers/mockSearch.js +93 -0
  390. package/tests/e2e/helpers/rightToLeft.js +29 -0
  391. package/tests/e2e/ia-production/ia-prod-base.js +17 -0
  392. package/tests/e2e/models/BookReader.js +11 -0
  393. package/tests/e2e/models/Navigation.js +56 -0
  394. package/tests/e2e/rightToLeft.test.js +20 -0
  395. package/tests/e2e/viewmode.test.js +37 -0
  396. package/tests/karma/BookNavigator/book-navigator.test.js +180 -0
  397. package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +133 -0
  398. package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +222 -0
  399. package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +64 -0
  400. package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
  401. package/tests/karma/BookNavigator/search/search-provider.test.js +23 -0
  402. package/tests/karma/BookNavigator/search/search-results.test.js +240 -0
  403. package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +40 -0
  404. package/tests/karma/BookNavigator/visual-adjustments.test.js +201 -0
  405. package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +160 -0
  406. package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
  407. package/tests/plugins/plugin.archive_analytics.test.js +23 -0
  408. package/tests/plugins/plugin.autoplay.test.js +52 -0
  409. package/tests/plugins/plugin.chapters.test.js +130 -0
  410. package/tests/plugins/plugin.iframe.test.js +42 -0
  411. package/tests/plugins/plugin.mobile_nav.test.js +66 -0
  412. package/tests/plugins/plugin.resume.test.js +98 -0
  413. package/tests/plugins/plugin.text_selection.test.js +193 -0
  414. package/tests/plugins/plugin.url.test.js +129 -0
  415. package/tests/plugins/plugin.vendor-fullscreen.test.js +65 -0
  416. package/tests/plugins/search/plugin.search.test.js +173 -0
  417. package/tests/plugins/search/plugin.search.view.test.js +106 -0
  418. package/tests/plugins/tts/AbstractTTSEngine.test.js +153 -0
  419. package/tests/plugins/tts/FestivalTTSEngine.test.js +59 -0
  420. package/tests/plugins/tts/PageChunk.test.js +57 -0
  421. package/tests/plugins/tts/PageChunkIterator.test.js +179 -0
  422. package/tests/plugins/tts/WebTTSEngine.test.js +126 -0
  423. package/tests/plugins/tts/utils.test.js +133 -0
  424. package/tests/util/browserSniffing.test.js +56 -0
  425. package/tests/util/docCookies.test.js +15 -0
  426. package/tests/util/strings.test.js +63 -0
  427. package/tests/utils.js +80 -0
  428. package/webpack.config.js +85 -0
@@ -0,0 +1,240 @@
1
+ import {
2
+ html,
3
+ fixture,
4
+ expect,
5
+ oneEvent,
6
+ } from '@open-wc/testing';
7
+ import sinon from 'sinon';
8
+ import { IABookSearchResults } from '../../../../src/BookNavigator/search/search-results.js';
9
+
10
+ const container = (results = [], query = '') => (
11
+ html`<ia-book-search-results .results=${results} .query=${query}></ia-book-search-results>`
12
+ );
13
+
14
+ console.log("ia-book-search-results-test");
15
+
16
+ const searchQuery = 'Bristol';
17
+
18
+ const results = [{
19
+ text: `In the drawing of caricatures and cartoons\u2014or any other com' mercial art, for that matter\u2014the artist should know something about the processes of reproduction for that particular form of art work. For pen and ink work the engraving is made on a sine printing plate. It is not necessary, however, to know all about these processes of reproduction. The artist should know that all work intended for line rqproducttons should be made on white paper or {{{${searchQuery}}}} Board with black drawing ink. The drawing to be reproduced is photographed on a chemically treated sine plate, which is then treated with acid. This acid eats away the surface of the sine, except the photographed' lines, which are left in relief, somewhat like printing type. Colored inks do not photograph well; neither does black ink on colored paper.`,
20
+ cover: '//placehold.it/30x44',
21
+ title: 'Book title',
22
+ par: [{
23
+ boxes: [{
24
+ r: 2672, b: 792, t: 689, page: 24, l: 2424,
25
+ }],
26
+ b: 1371,
27
+ t: 689,
28
+ page_width: 3658,
29
+ r: 3192,
30
+ l: 428,
31
+ page_height: 5357,
32
+ page: 24,
33
+ }],
34
+ }, {
35
+ text: `Drawings intended for sale should be made on a good grade of {{{${searchQuery}}}} Board, and a margin left all the way around the drawings. They should be mailed flat, and'require first class postage. Enclose postage for the return of the drawings. Only send good drawings of a reason- able quantity. Enclose a neat and terse letter to the one you are sending the drawings to, written with pen and ink or typewriter if possible, on`,
36
+ par: [{
37
+ boxes: [{
38
+ r: 698, b: 4460, t: 4324, page: 86, l: 450,
39
+ }],
40
+ b: 4938,
41
+ t: 4207,
42
+ page_width: 3658,
43
+ r: 3196,
44
+ l: 432,
45
+ page_height: 5357,
46
+ page: 86,
47
+ }],
48
+ }];
49
+
50
+ describe('<ia-book-search-results>', () => {
51
+ afterEach(() => {
52
+ sinon.restore();
53
+ });
54
+
55
+ it('sets default properties', async () => {
56
+ const query = 'bristol';
57
+ const el = await fixture(container(results, query));
58
+
59
+ expect(el.results).to.equal(results);
60
+ expect(el.query).to.equal(query);
61
+ });
62
+
63
+ it('sets results when passed in via event object', async () => {
64
+ const el = await fixture(container());
65
+
66
+ el.setResults({ detail: { results } });
67
+ expect(el.results).to.equal(results);
68
+ });
69
+
70
+ it('listens for a custom search callback event on the document', async () => {
71
+ IABookSearchResults.prototype.setResults = sinon.fake();
72
+ const el = await fixture(container());
73
+ const event = new Event('BookReader:SearchCallback');
74
+
75
+ event.detail = { results };
76
+ document.dispatchEvent(event);
77
+ expect(el.setResults.callCount).to.equal(1);
78
+ expect(el.setResults.firstArg).to.equal(event);
79
+ });
80
+
81
+ it('renders results that contain the book title', async () => {
82
+ sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
83
+ const el = await fixture(container(results));
84
+
85
+ expect(el.innerHTML).to.include(`${results[0].title}`);
86
+ });
87
+
88
+ it('renders results that contain a highlighted match', async () => {
89
+ sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
90
+ const el = await fixture(container(results));
91
+
92
+ expect(el.innerHTML).to.include(`<mark>${searchQuery}</mark>`);
93
+ });
94
+
95
+ it('renders results that contain an optional cover image', async () => {
96
+ sinon.replace(IABookSearchResults.prototype, 'createRenderRoot', function createRenderRoot() { return this; });
97
+ const el = await fixture(container(results));
98
+
99
+ expect(el.innerHTML).to.include(`<img src="${results[0].cover}">`);
100
+ });
101
+
102
+ it('sets a query prop when search input receives input', async () => {
103
+ const el = await fixture(container(results));
104
+ const searchInput = el.shadowRoot.querySelector('[name="query"]');
105
+
106
+ searchInput.value = searchQuery;
107
+ searchInput.dispatchEvent(new Event('keyup'));
108
+
109
+ expect(el.query).to.equal(searchQuery);
110
+ });
111
+
112
+ it('emits a custom event when search form submitted when input is populated', async () => {
113
+ const el = await fixture(container(results));
114
+
115
+ setTimeout(() => {
116
+ const form = el.shadowRoot.querySelector('form');
117
+ form.querySelector('input').value = 'foo';
118
+ form.dispatchEvent(new Event('submit'));
119
+ });
120
+ const response = await oneEvent(el, 'bookSearchInitiated');
121
+
122
+ expect(response).to.exist;
123
+ });
124
+
125
+ it('uses a singular noun when one result given', async () => {
126
+ const el = await fixture(container([results[0]]));
127
+ const resultsCount = await fixture(el.resultsCount);
128
+
129
+ expect(resultsCount.innerHTML).to.include('1 result');
130
+ });
131
+
132
+ it('can render header with active options count', async () => {
133
+ const el = await fixture(container(results));
134
+ el.renderHeader = true;
135
+
136
+ await el.updateComplete;
137
+
138
+ expect(el.shadowRoot.querySelector('header p').innerText).to.include('2');
139
+ });
140
+
141
+ it('renders search all files checkbox when enabled', async () => {
142
+ const el = await fixture(container(results));
143
+ el.renderSearchAllFiles = true;
144
+
145
+ await el.updateComplete;
146
+
147
+ expect(el.shadowRoot.querySelector('[name="all_files"]')).to.not.be.null;
148
+ });
149
+
150
+ it('emits a resultSelected event when a search result is clicked', async () => {
151
+ const el = await fixture(container(results));
152
+
153
+ setTimeout(() => (
154
+ el.shadowRoot.querySelector('book-search-result').querySelector('li').click()
155
+ ));
156
+ const response = await oneEvent(el, 'resultSelected');
157
+
158
+ expect(response).to.exist;
159
+ });
160
+
161
+ it('emits a closeMenu event when a search result is clicked', async () => {
162
+ const el = await fixture(container(results));
163
+
164
+ setTimeout(() => (
165
+ el.shadowRoot.querySelector('book-search-result').querySelector('li').click()
166
+ ));
167
+ const response = await oneEvent(el, 'closeMenu');
168
+
169
+ expect(response).to.exist;
170
+ });
171
+
172
+ describe('Search results placeholders', () => {
173
+ it('renders a loading state when queryInProgress is true', async () => {
174
+ const el = await fixture(container(results));
175
+
176
+ el.queryInProgress = true;
177
+ await el.updateComplete;
178
+
179
+ expect(el.shadowRoot.querySelector('.loading')).to.not.be.null;
180
+ });
181
+ it('renders an error message when provided', async () => {
182
+ const el = await fixture(container([]));
183
+ const message = 'Sample error message';
184
+ el.errorMessage = message;
185
+ await el.updateComplete;
186
+
187
+ expect(el.shadowRoot.querySelector('.error-message')).to.exist;
188
+ expect(el.shadowRoot.querySelector('.search-cta')).to.be.null;
189
+ });
190
+ it('displays call to search when no results or search errors are showing', async () => {
191
+ const el = await fixture(container([]));
192
+
193
+ expect(el.shadowRoot.querySelector('.search-cta')).to.exist;
194
+ expect(el.shadowRoot.querySelector('.error-message')).to.be.null;
195
+ expect(el.shadowRoot.querySelector('.results')).to.be.null;
196
+ });
197
+ });
198
+
199
+ it('displays results images when told to', async () => {
200
+ const el = await fixture(container(results));
201
+ el.displayResultImages = true;
202
+ await el.updateComplete;
203
+
204
+ expect(el.shadowRoot.querySelector('.results.show-image')).to.exist;
205
+ });
206
+
207
+ describe('search input focus', () => {
208
+ it('will always try to re-focus once the component updates', async () => {
209
+ const el = await fixture(container(results));
210
+ el.focusOnInputIfNecessary = sinon.fake();
211
+ // update any property to fire lifecycle
212
+ el.results = [];
213
+ await el.updateComplete;
214
+
215
+ expect(el.focusOnInputIfNecessary.callCount).to.equal(1);
216
+ });
217
+ it('refocuses on input when results are empty', async () => {
218
+ const el = await fixture(container(results));
219
+ el.results = [];
220
+ await el.updateComplete;
221
+
222
+ const searchInputField = el.shadowRoot.querySelector('input[type=\'search\']');
223
+ expect(searchInputField).to.equal(el.shadowRoot.activeElement);
224
+ });
225
+ });
226
+
227
+ // it("emits a bookSearchCanceled event when loading state's cancel action clicked", async () => {
228
+ // const el = await fixture(container(results));
229
+
230
+ // el.queryInProgress = true;
231
+ // await el.updateComplete;
232
+
233
+ // setTimeout(() => (
234
+ // el.shadowRoot.querySelector('button').click()
235
+ // ));
236
+ // const response = await oneEvent(el, 'bookSearchCanceled');
237
+
238
+ // expect(response).to.exist;
239
+ // });
240
+ });
@@ -0,0 +1,40 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ import sharingProvider from '../../../../src/ItemNavigator/providers/sharing.js';
4
+
5
+ afterEach(() => {
6
+ sinon.restore();
7
+ });
8
+
9
+ const mdStub = {
10
+ identifier: 'stubby-id'
11
+ };
12
+
13
+ const baseHostStub = 'foo.org';
14
+ const itemType = 'texts';
15
+ const subPrefix = 'beep-boop_12 4 5';
16
+
17
+ describe('Sharing Provider', () => {
18
+ describe('constructor', () => {
19
+ const provider = new sharingProvider(mdStub, baseHostStub, itemType, subPrefix);
20
+
21
+ expect(provider.id).to.equal('share');
22
+ expect(provider.icon).to.exist;
23
+ expect(provider.label).to.equal('Share this item');
24
+ expect(provider.itemType).to.equal(itemType);
25
+ expect(provider.idPath).to.exist;
26
+ expect(provider.component).to.exist;
27
+ });
28
+
29
+ describe('handles subprefix', () => {
30
+ it('encodes the subprefix if it has one', () => {
31
+ const provider = new sharingProvider(mdStub, baseHostStub, itemType, subPrefix);
32
+ const encodedSubprefix = encodeURIComponent(subPrefix);
33
+ expect(provider.idPath).to.equal(`${mdStub.identifier}/${encodedSubprefix}`);
34
+ });
35
+ it('does not add subprefix to path if subprefix is item id', () => {
36
+ const provider = new sharingProvider(mdStub, baseHostStub, itemType, mdStub.identifier);
37
+ expect(provider.idPath).to.equal(mdStub.identifier);
38
+ });
39
+ });
40
+ });
@@ -0,0 +1,201 @@
1
+ import {
2
+ html,
3
+ fixture,
4
+ expect,
5
+ oneEvent,
6
+ } from '@open-wc/testing';
7
+ import sinon from 'sinon';
8
+ import { IABookVisualAdjustments } from '../../../src/BookNavigator/visual-adjustments/visual-adjustments.js';
9
+
10
+ const options = [{
11
+ id: 'contrast',
12
+ name: 'Adjust contrast',
13
+ active: true,
14
+ min: 0,
15
+ max: 150,
16
+ step: 1,
17
+ value: 100,
18
+ }, {
19
+ id: 'invert',
20
+ name: 'Invert colors',
21
+ active: false,
22
+ }, {
23
+ id: 'brightness',
24
+ name: 'Adjust brightness',
25
+ active: false,
26
+ value: 100,
27
+ }];
28
+
29
+ const container = (renderHeader = false) => (
30
+ html`<ia-book-visual-adjustments .options=${options} ?renderHeader=${renderHeader}></ia-book-visual-adjustments>`
31
+ );
32
+
33
+ describe('<ia-book-visual-adjustments>', () => {
34
+ afterEach(() => {
35
+ sinon.restore();
36
+ });
37
+
38
+ it('sets default properties', async () => {
39
+ const el = await fixture(container());
40
+
41
+ expect(el.options).to.exist;
42
+ expect(el.options.length).to.equal(options.length);
43
+ expect(el.renderHeader).to.exist;
44
+ expect(el.renderHeader).to.be.false;
45
+ expect(el.activeCount).to.exist;
46
+ expect(el.showZoomControls).to.be.true;
47
+ });
48
+
49
+ it('renders all properties of a visual adjustment option', async () => {
50
+ const el = await fixture(container());
51
+
52
+ await el.updateComplete;
53
+
54
+ const label = el.shadowRoot.querySelector('label');
55
+ const name = label.querySelector('.name');
56
+ const checkbox = label.querySelector('input');
57
+ expect(name.innerText).to.equal(options[0].name);
58
+ expect(checkbox.checked).to.equal(true);
59
+ });
60
+
61
+ it('can render header with active options count', async () => {
62
+ const renderHeader = true;
63
+ const el = await fixture(container(renderHeader));
64
+ expect(el.shadowRoot.querySelector('header p').innerText).to.include('1');
65
+ });
66
+
67
+ it('does not render active options count element when none are selected', async () => {
68
+ const el = await fixture(container());
69
+
70
+ el.options = [options[1]];
71
+ await el.updateComplete;
72
+
73
+ expect(el.shadowRoot.querySelector('header p')).not.to.exist;
74
+ });
75
+
76
+ it('changes option\'s active state when input changed', async () => {
77
+ const el = await fixture(container());
78
+
79
+ el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
80
+ await el.updateComplete;
81
+
82
+ expect(el.options[0].active).to.equal(false);
83
+ });
84
+
85
+ it('renders zoom in and out controls when enabled', async () => {
86
+ const el = await fixture(container());
87
+
88
+ expect(el.shadowRoot.querySelector('.zoom_out')).to.exist;
89
+ expect(el.shadowRoot.querySelector('.zoom_in')).to.exist;
90
+ });
91
+
92
+ it('does not render zoom controls when disabled', async () => {
93
+ const el = await fixture(container());
94
+
95
+ el.showZoomControls = false;
96
+ await el.updateComplete;
97
+
98
+ expect(el.shadowRoot.querySelector('.zoom_out')).not.to.exist;
99
+ expect(el.shadowRoot.querySelector('.zoom_in')).not.to.exist;
100
+ });
101
+
102
+ describe('Custom events', () => {
103
+ it('prepareEventDetails returns proper params', async () => {
104
+ const el = await fixture(container());
105
+ await el.updateComplete;
106
+ const params = el.prepareEventDetails();
107
+
108
+ expect(params.activeCount).to.exist;
109
+ expect(typeof (params.activeCount)).to.be.equal('number');
110
+ expect(params.changedOptionId).to.exist;
111
+ expect(typeof (params.changedOptionId)).to.be.equal('string');
112
+ expect(params.options).to.exist;
113
+ expect(params.options.length).to.exist;
114
+ expect(params.options.length).to.be.greaterThan(0);
115
+ });
116
+ it('emitOptionChangedEvent calls for the params', async () => {
117
+ IABookVisualAdjustments.prototype.prepareEventDetails = sinon.fake();
118
+ const el = await fixture(container());
119
+ await el.updateComplete;
120
+
121
+ expect(el.prepareEventDetails.callCount).to.equal(1);
122
+ });
123
+ it('triggers an emitOptionChangedEvent event at firstUpdate', async () => {
124
+ IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
125
+ const el = await fixture(container());
126
+
127
+ expect(el.emitOptionChangedEvent.callCount).to.equal(1);
128
+ });
129
+
130
+ it('triggers an emitOptionChangedEvent event when a checkbox\'s change event fires', async () => {
131
+ IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
132
+ const el = await fixture(container());
133
+
134
+ expect(el.emitOptionChangedEvent.callCount).to.equal(1); // firstUpdate fire
135
+
136
+ el.shadowRoot.querySelector('li input').dispatchEvent(new Event('change'));
137
+ expect(el.emitOptionChangedEvent.callCount).to.equal(2);
138
+ });
139
+
140
+ it('triggers an emitOptionChangedEvent event when a range\'s change event fires', async () => {
141
+ IABookVisualAdjustments.prototype.emitOptionChangedEvent = sinon.fake();
142
+
143
+ const el = await fixture(container());
144
+ expect(el.emitOptionChangedEvent.callCount).to.equal(1); // firstUpdate fire
145
+
146
+ el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('change'));
147
+ expect(el.emitOptionChangedEvent.callCount).to.equal(2);
148
+ });
149
+
150
+ it('emits a zoom out event when zoom out button clicked', async () => {
151
+ const el = await fixture(container());
152
+
153
+ setTimeout(() => (
154
+ el.shadowRoot.querySelector('.zoom_out').click()
155
+ ));
156
+ const response = await oneEvent(el, 'visualAdjustmentZoomOut');
157
+
158
+ expect(response).to.exist;
159
+ });
160
+
161
+ it('emits a zoom in event when zoom in button clicked', async () => {
162
+ const el = await fixture(container());
163
+
164
+ setTimeout(() => (
165
+ el.shadowRoot.querySelector('.zoom_in').click()
166
+ ));
167
+ const response = await oneEvent(el, 'visualAdjustmentZoomIn');
168
+
169
+ expect(response).to.exist;
170
+ });
171
+ });
172
+
173
+ it('sets range defaults when none supplied', async () => {
174
+ const el = await fixture(container());
175
+ const brightnessRange = el.shadowRoot.querySelector('[name="brightness_range"]');
176
+
177
+ expect(brightnessRange.getAttribute('min')).to.equal('0');
178
+ expect(brightnessRange.getAttribute('max')).to.equal('100');
179
+ expect(brightnessRange.getAttribute('step')).to.equal('1');
180
+ });
181
+
182
+ it('sets the updated range value on the options prop', async () => {
183
+ const el = await fixture(container());
184
+ const { id } = options[0];
185
+ const newValue = 120;
186
+
187
+ el.setRangeValue(id, newValue);
188
+ await el.updateComplete;
189
+
190
+ expect(el.options[0].value).to.equal(newValue);
191
+ });
192
+
193
+ it('triggers a setRangeValue event when a range\'s input event fires', async () => {
194
+ IABookVisualAdjustments.prototype.setRangeValue = sinon.fake();
195
+
196
+ const el = await fixture(container());
197
+
198
+ el.shadowRoot.querySelector('[name="brightness_range"]').dispatchEvent(new Event('input'));
199
+ expect(el.setRangeValue.callCount).to.equal(1);
200
+ });
201
+ });
@@ -0,0 +1,160 @@
1
+ import { expect, fixture } from '@open-wc/testing';
2
+ import sinon from 'sinon';
3
+ import volumesProvider from '../../../../src/BookNavigator/volumes/volumes-provider';
4
+
5
+ const brOptions = {
6
+ "options": {
7
+ "enableMultipleBooks": true,
8
+ "multipleBooksList": {
9
+ "by_subprefix": {
10
+ "/details/SubBookTest": {
11
+ "url_path": "/details/SubBookTest",
12
+ "file_subprefix": "book1/GPORFP",
13
+ "orig_sort": 1,
14
+ "title": "book1/GPORFP.pdf",
15
+ "file_source": "/book1/GPORFP_jp2.zip"
16
+ },
17
+ "/details/SubBookTest/subdir/book2/brewster_kahle_internet_archive": {
18
+ "url_path": "/details/SubBookTest/subdir/book2/brewster_kahle_internet_archive",
19
+ "file_subprefix": "subdir/book2/brewster_kahle_internet_archive",
20
+ "orig_sort": 2,
21
+ "title": "subdir/book2/brewster_kahle_internet_archive.pdf",
22
+ "file_source": "/subdir/book2/brewster_kahle_internet_archive_jp2.zip"
23
+ },
24
+ "/details/SubBookTest/subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume": {
25
+ "url_path": "/details/SubBookTest/subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume",
26
+ "file_subprefix": "subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume",
27
+ "orig_sort": 3,
28
+ "title": "subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume.pdf",
29
+ "file_source": "/subdir/subsubdir/book3/Rfp008011ResponseInternetArchive-without-resume_jp2.zip"
30
+ }
31
+ }
32
+ }
33
+ }
34
+ };
35
+
36
+ afterEach(() => {
37
+ sinon.restore();
38
+ });
39
+
40
+ describe('Volumes Provider', () => {
41
+ it('constructor', () => {
42
+ const onSortClick = sinon.fake();
43
+ const baseHost = "https://archive.org";
44
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
45
+
46
+ const files = brOptions.options.multipleBooksList.by_subprefix;
47
+ const volumeCount = Object.keys(files).length;
48
+
49
+ expect(provider.optionChange).to.equal(onSortClick);
50
+ expect(provider.id).to.equal('volumes');
51
+ expect(provider.icon).to.exist;
52
+
53
+ expect(provider.label).to.equal(`Viewable files (${volumeCount})`);
54
+ expect(provider.viewableFiles).to.exist;
55
+ expect(provider.viewableFiles.length).to.equal(3);
56
+
57
+ expect(provider.component.hostUrl).to.exist;
58
+ expect(provider.component.hostUrl).to.equal(baseHost);
59
+ expect(provider.component).to.exist;
60
+ });
61
+
62
+ it('sorting cycles - render sort actionButton', async () => {
63
+ const onSortClick = sinon.fake();
64
+ const baseHost = "https://archive.org";
65
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
66
+
67
+ expect(provider.sortOrderBy).to.equal("orig_sort");
68
+
69
+ provider.sortVolumes("title_asc");
70
+ expect(provider.sortOrderBy).to.equal("title_asc");
71
+ expect(provider.sortButton.getHTML()).includes("sort-by asc-icon");
72
+
73
+ provider.sortVolumes("title_desc");
74
+ expect(provider.sortOrderBy).to.equal("title_desc");
75
+ expect(provider.sortButton.getHTML()).includes("sort-by desc-icon");
76
+
77
+ provider.sortVolumes("orig_sort");
78
+ expect(provider.sortOrderBy).to.equal("orig_sort");
79
+ expect(provider.sortButton.getHTML()).includes("sort-by neutral-icon");
80
+ });
81
+
82
+ it('sort volumes in initial order', async () => {
83
+ const onSortClick = sinon.fake();
84
+ const baseHost = "https://archive.org";
85
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
86
+
87
+ const parsedFiles = brOptions.options.multipleBooksList.by_subprefix;
88
+ const files = Object.keys(parsedFiles).map(item => parsedFiles[item]).sort((a, b) => a.orig_sort - b.orig_sort);
89
+ const origSortTitles = files.map(item => item.title);
90
+
91
+ provider.sortVolumes("orig_sort");
92
+
93
+ expect(provider.sortOrderBy).to.equal("orig_sort");
94
+ expect(provider.actionButton).to.exist;
95
+
96
+ const providerFileTitles = provider.viewableFiles.map(item => item.title);
97
+ // use `.eql` for "lose equality" in order to deeply compare values.
98
+ expect(providerFileTitles).to.eql([...origSortTitles]);
99
+ });
100
+
101
+ it('sort volumes in ascending title order', async () => {
102
+ const onSortClick = sinon.fake();
103
+ const baseHost = "https://archive.org";
104
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
105
+
106
+ const parsedFiles = brOptions.options.multipleBooksList.by_subprefix;
107
+ const files = Object.keys(parsedFiles).map(item => parsedFiles[item]);
108
+ const ascendingTitles = files.map(item => item.title).sort((a, b) => a.localeCompare(b));
109
+
110
+ provider.sortVolumes("title_asc");
111
+
112
+ expect(provider.sortOrderBy).to.equal("title_asc");
113
+ expect(provider.actionButton).to.exist;
114
+
115
+ const providerFileTitles = provider.viewableFiles.map(item => item.title);
116
+ // use `.eql` for "lose equality" in order to deeply compare values.
117
+ expect(providerFileTitles).to.eql([...ascendingTitles]);
118
+ });
119
+
120
+ it('sort volumes in descending title order', async () => {
121
+ const onSortClick = sinon.fake();
122
+ const baseHost = "https://archive.org";
123
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
124
+
125
+ provider.isSortAscending = false;
126
+
127
+ const parsedFiles = brOptions.options.multipleBooksList.by_subprefix;
128
+ const files = Object.keys(parsedFiles).map(item => parsedFiles[item]);
129
+ const descendingTitles = files.map(item => item.title).sort((a, b) => b.localeCompare(a));
130
+
131
+ provider.sortVolumes("title_desc");
132
+
133
+ expect(provider.sortOrderBy).to.equals("title_desc");
134
+ expect(provider.actionButton).to.exist;
135
+
136
+ const providerFileTitles = provider.viewableFiles.map(item => item.title);
137
+ // use `.eql` for "lose equality" in order to deeply compare values.
138
+ expect(providerFileTitles).to.eql([...descendingTitles]);
139
+ });
140
+
141
+ describe('Sorting icons', () => {
142
+ it('has 3 icons', async () => {
143
+ const onSortClick = sinon.fake();
144
+ const baseHost = "https://archive.org";
145
+ const provider = new volumesProvider(baseHost, brOptions, onSortClick);
146
+
147
+ provider.sortOrderBy = 'orig_sort';
148
+ const origSortButton = await fixture(provider.sortButton);
149
+ expect(origSortButton.classList.contains('neutral-icon')).to.be.true;
150
+
151
+ provider.sortOrderBy = 'title_asc';
152
+ const ascButton = await fixture(provider.sortButton);
153
+ expect(ascButton.classList.contains('asc-icon')).to.be.true;
154
+
155
+ provider.sortOrderBy = 'title_desc';
156
+ const descButton = await fixture(provider.sortButton);
157
+ expect(descButton.classList.contains('desc-icon')).to.be.true;
158
+ });
159
+ });
160
+ });