Upload via GUI (85 Dateien)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
// Teil des UI-Testlaufs (scripts/ui-smoke.js): prüft das Tray-Menüfenster in echtem Electron, ohne das
|
||||
// Tray-Symbol selbst. Zeigt das Fenster, fährt mit der Maus darüber, klickt, drückt Esc.
|
||||
// Gibt „✓ …“ und „✗ …“ Zeilen aus; Aufruf durch ui-smoke.js.
|
||||
|
||||
const { app } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const { createTrayPopup } = require(path.join(ROOT, 'src', 'features', 'trayPopup.js'));
|
||||
const trayMenu = require(path.join(ROOT, 'src', 'features', 'trayMenu.js'));
|
||||
|
||||
let failed = 0;
|
||||
function check(name, ok, detail = '') {
|
||||
if (!ok) failed++;
|
||||
console.log(`${ok ? '✓' : '✗'} ${name}${detail ? ` — ${detail}` : ''}`);
|
||||
}
|
||||
|
||||
app.disableHardwareAcceleration();
|
||||
app.on('window-all-closed', (e) => e.preventDefault());
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const log = [];
|
||||
let active = 1;
|
||||
const template = () => trayMenu.buildTrayTemplate({
|
||||
version: '0.0.0', active, queued: 2, paused: false, autostart: true,
|
||||
onOpen: () => log.push('open'), onHistory: () => log.push('history'), onPause: () => log.push('pause'),
|
||||
onCancel: () => log.push('cancel'), onAutostart: () => log.push('autostart'), onQuit: () => log.push('quit')
|
||||
});
|
||||
const popup = createTrayPopup({
|
||||
htmlPath: path.join(ROOT, 'renderer', 'tray-menu.html'),
|
||||
preloadPath: path.join(ROOT, 'tray-menu-preload.js'),
|
||||
getModel: () => trayMenu.serializeTemplate(template()),
|
||||
onAction: (id) => trayMenu.runAction(template(), id)
|
||||
});
|
||||
|
||||
const js = (code) => popup.getWindow().webContents.executeJavaScript(code);
|
||||
const items = async () => JSON.parse(await js(`JSON.stringify([...document.querySelectorAll('.item')].map(b => { const r = b.getBoundingClientRect(); return { text: b.innerText.trim(), disabled: b.disabled, x: r.x, y: r.y, h: r.height }; }))`));
|
||||
const mid = (i) => ({ x: Math.round(i.x + 40), y: Math.round(i.y + i.h / 2) });
|
||||
const bg = (label) => js(`(() => { const b = [...document.querySelectorAll('.item')].find(x => x.innerText.includes(${JSON.stringify(label)})); return getComputedStyle(b).backgroundColor; })()`);
|
||||
const mouse = (type, p, extra = {}) => popup.getWindow().webContents.sendInputEvent({ type, x: p.x, y: p.y, ...extra });
|
||||
|
||||
try {
|
||||
popup.warmUp();
|
||||
await wait(6000); // erster Renderer-Start dauert mehrere Sekunden
|
||||
popup.show();
|
||||
await wait(800);
|
||||
check('Menüfenster wird sichtbar', popup.isVisible());
|
||||
|
||||
let list = await items();
|
||||
check('Menü zeigt Einträge mit Pausieren und Abbrechen',
|
||||
['Fenster öffnen', 'Upload-Verlauf', 'Übertragung pausieren', 'Laufende Übertragung abbrechen', 'Beenden'].every((t) => list.some((i) => i.text.includes(t))));
|
||||
|
||||
// Hover folgt der Maus
|
||||
const history = list.find((i) => i.text.includes('Upload-Verlauf'));
|
||||
// Das frisch geöffnete Fenster braucht einen Moment, bis es sein erstes Bild gezeichnet hat und Hover annimmt.
|
||||
let hovered = 'rgba(0, 0, 0, 0)';
|
||||
for (let i = 0; i < 12 && hovered === 'rgba(0, 0, 0, 0)'; i++) {
|
||||
mouse('mouseMove', { x: mid(history).x + (i % 2), y: mid(history).y });
|
||||
await wait(250);
|
||||
hovered = await bg('Upload-Verlauf');
|
||||
}
|
||||
const other = await bg('Fenster öffnen');
|
||||
check('Hover markiert den Eintrag unter der Maus', hovered !== 'rgba(0, 0, 0, 0)' && other === 'rgba(0, 0, 0, 0)', `${hovered} / ${other}`);
|
||||
|
||||
// Gesperrter Eintrag bleibt unmarkiert und löst nichts aus
|
||||
active = 0; popup.refresh(); await wait(400);
|
||||
list = await items();
|
||||
const cancel = list.find((i) => i.text.includes('abbrechen'));
|
||||
mouse('mouseMove', mid(cancel));
|
||||
await wait(300);
|
||||
check('Gesperrter Eintrag wird nicht markiert', cancel.disabled && (await bg('abbrechen')) === 'rgba(0, 0, 0, 0)');
|
||||
mouse('mouseDown', mid(cancel), { button: 'left', clickCount: 1 });
|
||||
mouse('mouseUp', mid(cancel), { button: 'left', clickCount: 1 });
|
||||
await wait(400);
|
||||
check('Klick auf gesperrten Eintrag löst keine Aktion aus', log.length === 0 && popup.isVisible());
|
||||
|
||||
// Klick führt die Aktion aus und schließt das Fenster
|
||||
const open = list.find((i) => i.text.includes('Fenster öffnen'));
|
||||
mouse('mouseMove', mid(open));
|
||||
mouse('mouseDown', mid(open), { button: 'left', clickCount: 1 });
|
||||
mouse('mouseUp', mid(open), { button: 'left', clickCount: 1 });
|
||||
await wait(600);
|
||||
check('Klick führt die Aktion aus und schließt das Menü', log.join() === 'open' && !popup.isVisible());
|
||||
|
||||
// Esc schließt
|
||||
popup.show();
|
||||
await wait(900);
|
||||
const reopened = popup.isVisible();
|
||||
const win = popup.getWindow();
|
||||
win.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
|
||||
win.webContents.sendInputEvent({ type: 'keyUp', keyCode: 'Escape' });
|
||||
await wait(500);
|
||||
check('Esc schließt das Menü', reopened && !popup.isVisible());
|
||||
} catch (e) {
|
||||
check('Menüfenster-Test ohne Ausnahme', false, e.message);
|
||||
}
|
||||
|
||||
popup.destroy();
|
||||
app.exit(failed ? 1 : 0);
|
||||
});
|
||||
Reference in New Issue
Block a user