@panoramax/web-viewer 3.0.2-develop-a8ea8e60

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 (125) hide show
  1. package/.dockerignore +6 -0
  2. package/.gitlab-ci.yml +71 -0
  3. package/CHANGELOG.md +428 -0
  4. package/CODE_OF_CONDUCT.md +134 -0
  5. package/Dockerfile +14 -0
  6. package/LICENSE +21 -0
  7. package/README.md +39 -0
  8. package/build/editor.html +1 -0
  9. package/build/index.css +36 -0
  10. package/build/index.css.map +1 -0
  11. package/build/index.html +1 -0
  12. package/build/index.js +25 -0
  13. package/build/index.js.map +1 -0
  14. package/build/map.html +1 -0
  15. package/build/viewer.html +1 -0
  16. package/config/env.js +104 -0
  17. package/config/getHttpsConfig.js +66 -0
  18. package/config/getPackageJson.js +25 -0
  19. package/config/jest/babelTransform.js +29 -0
  20. package/config/jest/cssTransform.js +14 -0
  21. package/config/jest/fileTransform.js +40 -0
  22. package/config/modules.js +134 -0
  23. package/config/paths.js +72 -0
  24. package/config/pnpTs.js +35 -0
  25. package/config/webpack/persistentCache/createEnvironmentHash.js +9 -0
  26. package/config/webpack.config.js +885 -0
  27. package/config/webpackDevServer.config.js +127 -0
  28. package/docs/01_Start.md +149 -0
  29. package/docs/02_Usage.md +828 -0
  30. package/docs/03_URL_settings.md +140 -0
  31. package/docs/04_Advanced_examples.md +214 -0
  32. package/docs/05_Compatibility.md +85 -0
  33. package/docs/09_Develop.md +62 -0
  34. package/docs/90_Releases.md +27 -0
  35. package/docs/images/class_diagram.drawio +129 -0
  36. package/docs/images/class_diagram.jpg +0 -0
  37. package/docs/images/screenshot.jpg +0 -0
  38. package/mkdocs.yml +45 -0
  39. package/package.json +254 -0
  40. package/public/editor.html +54 -0
  41. package/public/favicon.ico +0 -0
  42. package/public/index.html +59 -0
  43. package/public/map.html +53 -0
  44. package/public/viewer.html +67 -0
  45. package/scripts/build.js +217 -0
  46. package/scripts/start.js +176 -0
  47. package/scripts/test.js +52 -0
  48. package/src/Editor.css +37 -0
  49. package/src/Editor.js +359 -0
  50. package/src/StandaloneMap.js +114 -0
  51. package/src/Viewer.css +203 -0
  52. package/src/Viewer.js +1186 -0
  53. package/src/components/CoreView.css +64 -0
  54. package/src/components/CoreView.js +159 -0
  55. package/src/components/Loader.css +56 -0
  56. package/src/components/Loader.js +111 -0
  57. package/src/components/Map.css +65 -0
  58. package/src/components/Map.js +841 -0
  59. package/src/components/Photo.css +36 -0
  60. package/src/components/Photo.js +687 -0
  61. package/src/img/arrow_360.svg +14 -0
  62. package/src/img/arrow_flat.svg +11 -0
  63. package/src/img/arrow_triangle.svg +10 -0
  64. package/src/img/arrow_turn.svg +9 -0
  65. package/src/img/bg_aerial.jpg +0 -0
  66. package/src/img/bg_streets.jpg +0 -0
  67. package/src/img/loader_base.jpg +0 -0
  68. package/src/img/loader_hd.jpg +0 -0
  69. package/src/img/logo_dead.svg +91 -0
  70. package/src/img/marker.svg +17 -0
  71. package/src/img/marker_blue.svg +20 -0
  72. package/src/img/switch_big.svg +44 -0
  73. package/src/img/switch_mini.svg +48 -0
  74. package/src/index.js +10 -0
  75. package/src/translations/de.json +163 -0
  76. package/src/translations/en.json +164 -0
  77. package/src/translations/eo.json +6 -0
  78. package/src/translations/es.json +164 -0
  79. package/src/translations/fi.json +1 -0
  80. package/src/translations/fr.json +164 -0
  81. package/src/translations/hu.json +133 -0
  82. package/src/translations/nl.json +1 -0
  83. package/src/translations/zh_Hant.json +136 -0
  84. package/src/utils/API.js +709 -0
  85. package/src/utils/Exif.js +198 -0
  86. package/src/utils/I18n.js +75 -0
  87. package/src/utils/Map.js +382 -0
  88. package/src/utils/PhotoAdapter.js +45 -0
  89. package/src/utils/Utils.js +568 -0
  90. package/src/utils/Widgets.js +477 -0
  91. package/src/viewer/URLHash.js +334 -0
  92. package/src/viewer/Widgets.css +711 -0
  93. package/src/viewer/Widgets.js +1196 -0
  94. package/tests/Editor.test.js +125 -0
  95. package/tests/StandaloneMap.test.js +44 -0
  96. package/tests/Viewer.test.js +363 -0
  97. package/tests/__snapshots__/Editor.test.js.snap +300 -0
  98. package/tests/__snapshots__/StandaloneMap.test.js.snap +30 -0
  99. package/tests/__snapshots__/Viewer.test.js.snap +195 -0
  100. package/tests/components/CoreView.test.js +91 -0
  101. package/tests/components/Loader.test.js +38 -0
  102. package/tests/components/Map.test.js +230 -0
  103. package/tests/components/Photo.test.js +335 -0
  104. package/tests/components/__snapshots__/Loader.test.js.snap +15 -0
  105. package/tests/components/__snapshots__/Map.test.js.snap +767 -0
  106. package/tests/components/__snapshots__/Photo.test.js.snap +205 -0
  107. package/tests/data/Map_geocoder_ban.json +36 -0
  108. package/tests/data/Map_geocoder_nominatim.json +56 -0
  109. package/tests/data/Viewer_pictures_1.json +148 -0
  110. package/tests/setupTests.js +5 -0
  111. package/tests/utils/API.test.js +906 -0
  112. package/tests/utils/Exif.test.js +124 -0
  113. package/tests/utils/I18n.test.js +28 -0
  114. package/tests/utils/Map.test.js +105 -0
  115. package/tests/utils/Utils.test.js +300 -0
  116. package/tests/utils/Widgets.test.js +107 -0
  117. package/tests/utils/__snapshots__/API.test.js.snap +132 -0
  118. package/tests/utils/__snapshots__/Exif.test.js.snap +43 -0
  119. package/tests/utils/__snapshots__/Map.test.js.snap +48 -0
  120. package/tests/utils/__snapshots__/Utils.test.js.snap +41 -0
  121. package/tests/utils/__snapshots__/Widgets.test.js.snap +44 -0
  122. package/tests/viewer/URLHash.test.js +537 -0
  123. package/tests/viewer/Widgets.test.js +127 -0
  124. package/tests/viewer/__snapshots__/URLHash.test.js.snap +98 -0
  125. package/tests/viewer/__snapshots__/Widgets.test.js.snap +393 -0
