mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
i18n: fix the repeat-review findings
- Status pieces translate in one place (src/ui/statusText.js): a Local
ADS-B error with a single piece now translates, and the analyst card
splits empty-layer notes into pieces (Transit, Local ADS-B).
- Translate the ALPR retry chip text, the ECCC error on the Air quality
card, "Upstream response too large" and the "entry {n}" feed label.
- The unmarked-text check also sees error/loadingLabel/statusMessage/
status assignments, `status:` properties and showToast?.( /
this._showToast( calls; the scene import preview marks its pack
statuses, data and model-facing text carry i18n-ignore with a reason.
- Tests check the real code: the HUD locality formatter moves to
src/hudLocalityFormat.js, the unsaved-keys test pins the teardown.
- One copy each: city names come from src/cityPois.js, the GNSS HTTP
template and wind "field unavailable" texts; dead fallbacks removed.
- Leftovers of the reverted vessel-label change and the reformatting of
detectionHost.test.mjs / keySetup.test.mjs are back to main.
Catalogs: es/ru 2617 messages each, complete.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
a2463ca2d2
commit
3157888780
60 files changed
+1577
-1606
No files matched your search
+19
-80
@@ -6,7 +6,9 @@ import {
|
||||
stripKeylessBasemapFromHash,
|
||||
bindKeySetupPlacement,
|
||||
waitForChatGptOAuth,
|
||||
initKeySetup,
|
||||
} from './keySetup.js';
|
||||
import { describeUnsavedWork } from './i18n/index.js';
|
||||
|
||||
test('setup placement moves the same button only in Cyber and disconnects on teardown', () => {
|
||||
const home = {
|
||||
@@ -59,20 +61,10 @@ test('setup placement moves the same button only in Cyber and disconnects on tea
|
||||
});
|
||||
|
||||
test('the chip counts what is missing, and retires the count at zero', () => {
|
||||
assert.equal(
|
||||
keySetupChipLabel({ setCount: 0, total: 8 }),
|
||||
'POWER UP · 8 KEYS WAITING',
|
||||
);
|
||||
assert.equal(
|
||||
keySetupChipLabel({ setCount: 7, total: 8 }),
|
||||
'POWER UP · 1 KEY WAITING',
|
||||
);
|
||||
assert.equal(keySetupChipLabel({ setCount: 0, total: 8 }), 'POWER UP · 8 KEYS WAITING');
|
||||
assert.equal(keySetupChipLabel({ setCount: 7, total: 8 }), 'POWER UP · 1 KEY WAITING');
|
||||
assert.equal(keySetupChipLabel({ setCount: 8, total: 8 }), 'POWERED UP');
|
||||
assert.equal(
|
||||
keySetupChipLabel(null),
|
||||
'POWERED UP',
|
||||
'no status is not a broken label',
|
||||
);
|
||||
assert.equal(keySetupChipLabel(null), 'POWERED UP', 'no status is not a broken label');
|
||||
});
|
||||
|
||||
test('collectKeyUpdates keeps only non-empty trimmed values', () => {
|
||||
@@ -112,27 +104,14 @@ test('OAuth login polling stops as soon as local ChatGPT auth becomes available'
|
||||
|
||||
test('OAuth login polling stops on login or HTTP failure instead of waiting for timeout', async () => {
|
||||
for (const result of [
|
||||
{
|
||||
ok: true,
|
||||
payload: {
|
||||
available: false,
|
||||
loginFailed: true,
|
||||
error: 'Sign-in failed.',
|
||||
},
|
||||
},
|
||||
{ ok: true, payload: { available: false, loginFailed: true, error: 'Sign-in failed.' } },
|
||||
{ ok: false, payload: { error: 'Sign-in is local only.' } },
|
||||
]) {
|
||||
let checks = 0;
|
||||
await assert.rejects(
|
||||
waitForChatGptOAuth({
|
||||
fetchImpl: async () => {
|
||||
checks += 1;
|
||||
return { ok: result.ok, json: async () => result.payload };
|
||||
},
|
||||
sleep: () => assert.fail('failed login must stop polling'),
|
||||
}),
|
||||
{ message: result.payload.error },
|
||||
);
|
||||
await assert.rejects(waitForChatGptOAuth({
|
||||
fetchImpl: async () => { checks += 1; return { ok: result.ok, json: async () => result.payload }; },
|
||||
sleep: () => assert.fail('failed login must stop polling'),
|
||||
}), { message: result.payload.error });
|
||||
assert.equal(checks, 1);
|
||||
}
|
||||
});
|
||||
@@ -140,34 +119,12 @@ test('OAuth login polling stops on login or HTTP failure instead of waiting for
|
||||
test('OAuth login polling respects timeout and an aborted setup surface', async () => {
|
||||
let clock = 0;
|
||||
let checks = 0;
|
||||
const poll = {
|
||||
fetchImpl: async () => {
|
||||
checks += 1;
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({ available: false, pending: true }),
|
||||
};
|
||||
},
|
||||
};
|
||||
assert.equal(
|
||||
await waitForChatGptOAuth({
|
||||
...poll,
|
||||
timeoutMs: 100,
|
||||
pollMs: 100,
|
||||
now: () => clock,
|
||||
sleep: async (ms) => {
|
||||
clock += ms;
|
||||
},
|
||||
}),
|
||||
false,
|
||||
);
|
||||
const poll = { fetchImpl: async () => { checks += 1; return { ok: true, json: async () => ({ available: false, pending: true }) }; } };
|
||||
assert.equal(await waitForChatGptOAuth({ ...poll, timeoutMs: 100, pollMs: 100, now: () => clock, sleep: async (ms) => { clock += ms; } }), false);
|
||||
assert.equal(checks, 2);
|
||||
const controller = new AbortController();
|
||||
controller.abort();
|
||||
assert.equal(
|
||||
await waitForChatGptOAuth({ ...poll, signal: controller.signal }),
|
||||
false,
|
||||
);
|
||||
assert.equal(await waitForChatGptOAuth({ ...poll, signal: controller.signal }), false);
|
||||
assert.equal(checks, 2, 'aborted polling does not fetch');
|
||||
});
|
||||
|
||||
@@ -175,22 +132,14 @@ test('OAuth polling ignores a ready response received after the surface was abor
|
||||
const controller = new AbortController();
|
||||
const available = await waitForChatGptOAuth({
|
||||
signal: controller.signal,
|
||||
fetchImpl: async () => ({
|
||||
ok: true,
|
||||
json: async () => {
|
||||
controller.abort();
|
||||
return { available: true };
|
||||
},
|
||||
}),
|
||||
fetchImpl: async () => ({ ok: true, json: async () => { controller.abort(); return { available: true }; } }),
|
||||
sleep: () => assert.fail('aborted polling must not continue'),
|
||||
});
|
||||
assert.equal(available, false);
|
||||
});
|
||||
|
||||
test('the first Google key strips ONLY the keyless OSM basemap from the share hash', () => {
|
||||
const stripped = stripKeylessBasemapFromHash(
|
||||
'lat=30.2&lon=-97.7&map=osm&style=normal',
|
||||
);
|
||||
const stripped = stripKeylessBasemapFromHash('lat=30.2&lon=-97.7&map=osm&style=normal');
|
||||
assert.ok(stripped !== null);
|
||||
const params = new URLSearchParams(stripped);
|
||||
assert.equal(params.get('map'), null, 'osm basemap removed');
|
||||
@@ -198,11 +147,7 @@ test('the first Google key strips ONLY the keyless OSM basemap from the share ha
|
||||
assert.equal(params.get('style'), 'normal', 'style survives');
|
||||
// A stack under any other name was chosen or shared on purpose.
|
||||
assert.equal(stripKeylessBasemapFromHash('map=bing-aerial&lat=1'), null);
|
||||
assert.equal(
|
||||
stripKeylessBasemapFromHash('lat=1&lon=2'),
|
||||
null,
|
||||
'no stack, nothing to do',
|
||||
);
|
||||
assert.equal(stripKeylessBasemapFromHash('lat=1&lon=2'), null, 'no stack, nothing to do');
|
||||
assert.equal(stripKeylessBasemapFromHash(''), null);
|
||||
assert.equal(stripKeylessBasemapFromHash(undefined), null);
|
||||
});
|
||||
@@ -216,15 +161,11 @@ test('aborting pending setup removes its surface and ignores a late response', a
|
||||
let requestSignal;
|
||||
const controller = new AbortController();
|
||||
const pending = initKeySetup({
|
||||
documentRef: {
|
||||
getElementById: (id) => (id === 'key-setup-chip' ? chip : root),
|
||||
},
|
||||
documentRef: { getElementById: (id) => id === 'key-setup-chip' ? chip : root },
|
||||
signal: controller.signal,
|
||||
fetchImpl: (_url, { signal }) => {
|
||||
requestSignal = signal;
|
||||
return new Promise((resolve) => {
|
||||
resolveResponse = resolve;
|
||||
});
|
||||
return new Promise((resolve) => { resolveResponse = resolve; });
|
||||
},
|
||||
});
|
||||
controller.abort();
|
||||
@@ -233,10 +174,7 @@ test('aborting pending setup removes its surface and ignores a late response', a
|
||||
resolveResponse({ ok: true, json: async () => ({ keys: [] }) });
|
||||
assert.equal(await pending, null);
|
||||
});
|
||||
|
||||
test('a pasted, unsaved key makes the language switch ask first until teardown', async () => {
|
||||
const { initKeySetup } = await import('./keySetup.js');
|
||||
const { describeUnsavedWork } = await import('./i18n/index.js');
|
||||
const node = () => ({
|
||||
dataset: {},
|
||||
addEventListener() {},
|
||||
@@ -271,6 +209,7 @@ test('a pasted, unsaved key makes the language switch ask first until teardown',
|
||||
assert.deepEqual(describeUnsavedWork(), []);
|
||||
input.value = 'AIza-pasted';
|
||||
assert.deepEqual(describeUnsavedWork(), ['unsaved provider keys']);
|
||||
// The field still holds the key, so only teardown dropping the check clears it.
|
||||
controller.abort();
|
||||
assert.deepEqual(describeUnsavedWork(), []);
|
||||
});
|
||||
Reference in new issue
Block a user