@panoramax/web-viewer 4.4.0-develop-3839b5a4 → 4.4.0-develop-f91f6758

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 (341) hide show
  1. package/{src → build}/components/core/Basic.js +22 -16
  2. package/{src → build}/components/core/CoverageMap.js +19 -14
  3. package/{src → build}/components/core/Editor.js +16 -16
  4. package/{src → build}/components/core/PhotoViewer.js +30 -29
  5. package/{src → build}/components/core/Viewer.js +21 -20
  6. package/build/components/core/index.js +10 -0
  7. package/build/components/index.js +11 -0
  8. package/build/components/index_photoviewer.js +6 -0
  9. package/{src → build}/components/layout/BottomDrawer.js +4 -4
  10. package/{src → build}/components/layout/CorneredGrid.js +1 -1
  11. package/{src → build}/components/layout/Mini.js +5 -4
  12. package/{src → build}/components/layout/Tabs.js +1 -1
  13. package/build/components/layout/index.js +9 -0
  14. package/{src → build}/components/menus/LocationPrecisionDoc.js +4 -6
  15. package/{src → build}/components/menus/MapBackground.js +4 -6
  16. package/{src → build}/components/menus/MapFilters.js +16 -21
  17. package/{src → build}/components/menus/MapLayers.js +20 -24
  18. package/{src → build}/components/menus/MapLegend.js +3 -4
  19. package/{src → build}/components/menus/MiniPictureLegend.js +3 -4
  20. package/{src → build}/components/menus/PictureLegend.js +10 -15
  21. package/{src → build}/components/menus/PictureMetadata.js +12 -19
  22. package/{src → build}/components/menus/PlayerOptions.js +5 -7
  23. package/{src → build}/components/menus/QualityScoreDoc.js +3 -4
  24. package/{src → build}/components/menus/ReportForm.js +8 -9
  25. package/{src → build}/components/menus/SemanticsDoc.js +3 -4
  26. package/{src → build}/components/menus/SemanticsDownload.js +3 -3
  27. package/{src → build}/components/menus/SemanticsFilters.js +7 -8
  28. package/{src → build}/components/menus/SemanticsList.js +11 -18
  29. package/{src → build}/components/menus/SemanticsMetadata.js +8 -11
  30. package/{src → build}/components/menus/Share.js +6 -7
  31. package/build/components/menus/index.js +22 -0
  32. package/build/components/menus/index_photoviewer.js +11 -0
  33. package/{src → build}/components/styles.js +0 -2
  34. package/{src → build}/components/ui/AnnotationsSwitch.js +6 -8
  35. package/{src → build}/components/ui/Button.js +1 -1
  36. package/{src → build}/components/ui/ButtonGroup.js +2 -1
  37. package/{src → build}/components/ui/CopyButton.js +4 -6
  38. package/{src → build}/components/ui/Grade.js +5 -5
  39. package/{src → build}/components/ui/GradeFilter.js +3 -3
  40. package/{src → build}/components/ui/IconSwitch.js +1 -1
  41. package/{src → build}/components/ui/LinkButton.js +1 -1
  42. package/{src → build}/components/ui/ListGroup.js +3 -3
  43. package/{src → build}/components/ui/ListItem.js +1 -1
  44. package/{src → build}/components/ui/Loader.js +8 -7
  45. package/{src → build}/components/ui/Map.js +38 -26
  46. package/{src → build}/components/ui/MapMore.js +7 -7
  47. package/{src → build}/components/ui/Photo.js +29 -27
  48. package/{src → build}/components/ui/Popup.js +4 -4
  49. package/{src → build}/components/ui/QualityScore.js +4 -4
  50. package/{src → build}/components/ui/SearchBar.js +6 -7
  51. package/{src → build}/components/ui/SemanticsEditor.js +14 -15
  52. package/{src → build}/components/ui/SemanticsTable.js +4 -5
  53. package/{src → build}/components/ui/Switch.js +1 -1
  54. package/{src → build}/components/ui/TogglableGroup.js +4 -4
  55. package/build/components/ui/index.js +29 -0
  56. package/build/components/ui/index_photoviewer.js +21 -0
  57. package/{src → build}/components/ui/widgets/CopyCoordinates.js +5 -5
  58. package/{src → build}/components/ui/widgets/GeoSearch.js +10 -10
  59. package/{src → build}/components/ui/widgets/Legend.js +9 -8
  60. package/{src → build}/components/ui/widgets/LevelSelect.js +9 -7
  61. package/{src → build}/components/ui/widgets/MapFiltersButton.js +5 -5
  62. package/{src → build}/components/ui/widgets/MapLayersButton.js +5 -5
  63. package/{src → build}/components/ui/widgets/OSMEditors.js +8 -8
  64. package/{src → build}/components/ui/widgets/PictureLegendActions.js +4 -4
  65. package/{src → build}/components/ui/widgets/Player.js +6 -7
  66. package/{src → build}/components/ui/widgets/SemanticsFiltersButton.js +6 -7
  67. package/{src → build}/components/ui/widgets/Zoom.js +6 -6
  68. package/build/components/ui/widgets/index.js +16 -0
  69. package/build/components/ui/widgets/index_photoviewer.js +7 -0
  70. package/build/editor.html +94 -10
  71. package/{src → build}/img/arrow_triangle.svg +0 -1
  72. package/{src → build}/img/arrow_turn.svg +0 -1
  73. package/build/index.html +111 -1
  74. package/build/index.js +6 -95
  75. package/build/index_photoviewer.js +4 -0
  76. package/build/map.html +97 -1
  77. package/build/package.json +141 -0
  78. package/build/photo.html +85 -1
  79. package/build/servers.js +3 -4
  80. package/{src → build}/utils/API.js +33 -33
  81. package/{src → build}/utils/InitParameters.js +11 -9
  82. package/{src → build}/utils/MapStyleComposer.js +39 -37
  83. package/{src → build}/utils/PhotoAdapter.js +1 -0
  84. package/{src → build}/utils/PresetsManager.js +4 -4
  85. package/{src → build}/utils/SemanticsMapProtocol.js +3 -4
  86. package/{src → build}/utils/URLHandler.js +16 -14
  87. package/{src → build}/utils/geocoder.js +5 -5
  88. package/{src → build}/utils/i18n.js +21 -20
  89. package/build/utils/index.js +17 -0
  90. package/build/utils/index_photoviewer.js +14 -0
  91. package/{src → build}/utils/indoor.js +9 -5
  92. package/{src → build}/utils/map.js +15 -11
  93. package/{src → build}/utils/picture.js +22 -17
  94. package/{src → build}/utils/semantics.js +9 -5
  95. package/{src → build}/utils/utils.js +8 -4
  96. package/{src → build}/utils/widgets.js +2 -2
  97. package/build/viewer.html +120 -35
  98. package/build/viewer_indoor.html +90 -8
  99. package/build/widgets.html +410 -1
  100. package/package.json +81 -204
  101. package/.dockerignore +0 -7
  102. package/.gitlab-ci.yml +0 -78
  103. package/CHANGELOG.md +0 -853
  104. package/CODE_OF_CONDUCT.md +0 -134
  105. package/Dockerfile +0 -14
  106. package/build/index.css +0 -36
  107. package/build/index.css.map +0 -1
  108. package/build/index.js.map +0 -1
  109. package/build/photoviewer.css +0 -36
  110. package/build/photoviewer.css.map +0 -1
  111. package/build/photoviewer.js +0 -86
  112. package/build/photoviewer.js.map +0 -1
  113. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff +0 -0
  114. package/build/static/media/atkinson-hyperlegible-next-latin-400-normal..woff2 +0 -0
  115. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff +0 -0
  116. package/build/static/media/atkinson-hyperlegible-next-latin-ext-400-normal..woff2 +0 -0
  117. package/config/env.js +0 -104
  118. package/config/getHttpsConfig.js +0 -69
  119. package/config/getPackageJson.js +0 -25
  120. package/config/jest/babelTransform.js +0 -29
  121. package/config/jest/cssTransform.js +0 -14
  122. package/config/jest/fileTransform.js +0 -40
  123. package/config/jest/mocks.js +0 -230
  124. package/config/modules.js +0 -134
  125. package/config/paths.js +0 -76
  126. package/config/pnpTs.js +0 -35
  127. package/config/webpack/persistentCache/createEnvironmentHash.js +0 -9
  128. package/config/webpack.config.js +0 -825
  129. package/config/webpackDevServer.config.js +0 -131
  130. package/docs/03_URL_settings.md +0 -218
  131. package/docs/05_Compatibility.md +0 -83
  132. package/docs/09_Develop.md +0 -141
  133. package/docs/90_Releases.md +0 -27
  134. package/docs/images/class_diagram.drawio +0 -144
  135. package/docs/images/class_diagram.jpg +0 -0
  136. package/docs/images/comparative_3drender.jpg +0 -0
  137. package/docs/images/indoor_level.png +0 -0
  138. package/docs/images/screenshot.jpg +0 -0
  139. package/docs/index.md +0 -159
  140. package/docs/reference/components/core/Basic.md +0 -211
  141. package/docs/reference/components/core/CoverageMap.md +0 -220
  142. package/docs/reference/components/core/Editor.md +0 -252
  143. package/docs/reference/components/core/PhotoViewer.md +0 -320
  144. package/docs/reference/components/core/Viewer.md +0 -398
  145. package/docs/reference/components/layout/BottomDrawer.md +0 -35
  146. package/docs/reference/components/layout/CorneredGrid.md +0 -29
  147. package/docs/reference/components/layout/Mini.md +0 -45
  148. package/docs/reference/components/layout/Tabs.md +0 -46
  149. package/docs/reference/components/menus/LocationPrecisionDoc.md +0 -15
  150. package/docs/reference/components/menus/MapBackground.md +0 -32
  151. package/docs/reference/components/menus/MapFilters.md +0 -37
  152. package/docs/reference/components/menus/MapLayers.md +0 -15
  153. package/docs/reference/components/menus/MapLegend.md +0 -32
  154. package/docs/reference/components/menus/MiniPictureLegend.md +0 -15
  155. package/docs/reference/components/menus/PictureLegend.md +0 -45
  156. package/docs/reference/components/menus/PictureMetadata.md +0 -32
  157. package/docs/reference/components/menus/PlayerOptions.md +0 -15
  158. package/docs/reference/components/menus/QualityScoreDoc.md +0 -15
  159. package/docs/reference/components/menus/ReportForm.md +0 -15
  160. package/docs/reference/components/menus/SemanticsDoc.md +0 -15
  161. package/docs/reference/components/menus/SemanticsDownload.md +0 -15
  162. package/docs/reference/components/menus/SemanticsFilters.md +0 -33
  163. package/docs/reference/components/menus/SemanticsList.md +0 -97
  164. package/docs/reference/components/menus/SemanticsMetadata.md +0 -15
  165. package/docs/reference/components/menus/ShareMenu.md +0 -32
  166. package/docs/reference/components/ui/AnnotationsSwitch.md +0 -32
  167. package/docs/reference/components/ui/Button.md +0 -40
  168. package/docs/reference/components/ui/ButtonGroup.md +0 -36
  169. package/docs/reference/components/ui/CopyButton.md +0 -41
  170. package/docs/reference/components/ui/Grade.md +0 -32
  171. package/docs/reference/components/ui/GradeFilter.md +0 -42
  172. package/docs/reference/components/ui/IconSwitch.md +0 -53
  173. package/docs/reference/components/ui/LinkButton.md +0 -45
  174. package/docs/reference/components/ui/ListGroup.md +0 -22
  175. package/docs/reference/components/ui/ListItem.md +0 -39
  176. package/docs/reference/components/ui/Loader.md +0 -56
  177. package/docs/reference/components/ui/Map.md +0 -150
  178. package/docs/reference/components/ui/MapMore.md +0 -150
  179. package/docs/reference/components/ui/Photo.md +0 -495
  180. package/docs/reference/components/ui/Popup.md +0 -56
  181. package/docs/reference/components/ui/ProgressBar.md +0 -32
  182. package/docs/reference/components/ui/QualityScore.md +0 -45
  183. package/docs/reference/components/ui/SearchBar.md +0 -63
  184. package/docs/reference/components/ui/SemanticsEditor.md +0 -113
  185. package/docs/reference/components/ui/SemanticsTable.md +0 -32
  186. package/docs/reference/components/ui/Switch.md +0 -49
  187. package/docs/reference/components/ui/TogglableGroup.md +0 -39
  188. package/docs/reference/components/ui/widgets/CopyCoordinates.md +0 -32
  189. package/docs/reference/components/ui/widgets/GeoSearch.md +0 -36
  190. package/docs/reference/components/ui/widgets/Legend.md +0 -58
  191. package/docs/reference/components/ui/widgets/LevelSelect.md +0 -16
  192. package/docs/reference/components/ui/widgets/MapFiltersButton.md +0 -37
  193. package/docs/reference/components/ui/widgets/MapLayersButton.md +0 -15
  194. package/docs/reference/components/ui/widgets/OSMEditors.md +0 -15
  195. package/docs/reference/components/ui/widgets/PictureLegendActions.md +0 -32
  196. package/docs/reference/components/ui/widgets/Player.md +0 -34
  197. package/docs/reference/components/ui/widgets/SemanticsFiltersButton.md +0 -15
  198. package/docs/reference/components/ui/widgets/Zoom.md +0 -15
  199. package/docs/reference/utils/API.md +0 -389
  200. package/docs/reference/utils/InitParameters.md +0 -68
  201. package/docs/reference/utils/MapStyleComposer.md +0 -408
  202. package/docs/reference/utils/PanoraMapProtocol.md +0 -28
  203. package/docs/reference/utils/PresetsManager.md +0 -43
  204. package/docs/reference/utils/SemanticsMapProtocol.md +0 -43
  205. package/docs/reference/utils/URLHandler.md +0 -114
  206. package/docs/reference.md +0 -99
  207. package/docs/shortcuts.md +0 -11
  208. package/docs/tutorials/aerial_imagery.md +0 -21
  209. package/docs/tutorials/authentication.md +0 -10
  210. package/docs/tutorials/custom_widgets.md +0 -59
  211. package/docs/tutorials/indoor_maps.md +0 -50
  212. package/docs/tutorials/map_style.md +0 -83
  213. package/docs/tutorials/migrate_v4.md +0 -153
  214. package/docs/tutorials/migrate_v5.md +0 -103
  215. package/docs/tutorials/semantics_overlays.md +0 -74
  216. package/docs/tutorials/synced_coverage.md +0 -43
  217. package/mkdocs.yml +0 -131
  218. package/public/editor.html +0 -53
  219. package/public/index.html +0 -70
  220. package/public/map.html +0 -55
  221. package/public/photo.html +0 -43
  222. package/public/servers.js +0 -15
  223. package/public/viewer.html +0 -79
  224. package/public/viewer_indoor.html +0 -48
  225. package/public/widgets.html +0 -366
  226. package/scripts/build.js +0 -217
  227. package/scripts/doc.js +0 -79
  228. package/scripts/start.js +0 -172
  229. package/scripts/test.js +0 -52
  230. package/src/components/core/index.js +0 -12
  231. package/src/components/index.js +0 -13
  232. package/src/components/index_photoviewer.js +0 -8
  233. package/src/components/layout/index.js +0 -9
  234. package/src/components/menus/index.js +0 -22
  235. package/src/components/menus/index_photoviewer.js +0 -13
  236. package/src/components/ui/index.js +0 -29
  237. package/src/components/ui/index_photoviewer.js +0 -23
  238. package/src/components/ui/widgets/index.js +0 -16
  239. package/src/components/ui/widgets/index_photoviewer.js +0 -9
  240. package/src/index.js +0 -8
  241. package/src/index_photoviewer.js +0 -6
  242. package/src/utils/index.js +0 -17
  243. package/src/utils/index_photoviewer.js +0 -16
  244. package/tests/components/core/Basic.test.js +0 -168
  245. package/tests/components/core/BasicMock.js +0 -25
  246. package/tests/components/core/CoverageMap.test.js +0 -20
  247. package/tests/components/core/Editor.test.js +0 -20
  248. package/tests/components/core/PhotoViewer.test.js +0 -57
  249. package/tests/components/core/Viewer.test.js +0 -85
  250. package/tests/components/core/__snapshots__/PhotoViewer.test.js.snap +0 -96
  251. package/tests/components/core/__snapshots__/Viewer.test.js.snap +0 -188
  252. package/tests/components/ui/CopyButton.test.js +0 -52
  253. package/tests/components/ui/Loader.test.js +0 -55
  254. package/tests/components/ui/Map.test.js +0 -145
  255. package/tests/components/ui/Photo.test.js +0 -437
  256. package/tests/components/ui/Popup.test.js +0 -26
  257. package/tests/components/ui/QualityScore.test.js +0 -18
  258. package/tests/components/ui/SearchBar.test.js +0 -110
  259. package/tests/components/ui/__snapshots__/CopyButton.test.js.snap +0 -33
  260. package/tests/components/ui/__snapshots__/Loader.test.js.snap +0 -56
  261. package/tests/components/ui/__snapshots__/Map.test.js.snap +0 -16
  262. package/tests/components/ui/__snapshots__/Photo.test.js.snap +0 -263
  263. package/tests/components/ui/__snapshots__/Popup.test.js.snap +0 -29
  264. package/tests/components/ui/__snapshots__/QualityScore.test.js.snap +0 -11
  265. package/tests/components/ui/__snapshots__/SearchBar.test.js.snap +0 -65
  266. package/tests/data/Map_geocoder_ban.json +0 -36
  267. package/tests/data/Map_geocoder_nominatim.json +0 -41
  268. package/tests/data/Viewer_pictures_1.json +0 -148
  269. package/tests/setupTests.js +0 -5
  270. package/tests/utils/API.test.js +0 -752
  271. package/tests/utils/InitParameters.test.js +0 -599
  272. package/tests/utils/MapStyleComposer.test.js +0 -697
  273. package/tests/utils/PresetsManager.test.js +0 -123
  274. package/tests/utils/URLHandler.test.js +0 -587
  275. package/tests/utils/__snapshots__/API.test.js.snap +0 -40
  276. package/tests/utils/__snapshots__/MapStyleComposer.test.js.snap +0 -767
  277. package/tests/utils/__snapshots__/URLHandler.test.js.snap +0 -21
  278. package/tests/utils/__snapshots__/geocoder.test.js.snap +0 -37
  279. package/tests/utils/__snapshots__/map.test.js.snap +0 -1249
  280. package/tests/utils/__snapshots__/picture.test.js.snap +0 -327
  281. package/tests/utils/__snapshots__/widgets.test.js.snap +0 -19
  282. package/tests/utils/geocoder.test.js +0 -37
  283. package/tests/utils/i18n.test.js +0 -111
  284. package/tests/utils/map.test.js +0 -200
  285. package/tests/utils/picture.test.js +0 -745
  286. package/tests/utils/semantics.test.js +0 -174
  287. package/tests/utils/utils.test.js +0 -358
  288. package/tests/utils/widgets.test.js +0 -31
  289. /package/{src → build}/components/core/Basic.css +0 -0
  290. /package/{src → build}/components/core/CoverageMap.css +0 -0
  291. /package/{src → build}/components/core/Editor.css +0 -0
  292. /package/{src → build}/components/core/PhotoViewer.css +0 -0
  293. /package/{src → build}/components/core/Viewer.css +0 -0
  294. /package/{src → build}/components/ui/ButtonGroup.css +0 -0
  295. /package/{src → build}/components/ui/Map.css +0 -0
  296. /package/{src → build}/components/ui/Photo.css +0 -0
  297. /package/{src → build}/components/ui/ProgressBar.js +0 -0
  298. /package/{src → build}/components/ui/widgets/GeoSearch.css +0 -0
  299. /package/{src → build}/components/ui/widgets/LevelSelect.css +0 -0
  300. /package/{src → build}/components/ui/widgets/Player.css +0 -0
  301. /package/{public → build}/favicon.ico +0 -0
  302. /package/{src → build}/img/arrow_360.svg +0 -0
  303. /package/{src → build}/img/arrow_flat.svg +0 -0
  304. /package/{src → build}/img/bg_aerial.jpg +0 -0
  305. /package/{src → build}/img/bg_streets.jpg +0 -0
  306. /package/{src → build}/img/loader_base.jpg +0 -0
  307. /package/{src → build}/img/logo_dead.svg +0 -0
  308. /package/{src → build}/img/marker.svg +0 -0
  309. /package/{src → build}/img/marker_blue.svg +0 -0
  310. /package/{src → build}/img/osm.svg +0 -0
  311. /package/{src → build}/img/panoramax.svg +0 -0
  312. /package/{src → build}/img/switch_big.svg +0 -0
  313. /package/{src → build}/img/switch_mini.svg +0 -0
  314. /package/{src → build}/img/wd.svg +0 -0
  315. /package/{src → build}/translations/ar.json +0 -0
  316. /package/{src → build}/translations/be.json +0 -0
  317. /package/{src → build}/translations/br.json +0 -0
  318. /package/{src → build}/translations/cy.json +0 -0
  319. /package/{src → build}/translations/da.json +0 -0
  320. /package/{src → build}/translations/de.json +0 -0
  321. /package/{src → build}/translations/en.json +0 -0
  322. /package/{src → build}/translations/eo.json +0 -0
  323. /package/{src → build}/translations/es.json +0 -0
  324. /package/{src → build}/translations/fi.json +0 -0
  325. /package/{src → build}/translations/fr.json +0 -0
  326. /package/{src → build}/translations/hu.json +0 -0
  327. /package/{src → build}/translations/it.json +0 -0
  328. /package/{src → build}/translations/ja.json +0 -0
  329. /package/{src → build}/translations/ko.json +0 -0
  330. /package/{src → build}/translations/nl.json +0 -0
  331. /package/{src → build}/translations/nn.json +0 -0
  332. /package/{src → build}/translations/pl.json +0 -0
  333. /package/{src → build}/translations/pt.json +0 -0
  334. /package/{src → build}/translations/pt_BR.json +0 -0
  335. /package/{src → build}/translations/sv.json +0 -0
  336. /package/{src → build}/translations/ti.json +0 -0
  337. /package/{src → build}/translations/tr.json +0 -0
  338. /package/{src → build}/translations/uk.json +0 -0
  339. /package/{src → build}/translations/zh_Hant.json +0 -0
  340. /package/{src → build}/utils/PanoraMapProtocol.js +0 -0
  341. /package/{src → build}/utils/services.js +0 -0
