Internationalization
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { readAppFile } from '../test-support/i18n.js';
|
||||
import { loadI18n } from '../test-support/i18n.js';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
@@ -7,7 +9,7 @@ import vm from 'node:vm';
|
||||
const root = path.resolve(import.meta.dirname, '..');
|
||||
|
||||
async function read(relativePath) {
|
||||
return fs.readFile(path.join(root, relativePath), 'utf8');
|
||||
return readAppFile(relativePath);
|
||||
}
|
||||
|
||||
async function clientSources() {
|
||||
@@ -72,6 +74,7 @@ test('mobile navigation footer contains a rotating SVG arrow and exact metre out
|
||||
test('client bearing calculation points north and east correctly', async () => {
|
||||
const source = await read('public/js/distance.js');
|
||||
const context = { Wegwichtel: {} };
|
||||
await loadI18n(context);
|
||||
vm.runInNewContext(source, context);
|
||||
|
||||
const distance = context.Wegwichtel.Distance;
|
||||
@@ -96,10 +99,10 @@ test('route controls use accessible icon buttons with start, pause and stop stat
|
||||
assert.match(html, /id="start-route"[\s\S]*images\/icons\/play\.svg/);
|
||||
assert.match(html, /id="pause-route"[\s\S]*images\/icons\/pause\.svg/);
|
||||
assert.match(html, /id="stop-route"[\s\S]*images\/icons\/stop\.svg/);
|
||||
assert.match(html, /aria-label="Route starten"/);
|
||||
assert.match(html, /aria-label="Route pausieren"/);
|
||||
assert.match(html, /aria-label="Route beenden"/);
|
||||
assert.match(html, /<fieldset>[\s\S]*<legend>Routensteuerung<\/legend>/);
|
||||
assert.match(html, /aria-label="Strecke starten"/);
|
||||
assert.match(html, /aria-label="Strecke pausieren"/);
|
||||
assert.match(html, /aria-label="Strecke beenden"/);
|
||||
assert.match(html, /<fieldset>[\s\S]*<legend>Unterwegs<\/legend>/);
|
||||
assert.doesNotMatch(html, /role="group"/);
|
||||
assert.doesNotMatch(html, /aria-type=/);
|
||||
assert.match(app, /routeState:\s*'idle'/);
|
||||
@@ -131,7 +134,7 @@ test('pause and stop control audio and stop returns to route selection', async (
|
||||
assert.match(audio, /audio\.load\(\)/);
|
||||
});
|
||||
|
||||
test('the selected or triggered Streckenpunkt is highlighted semantically', async () => {
|
||||
test('the selected or triggered Station is highlighted semantically', async () => {
|
||||
const app = await read('public/js/app.js');
|
||||
const css = await read('public/css/app.css');
|
||||
|
||||
@@ -141,7 +144,7 @@ test('the selected or triggered Streckenpunkt is highlighted semantically', asyn
|
||||
assert.match(css, /aktuelle Station/);
|
||||
});
|
||||
|
||||
test('Streckenpunkte have live direction and metre indicators and take navigation priority', async () => {
|
||||
test('Stationen have live direction and metre indicators and take navigation priority', async () => {
|
||||
const app = await read('public/js/app.js');
|
||||
const css = await read('public/css/app.css');
|
||||
const html = await read('public/index.html');
|
||||
@@ -150,16 +153,16 @@ test('Streckenpunkte have live direction and metre indicators and take navigatio
|
||||
assert.match(app, /function updatePoiIndicators\(position\)/);
|
||||
assert.match(app, /function nearestPendingPoi\(metrics\)/);
|
||||
assert.match(app, /if \(nextPoi\) showPoiNavigation\(position, nextPoi\)/);
|
||||
assert.match(app, /Nächster Streckenpunkt:/);
|
||||
assert.match(app, /Nächste Station:/);
|
||||
assert.match(app, /find\('small'\)\.text\(`\$\{distance\} m`\)/);
|
||||
assert.match(app, /find\('svg'\)\.css\('transform'/);
|
||||
assert.match(css, /\.poi-proximity[\s\S]*grid-column:\s*2/);
|
||||
assert.match(css, /\.poi-proximity svg[\s\S]*transition:\s*transform/);
|
||||
assert.match(html, /Richtung zum nächsten Streckenpunkt/);
|
||||
assert.match(html, /Richtung zum nächsten Station/);
|
||||
});
|
||||
|
||||
|
||||
test('reaching a Streckenpunkt preloads audio without autoplay and uses the vibration wrapper', async () => {
|
||||
test('reaching a Station preloads audio without autoplay and uses the vibration wrapper', async () => {
|
||||
const app = await read('public/js/app.js');
|
||||
const audio = await read('public/js/audio-player.js');
|
||||
const html = await read('public/index.html');
|
||||
@@ -171,14 +174,14 @@ test('reaching a Streckenpunkt preloads audio without autoplay and uses the vibr
|
||||
assert.doesNotMatch(app, /navigator\.vibrate/);
|
||||
assert.match(app, /function stopRouteSensors\(\)[\s\S]*ns\.Vibration\.stop\(\)/);
|
||||
assert.match(audio, /audio\.load\(\)/);
|
||||
assert.match(html, /<audio id="poi-audio" controls preload="metadata" aria-label="Audiowiedergabe zum Streckenpunkt" hidden>/);
|
||||
assert.match(html, /<audio id="poi-audio" controls preload="metadata" aria-label="Ton zur Station" hidden>/);
|
||||
assert.match(audio, /removeAttr\('hidden'\)/);
|
||||
assert.match(audio, /Date\.now\(\)/);
|
||||
assert.match(loader, /'vibration'/);
|
||||
});
|
||||
|
||||
|
||||
test('Streckenpunkt page uses icon-based back and slideshow controls in a single responsive row', async () => {
|
||||
test('Station page uses icon-based back and slideshow controls in a single responsive row', async () => {
|
||||
const html = await read('public/index.html');
|
||||
const css = await read('public/css/app.css');
|
||||
const loader = await read('public/js/bootstrap-loader.js');
|
||||
@@ -196,7 +199,7 @@ test('Streckenpunkt page uses icon-based back and slideshow controls in a single
|
||||
assert.match(css, /#slide-caption[\s\S]*overflow-wrap:\s*anywhere/);
|
||||
assert.match(css, /#slide-image[\s\S]*object-fit:\s*contain/);
|
||||
assert.doesNotMatch(css, /#slideshow img\s*\{/);
|
||||
assert.match(html, /images\/icons\/play\.svg" alt="Route starten"/);
|
||||
assert.match(html, /images\/icons\/play\.svg" alt="Strecke starten"/);
|
||||
assert.match(html, /images\/icons\/chevron-left\.svg" alt="Vorheriges Bild"/);
|
||||
assert.doesNotMatch(loader, /controlgroup/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user