mirror of
https://github.com/KingHWJ/WeReadBoard.git
synced 2026-11-03 18:24:58 +08:00
feat(reading-goals): 持久化阅读目标并收紧看板布局
This commit is contained in:
1 parent
61d3951905
commit
094e1aca3d
13 files changed
+834
-39
No files matched your search
@@ -0,0 +1,71 @@
|
||||
const { test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const vm = require('node:vm');
|
||||
|
||||
function app() {
|
||||
const nodes = new Map();
|
||||
const node = selector => {
|
||||
if (!nodes.has(selector)) nodes.set(selector, {
|
||||
value: '', textContent: '', innerHTML: '', disabled: false,
|
||||
classList: { add() {}, remove() {}, toggle() {} },
|
||||
setAttribute() {}, addEventListener() {}, setCustomValidity() {}, reportValidity() {},
|
||||
showModal() { this.open = true; }, close() { this.open = false; },
|
||||
});
|
||||
return nodes.get(selector);
|
||||
};
|
||||
const pending = () => new Promise(() => {});
|
||||
const context = vm.createContext({
|
||||
document: { querySelector: node, querySelectorAll: () => [], addEventListener() {}, documentElement: { dataset: {} } },
|
||||
localStorage: { getItem: () => null },
|
||||
WeApi: { status: pending, shelf: pending, dashboard: pending, goals: pending },
|
||||
crypto: { randomUUID: () => 'test-goal' },
|
||||
setTimeout() {}, clearTimeout() {}, console,
|
||||
});
|
||||
vm.runInContext(fs.readFileSync('static/js/app.js', 'utf8'), context);
|
||||
return { context, node, run: code => vm.runInContext(code, context) };
|
||||
}
|
||||
|
||||
test('目标书籍不在当前书架时仍保留总数,并可打开和编辑', () => {
|
||||
const { run, node } = app();
|
||||
run(`loadState.goals = 'ready';
|
||||
books = [{id:'known',title:'已读书',status:'done'}];
|
||||
goals = [{id:'g',name:'阅读',start:'2026-09-01',end:'2026-09-30',ids:['known','missing'],sources:[]}];
|
||||
shelfData = {};`);
|
||||
assert.equal(run('goalMetrics(goals[0]).total'), 2);
|
||||
assert.equal(run('goalMetrics(goals[0]).percent'), 50);
|
||||
run("openGoalDetail('g'); openGoalEditor('g');");
|
||||
assert.match(node('#goal-picker').innerHTML, /状态待同步/);
|
||||
assert.equal(run("selectedGoalBooks().includes('missing')"), true);
|
||||
});
|
||||
|
||||
test('数据库保存失败时保留原目标和编辑草稿,允许重试', async () => {
|
||||
const { context, run, node } = app();
|
||||
run(`loadState.goals = 'ready';
|
||||
shelfData = {}; books = [{id:'known',title:'一本书',status:'done'}];
|
||||
goals = [{id:'g',name:'原名称',start:'2026-09-01',end:'2026-09-30',ids:['known'],sources:[]}];
|
||||
openGoalEditor('g');`);
|
||||
node('#goal-name').value = '新名称';
|
||||
context.WeApi.saveGoal = async () => { throw new Error('数据库暂不可用'); };
|
||||
await run('saveGoal({preventDefault(){}})');
|
||||
assert.equal(run('goals[0].name'), '原名称');
|
||||
assert.equal(node('#goal-editor').open, true);
|
||||
assert.equal(node('#goal-name').value, '新名称');
|
||||
assert.match(node('#goal-error').textContent, /数据库暂不可用/);
|
||||
context.WeApi.saveGoal = async goal => ({ goal });
|
||||
await run('saveGoal({preventDefault(){}})');
|
||||
assert.equal(run('goals[0].name'), '新名称');
|
||||
assert.equal(node('#goal-editor').open, false);
|
||||
});
|
||||
|
||||
test('目标列表未完成加载时不打开编辑器', () => {
|
||||
const { run, node } = app();
|
||||
run(`page = 'overview';
|
||||
loadState.goals = 'loading';
|
||||
shelfData = {};
|
||||
books = [{id:'known',title:'一本书',status:'done'}];
|
||||
openGoalEditor(null, ['known'], []);`);
|
||||
assert.notEqual(node('#goal-editor').open, true);
|
||||
assert.equal(run('page'), 'goals');
|
||||
assert.match(node('#page-content').innerHTML, /正在读取阅读目标/);
|
||||
});
|
||||
Reference in new issue
Block a user