166 lines
4.2 KiB
JavaScript
166 lines
4.2 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import vm from 'node:vm';
|
|
|
|
const root = path.resolve(import.meta.dirname, '..');
|
|
|
|
class ClassList {
|
|
constructor() {
|
|
this.values = new Set();
|
|
}
|
|
|
|
add(...names) {
|
|
names.forEach(name => this.values.add(name));
|
|
}
|
|
|
|
remove(...names) {
|
|
names.forEach(name => this.values.delete(name));
|
|
}
|
|
|
|
contains(name) {
|
|
return this.values.has(name);
|
|
}
|
|
}
|
|
|
|
class FakeElement extends EventTarget {
|
|
constructor(id = '') {
|
|
super();
|
|
this.id = id;
|
|
this.hidden = false;
|
|
this.value = 0;
|
|
this.textContent = '';
|
|
this.src = '';
|
|
this.async = true;
|
|
this.classList = new ClassList();
|
|
this.attributes = new Map();
|
|
this.focused = false;
|
|
}
|
|
|
|
focus() {
|
|
this.focused = true;
|
|
}
|
|
|
|
setAttribute(name, value) {
|
|
this.attributes.set(name, String(value));
|
|
}
|
|
|
|
closest() {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function pointerEvent() {
|
|
const event = new Event('pointerup', { cancelable: true });
|
|
Object.defineProperties(event, {
|
|
isPrimary: { value: true },
|
|
pointerType: { value: 'touch' },
|
|
button: { value: 0 }
|
|
});
|
|
return event;
|
|
}
|
|
|
|
test('bootstrap remains visible after loading and opens the app only after deliberate activation', async () => {
|
|
const sourcePath = path.join(root, 'public/js/bootstrap-loader.js');
|
|
const source = await fs.readFile(sourcePath, 'utf8');
|
|
const ids = [
|
|
'bootstrap-screen',
|
|
'bootstrap-progress',
|
|
'bootstrap-error',
|
|
'bootstrap-retry',
|
|
'bootstrap-enter',
|
|
'bootstrap-ready',
|
|
'storage-cleanup-status',
|
|
'app-shell'
|
|
];
|
|
const elements = new Map(ids.map(id => [id, new FakeElement(id)]));
|
|
const steps = new Map([
|
|
'jquery',
|
|
'jquery-ui',
|
|
'modules',
|
|
'server',
|
|
'routes',
|
|
'location'
|
|
].map(name => [name, new FakeElement(name)]));
|
|
const navigations = [];
|
|
|
|
function jquery() {
|
|
return {
|
|
button() {
|
|
return this;
|
|
}
|
|
};
|
|
}
|
|
|
|
const context = {
|
|
Wegwichtel: {
|
|
PrivacyStorage: {
|
|
async cleanupExpired(callback) {
|
|
callback(0, 1);
|
|
callback(1, 1);
|
|
return { removed: 1, total: 1 };
|
|
}
|
|
},
|
|
App: {
|
|
async initialize({ markStep }) {
|
|
markStep('server', 'done');
|
|
markStep('routes', 'done');
|
|
markStep('location', 'done');
|
|
},
|
|
navigate(...args) {
|
|
navigations.push(args);
|
|
}
|
|
}
|
|
},
|
|
document: {
|
|
getElementById: id => elements.get(id),
|
|
querySelector(selector) {
|
|
const match = selector.match(/^\[data-step="(.+)"\]$/);
|
|
return match ? steps.get(match[1]) : null;
|
|
},
|
|
querySelectorAll(selector) {
|
|
if (selector === '#bootstrap-steps .done') {
|
|
return [...steps.values()].filter(step => step.classList.contains('done'));
|
|
}
|
|
return [];
|
|
},
|
|
createElement: () => new FakeElement('script'),
|
|
head: {
|
|
appendChild(script) {
|
|
if (script.src.includes('/jquery-4.0.0.min.js')) {
|
|
jquery.fn = { jquery: '4.0.0' };
|
|
context.jQuery = jquery;
|
|
}
|
|
if (script.src.includes('/jquery-ui-1.14.2.min.js')) {
|
|
jquery.ui = { version: '1.14.2' };
|
|
}
|
|
queueMicrotask(() => script.onload());
|
|
}
|
|
}
|
|
},
|
|
Event,
|
|
EventTarget,
|
|
Promise,
|
|
console,
|
|
encodeURIComponent,
|
|
queueMicrotask,
|
|
location: { reload() {} }
|
|
};
|
|
context.globalThis = context;
|
|
vm.runInNewContext(source, context, { filename: sourcePath });
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 20));
|
|
assert.equal(elements.get('bootstrap-screen').hidden, false);
|
|
assert.equal(elements.get('bootstrap-screen').attributes.get('aria-busy'), 'false');
|
|
assert.equal(elements.get('bootstrap-enter').hidden, false);
|
|
assert.equal(elements.get('storage-cleanup-status').textContent, 'Entferne alte Streckendaten aus dem Speicher (1 / 1)');
|
|
assert.equal(navigations.length, 0);
|
|
|
|
elements.get('bootstrap-screen').dispatchEvent(pointerEvent());
|
|
assert.equal(elements.get('bootstrap-screen').hidden, true);
|
|
assert.equal(elements.get('app-shell').hidden, false);
|
|
assert.equal(navigations[0][0], '#routes-page');
|
|
assert.equal(navigations[0][1].replace, true);
|
|
});
|