@@ -1,752 +0,0 @@
1
- import API from "../../src/utils/API";
2
-
3
- global.AbortSignal = { timeout: jest.fn() };
4
- global.console = { log: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn() };
5
-
6
- const ENDPOINT = "https://panoramax.ign.fr/api";
7
- const VALID_LANDING = {
8
- stac_version: "1.0.0",
9
- links: [
10
- { "rel": "data", "type": "application/rss+xml", "href": ENDPOINT+"/collections?format=rss" },
11
- { "rel": "data", "type": "application/json", "href": ENDPOINT+"/collections" },
12
- { "rel": "search", "type": "application/geo+json", "href": ENDPOINT+"/search" },
13
- { "rel": "xyz", "type": "application/vnd.mapbox-vector-tile", "href": ENDPOINT+"/map/{z}/{x}/{y}.mvt" },
14
- { "rel": "collection-preview", "type": "image/jpeg", "href": ENDPOINT+"/collections/{id}/thumb.jpg" },
15
- { "rel": "item-preview", "type": "image/jpeg", "href": ENDPOINT+"/pictures/{id}/thumb.jpg" },
16
- { "rel": "report", "type": "application/json", "href": ENDPOINT+"/reports" },
17
- ],
18
- "extent": {
19
- "spatial": {
20
- "bbox": [[-0.586, 0, 6.690, 49.055]]
21
- },
22
- "temporal": {
23
- "interval": [[ "2019-08-18T14:11:29+00:00", "2023-05-30T18:16:21.167000+00:00" ]]
24
- }
25
- }
26
- };
27
- const LANDING_NO_PREVIEW = {
28
- stac_version: "1.0.0",
29
- links: [
30
- { "rel": "data", "type": "application/json", "href": ENDPOINT+"/collections" },
31
- { "rel": "search", "type": "application/geo+json", "href": ENDPOINT+"/search" },
32
- ]
33
- };
34
-
35
- describe("constructor", () => {
36
- // Mock landing fetch
37
- global.fetch = () => Promise.resolve({
38
- json: () => new Promise(resolve => setTimeout(() => resolve(VALID_LANDING), 50))
39
- });
40
-
41
- it("works with valid endpoint", () => {
42
- const api = new API(ENDPOINT);
43
- expect(api._endpoint).toBe(ENDPOINT);
44
- });
45
-
46
- it("works with relative path", () => {
47
- const api = new API("/api");
48
- expect(api._endpoint).toBe("http://localhost/api");
49
- });
50
-
51
- it("handles tiles overrides", () => {
52
- const listener = jest.fn();
53
- const api = new API(ENDPOINT, { tiles: "https://my.custom.tiles/" });
54
- api.addEventListener("ready", listener);
55
- return api.onceReady().then(() => {
56
- expect(api._endpoint).toBe(ENDPOINT);
57
- expect(api._endpoints.tiles).toBe("https://my.custom.tiles/");
58
- expect(listener).toHaveBeenCalled();
59
- });
60
- });
61
-
62
- it("fails if endpoint is invalid", () => {
63
- expect(() => new API("not an url")).toThrow("endpoint parameter is not a valid URL: not an url");
64
- });
65
-
66
- it("fails if endpoint is empty", () => {
67
- expect(() => new API()).toThrow("endpoint parameter is empty or not a valid string");
68
- });
69
-
70
- it("fails on fetch failure", async () => {
71
- // Mock landing fetch
72
- global.fetch = () => Promise.resolve({
73
- json: () => new Promise((resolve, reject) => setTimeout(() => reject(new Error("brok")), 50))
74
- });
75
-
76
- const listener = jest.fn();
77
- const api = new API(ENDPOINT);
78
- api.addEventListener("broken", listener);
79
- return api.onceReady().catch(e => {
80
- expect(e).toEqual("Viewer failed to communicate with API");
81
- expect(listener.mock.calls).toMatchSnapshot();
82
- });
83
- });
84
-
85
- it("accepts fetch options", () => {
86
- const api = new API("/api", { fetch: { bla: "bla" } });
87
- expect(api._getFetchOptions()).toEqual({ bla: "bla" });
88
- });
89
- });
90
-
91
- describe("onceReady", () => {
92
- it("works if API is ready", async () => {
93
- // Mock landing fetch
94
- global.fetch = jest.fn(() => Promise.resolve({
95
- json: () => Promise.resolve(VALID_LANDING)
96
- }));
97
-
98
- const api = new API(ENDPOINT);
99
- const res = await api.onceReady();
100
- expect(res).toBe("API is ready");
101
-
102
- // Also work after initial promise resolve
103
- const res2 = await api.onceReady();
104
- expect(res2).toBe("API is ready");
105
- });
106
-
107
- it("handles API failures", async () => {
108
- // Mock landing fetch
109
- fetch.mockRejectedValueOnce();
110
-
111
- const api = new API(ENDPOINT);
112
- await expect(api.onceReady()).rejects.toBe("Viewer failed to communicate with API");
113
-
114
- // Also work after initial promise end
115
- await expect(api.onceReady()).rejects.toBe("Viewer failed to communicate with API");
116
- });
117
- });
118
-
119
- describe("isReady", () => {
120
- // Randomly fails for no reason
121
- it.skip("works if API is ready", async () => {
122
- // Mock landing fetch
123
- global.fetch = jest.fn(() => Promise.resolve({
124
- json: () => Promise.resolve(VALID_LANDING)
125
- }));
126
-
127
- const api = new API(ENDPOINT);
128
- await api.onceReady();
129
- expect(api.isReady()).toBeTruthy();
130
- });
131
-
132
- it("works with API failing", async () => {
133
- // Mock landing fetch
134
- fetch.mockRejectedValueOnce();
135
-
136
- const api = new API(ENDPOINT);
137
- try {
138
- return await api.onceReady();
139
- } catch {
140
- expect(api.isReady()).toBeFalsy();
141
- }
142
- });
143
- });
144
-
145
- describe("getAvailableFeatures", () => {
146
- it("works", () => {
147
- const api = new API(ENDPOINT, { skipReadLanding: true });
148
- api._parseLanding(LANDING_NO_PREVIEW);
149
- expect(api.getAvailableFeatures()).toStrictEqual(["collections", "search"]);
150
- });
151
- });
152
-
153
- describe("getUnavailableFeatures", () => {
154
- it("works", () => {
155
- const api = new API(ENDPOINT, { skipReadLanding: true });
156
- api._parseLanding(LANDING_NO_PREVIEW);
157
- expect(api.getUnavailableFeatures()).toStrictEqual(["style", "user_style", "tiles", "user_tiles", "user_search", "collection_preview", "item_preview", "rss", "report", "queryables"]);
158
- });
159
- });
160
-
161
- describe("_parseLanding", () => {
162
- it("handles overrides for tiles URL", () => {
163
- const api = new API (ENDPOINT, { skipReadLanding: true });
164
- api._parseLanding(VALID_LANDING, { tiles: "https://my.custom.tiles/" });
165
- expect(api._endpoints.tiles).toBe("https://my.custom.tiles/");
166
- });
167
-
168
- it("fails if landing JSON lacks info", () => {
169
- const api = new API (ENDPOINT, { skipReadLanding: true });
170
- expect(() => api._parseLanding({})).toThrow("API Landing page doesn't contain 'links' list");
171
- });
172
-
173
- it.each([
174
- ["search", "application/geo+json"],
175
- ["data", "application/json"],
176
- ["data", "application/rss+xml"],
177
- ["xyz", "application/vnd.mapbox-vector-tile"],
178
- ["xyz-style", "application/json"],
179
- ["user-xyz", "application/vnd.mapbox-vector-tile"],
180
- ["user-xyz-style", "application/json"],
181
- ["user-search", "application/json"],
182
- ["collection-preview", "image/jpeg"],
183
- ["item-preview", "image/jpeg"],
184
- ["report", "application/json"],
185
- ])("fails if link rel=%s type=%s is invalid", (rel, type) => {
186
- const api = new API (ENDPOINT, { skipReadLanding: true });
187
- const landing = {
188
- stac_version: "1.0.0",
189
- links: [
190
- { "rel": rel, "href": "bla", "type": type }
191
- ]
192
- };
193
- try {
194
- api._parseLanding(landing);
195
- throw new Error("Should not succeed");
196
- }
197
- catch(e) {
198
- expect(e.message).toMatchSnapshot();
199
- }
200
- });
201
-
202
-
203
- it("fails if API version is not supported", () => {
204
- const api = new API (ENDPOINT, { skipReadLanding: true });
205
- const landing = { stac_version: "0.1", links: [] };
206
- expect(() => api._parseLanding(landing)).toThrow("API is not in a supported STAC version (Panoramax viewer supports only 1.x, API is 0.1)");
207
- });
208
-
209
- it("fails if mandatory links are not set", () => {
210
- const api = new API (ENDPOINT, { skipReadLanding: true });
211
- const landing = {
212
- stac_version: "1.0.0",
213
- links: []
214
- };
215
- try {
216
- api._parseLanding(landing);
217
- throw new Error("Should not succeed");
218
- }
219
- catch(e) {
220
- expect(e.message).toMatchSnapshot();
221
- }
222
- });
223
- });
224
-
225
- describe("_getFetchOptions", () => {
226
- const api = new API(ENDPOINT, { fetch: { bla: true }, skipReadLanding: true });
227
- api._parseLanding(LANDING_NO_PREVIEW);
228
-
229
- it("works with defaults", () => {
230
- const res = api._getFetchOptions();
231
- expect(res).toStrictEqual({ bla: true, signal: AbortSignal.timeout(15000) });
232
- });
233
-
234
- it("works with noTimeout", () => {
235
- const res = api._getFetchOptions(true);
236
- expect(res).toStrictEqual({ bla: true });
237
- });
238
- });
239
-
240
- describe("_getMapRequestTransform", () => {
241
- it("does nothing if no tiles enabled", () => {
242
- const api = new API(ENDPOINT, { skipReadLanding: true });
243
- api._parseLanding(LANDING_NO_PREVIEW);
244
- const res = api._getMapRequestTransform();
245
- expect(res(ENDPOINT)).toBeUndefined();
246
- });
247
-
248
- it("does nothing if no fetch options defined", () => {
249
- const api = new API(ENDPOINT, { skipReadLanding: true });
250
- api._parseLanding(VALID_LANDING);
251
- const res = api._getMapRequestTransform();
252
- expect(res(ENDPOINT)).toBeUndefined();
253
- });
254
-
255
- it("overrides IGN sprites URL", () => {
256
- const api = new API(ENDPOINT, { skipReadLanding: true });
257
- api._parseLanding(VALID_LANDING);
258
- const res = api._getMapRequestTransform();
259
- expect(res("https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/sprite/PlanIgn-Gris@2x.json"))
260
- .toEqual({ url: "https://data.geopf.fr/annexes/ressources/vectorTiles/styles/PLAN.IGN/sprite/PlanIgn-Gris.json" });
261
- });
262
-
263
- it("returns a function with correct options if fetch options defined", () => {
264
- const api = new API(ENDPOINT, {
265
- skipReadLanding: true,
266
- fetch: {
267
- credentials: "include",
268
- headers: { "Accept-Header": "Whatever" }
269
- }
270
- });
271
- api._parseLanding(VALID_LANDING);
272
-
273
- // With tiles endpoint called
274
- const res = api._getMapRequestTransform();
275
- const res1 = res(ENDPOINT+"/map/8/1234/4567.mvt");
276
- expect(res1).toEqual({
277
- url: ENDPOINT+"/map/8/1234/4567.mvt",
278
- credentials: "include",
279
- headers: { "Accept-Header": "Whatever" }
280
- });
281
-
282
- // With external endpoint called
283
- const res2 = res("https://my-tile-provider.fr/map/1/2/3.mvt");
284
- expect(res2).toEqual(undefined);
285
- });
286
- });
287
-
288
- describe("_getPSVWithCredentials", () => {
289
- it("works with credentials", () => {
290
- const api = new API(ENDPOINT, { skipReadLanding: true, fetch: {credentials: "include"} });
291
- api._parseLanding(VALID_LANDING);
292
- const res = api._getPSVWithCredentials();
293
- expect(typeof res).toBe("function");
294
- expect(res(ENDPOINT)).toBe(true);
295
- expect(res("bla")).toBe(false);
296
- });
297
-
298
- it("works without credentials", () => {
299
- const api = new API(ENDPOINT, { skipReadLanding: true });
300
- api._parseLanding(VALID_LANDING);
301
- const res = api._getPSVWithCredentials();
302
- expect(res).toBeUndefined();
303
- });
304
- });
305
-
306
- describe("cleanResourceURL", () => {
307
- it("works with empty", () => {
308
- const api = new API(ENDPOINT, { skipReadLanding: true });
309
- expect(api.cleanResourceURL()).toBeUndefined();
310
- expect(api.cleanResourceURL("")).toBeUndefined();
311
- });
312
-
313
- it("works with full URL", () => {
314
- const api = new API(ENDPOINT, { skipReadLanding: true });
315
- expect(api.cleanResourceURL("https://panoramax.fr/bla")).toBe("https://panoramax.fr/bla");
316
- });
317
-
318
- it("works with absolute URL", () => {
319
- const api = new API(ENDPOINT, { skipReadLanding: true });
320
- expect(api.cleanResourceURL("/api/bla")).toBe(ENDPOINT+"/bla");
321
- });
322
-
323
- it("works with relative URL", () => {
324
- const api = new API(ENDPOINT, { skipReadLanding: true });
325
- expect(api.cleanResourceURL("./bla")).toBe(ENDPOINT+"/bla");
326
- });
327
- });
328
-
329
- describe("getPicturesAroundCoordinatesUrl", () => {
330
- it("works with valid coordinates", () => {
331
- const api = new API(ENDPOINT, { skipReadLanding: true });
332
- api._parseLanding(VALID_LANDING);
333
- api._isReady = 1;
334
- expect(api.getPicturesAroundCoordinatesUrl(48.7, -1.25)).toBe(`${ENDPOINT}/search?bbox=-1.2505000,48.6995000,-1.2495000,48.7005000`);
335
- });
336
-
337
- it("fails if coordinates are invalid", () => {
338
- const api = new API(ENDPOINT, { skipReadLanding: true });
339
- api._parseLanding(VALID_LANDING);
340
- api._isReady = 1;
341
- expect(() => api.getPicturesAroundCoordinatesUrl()).toThrow("lat and lon parameters should be valid numbers");
342
- });
343
- });
344
-
345
- describe("getPictureMetadataUrl", () => {
346
- it("works with valid ID", () => {
347
- const api = new API(ENDPOINT, { skipReadLanding: true });
348
- api._parseLanding(VALID_LANDING);
349
- api._isReady = 1;
350
- expect(api.getPictureMetadataUrl("whatever-id")).toBe(`${ENDPOINT}/search?ids=whatever-id`);
351
- });
352
-
353
- it("works with valid ID and sequence", () => {
354
- const api = new API(ENDPOINT, { skipReadLanding: true });
355
- api._parseLanding(VALID_LANDING);
356
- api._isReady = 1;
357
- expect(api.getPictureMetadataUrl("whatever-id", "my-sequence")).toBe(`${ENDPOINT}/collections/my-sequence/items/whatever-id`);
358
- });
359
-
360
- it("fails if picId is invalid", () => {
361
- const api = new API(ENDPOINT, { skipReadLanding: true });
362
- api._parseLanding(VALID_LANDING);
363
- api._isReady = 1;
364
- expect(() => api.getPictureMetadataUrl()).toThrow("id should be a valid picture unique identifier");
365
- });
366
- });
367
-
368
- describe("findThumbnailInPictureFeature", () => {
369
- it("works if a thumbnail exists", () => {
370
- const api = new API(ENDPOINT, { skipReadLanding: true });
371
- api._parseLanding(VALID_LANDING);
372
- api._isReady = 1;
373
- const res = api.findThumbnailInPictureFeature({
374
- assets: {
375
- t: {
376
- roles: ["thumbnail"],
377
- type: "image/jpeg",
378
- href: "https://geovisio.fr/thumb.jpg"
379
- }
380
- }
381
- });
382
- expect(res).toEqual("https://geovisio.fr/thumb.jpg");
383
- });
384
-
385
- it("works if a visual exists", () => {
386
- const api = new API(ENDPOINT, { skipReadLanding: true });
387
- api._parseLanding(VALID_LANDING);
388
- api._isReady = 1;
389
- const res = api.findThumbnailInPictureFeature({
390
- assets: {
391
- t: {
392
- roles: ["visual"],
393
- type: "image/jpeg",
394
- href: "https://geovisio.fr/thumb.jpg"
395
- }
396
- }
397
- });
398
- expect(res).toEqual("https://geovisio.fr/thumb.jpg");
399
- });
400
-
401
- it("works if no thumbnail is found", () => {
402
- const api = new API(ENDPOINT, { skipReadLanding: true });
403
- api._parseLanding(VALID_LANDING);
404
- api._isReady = 1;
405
- const res = api.findThumbnailInPictureFeature({});
406
- expect(res).toBe(null);
407
- });
408
- });
409
-
410
- describe("getPictureThumbnailURLForSequence", () => {
411
- it("works with a collection-preview endpoint", () => {
412
- const api = new API(ENDPOINT, { skipReadLanding: true });
413
- api._parseLanding(VALID_LANDING);
414
- api._isReady = 1;
415
- return api.getPictureThumbnailURLForSequence("12345").then(url => {
416
- expect(url).toBe(ENDPOINT+"/collections/12345/thumb.jpg");
417
- });
418
- });
419
-
420
- it("works if a preview is defined in sequence metadata", () => {
421
- const api = new API(ENDPOINT, { skipReadLanding: true });
422
- api._parseLanding(LANDING_NO_PREVIEW);
423
- api._isReady = 1;
424
- const seq = {
425
- links: [
426
- { "type": "image/jpeg", "rel": "preview", "href": "https://geovisio.fr/preview/thumb.jpg" }
427
- ]
428
- };
429
- return api.getPictureThumbnailURLForSequence("12345", seq).then(url => {
430
- expect(url).toBe("https://geovisio.fr/preview/thumb.jpg");
431
- });
432
- });
433
-
434
-
435
- it("works with an existing sequence", () => {
436
- const resPicId = "cbfc3add-8173-4464-98c8-de2a43c6a50f";
437
- const thumbUrl = "http://my.custom.api/pic/thumb.jpg";
438
- // Mock API search
439
- global.fetch = jest.fn(() => Promise.resolve({
440
- json: () => Promise.resolve({
441
- features: [ {
442
- "id": resPicId,
443
- "assets": {
444
- "thumb": {
445
- "href": thumbUrl,
446
- "roles": ["thumbnail"],
447
- "type": "image/jpeg"
448
- }
449
- }
450
- }]
451
- })
452
- }));
453
-
454
- const api = new API(ENDPOINT, { skipReadLanding: true });
455
- api._parseLanding(LANDING_NO_PREVIEW);
456
- api._isReady = 1;
457
- return api.getPictureThumbnailURLForSequence("208b981a-262e-4966-97b6-98ee0ceb8df0").then(url => {
458
- expect(url).toBe(thumbUrl);
459
- });
460
- });
461
-
462
- it("works with no results", () => {
463
- // Mock API search
464
- global.fetch = jest.fn(() => Promise.resolve({
465
- json: () => Promise.resolve({
466
- features: []
467
- })
468
- }));
469
-
470
- const api = new API(ENDPOINT, { skipReadLanding: true });
471
- api._parseLanding(LANDING_NO_PREVIEW);
472
- api._isReady = 1;
473
- return api.getPictureThumbnailURLForSequence("208b981a-262e-4966-97b6-98ee0ceb8df0").then(url => {
474
- expect(url).toBe(null);
475
- });
476
- });
477
- });
478
-
479
- describe("getPictureThumbnailURL", () => {
480
- it("works with a item-preview endpoint", () => {
481
- const api = new API(ENDPOINT, { skipReadLanding: true });
482
- api._parseLanding(VALID_LANDING);
483
- api._isReady = 1;
484
- return api.getPictureThumbnailURL("12345").then(url => {
485
- expect(url).toBe(ENDPOINT+"/pictures/12345/thumb.jpg");
486
- });
487
- });
488
-
489
- it("works with picture and sequence ID defined", () => {
490
- const api = new API(ENDPOINT, { skipReadLanding: true });
491
- api._parseLanding(LANDING_NO_PREVIEW);
492
- api._isReady = 1;
493
-
494
- // Mock API search
495
- global.fetch = jest.fn(() => Promise.resolve({
496
- json: () => Promise.resolve({
497
- "assets": {
498
- "thumb": {
499
- "href": ENDPOINT+"/pictures/pic1/thumb.jpg",
500
- "roles": ["thumbnail"],
501
- "type": "image/jpeg"
502
- }
503
- }
504
- })
505
- }));
506
-
507
- return api.getPictureThumbnailURL("pic1", "seq1").then(url => {
508
- expect(url).toBe(ENDPOINT+"/pictures/pic1/thumb.jpg");
509
- });
510
- });
511
-
512
- it("works with picture and sequence ID defined, but no thumb found", () => {
513
- const api = new API(ENDPOINT, { skipReadLanding: true });
514
- api._parseLanding(LANDING_NO_PREVIEW);
515
- api._isReady = 1;
516
-
517
- // Mock API search
518
- global.fetch = jest.fn(() => Promise.resolve({
519
- json: () => Promise.resolve({})
520
- }));
521
-
522
- return api.getPictureThumbnailURL("pic1", "seq1").then(url => {
523
- expect(url).toBe(null);
524
- });
525
- });
526
-
527
- it("works with picture ID defined", () => {
528
- const api = new API(ENDPOINT, { skipReadLanding: true });
529
- api._parseLanding(LANDING_NO_PREVIEW);
530
- api._isReady = 1;
531
-
532
- // Mock API search
533
- global.fetch = jest.fn(() => Promise.resolve({
534
- json: () => Promise.resolve({
535
- features: [{
536
- "assets": {
537
- "thumb": {
538
- "href": ENDPOINT+"/pictures/pic1/thumb.jpg",
539
- "roles": ["thumbnail"],
540
- "type": "image/jpeg"
541
- }
542
- }
543
- }]
544
- })
545
- }));
546
-
547
- return api.getPictureThumbnailURL("pic1").then(url => {
548
- expect(url).toBe(ENDPOINT+"/pictures/pic1/thumb.jpg");
549
- });
550
- });
551
-
552
- it("works with picture ID defined but no results", () => {
553
- const api = new API(ENDPOINT, { skipReadLanding: true });
554
- api._parseLanding(LANDING_NO_PREVIEW);
555
- api._isReady = 1;
556
-
557
- // Mock API search
558
- global.fetch = jest.fn(() => Promise.resolve({
559
- json: () => Promise.resolve({
560
- features: []
561
- })
562
- }));
563
-
564
- return api.getPictureThumbnailURL("pic1").then(url => {
565
- expect(url).toBe(null);
566
- });
567
- });
568
- });
569
-
570
- describe("getRSSURL", () => {
571
- it("works without RSS", () => {
572
- const api = new API(ENDPOINT, { skipReadLanding: true });
573
- api._parseLanding(LANDING_NO_PREVIEW);
574
- api._isReady = 1;
575
- expect(api.getRSSURL()).toBeNull();
576
- });
577
-
578
- it("works with RSS and no bbox", () => {
579
- const api = new API(ENDPOINT, { skipReadLanding: true });
580
- api._parseLanding(VALID_LANDING);
581
- api._isReady = 1;
582
- expect(api.getRSSURL()).toBe(ENDPOINT+"/collections?format=rss");
583
- });
584
-
585
- it("works with RSS and bbox with query string", () => {
586
- const api = new API(ENDPOINT, { skipReadLanding: true });
587
- api._parseLanding(VALID_LANDING);
588
- api._isReady = 1;
589
- const bbox = {
590
- getSouth: () => -1.7,
591
- getNorth: () => -1.6,
592
- getWest: () => 47.1,
593
- getEast: () => 48.2
594
- };
595
- expect(api.getRSSURL(bbox)).toBe(ENDPOINT+"/collections?format=rss&bbox=47.1,-1.7,48.2,-1.6");
596
- });
597
-
598
- it("works with RSS and bbox without query string", () => {
599
- const api = new API(ENDPOINT, { skipReadLanding: true });
600
- api._parseLanding({
601
- stac_version: "1.0.0",
602
- links: [
603
- { "rel": "data", "type": "application/json", "href": ENDPOINT+"/collections" },
604
- { "rel": "search", "type": "application/geo+json", "href": ENDPOINT+"/search" },
605
- { "rel": "data", "href": ENDPOINT+"/collections", "type": "application/rss+xml" }
606
- ]
607
- });
608
- api._isReady = 1;
609
- const bbox = {
610
- getSouth: () => -1.7,
611
- getNorth: () => -1.6,
612
- getWest: () => 47.1,
613
- getEast: () => 48.2
614
- };
615
- expect(api.getRSSURL(bbox)).toBe(ENDPOINT+"/collections?bbox=47.1,-1.7,48.2,-1.6");
616
- });
617
- });
618
-
619
- describe("getSequenceMetadataUrl", () => {
620
- it("works", () => {
621
- const api = new API(ENDPOINT, { skipReadLanding: true });
622
- api._parseLanding(VALID_LANDING);
623
- api._isReady = 1;
624
- expect(api.getSequenceMetadataUrl("blabla")).toBe(ENDPOINT+"/collections/blabla");
625
- });
626
- });
627
-
628
- describe("getDataBbox", () => {
629
- it("works with landing spatial extent defined", () => {
630
- const api = new API(ENDPOINT, { skipReadLanding: true });
631
- api._parseLanding(VALID_LANDING);
632
- api._isReady = 1;
633
- expect(api.getDataBbox()).toEqual([[-0.586, 0], [6.690, 49.055]]);
634
- });
635
-
636
- it("works with no landing spatial extent defined", () => {
637
- const api = new API(ENDPOINT, { skipReadLanding: true });
638
- api._parseLanding(LANDING_NO_PREVIEW);
639
- api._isReady = 1;
640
- expect(api.getDataBbox()).toBe(null);
641
- });
642
- });
643
-
644
- describe("sendReport", () => {
645
- let api;
646
-
647
- beforeEach(() => {
648
- api = new API(ENDPOINT, { skipReadLanding: true });
649
- api._parseLanding(VALID_LANDING);
650
- api.isReady = () => true;
651
- });
652
-
653
- it("throws an error if API is not ready", () => {
654
- api.isReady = () => false;
655
- expect(() => api.sendReport({})).toThrow("API is not ready to use");
656
- });
657
-
658
- it("throws an error if report endpoint is not available", () => {
659
- api._endpoints.report = null;
660
- expect(() => api.sendReport({})).toThrow("Report sending is not available");
661
- });
662
-
663
- it("sends a report successfully", async () => {
664
- // Mock fetch response
665
- const mockResponse = {
666
- status: 200,
667
- json: jest.fn().mockResolvedValue({ id: "bla" })
668
- };
669
- global.fetch = jest.fn().mockResolvedValue(mockResponse);
670
-
671
- const data = {
672
- issue: "blur_missing",
673
- picture_id: "bla1",
674
- sequence_id: "bla2",
675
- };
676
-
677
- const response = await api.sendReport(data);
678
-
679
- expect(fetch).toHaveBeenCalledWith(ENDPOINT+"/reports", {
680
- method: "POST",
681
- body: JSON.stringify(data),
682
- headers: { "Content-Type": "application/json" }
683
- });
684
- expect(response).toEqual({ id: "bla" });
685
- });
686
-
687
- it("handles API errors and rejects with message", async () => {
688
- // Mock fetch response with an error
689
- const mockResponse = {
690
- status: 400,
691
- text: jest.fn().mockResolvedValue(JSON.stringify({ message: "Error occurred" }))
692
- };
693
- global.fetch = jest.fn().mockResolvedValue(mockResponse);
694
-
695
- const data = {
696
- issue: "blur_missing",
697
- picture_id: "bla1",
698
- sequence_id: "bla2",
699
- };
700
-
701
- await expect(api.sendReport(data)).rejects.toEqual("Error occurred");
702
-
703
- expect(fetch).toHaveBeenCalledWith(ENDPOINT+"/reports", {
704
- method: "POST",
705
- body: JSON.stringify(data),
706
- headers: { "Content-Type": "application/json" }
707
- });
708
- });
709
-
710
- it("handles API errors and rejects with text if no message in JSON", async () => {
711
- // Mock fetch response with an error and no "message" key
712
- const mockResponse = {
713
- status: 400,
714
- text: jest.fn().mockResolvedValue("Some error text")
715
- };
716
- global.fetch = jest.fn().mockResolvedValue(mockResponse);
717
-
718
- const data = {
719
- issue: "blur_missing",
720
- picture_id: "bla1",
721
- sequence_id: "bla2",
722
- };
723
-
724
- await expect(api.sendReport(data)).rejects.toEqual("Some error text");
725
-
726
- expect(fetch).toHaveBeenCalledWith(ENDPOINT+"/reports", {
727
- method: "POST",
728
- body: JSON.stringify(data),
729
- headers: { "Content-Type": "application/json" }
730
- });
731
- });
732
- });
733
-
734
- describe("isValidHttpUrl", () => {
735
- it("works with valid endpoint", () => {
736
- expect(API.isValidHttpUrl(ENDPOINT)).toBeTruthy();
737
- });
738
-
739
- it("fails if endpoint is invalid", () => {
740
- expect(API.isValidHttpUrl("not an url")).toBeFalsy();
741
- });
742
- });
743
-
744
- describe("isValidId", () => {
745
- it("works with valid ID", () => {
746
- expect(API.isIdValid("blabla")).toBeTruthy();
747
- });
748
-
749
- it("fails with invalid ID", () => {
750
- expect(() => API.isIdValid(null)).toThrowError("id should be a valid picture unique identifier");
751
- });
752
- });