import assert from 'node:assert/strict'; import { test } from 'node:test'; import { emit, field, find, install, nodes, server, settle } from './flow-helpers.mjs'; const ui = install(); const { api, setUnauthorizedHandler } = await import('../../bindery/static/js/lib.js'); const { stopPolling } = await import('../../bindery/static/js/jobs.js'); test('local login, retry, session expiry and logout use the existing form', async (t) => { t.mock.timers.enable({ apis: ['setTimeout'] }); const backend = server(t); let auth = { authenticated: false, mode: 'local', user: null }; backend.on('GET', 'auth/check', () => auth); backend.on('GET', 'config', { metadata_fields: {}, mode_labels: {}, library_available: false, download_fields: {} }); backend.on('GET', 'stories', []); backend.on('GET', 'jobs', []); backend.on('GET', 'expired', { error: 'Session ended' }, 401); backend.on('POST', 'auth/logout', () => { auth = { ...auth, authenticated: false, user: null }; return {}; }); t.after(() => { stopPolling(); setUnauthorizedHandler(() => {}); }); await import('../../bindery/static/js/main.js'); await settle(); assert.match(ui.app.textContent, /Log in with your Bindery account/); assert.doesNotMatch(ui.app.textContent, /CWA account/); assert.equal(document.activeElement, field(ui.app, 'username')); assert.equal(backend.sent('GET', 'config').length, 0); const form = () => nodes(ui.app).find((el) => el.tagName === 'form'); field(ui.app, 'username').value = 'reader'; field(ui.app, 'password').value = 'wrong'; backend.on('POST', 'auth/login', { error: 'Wrong user name or password' }, 401); await emit(form(), 'submit'); assert.match(ui.app.textContent, /Wrong user name or password/); assert.equal(find(ui.app, 'button', 'Log in').disabled, false); assert.deepEqual(backend.sent('POST', 'auth/login')[0].body, { username: 'reader', password: 'wrong', remember: true }); field(ui.app, 'password').value = 'correct'; nodes(form()).find((el) => el.attributes.type === 'checkbox').checked = false; backend.on('POST', 'auth/login', () => { auth = { authenticated: true, mode: 'local', user: 'reader' }; return {}; }); await emit(form(), 'submit'); await settle(); assert.ok(find(ui.app, 'button', 'Log out')); assert.match(ui.app.textContent, /reader/); const request = backend.sent('POST', 'auth/login')[1]; assert.deepEqual(request.body, { username: 'reader', password: 'correct', remember: false }); assert.equal(request.headers['X-Requested-With'], 'bindery'); auth = { ...auth, authenticated: false }; await assert.rejects(api('expired'), /Session ended/); await settle(); assert.ok(find(ui.app, 'button', 'Log in')); const polls = backend.sent('GET', 'jobs').length; t.mock.timers.tick(60000); await settle(); assert.equal(backend.sent('GET', 'jobs').length, polls); await emit(form(), 'submit'); await settle(); await emit(find(ui.app, 'button', 'Log out'), 'click'); await settle(); assert.equal(backend.sent('POST', 'auth/logout').length, 1); assert.ok(find(ui.app, 'button', 'Log in')); });