@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.
- package/.dockerignore +6 -0
- package/.gitlab-ci.yml +71 -0
- package/CHANGELOG.md +428 -0
- package/CODE_OF_CONDUCT.md +134 -0
- package/Dockerfile +14 -0
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/build/editor.html +1 -0
- package/build/index.css +36 -0
- package/build/index.css.map +1 -0
- package/build/index.html +1 -0
- package/build/index.js +25 -0
- package/build/index.js.map +1 -0
- package/build/map.html +1 -0
- package/build/viewer.html +1 -0
- package/config/env.js +104 -0
- package/config/getHttpsConfig.js +66 -0
- package/config/getPackageJson.js +25 -0
- package/config/jest/babelTransform.js +29 -0
- package/config/jest/cssTransform.js +14 -0
- package/config/jest/fileTransform.js +40 -0
- package/config/modules.js +134 -0
- package/config/paths.js +72 -0
- package/config/pnpTs.js +35 -0
- package/config/webpack/persistentCache/createEnvironmentHash.js +9 -0
- package/config/webpack.config.js +885 -0
- package/config/webpackDevServer.config.js +127 -0
- package/docs/01_Start.md +149 -0
- package/docs/02_Usage.md +828 -0
- package/docs/03_URL_settings.md +140 -0
- package/docs/04_Advanced_examples.md +214 -0
- package/docs/05_Compatibility.md +85 -0
- package/docs/09_Develop.md +62 -0
- package/docs/90_Releases.md +27 -0
- package/docs/images/class_diagram.drawio +129 -0
- package/docs/images/class_diagram.jpg +0 -0
- package/docs/images/screenshot.jpg +0 -0
- package/mkdocs.yml +45 -0
- package/package.json +254 -0
- package/public/editor.html +54 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +59 -0
- package/public/map.html +53 -0
- package/public/viewer.html +67 -0
- package/scripts/build.js +217 -0
- package/scripts/start.js +176 -0
- package/scripts/test.js +52 -0
- package/src/Editor.css +37 -0
- package/src/Editor.js +359 -0
- package/src/StandaloneMap.js +114 -0
- package/src/Viewer.css +203 -0
- package/src/Viewer.js +1186 -0
- package/src/components/CoreView.css +64 -0
- package/src/components/CoreView.js +159 -0
- package/src/components/Loader.css +56 -0
- package/src/components/Loader.js +111 -0
- package/src/components/Map.css +65 -0
- package/src/components/Map.js +841 -0
- package/src/components/Photo.css +36 -0
- package/src/components/Photo.js +687 -0
- package/src/img/arrow_360.svg +14 -0
- package/src/img/arrow_flat.svg +11 -0
- package/src/img/arrow_triangle.svg +10 -0
- package/src/img/arrow_turn.svg +9 -0
- package/src/img/bg_aerial.jpg +0 -0
- package/src/img/bg_streets.jpg +0 -0
- package/src/img/loader_base.jpg +0 -0
- package/src/img/loader_hd.jpg +0 -0
- package/src/img/logo_dead.svg +91 -0
- package/src/img/marker.svg +17 -0
- package/src/img/marker_blue.svg +20 -0
- package/src/img/switch_big.svg +44 -0
- package/src/img/switch_mini.svg +48 -0
- package/src/index.js +10 -0
- package/src/translations/de.json +163 -0
- package/src/translations/en.json +164 -0
- package/src/translations/eo.json +6 -0
- package/src/translations/es.json +164 -0
- package/src/translations/fi.json +1 -0
- package/src/translations/fr.json +164 -0
- package/src/translations/hu.json +133 -0
- package/src/translations/nl.json +1 -0
- package/src/translations/zh_Hant.json +136 -0
- package/src/utils/API.js +709 -0
- package/src/utils/Exif.js +198 -0
- package/src/utils/I18n.js +75 -0
- package/src/utils/Map.js +382 -0
- package/src/utils/PhotoAdapter.js +45 -0
- package/src/utils/Utils.js +568 -0
- package/src/utils/Widgets.js +477 -0
- package/src/viewer/URLHash.js +334 -0
- package/src/viewer/Widgets.css +711 -0
- package/src/viewer/Widgets.js +1196 -0
- package/tests/Editor.test.js +125 -0
- package/tests/StandaloneMap.test.js +44 -0
- package/tests/Viewer.test.js +363 -0
- package/tests/__snapshots__/Editor.test.js.snap +300 -0
- package/tests/__snapshots__/StandaloneMap.test.js.snap +30 -0
- package/tests/__snapshots__/Viewer.test.js.snap +195 -0
- package/tests/components/CoreView.test.js +91 -0
- package/tests/components/Loader.test.js +38 -0
- package/tests/components/Map.test.js +230 -0
- package/tests/components/Photo.test.js +335 -0
- package/tests/components/__snapshots__/Loader.test.js.snap +15 -0
- package/tests/components/__snapshots__/Map.test.js.snap +767 -0
- package/tests/components/__snapshots__/Photo.test.js.snap +205 -0
- package/tests/data/Map_geocoder_ban.json +36 -0
- package/tests/data/Map_geocoder_nominatim.json +56 -0
- package/tests/data/Viewer_pictures_1.json +148 -0
- package/tests/setupTests.js +5 -0
- package/tests/utils/API.test.js +906 -0
- package/tests/utils/Exif.test.js +124 -0
- package/tests/utils/I18n.test.js +28 -0
- package/tests/utils/Map.test.js +105 -0
- package/tests/utils/Utils.test.js +300 -0
- package/tests/utils/Widgets.test.js +107 -0
- package/tests/utils/__snapshots__/API.test.js.snap +132 -0
- package/tests/utils/__snapshots__/Exif.test.js.snap +43 -0
- package/tests/utils/__snapshots__/Map.test.js.snap +48 -0
- package/tests/utils/__snapshots__/Utils.test.js.snap +41 -0
- package/tests/utils/__snapshots__/Widgets.test.js.snap +44 -0
- package/tests/viewer/URLHash.test.js +537 -0
- package/tests/viewer/Widgets.test.js +127 -0
- package/tests/viewer/__snapshots__/URLHash.test.js.snap +98 -0
- 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>"`;
|