style: format the phase 2 files and add them to the format scope

Prettier on the 13 new test files that failed --check; format-scope.json
now lists every file phase 2 added (src/globe/**, engineChoice, navaraMode,
cameraAngles, the QA scripts and pages, build/navaraAssets and tests).
This commit is contained in:
German Khokhlov committed 2026-10-15 22:34:25 +04:00
1 parent 312ed416e9
commit 80cc0b536e
14 files changed
+229 -46

No files matched your search

+58 -1
View File
@@ -1002,5 +1002,62 @@
"src/tools/globePanel.test.mjs", "src/tools/globePanel.test.mjs",
"src/costEndpointThrottle.test.mjs", "src/costEndpointThrottle.test.mjs",
"src/sources/gbfsStations.test.mjs", "src/sources/gbfsStations.test.mjs",
"scripts/qa-gbfs-names.mjs" "scripts/qa-gbfs-names.mjs",
"build/navaraAssets.js",
"scripts/qa-engine-bench.mjs",
"scripts/qa-engine-shell.mjs",
"scripts/qa/navara-contract.html",
"scripts/qa/navaraContractPage.js",
"src/annotations/resolverEngine.test.mjs",
"src/app/controls.test.mjs",
"src/app/engineChoice.js",
"src/app/engineChoice.test.mjs",
"src/app/navaraMode.js",
"src/app/navaraScene.test.mjs",
"src/app/viewerlessTools.test.mjs",
"src/cameraAngles.js",
"src/cameraAngles.test.mjs",
"src/data/cameraArrival.test.mjs",
"src/data/cameraSensitivity.test.mjs",
"src/globe/cesium/camera.js",
"src/globe/cesium/convert.js",
"src/globe/cesium/createCesiumEngine.js",
"src/globe/cesium/credits.js",
"src/globe/cesium/events.js",
"src/globe/cesium/frames.js",
"src/globe/cesium/input.js",
"src/globe/cesium/maps.js",
"src/globe/cesium/picker.js",
"src/globe/cesium/projector.js",
"src/globe/cesium/render.js",
"src/globe/cesium/surface.js",
"src/globe/contract.js",
"src/globe/navara/cameraMath.js",
"src/globe/navara/cameraMath.test.mjs",
"src/globe/navara/cameraModel.js",
"src/globe/navara/cameraModel.test.mjs",
"src/globe/navara/createNavaraEngine.js",
"src/globe/navara/createNavaraEngine.test.mjs",
"src/globe/navara/credits.js",
"src/globe/navara/credits.test.mjs",
"src/globe/navara/groundFloor.js",
"src/globe/navara/groundFloor.test.mjs",
"src/globe/navara/index.js",
"src/globe/navara/input.js",
"src/globe/navara/input.test.mjs",
"src/globe/navara/internals.js",
"src/globe/navara/internals.test.mjs",
"src/globe/navara/maps.js",
"src/globe/navara/maps.test.mjs",
"src/globe/navara/surface.js",
"src/globe/navara/surface.test.mjs",
"src/globe/navara/viewOptions.js",
"src/globe/navara/viewOptions.test.mjs",
"src/globe/testing/contractSuite.mjs",
"src/globe/testing/fakeEngine.js",
"src/mapStackController.test.mjs",
"src/orbit.test.mjs",
"src/services/groundSnap.test.mjs",
"src/sharelinkPose.test.mjs",
"src/tooling/navaraAssets.test.mjs"
] ]
+18 -4
View File
@@ -33,7 +33,10 @@ test('viewportBias reads the engine view rectangle', () => {
east: geo.math.toRadians(-97.5), east: geo.math.toRadians(-97.5),
north: geo.math.toRadians(30.5), north: geo.math.toRadians(30.5),
}); });
assert.equal(resolver.viewportBias(engine), '30.0000,-98.0000|30.5000,-97.5000'); assert.equal(
resolver.viewportBias(engine),
'30.0000,-98.0000|30.5000,-97.5000',
);
engine.fake.script('viewRectangle', undefined); engine.fake.script('viewRectangle', undefined);
assert.equal(resolver.viewportBias(engine), null); assert.equal(resolver.viewportBias(engine), null);
}); });
@@ -43,7 +46,9 @@ test('pickWorldFromScreen tries the depth pick, then the ellipsoid, then the glo
const depth = geo.cartesian3.fromDegrees(-97.7, 30.3, 210); const depth = geo.cartesian3.fromDegrees(-97.7, 30.3, 210);
engine.fake.script('pickPosition', depth); engine.fake.script('pickPosition', depth);
const picked = resolver.pickWorldFromScreen(engine, 0.5, 0.5); const picked = resolver.pickWorldFromScreen(engine, 0.5, 0.5);
assert.ok(Math.abs(picked.lat - 30.3) < 1e-9 && Math.abs(picked.height - 210) < 1e-6); assert.ok(
Math.abs(picked.lat - 30.3) < 1e-9 && Math.abs(picked.height - 210) < 1e-6,
);
const [screen] = engine.fake.callsOf('picker.pickPosition')[0].args; const [screen] = engine.fake.callsOf('picker.pickPosition')[0].args;
assert.deepEqual([screen.x, screen.y], [512, 384]); assert.deepEqual([screen.x, screen.y], [512, 384]);
@@ -53,7 +58,10 @@ test('pickWorldFromScreen tries the depth pick, then the ellipsoid, then the glo
assert.ok(Math.abs(ellipsoid.height) < 1e-3); assert.ok(Math.abs(ellipsoid.height) < 1e-3);
engine.fake.script('pickEllipsoid', undefined); engine.fake.script('pickEllipsoid', undefined);
engine.fake.script('pickGlobe', geo.cartesian3.fromDegrees(-97.71, 30.25, 300)); engine.fake.script(
'pickGlobe',
geo.cartesian3.fromDegrees(-97.71, 30.25, 300),
);
const globe = resolver.pickWorldFromScreen(engine, 0.5, 0.5); const globe = resolver.pickWorldFromScreen(engine, 0.5, 0.5);
assert.ok(Math.abs(globe.height - 300) < 1e-6); assert.ok(Math.abs(globe.height - 300) < 1e-6);
engine.fake.script('pickGlobe', undefined); engine.fake.script('pickGlobe', undefined);
@@ -71,7 +79,13 @@ test('near-view recovery centres on the engine camera when nothing is picked', a
return []; return [];
}, },
}; };
await resolver.placesNearViewRecovery(engine, 'cafe', null, undefined, placeSearch); await resolver.placesNearViewRecovery(
engine,
'cafe',
null,
undefined,
placeSearch,
);
assert.equal(centres.length, 1); assert.equal(centres.length, 1);
assert.ok(Math.abs(centres[0].latitude - 48.85) < 1e-9); assert.ok(Math.abs(centres[0].latitude - 48.85) < 1e-9);
assert.ok(Math.abs(centres[0].longitude - 2.35) < 1e-9); assert.ok(Math.abs(centres[0].longitude - 2.35) < 1e-9);
+4 -1
View File
@@ -11,7 +11,10 @@ const read = (relative) =>
test('the controls pass the scene engine to the shell', () => { test('the controls pass the scene engine to the shell', () => {
const controls = read('./controls.js'); const controls = read('./controls.js');
assert.match(controls, /scene: \{ viewer, engine, mapStackController, operations \}/); assert.match(
controls,
/scene: \{ viewer, engine, mapStackController, operations \}/,
);
assert.match(controls, /new Controls\(viewer, \{[\s\S]*?\n\s+engine,\n/); assert.match(controls, /new Controls\(viewer, \{[\s\S]*?\n\s+engine,\n/);
}); });
+8 -2
View File
@@ -12,8 +12,14 @@ test('claims on a globe engine set its camera sensitivity and share one ledger',
assert.equal(claimCameraSensitivity(engine, 'traffic', 0.05), 0.05); assert.equal(claimCameraSensitivity(engine, 'traffic', 0.05), 0.05);
assert.equal(engine.camera.percentageChanged, 0.05); assert.equal(engine.camera.percentageChanged, 0.05);
// The engine and its camera are the same claimant. // The engine and its camera are the same claimant.
assert.equal(claimCameraSensitivity(engine.camera, 'installations', 0.01), 0.01); assert.equal(
assert.deepEqual(cameraSensitivityClaims(engine), ['traffic', 'installations']); claimCameraSensitivity(engine.camera, 'installations', 0.01),
0.01,
);
assert.deepEqual(cameraSensitivityClaims(engine), [
'traffic',
'installations',
]);
assert.equal(releaseCameraSensitivity(engine, 'installations'), 0.05); assert.equal(releaseCameraSensitivity(engine, 'installations'), 0.05);
assert.equal(releaseCameraSensitivity(engine.camera, 'traffic'), 0.5); assert.equal(releaseCameraSensitivity(engine.camera, 'traffic'), 0.5);
assert.equal(engine.camera.percentageChanged, 0.5); assert.equal(engine.camera.percentageChanged, 0.5);
+12 -5
View File
@@ -56,7 +56,12 @@ function cameraAt(lon, lat, height, heading, pitch, roll, size = [1280, 800]) {
test('heading π/2 at pitch 0 looks east with up along the local up', () => { test('heading π/2 at pitch 0 looks east with up along the local up', () => {
const position = cartesian3.fromDegrees(-120, 35, 3000); const position = cartesian3.fromDegrees(-120, 35, 3000);
const { direction, up } = orientationVectors(position, math.PI_OVER_TWO, 0, 0); const { direction, up } = orientationVectors(
position,
math.PI_OVER_TWO,
0,
0,
);
const axes = axesAt(position); const axes = axesAt(position);
near(dot(direction, axes.east), 1, 1e-12, 'direction·east'); near(dot(direction, axes.east), 1, 1e-12, 'direction·east');
near(dot(up, axes.up), 1, 1e-12, 'up·up'); near(dot(up, axes.up), 1, 1e-12, 'up·up');
@@ -183,11 +188,11 @@ test('viewProjection agrees with projectToWindow', () => {
test('horizonVisible: the nadir is visible and the antipode hidden', () => { test('horizonVisible: the nadir is visible and the antipode hidden', () => {
const eye = cartesian3.fromDegrees(20, 10, 1e6); const eye = cartesian3.fromDegrees(20, 10, 1e6);
assert.equal(horizonVisible(eye, cartesian3.fromDegrees(20, 10, 0)), true); assert.equal(horizonVisible(eye, cartesian3.fromDegrees(20, 10, 0)), true);
assert.equal(horizonVisible(eye, cartesian3.fromDegrees(-160, -10, 0)), false);
assert.equal( assert.equal(
horizonVisible(eye, cartesian3.fromDegrees(-70, 10, 2e7)), horizonVisible(eye, cartesian3.fromDegrees(-160, -10, 0)),
true, false,
); );
assert.equal(horizonVisible(eye, cartesian3.fromDegrees(-70, 10, 2e7)), true);
}); });
test("viewRectangle matches Cesium's computeViewRectangle (S4 reference poses)", () => { test("viewRectangle matches Cesium's computeViewRectangle (S4 reference poses)", () => {
@@ -255,7 +260,9 @@ test('rectangleViewPosition frames a rectangle at the centre of a nadir view', (
[rectangle.east, rectangle.north], [rectangle.east, rectangle.north],
]) { ]) {
const corner = projectToWindow(camera, cartesian3.fromRadians(lon, lat)); const corner = projectToWindow(camera, cartesian3.fromRadians(lon, lat));
assert.ok(corner.x >= 0 && corner.x <= 1280 && corner.y >= 0 && corner.y <= 800); assert.ok(
corner.x >= 0 && corner.x <= 1280 && corner.y >= 0 && corner.y <= 800,
);
} }
}); });
+24 -7
View File
@@ -326,9 +326,11 @@ test('lookAt locks the transform, aims at the target and release keeps the pose'
target, target,
geo.ellipsoid.WGS84, geo.ellipsoid.WGS84,
); );
camera.transform().forEach((value, index) => camera
near(value, frame[index], 1e-9, `transform[${index}]`), .transform()
); .forEach((value, index) =>
near(value, frame[index], 1e-9, `transform[${index}]`),
);
camera.release(); camera.release();
assert.deepEqual(camera.transform(), [...matrix4.IDENTITY]); assert.deepEqual(camera.transform(), [...matrix4.IDENTITY]);
near( near(
@@ -395,8 +397,15 @@ test('picks, projection and view rectangle come from the pose and canvas size',
const back = model.worldToWindow(hit); const back = model.worldToWindow(hit);
near(back.x, centre.x, 1e-6, 'x'); near(back.x, centre.x, 1e-6, 'x');
const rectangle = camera.viewRectangle(); const rectangle = camera.viewRectangle();
assert.ok(rectangle.west < math.toRadians(20) && math.toRadians(20) < rectangle.east); assert.ok(
near(camera.pose().fovy, 2 * Math.atan(Math.tan(Math.PI / 6) / 1.6), 1e-15, 'fovy'); rectangle.west < math.toRadians(20) && math.toRadians(20) < rectangle.east,
);
near(
camera.pose().fovy,
2 * Math.atan(Math.tan(Math.PI / 6) / 1.6),
1e-15,
'fovy',
);
}); });
test('destroy cancels a running flight and stops the moveEnd timer', () => { test('destroy cancels a running flight and stops the moveEnd timer', () => {
@@ -452,7 +461,12 @@ test('livePosition is one engine-owned object holding the current position; heig
const moved = cartesian3.fromDegrees(21, 11, 9e5); const moved = cartesian3.fromDegrees(21, 11, 9e5);
port.drawn = { position: moved, ...orientationVectors(moved, 0.3, -1, 0) }; port.drawn = { position: moved, ...orientationVectors(moved, 0.3, -1, 0) };
frame(); frame();
near(cartesian3.distance(camera.livePosition, moved), 0, 1e-9, 'follows Navara'); near(
cartesian3.distance(camera.livePosition, moved),
0,
1e-9,
'follows Navara',
);
near(camera.height(), 9e5, 1e-6, 'height after a user move'); near(camera.height(), 9e5, 1e-6, 'height after a user move');
const pose = camera.pose(); const pose = camera.pose();
assert.notEqual(pose.position, live, 'pose shares the live object'); assert.notEqual(pose.position, live, 'pose shares the live object');
@@ -469,7 +483,10 @@ test('commanded fires before each camera command and never for reads', () => {
assert.equal(raised, 0); assert.equal(raised, 0);
const target = cartesian3.fromDegrees(10, 10, 0); const target = cartesian3.fromDegrees(10, 10, 0);
camera.setView({ destination: cartesian3.fromDegrees(10, 10, 1e6) }); camera.setView({ destination: cartesian3.fromDegrees(10, 10, 1e6) });
camera.flyTo({ destination: cartesian3.fromDegrees(11, 10, 1e6), duration: 0 }); camera.flyTo({
destination: cartesian3.fromDegrees(11, 10, 1e6),
duration: 0,
});
camera.flyToSphere({ center: target, radius: 10 }, { duration: 0 }); camera.flyToSphere({ center: target, radius: 10 }, { duration: 0 });
camera.lookAt(target, { heading: 0, pitch: -1, range: 500 }); camera.lookAt(target, { heading: 0, pitch: -1, range: 500 });
camera.cancelFlight(); camera.cancelFlight();
+39 -9
View File
@@ -18,14 +18,31 @@ function fakeView() {
parentElement: { id: 'container' }, parentElement: { id: 'container' },
}); });
const position = cartesian3.fromDegrees(0, 0, 1e7); const position = cartesian3.fromDegrees(0, 0, 1e7);
const { direction, up } = orientationVectors(position, 0, -math.PI_OVER_TWO, 0); const { direction, up } = orientationVectors(
position,
0,
-math.PI_OVER_TWO,
0,
);
// three's camera.matrixWorld: columns right, up, back (−direction), position. // three's camera.matrixWorld: columns right, up, back (−direction), position.
const right = cartesian3.cross(direction, up, cartesian3.create()); const right = cartesian3.cross(direction, up, cartesian3.create());
const elements = [ const elements = [
right.x, right.y, right.z, 0, right.x,
up.x, up.y, up.z, 0, right.y,
-direction.x, -direction.y, -direction.z, 0, right.z,
position.x, position.y, position.z, 1, 0,
up.x,
up.y,
up.z,
0,
-direction.x,
-direction.y,
-direction.z,
0,
position.x,
position.y,
position.z,
1,
]; ];
const view = { const view = {
canvas, canvas,
@@ -58,7 +75,9 @@ function fakeView() {
view.calls.push(['setCamera', pose]); view.calls.push(['setCamera', pose]);
}, },
flyTo(pose, options) { flyTo(pose, options) {
return new Promise((resolve) => view.flights.push({ pose, options, resolve })); return new Promise((resolve) =>
view.flights.push({ pose, options, resolve }),
);
}, },
forceUpdate() { forceUpdate() {
view.calls.push(['forceUpdate']); view.calls.push(['forceUpdate']);
@@ -135,7 +154,12 @@ test("the camera starts from Navara's drawn camera and pushes poses with setCame
test("Navara's fov follows Cesium's vertical fov, also after a resize", () => { test("Navara's fov follows Cesium's vertical fov, also after a resize", () => {
const { view, engine } = setup(); const { view, engine } = setup();
near(view.camera.fovs.at(-1), math.toDegrees(cesiumFovy(1280, 800)), 1e-12, 'fov'); near(
view.camera.fovs.at(-1),
math.toDegrees(cesiumFovy(1280, 800)),
1e-12,
'fov',
);
view.canvas.clientWidth = 600; view.canvas.clientWidth = 600;
view.canvas.clientHeight = 900; view.canvas.clientHeight = 900;
view.emit('resize', 600, 900); view.emit('resize', 600, 900);
@@ -187,7 +211,10 @@ test('the projector agrees with the camera', () => {
const window = engine.projector.worldToWindow(ahead); const window = engine.projector.worldToWindow(ahead);
near(window.x, 640, 1e-6, 'x'); near(window.x, 640, 1e-6, 'x');
near(window.y, 400, 1e-6, 'y'); near(window.y, 400, 1e-6, 'y');
assert.equal(engine.projector.horizonVisible(cartesian3.fromDegrees(0, 0)), true); assert.equal(
engine.projector.horizonVisible(cartesian3.fromDegrees(0, 0)),
true,
);
}); });
test('destroy removes its Navara listeners, keeps the view and is idempotent', () => { test('destroy removes its Navara listeners, keeps the view and is idempotent', () => {
@@ -224,7 +251,10 @@ test('pickGlobe meets the terrain along the pick ray, or the ellipsoid', () => {
const place = geo.cartographic.fromCartesian(raised); const place = geo.cartographic.fromCartesian(raised);
near(place.height, 2000, 0.5, 'terrain height (m)'); near(place.height, 2000, 0.5, 'terrain height (m)');
near(math.toDegrees(place.longitude), 0, 1e-6, 'longitude'); near(math.toDegrees(place.longitude), 0, 1e-6, 'longitude');
assert.equal(engine.picker.pickGlobe(cartesian2.create(640, -1e7)), undefined); assert.equal(
engine.picker.pickGlobe(cartesian2.create(640, -1e7)),
undefined,
);
}); });
test('a user gesture cancels a flight without raising camera.commanded', () => { test('a user gesture cancels a flight without raising camera.commanded', () => {
+6 -2
View File
@@ -12,7 +12,9 @@ function fakeAttribution() {
}, },
add(items) { add(items) {
for (const item of items) for (const item of items)
if (!shown.some((entry) => entry.attributionHtml === item.attributionHtml)) if (
!shown.some((entry) => entry.attributionHtml === item.attributionHtml)
)
shown.push(item); shown.push(item);
}, },
remove(items) { remove(items) {
@@ -31,7 +33,9 @@ test('addStatic shows HTML in the attribution and the remover is idempotent', ()
const attribution = fakeAttribution(); const attribution = fakeAttribution();
const { credits } = createNavaraCredits({ attribution }); const { credits } = createNavaraCredits({ attribution });
const remove = credits.addStatic('<a href="x">X</a>', { onScreen: true }); const remove = credits.addStatic('<a href="x">X</a>', { onScreen: true });
assert.deepEqual(attribution.shown, [{ attributionHtml: '<a href="x">X</a>' }]); assert.deepEqual(attribution.shown, [
{ attributionHtml: '<a href="x">X</a>' },
]);
remove(); remove();
remove(); remove();
assert.deepEqual(attribution.shown, []); assert.deepEqual(attribution.shown, []);
+4 -1
View File
@@ -107,7 +107,10 @@ test('modifiers: a listener fires only for its own key, an unmodified one only w
test('on validates its arguments and returns an idempotent remover', () => { test('on validates its arguments and returns an idempotent remover', () => {
const { canvas, input } = setup(); const { canvas, input } = setup();
assert.throws(() => input.on('wheel', () => {}), TypeError); assert.throws(() => input.on('wheel', () => {}), TypeError);
assert.throws(() => input.on('click', () => {}, { modifier: 'meta' }), TypeError); assert.throws(
() => input.on('click', () => {}, { modifier: 'meta' }),
TypeError,
);
let count = 0; let count = 0;
const off = input.on('down', () => count++); const off = input.on('down', () => count++);
off(); off();
+6 -1
View File
@@ -24,7 +24,12 @@ test('Navara internals are pinned: package.json and internals.js name the same e
const PRIVATE_ACCESS = /\.\s*_[A-Za-z]|\[\s*['"`]_[A-Za-z]/; const PRIVATE_ACCESS = /\.\s*_[A-Za-z]|\[\s*['"`]_[A-Za-z]/;
test('the private-member pattern catches dotted and bracketed access', () => { test('the private-member pattern catches dotted and bracketed access', () => {
for (const code of ['view._isIdle', 'view?._scenes', "view['_isIdle']", 'v[ "_x" ]']) for (const code of [
'view._isIdle',
'view?._scenes',
"view['_isIdle']",
'v[ "_x" ]',
])
assert.ok(PRIVATE_ACCESS.test(code), code); assert.ok(PRIVATE_ACCESS.test(code), code);
for (const code of ['view.isIdle', 'a_b.c', "map['key']"]) for (const code of ['view.isIdle', 'a_b.c', "map['key']"])
assert.ok(!PRIVATE_ACCESS.test(code), code); assert.ok(!PRIVATE_ACCESS.test(code), code);
+24 -7
View File
@@ -71,14 +71,19 @@ test('setBaseImagery builds Navara raster layers for OSM and Esri, one at a time
'https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
); );
assert.equal(layer.desc.source, view.sources[0]); assert.equal(layer.desc.source, view.sources[0]);
assert.ok(view.shown.some((item) => /OpenStreetMap/.test(JSON.stringify(item)))); assert.ok(
view.shown.some((item) => /OpenStreetMap/.test(JSON.stringify(item))),
);
await maps.setBaseImagery({ await maps.setBaseImagery({
descriptor: { id: 'esri-imagery', kind: 'esri-imagery' }, descriptor: { id: 'esri-imagery', kind: 'esri-imagery' },
credit: '<a href="https://www.esri.com">Powered by Esri</a>', credit: '<a href="https://www.esri.com">Powered by Esri</a>',
}); });
assert.equal(layersOf(view, 'raster').length, 1); assert.equal(layersOf(view, 'raster').length, 1);
assert.equal(view.sources.length, 1); assert.equal(view.sources.length, 1);
assert.match(view.sources[0].desc.url, /World_Imagery\/MapServer\/tile\/\{z\}\/\{y\}\/\{x\}$/); assert.match(
view.sources[0].desc.url,
/World_Imagery\/MapServer\/tile\/\{z\}\/\{y\}\/\{x\}$/,
);
assert.deepEqual(view.shown, [ assert.deepEqual(view.shown, [
{ attributionHtml: '<a href="https://www.esri.com">Powered by Esri</a>' }, { attributionHtml: '<a href="https://www.esri.com">Powered by Esri</a>' },
]); ]);
@@ -100,7 +105,10 @@ test('an imagery source Navara cannot build rejects and the current one stays',
await maps.setBaseImagery({ kind: 'osm' }); await maps.setBaseImagery({ kind: 'osm' });
await assert.rejects(maps.setBaseImagery({ kind: 'ion', style: 2 }), /ion/); await assert.rejects(maps.setBaseImagery({ kind: 'ion', style: 2 }), /ion/);
await assert.rejects(maps.setBaseImagery({ kind: 'nope' }), TypeError); await assert.rejects(maps.setBaseImagery({ kind: 'nope' }), TypeError);
assert.equal(view.sources[0].desc.url, 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'); assert.equal(
view.sources[0].desc.url,
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
);
}); });
test('setTerrain: keyless Re:Earth mesh, flat ellipsoid, and ion world terrain with a token', async () => { test('setTerrain: keyless Re:Earth mesh, flat ellipsoid, and ion world terrain with a token', async () => {
@@ -150,7 +158,10 @@ test('a newer terrain request wins over an older one still resolving', async ()
}); });
const world = maps.setTerrain({ kind: 'world', accessToken: 't' }); const world = maps.setTerrain({ kind: 'world', accessToken: 't' });
await maps.setTerrain({ kind: 'keyless' }); await maps.setTerrain({ kind: 'keyless' });
answer({ ok: true, json: async () => ({ url: 'https://x/', accessToken: 'y' }) }); answer({
ok: true,
json: async () => ({ url: 'https://x/', accessToken: 'y' }),
});
await world; await world;
const [terrain] = layersOf(view, 'terrain'); const [terrain] = layersOf(view, 'terrain');
assert.match(terrain.desc.source.desc.url, /reearth/); assert.match(terrain.desc.source.desc.url, /reearth/);
@@ -240,7 +251,11 @@ test('current() returns the passed sources: base while the globe shows, tiles wh
await maps.setBaseImagery(esri); await maps.setBaseImagery(esri);
const [raster] = layersOf(view, 'raster'); const [raster] = layersOf(view, 'raster');
assert.match(raster.desc.source.desc.url, /World_Imagery/); assert.match(raster.desc.source.desc.url, /World_Imagery/);
assert.equal(raster.desc.raster?.show, false, 'the new layer shows over tiles'); assert.equal(
raster.desc.raster?.show,
false,
'the new layer shows over tiles',
);
assert.ok( assert.ok(
!view.shown.some((item) => /esri/i.test(JSON.stringify(item))), !view.shown.some((item) => /esri/i.test(JSON.stringify(item))),
'its credit shows over tiles', 'its credit shows over tiles',
@@ -250,7 +265,10 @@ test('current() returns the passed sources: base while the globe shows, tiles wh
await maps.setPhotorealTiles(null); await maps.setPhotorealTiles(null);
assert.deepEqual(maps.current(), { baseImagery: esri, photoreal: null }); assert.deepEqual(maps.current(), { baseImagery: esri, photoreal: null });
assert.notEqual(raster.desc.raster?.show, false, 'base not back'); assert.notEqual(raster.desc.raster?.show, false, 'base not back');
assert.ok(view.shown.some((item) => /esri/i.test(JSON.stringify(item))), 'credit not back'); assert.ok(
view.shown.some((item) => /esri/i.test(JSON.stringify(item))),
'credit not back',
);
}); });
test('the same tiles under a new source object count as that source', async () => { test('the same tiles under a new source object count as that source', async () => {
@@ -277,4 +295,3 @@ test('releasePhotorealTiles forgets the source and takes its tiles away if shown
assert.equal(maps.current().photoreal, null); assert.equal(maps.current().photoreal, null);
assert.equal(layersOf(view, '3d-tiles').length, 0); assert.equal(layersOf(view, '3d-tiles').length, 0);
}); });
+6 -1
View File
@@ -52,7 +52,12 @@ function tileAt(lon, lat, height, half = 100) {
return { tile, mesh }; return { tile, mesh };
} }
function setup({ tiles = [], terrain = () => undefined, idle = true, retain } = {}) { function setup({
tiles = [],
terrain = () => undefined,
idle = true,
retain,
} = {}) {
const view = { const view = {
sampleTerrainHeight: (place) => terrain(place), sampleTerrainHeight: (place) => terrain(place),
}; };
+12 -3
View File
@@ -21,20 +21,29 @@ test('orbit locks onto the target every frame from the current heading, and stop
}); });
const target = geo.cartesian3.fromDegrees(-97.74, 30.27, 30); const target = geo.cartesian3.fromDegrees(-97.74, 30.27, 30);
const orbit = new OrbitController(engine); const orbit = new OrbitController(engine);
assert.equal(orbit.toggle(target, { radius: 800, pitch: -20, speed: 10 }), true); assert.equal(
orbit.toggle(target, { radius: 800, pitch: -20, speed: 10 }),
true,
);
assert.ok(getRenderGovernorDiagnostics().holds.includes('camera-orbit')); assert.ok(getRenderGovernorDiagnostics().holds.includes('camera-orbit'));
t.mock.timers.tick(500); t.mock.timers.tick(500);
engine.fake.frame(); engine.fake.frame();
const [first] = engine.fake.callsOf('camera.lookAt'); const [first] = engine.fake.callsOf('camera.lookAt');
assert.deepEqual(first.args[0], target); assert.deepEqual(first.args[0], target);
assert.ok(Math.abs(first.args[1].heading - (0.4 + geo.math.toRadians(5))) < 1e-9); assert.ok(
Math.abs(first.args[1].heading - (0.4 + geo.math.toRadians(5))) < 1e-9,
);
assert.equal(first.args[1].pitch, geo.math.toRadians(-20)); assert.equal(first.args[1].pitch, geo.math.toRadians(-20));
assert.equal(first.args[1].range, 800); assert.equal(first.args[1].range, 800);
assert.equal(orbit.toggle(), false); assert.equal(orbit.toggle(), false);
assert.equal(engine.fake.callsOf('camera.release').length, 1); assert.equal(engine.fake.callsOf('camera.release').length, 1);
assert.ok(!getRenderGovernorDiagnostics().holds.includes('camera-orbit')); assert.ok(!getRenderGovernorDiagnostics().holds.includes('camera-orbit'));
engine.fake.frame(); engine.fake.frame();
assert.equal(engine.fake.callsOf('camera.lookAt').length, 1, 'no frames after stop'); assert.equal(
engine.fake.callsOf('camera.lookAt').length,
1,
'no frames after stop',
);
}); });
test('orbit needs a target', () => { test('orbit needs a target', () => {
+8 -2
View File
@@ -15,7 +15,10 @@ function linkFor(pose) {
const params = new URLSearchParams(manager._buildHashParams().toString()); const params = new URLSearchParams(manager._buildHashParams().toString());
manager.destroy(); manager.destroy();
return Object.fromEntries( return Object.fromEntries(
['lat', 'lon', 'alt', 'heading', 'pitch', 'roll'].map((k) => [k, params.get(k)]), ['lat', 'lon', 'alt', 'heading', 'pitch', 'roll'].map((k) => [
k,
params.get(k),
]),
); );
} }
@@ -43,7 +46,10 @@ test('a straight-down view writes roll 0; other angles round as before', () => {
assert.equal(down.roll, '0'); assert.equal(down.roll, '0');
assert.equal(down.pitch, '-90'); assert.equal(down.pitch, '-90');
const oblique = linkFor(at(45.4, -29.6, 2)); const oblique = linkFor(at(45.4, -29.6, 2));
assert.deepEqual([oblique.heading, oblique.pitch, oblique.roll], ['45', '-30', '2']); assert.deepEqual(
[oblique.heading, oblique.pitch, oblique.roll],
['45', '-30', '2'],
);
assert.equal(linkFor(at(359.7, -30)).heading, '360'); assert.equal(linkFor(at(359.7, -30)).heading, '360');
}); });