Reconcile verified account IDs and make language repairs observable
Magent CI/CD / verify (push) Successful in 1m50s
Magent CI/CD / deploy-prod (push) Skipped
Magent CI/CD / deploy-beta (push) Skipped

This commit is contained in:
2026-09-11 19:56:32 +12:00
parent 38169b881e
commit de25255ea8
25 changed files with 593 additions and 160 deletions
+52
View File
@@ -0,0 +1,52 @@
const assert = require('node:assert/strict');
const { chromium } = require(process.env.PLAYWRIGHT_PACKAGE || 'playwright');
const base = process.env.REVIEW_BASE || 'http://localhost:3114';
(async () => {
const browser = await chromium.launch();
try {
const context = await browser.newContext();
await context.addCookies([{ name: 'magent_logged_in', value: '1', url: base }]);
let finish, original = false, outcome = 'attention'; const writes = [], errors = [];
await context.route('**/api/**', async route => {
const req = route.request(), path = new URL(req.url()).pathname;
const reply = json => route.fulfill({ json });
if (path === '/api/auth/me') return reply({ username: 'Admin', role: 'admin' });
if (path.endsWith('/snapshot')) return reply({ request_id: '3976', title: 'Downfall', request_type: 'movie', state: 'ADDED_TO_ARR', timeline: [], actions: [{ id: 'search_auto', label: 'Search and auto-download', requires_confirmation: false }], presentation: { status: { label: 'Waiting', meaning: 'Waiting for a release.' }, nextStep: { title: 'Search', description: 'Search for a download.', actionIds: ['search_auto'] }, pipeline: [] } });
if (path.endsWith('/language') && req.method() === 'GET') return reply({ language: { code: 'de' }, originalEnabled: original, canChange: true, profileLanguage: original ? 'Original' : 'English' });
if (path.includes('/operations/')) return reply({ id: path.split('/').pop(), label: 'Working on request', status: 'running', events: [{ id: 'search', service: 'Radarr', state: 'active', message: 'Searching indexers for Downfall…' }] });
if (path.endsWith('/actions/search_auto') || path.endsWith('/actions/language')) {
writes.push({ path, payload: req.postData() ? req.postDataJSON() : null });
await new Promise(resolve => { finish = resolve; });
if (path.endsWith('/language')) original = true;
return reply({ status: outcome, message: outcome === 'attention' ? 'Search finished, but no download appeared. Review matching releases and rejection reasons.' : 'Radarr has a download queued for this movie.' });
}
if (path.includes('/events/stream')) return route.fulfill({ contentType: 'text/event-stream', body: ': fixture\n\n' });
return reply({});
});
const page = await context.newPage(); page.on('pageerror', e => errors.push(e.message));
for (const width of [1440, 390]) {
original = false; outcome = 'attention';
await page.setViewportSize({ width, height: 900 }); await page.goto(base + '/requests/3976');
await page.getByRole('heading', { name: 'German audio may need your approval' }).waitFor();
await page.getByRole('button', { name: 'Search and auto-download', exact: true }).first().click();
let dialog = page.getByRole('dialog'); await dialog.waitFor();
assert(await dialog.getByText(/Working on your request/).isVisible(), 'Progress opens automatically');
await dialog.getByText('Searching indexers for Downfall…', { exact: true }).waitFor(); finish();
await dialog.getByText('Search finished, but no download appeared. Review matching releases and rejection reasons.', { exact: true }).waitFor();
await dialog.getByRole('button', { name: 'Dismiss activity' }).click();
outcome = 'downloading';
await page.getByRole('button', { name: 'Use German audio & search', exact: true }).click();
dialog = page.getByRole('dialog'); await dialog.waitFor();
await dialog.getByText('Searching indexers for Downfall…', { exact: true }).waitFor(); finish();
await dialog.getByText('Radarr has a download queued for this movie.', { exact: true }).waitFor();
if (process.env.REVIEW_DIR) await page.screenshot({ path: `${process.env.REVIEW_DIR}/downfall-progress-${width}.png`, animations: 'disabled' });
await dialog.getByRole('button', { name: 'Dismiss activity' }).click();
await page.getByRole('heading', { name: 'German audio enabled' }).waitFor();
assert.notEqual(await page.evaluate(() => document.body.style.overflow), 'hidden');
assert(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth));
}
assert(writes.filter(w => w.path.endsWith('/language')).every(w => w.payload.acceptOriginalLanguage === true && w.payload.languageCode === 'de'));
assert.deepEqual(errors, []);
console.log('Passed: desktop/mobile automatic repair overlay, live events, no-download outcome, prominent German audio choice, saved state, queue confirmation and scroll restoration. All APIs intercepted.');
} finally { await browser.close(); }
})().catch(e => { console.error(e); process.exitCode = 1; });