@@ -0,0 +1,230 @@
1
+ import Map from "../../src/components/Map";
2
+
3
+ jest.mock("maplibre-gl", () => ({
4
+ addProtocol: jest.fn(),
5
+ AttributionControl: jest.fn(),
6
+ GeolocateControl: class {
7
+ onAdd() {;}
8
+ },
9
+ Marker: jest.fn(),
10
+ Popup: class {
11
+ on() {;}
12
+ },
13
+ Map: class {
14
+ constructor(opts) {
15
+ this._mapOpts = opts;
16
+ }
17
+ getContainer() {
18
+ return this._mapOpts.container;
19
+ }
20
+ addControl() {;}
21
+ addSource() {;}
22
+ addLayer() {;}
23
+ getLayer() {;}
24
+ setLayoutProperty() {;}
25
+ getStyle() {
26
+ return {
27
+ layers: [],
28
+ sources: {},
29
+ };
30
+ }
31
+ resize() {;}
32
+ on(type, handler) {
33
+ if(!this._handlers) { this._handlers = {}; }
34
+ if(!this._handlers[type]) { this._handlers[type] = []; }
35
+ this._handlers[type].push(handler);
36
+ }
37
+ _fire(type) {
38
+ this._handlers[type].forEach(f => f());
39
+ }
40
+ },
41
+ }));
42
+
43
+ const createParent = () => ({
44
+ addEventListener: jest.fn(),
45
+ dispatchEvent: jest.fn(),
46
+ isWidthSmall: jest.fn(),
47
+ _options: {
48
+ users: ["geovisio"],
49
+ },
50
+ _api: {
51
+ onceReady: () => Promise.resolve(),
52
+ getDataBbox: jest.fn(),
53
+ getPicturesTilesUrl: jest.fn(),
54
+ _getMapRequestTransform: jest.fn(),
55
+ getMapStyle: () => ({ sources: {}, layers: [] }),
56
+ },
57
+ _t: {
58
+ maplibre: {},
59
+ }
60
+ });
61
+
62
+
63
+ describe("reloadVectorTiles", () => {
64
+ it("works", () => {
65
+ const p = createParent();
66
+ const c = document.createElement("div");
67
+ const m = new Map(p, c);
68
+ const setter = jest.fn();
69
+ m.getSource = (user) => ({ tiles: [`https://bla.xyz/${user}/x/y/z`], setTiles: setter });
70
+ m._userLayers = ["geovisio", "toto"];
71
+ m.reloadVectorTiles();
72
+ expect(setter.mock.calls).toMatchSnapshot();
73
+ });
74
+ });
75
+
76
+ describe("hasTwoBackgrounds", () => {
77
+ it("is true if 2 bg", () => {
78
+ const p = createParent();
79
+ const c = document.createElement("div");
80
+ const m = new Map(p, c);
81
+ m.getLayer = (id) => id == "gvs-aerial";
82
+ expect(m.hasTwoBackgrounds()).toBeTruthy();
83
+ });
84
+
85
+ it("is false if 1 bg", () => {
86
+ const p = createParent();
87
+ const c = document.createElement("div");
88
+ const m = new Map(p, c);
89
+ m.getLayer = (id) => id == "gvs-aerial" ? undefined : {};
90
+ expect(m.hasTwoBackgrounds()).toBeFalsy();
91
+ });
92
+ });
93
+
94
+ describe("getBackground", () => {
95
+ it("works if raster is enabled", () => {
96
+ const p = createParent();
97
+ const c = document.createElement("div");
98
+ const m = new Map(p, c, { raster: { type: "raster" } });
99
+ m.getLayer = () => true;
100
+ m.getLayoutProperty = () => "hidden";
101
+ expect(m.getBackground()).toBe("streets");
102
+ m.getLayoutProperty = () => "visible";
103
+ expect(m.getBackground()).toBe("aerial");
104
+ });
105
+
106
+ it("works if no raster enabled", () => {
107
+ const p = createParent();
108
+ const c = document.createElement("div");
109
+ const m = new Map(p, c);
110
+ expect(m.getBackground()).toBe("streets");
111
+ });
112
+ });
113
+
114
+ describe("setBackground", () => {
115
+ it("works if raster is enabled", () => {
116
+ const p = createParent();
117
+ p.dispatchEvent = jest.fn();
118
+ const c = document.createElement("div");
119
+ const m = new Map(p, c, { raster: { type: "raster" } });
120
+ m.setLayoutProperty = jest.fn();
121
+ m.getLayer = () => true;
122
+ m.setBackground("aerial");
123
+ expect(m.setLayoutProperty.mock.calls).toMatchSnapshot();
124
+ expect(p.dispatchEvent.mock.calls).toMatchSnapshot();
125
+ });
126
+
127
+ it("skips if setting streets and no raster available", () => {
128
+ const p = createParent();
129
+ const c = document.createElement("div");
130
+ const m = new Map(p, c);
131
+ m.setLayoutProperty = jest.fn();
132
+ m.setBackground("streets");
133
+ expect(m.setLayoutProperty.mock.calls.length).toBe(0);
134
+ });
135
+
136
+ it("fails if no raster available", () => {
137
+ const p = createParent();
138
+ const c = document.createElement("div");
139
+ const m = new Map(p, c);
140
+ expect(() => m.setBackground("aerial")).toThrowError("No aerial imagery available");
141
+ });
142
+ });
143
+
144
+ describe("getVisibleUsers", () => {
145
+ it("works", () => {
146
+ const p = createParent();
147
+ const c = document.createElement("div");
148
+ const m = new Map(p, c);
149
+ m.getSource = () => true;
150
+ m.setPaintProperty = jest.fn();
151
+ m._fire("load");
152
+ m.getLayoutProperty = () => "visible";
153
+ expect(m.getVisibleUsers()).toStrictEqual(["geovisio"]);
154
+ });
155
+ });
156
+
157
+ describe("setVisibleUsers", () => {
158
+ it("works when no users exists", async () => {
159
+ const p = createParent();
160
+ const c = document.createElement("div");
161
+ const m = new Map(p, c);
162
+ m._createPicturesTilesLayer = (url, id) => m._userLayers.add(id);
163
+ m.setLayoutProperty = jest.fn();
164
+ await m.setVisibleUsers(["blabla"]);
165
+ expect(m.setLayoutProperty.mock.calls).toMatchSnapshot();
166
+ expect(p.dispatchEvent.mock.calls).toMatchSnapshot();
167
+ });
168
+
169
+ it("works when user already exist but is hidden", async () => {
170
+ const p = createParent();
171
+ p._options.users = ["blabla", "geovisio"];
172
+ const c = document.createElement("div");
173
+ const m = new Map(p, c);
174
+ m.setPaintProperty = jest.fn();
175
+ m.getSource = () => true;
176
+ m.getLayer = () => true;
177
+ let cptlCount = 0;
178
+ let deCalls = [];
179
+ return new Promise(resolve => {
180
+ p.dispatchEvent = (e) => {
181
+ deCalls.push(e);
182
+ if(e.type == "map:users-changed") {
183
+ resolve();
184
+ }
185
+ };
186
+ m._fire("load");
187
+ }).then(() => {
188
+ m.setLayoutProperty = jest.fn();
189
+ m._createPicturesTilesLayer = () => { cptlCount++; return Promise.resolve(); };
190
+ expect(m._userLayers).toEqual(new Set(["blabla", "geovisio"]));
191
+ m.setVisibleUsers(["blabla"]);
192
+ }).then(() => {
193
+ expect(cptlCount).toBe(0);
194
+ expect(deCalls).toMatchSnapshot();
195
+ expect(m.setLayoutProperty.mock.calls).toMatchSnapshot();
196
+ });
197
+ });
198
+ });
199
+
200
+ describe("filterUserLayersContent", () => {
201
+ it("works", () => {
202
+ const p = createParent();
203
+ p._options.users = ["blabla", "geovisio"];
204
+ const c = document.createElement("div");
205
+ const m = new Map(p, c);
206
+ m.getSource = () => true;
207
+ m.setPaintProperty = jest.fn();
208
+ m._fire("load");
209
+ m.setFilter = jest.fn();
210
+ m.filterUserLayersContent("pictures", [["test", "true"]]);
211
+ expect(m.setFilter.mock.calls).toMatchSnapshot();
212
+ });
213
+ });
214
+
215
+ describe("reloadLayersStyles", () => {
216
+ it("works", () => {
217
+ const p = createParent();
218
+ p._options.users = ["blabla", "geovisio"];
219
+ const c = document.createElement("div");
220
+ const m = new Map(p, c);
221
+ m.getSource = () => true;
222
+ m.setPaintProperty = jest.fn();
223
+ m._fire("load");
224
+ m.setLayoutProperty = jest.fn();
225
+ m.setPaintProperty = jest.fn();
226
+ m.reloadLayersStyles();
227
+ expect(m.setLayoutProperty.mock.calls).toMatchSnapshot();
228
+ expect(m.setPaintProperty.mock.calls).toMatchSnapshot();
229
+ });
230
+ });
@@ -0,0 +1,335 @@
1
+ import Photo from "../../src/components/Photo";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ jest.mock("@photo-sphere-viewer/core", () => ({
6
+ Viewer: class {
7
+ constructor(opts) {
8
+ this._psvOpts = opts;
9
+ this.loader = {
10
+ canvas: { setAttribute: jest.fn() },
11
+ __updateContent: jest.fn(),
12
+ show: jest.fn(),
13
+ };
14
+ this.renderer = {
15
+ renderer: {
16
+ toneMapping: null,
17
+ toneMappingExposure: null,
18
+ }
19
+ };
20
+ }
21
+ addEventListener() {;}
22
+ getPlugin() {
23
+ return {
24
+ addEventListener: jest.fn(),
25
+ datasource: {
26
+ nodeResolver: jest.fn(),
27
+ },
28
+ arrowsRenderer: {
29
+ clear: jest.fn(),
30
+ },
31
+ state: {
32
+ currentNode: null,
33
+ datasource: { nodes: {} },
34
+ },
35
+ config: {
36
+ transitionOptions: jest.fn(),
37
+ },
38
+ __onEnterObject: jest.fn(),
39
+ __onLeaveObject: jest.fn(),
40
+ };
41
+ }
42
+ }
43
+ }));
44
+
45
+ jest.mock("@photo-sphere-viewer/equirectangular-tiles-adapter", () => ({
46
+ EquirectangularTilesAdapter: jest.fn(),
47
+ }));
48
+
49
+ jest.mock("@photo-sphere-viewer/virtual-tour-plugin", () => ({
50
+ VirtualTourPlugin: jest.fn(),
51
+ }));
52
+
53
+ const createParent = () => ({
54
+ addEventListener: jest.fn(),
55
+ dispatchEvent: jest.fn(),
56
+ isWidthSmall: jest.fn(),
57
+ select: jest.fn(),
58
+ _t: { gvs: {} },
59
+ _api: {
60
+ _getFetchOptions: jest.fn(),
61
+ getPictureMetadataUrl: (picId, seqId) => `https://geovisio.fr/api/collections/${seqId}/items/${picId}`
62
+ },
63
+ });
64
+
65
+
66
+ describe("constructor", () => {
67
+ it("works", () => {
68
+ const p = createParent();
69
+ const c = document.createElement("div");
70
+ const ph = new Photo(p, c);
71
+ expect(c.className).toBe("gvs-psv");
72
+ });
73
+ });
74
+
75
+ describe("_getNodeFromAPI", () => {
76
+ beforeEach(() => {
77
+ jest.clearAllMocks();
78
+ });
79
+
80
+ it("works", async () => {
81
+ const p = createParent();
82
+ const c = document.createElement("div");
83
+ const ph = new Photo(p, c);
84
+ global.fetch = jest.fn(() =>
85
+ Promise.resolve({
86
+ ok: true,
87
+ json: () => Promise.resolve(JSON.parse(fs.readFileSync(path.join(__dirname, "..", "data", "Viewer_pictures_1.json")))),
88
+ })
89
+ );
90
+ global.Date = jest.fn(() => ({ toLocaleDateString: () => "June 3 2022" }));
91
+ const res = await ph._getNodeFromAPI("id");
92
+ expect(res).toMatchSnapshot();
93
+ });
94
+
95
+ it("works with nav filter", async () => {
96
+ const p = createParent();
97
+ const c = document.createElement("div");
98
+ const ph = new Photo(p, c);
99
+ p._picturesNavFilter = () => false;
100
+ global.fetch = jest.fn(() =>
101
+ Promise.resolve({
102
+ ok: true,
103
+ json: () => Promise.resolve(JSON.parse(fs.readFileSync(path.join(__dirname, "..", "data", "Viewer_pictures_1.json")))),
104
+ })
105
+ );
106
+ global.Date = jest.fn(() => ({ toLocaleDateString: () => "June 3 2022" }));
107
+ const res = await ph._getNodeFromAPI("id");
108
+ expect(res).toMatchSnapshot();
109
+ });
110
+ });
111
+
112
+ describe("getPictureMetadata", () => {
113
+ it("works when pic is selected", () => {
114
+ const p = createParent();
115
+ const c = document.createElement("div");
116
+ const ph = new Photo(p, c);
117
+ ph._myVTour.state.currentNode = { bla: "bla" };
118
+ expect(ph.getPictureMetadata()).toStrictEqual({ bla: "bla" });
119
+ });
120
+
121
+ it("nulls when no pic is selected", () => {
122
+ const p = createParent();
123
+ const c = document.createElement("div");
124
+ const ph = new Photo(p, c);
125
+ expect(ph.getPictureMetadata()).toBeNull();
126
+ });
127
+ });
128
+
129
+ describe("_onSelect", () => {
130
+ it("works", () => {
131
+ const p = createParent();
132
+ const c = document.createElement("div");
133
+ const ph = new Photo(p, c);
134
+ ph._myVTour = { setCurrentNode: jest.fn(() => Promise.resolve()), getCurrentNode: jest.fn() };
135
+ ph._onSelect({ detail: { picId: "id" } });
136
+ expect(ph._myVTour.setCurrentNode.mock.calls).toEqual([["id"]]);
137
+ });
138
+
139
+ it("works on pic ID already used", () => {
140
+ const p = createParent();
141
+ const c = document.createElement("div");
142
+ const ph = new Photo(p, c);
143
+ ph._myVTour = { setCurrentNode: jest.fn(() => Promise.resolve()), getCurrentNode: () => "id" };
144
+ ph._onSelect({ detail: { picId: "id" } });
145
+ expect(ph._myVTour.setCurrentNode.mock.calls).toEqual([["id"]]);
146
+ });
147
+ });
148
+
149
+ describe("goToNextPicture", () => {
150
+ it("fails if no current picture", () => {
151
+ const p = createParent();
152
+ const c = document.createElement("div");
153
+ const ph = new Photo(p, c);
154
+ ph._myVTour = { state: { currentNode: undefined } };
155
+ expect(() => ph.goToNextPicture()).toThrow(new Error("No picture currently selected"));
156
+ });
157
+
158
+ it("works if next pic exists", () => {
159
+ const p = createParent();
160
+ const c = document.createElement("div");
161
+ const ph = new Photo(p, c);
162
+ ph._myVTour = { state: { currentNode: { sequence: { id: "seq", nextPic: "idnext" } } } };
163
+ ph.goToNextPicture();
164
+ expect(p.select.mock.calls).toEqual([["seq", "idnext"]]);
165
+ });
166
+
167
+ it("fails if no next picture", () => {
168
+ const p = createParent();
169
+ const c = document.createElement("div");
170
+ const ph = new Photo(p, c);
171
+ ph._myVTour = { state: { currentNode: { sequence: {} } } };
172
+ expect(() => ph.goToNextPicture()).toThrow(new Error("No next picture available"));
173
+ });
174
+ });
175
+
176
+ describe("goToPrevPicture", () => {
177
+ it("fails if no current picture", () => {
178
+ const p = createParent();
179
+ const c = document.createElement("div");
180
+ const ph = new Photo(p, c);
181
+ ph._myVTour = { state: { currentNode: undefined } };
182
+ expect(() => ph.goToPrevPicture()).toThrow(new Error("No picture currently selected"));
183
+ });
184
+
185
+ it("works if next pic exists", () => {
186
+ const p = createParent();
187
+ const c = document.createElement("div");
188
+ const ph = new Photo(p, c);
189
+ ph._myVTour = { state: { currentNode: { sequence: { id: "seq", prevPic: "idprev" } } } };
190
+ ph.goToPrevPicture();
191
+ expect(p.select.mock.calls).toEqual([["seq", "idprev"]]);
192
+ });
193
+
194
+ it("fails if no next picture", () => {
195
+ const p = createParent();
196
+ const c = document.createElement("div");
197
+ const ph = new Photo(p, c);
198
+ ph._myVTour = { state: { currentNode: { sequence: {} } } };
199
+ expect(() => ph.goToPrevPicture()).toThrow(new Error("No previous picture available"));
200
+ });
201
+ });
202
+
203
+ describe("goToPosition", () => {
204
+ it("works", async () => {
205
+ const p = createParent();
206
+ const c = document.createElement("div");
207
+ const ph = new Photo(p, c);
208
+ p._api = {
209
+ getPicturesAroundCoordinates: () => Promise.resolve(JSON.parse(fs.readFileSync(path.join(__dirname, "..", "data", "Viewer_pictures_1.json")))),
210
+ _getFetchOptions: jest.fn()
211
+ };
212
+
213
+ const res = await ph.goToPosition(48.7, -1.8);
214
+
215
+ expect(res).toEqual("0005086d-65eb-4a90-9764-86b3661aaa77");
216
+ expect(p.select.mock.calls).toEqual([["bb129602-5ac1-4512-bf67-9ec1fa23033f", "0005086d-65eb-4a90-9764-86b3661aaa77"]]);
217
+ });
218
+
219
+ it("handles empty result from API", () => {
220
+ const p = createParent();
221
+ const c = document.createElement("div");
222
+ const ph = new Photo(p, c);
223
+ p._api = {
224
+ getPicturesAroundCoordinates: () => Promise.resolve({ "features": [] }),
225
+ _getFetchOptions: jest.fn()
226
+ };
227
+ return expect(ph.goToPosition()).rejects.toStrictEqual(new Error("No picture found nearby given coordinates"));
228
+ });
229
+ });
230
+
231
+ describe("getXY", () => {
232
+ it("works", () => {
233
+ const p = createParent();
234
+ const c = document.createElement("div");
235
+ const ph = new Photo(p, c);
236
+ ph.getPosition = () => ({ yaw: 0.7853981634, pitch: -1.2217304764 });
237
+ expect(ph.getXY()).toEqual({ x: 45.0000000001462, y: -70.00000000022743 });
238
+ });
239
+ });
240
+
241
+ describe("getXYZ", () => {
242
+ it("works", () => {
243
+ const p = createParent();
244
+ const c = document.createElement("div");
245
+ const ph = new Photo(p, c);
246
+ ph.getPosition = () => ({ yaw: 0.7853981634, pitch: -1.2217304764 });
247
+ ph.getZoomLevel = () => 15;
248
+ expect(ph.getXYZ()).toEqual({ x: 45.0000000001462, y: -70.00000000022743, z: 15 });
249
+ });
250
+ });
251
+
252
+ describe("clearPictureMetadataCache", () => {
253
+ it("works when no pic is selected", async () => {
254
+ const p = createParent();
255
+ const c = document.createElement("div");
256
+ const ph = new Photo(p, c);
257
+ await ph.clearPictureMetadataCache();
258
+ expect(ph._myVTour.state.currentNode).toBeNull();
259
+ expect(ph._myVTour.state.datasource.nodes).toStrictEqual({});
260
+ });
261
+
262
+ it("works when a pic is selected", async () => {
263
+ const p = createParent();
264
+ const c = document.createElement("div");
265
+ const ph = new Photo(p, c);
266
+ ph._myVTour.state.currentNode = { id: "pic", sequence: { id: "seq" } };
267
+ await ph.clearPictureMetadataCache();
268
+ expect(p.select.mock.calls).toMatchSnapshot();
269
+ });
270
+ });
271
+
272
+ describe("setXYZ", () => {
273
+ it("works", () => {
274
+ const p = createParent();
275
+ const c = document.createElement("div");
276
+ const ph = new Photo(p, c);
277
+ ph.rotate = jest.fn();
278
+ ph.zoom = jest.fn();
279
+ ph.setXYZ(45, -45, 3);
280
+ expect(ph.zoom.mock.calls).toEqual([[3]]);
281
+ expect(ph.rotate.mock.calls).toEqual([[{ yaw: 0.7853981633974483, pitch: -0.7853981633974483 }]]);
282
+ });
283
+ });
284
+
285
+ describe("setHigherContrast", () => {
286
+ it("works on enable", () => {
287
+ const p = createParent();
288
+ const c = document.createElement("div");
289
+ const ph = new Photo(p, c);
290
+ ph.needsUpdate = jest.fn();
291
+ ph.setHigherContrast(true);
292
+ expect(ph.renderer.renderer.toneMapping).toBe(3);
293
+ expect(ph.renderer.renderer.toneMappingExposure).toBe(2);
294
+ expect(ph.needsUpdate.mock.calls.length).toBe(1);
295
+ });
296
+
297
+ it("works on disable", () => {
298
+ const p = createParent();
299
+ const c = document.createElement("div");
300
+ const ph = new Photo(p, c);
301
+ ph.needsUpdate = jest.fn();
302
+ ph.setHigherContrast(false);
303
+ expect(ph.renderer.renderer.toneMapping).toBe(0);
304
+ expect(ph.renderer.renderer.toneMappingExposure).toBe(1);
305
+ expect(ph.needsUpdate.mock.calls.length).toBe(1);
306
+ });
307
+ });
308
+
309
+ describe("getTransitionDuration", () => {
310
+ it("works", () => {
311
+ const p = createParent();
312
+ const c = document.createElement("div");
313
+ const ph = new Photo(p, c, { transitionDuration: 42 });
314
+ expect(ph.getTransitionDuration()).toBe(42);
315
+ });
316
+ });
317
+
318
+ describe("setTransitionDuration", () => {
319
+ it("works", () => {
320
+ const p = createParent();
321
+ const c = document.createElement("div");
322
+ const ph = new Photo(p, c);
323
+ ph.setTransitionDuration(1024);
324
+ expect(ph.getTransitionDuration()).toBe(1024);
325
+ expect(p.dispatchEvent.mock.calls).toMatchSnapshot();
326
+ });
327
+
328
+ it("fails when value is invalid", () => {
329
+ const p = createParent();
330
+ const c = document.createElement("div");
331
+ const ph = new Photo(p, c);
332
+ expect(() => ph.setTransitionDuration(-1)).toThrowError("Invalid transition duration (should be between 100 and 3000)");
333
+ expect(() => ph.setTransitionDuration(3001)).toThrowError("Invalid transition duration (should be between 100 and 3000)");
334
+ });
335
+ });
@@ -0,0 +1,15 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`constructor works 1`] = `"<img src=\\"marker.svg\\" title=\\"undefined\\" class=\\"gvs-loader-img\\"><div><span>Loading...</span></div>"`;
4
+
5
+ exports[`dismiss works when no error set 1`] = `
6
+ Array [
7
+ Array [
8
+ CustomEvent {
9
+ "isTrusted": false,
10
+ },
11
+ ],
12
+ ]
13
+ `;
14
+
15
+ exports[`dismiss works with error set 1`] = `"<img src=\\"logo_dead.svg\\" title=\\"undefined\\" class=\\"gvs-loader-img\\" style=\\"width: 200px; animation: unset;\\"><div>undefined<br>Oops it's broken<br><small>undefined</small></div>"`;