101 lines
4.7 KiB
JavaScript
101 lines
4.7 KiB
JavaScript
// The legacy admin and gallery pages show a server refusal's reason (#220, PR #289 review I1 and M8): a job that
|
|
// runs in the workspace refuses their record-changing requests, and a corrupt config.json refuses a settings save.
|
|
// Each page must name the reason, not report a lost connection, a bare HTTP status or a success.
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const vm = require('node:vm');
|
|
|
|
function elements() {
|
|
const nodes = {};
|
|
return {
|
|
nodes,
|
|
getElementById: id => nodes[id] ||= { id, textContent: '', innerHTML: '', disabled: false, style: {},
|
|
value: '', checked: false, addEventListener() {}, querySelectorAll: () => [] },
|
|
};
|
|
}
|
|
|
|
function jsonResponse(status, body) {
|
|
return { ok: status >= 200 && status < 300, status, statusText: status === 409 ? 'Conflict' : 'OK',
|
|
json: async () => body };
|
|
}
|
|
|
|
function load(file, className, fetchUrl, extra = {}, dom = elements()) {
|
|
const timers = [];
|
|
const notifications = [];
|
|
const storage = new Map([['pm_cached', '1'], ['userData', 'keep'], ['pm_workspace_theme', 'light'],
|
|
['pm_update_notice_dismissed', '3.3.0']]);
|
|
const localStorage = {
|
|
get length() { return storage.size; },
|
|
key: index => [...storage.keys()][index] ?? null,
|
|
getItem: key => storage.get(key) ?? null,
|
|
setItem: (key, value) => storage.set(key, String(value)),
|
|
removeItem: key => storage.delete(key),
|
|
};
|
|
const context = vm.createContext({
|
|
document: { readyState: 'loading', addEventListener() {}, getElementById: dom.getElementById,
|
|
querySelectorAll: () => [] },
|
|
window: {}, console: { error() {}, warn() {}, debug() {} },
|
|
setTimeout: callback => timers.push(callback),
|
|
confirm: () => true,
|
|
localStorage,
|
|
TextDecoder, TextEncoder, JSON,
|
|
ApiClient: { fetchUrl },
|
|
...extra,
|
|
});
|
|
// gallery.html loads cache-ownership.js before gallery.js (#222).
|
|
vm.runInContext(fs.readFileSync(path.join(__dirname, '../../web/js/cache-ownership.js'), 'utf8'), context);
|
|
const source = fs.readFileSync(path.join(__dirname, `../../web/js/${file}`), 'utf8');
|
|
const Page = vm.runInContext(`${source}\n${className};`, context, { filename: path.join(__dirname, `../../web/js/${file}`) });
|
|
const page = Object.create(Page.prototype);
|
|
page.showNotification = (message, type) => notifications.push([type, message]);
|
|
page.showModal = id => notifications.push(['show', id]);
|
|
page.hideModal = id => notifications.push(['hide', id]);
|
|
return { page, dom, timers, notifications, storage };
|
|
}
|
|
|
|
test('admin settings save shows why config.json refused it', async () => {
|
|
const message = 'config.json cannot be read, so nothing was saved. Fix or remove the file, then save again.';
|
|
const { page, notifications } = load('admin.js', 'PromptAdmin',
|
|
async () => jsonResponse(409, { success: false, persisted: false, code: 'config-unreadable', error: message }));
|
|
page.settings = {};
|
|
page.setInfiniteScroll = () => assert.fail('nothing changes after a refusal');
|
|
|
|
await page.saveSettings();
|
|
|
|
assert.deepEqual(notifications, [['error', `Failed to save settings: ${message}`]]);
|
|
});
|
|
|
|
test('admin settings save keeps its plain message when the reply has no reason', async () => {
|
|
const { page, notifications } = load('admin.js', 'PromptAdmin', async () => ({ ok: false, status: 500,
|
|
json: async () => { throw new SyntaxError('not json'); } }));
|
|
page.settings = {};
|
|
|
|
await page.saveSettings();
|
|
|
|
assert.deepEqual(notifications, [['error', 'Failed to save settings']]);
|
|
});
|
|
|
|
// #330 S13-9: the admin page's reduced Page options save sends only the list's scroll default, so a stale legacy form
|
|
// can no longer overwrite scan folders or other settings edited in System.
|
|
test('admin Page options save posts only infinite_scroll', async () => {
|
|
const sent = [];
|
|
const { page, dom, notifications } = load('admin.js', 'PromptAdmin', async (url, init) => {
|
|
sent.push([url, init.method, JSON.parse(init.body)]);
|
|
return jsonResponse(200, { success: true, restart_required: true });
|
|
});
|
|
page.settings = { infiniteScroll: false };
|
|
const scrolled = [];
|
|
page.setInfiniteScroll = (on, options) => scrolled.push([on, { ...options }]);
|
|
dom.getElementById('infiniteScrollDefault').checked = true;
|
|
|
|
await page.saveSettings();
|
|
|
|
assert.deepEqual(sent, [['/prompt_manager/settings', 'POST', { infinite_scroll: true }]]);
|
|
assert.deepEqual(scrolled, [[true, { session: false }]]);
|
|
assert.equal(page.settings.infiniteScroll, true);
|
|
assert.deepEqual(notifications, [['success', 'Page options saved'], ['hide', 'settingsModal']]);
|
|
});
|
|
|