openvibers/openvibe.news Commits

Tests: the editor desk shows upstream flags, pending revisions and removal reasons; AI drafts are reviewed through the no-JS form

OP OpenVibers committed 23 Sept 2026 · 13a1011850 · 2 files, +24 −0


Changes

ddiff --git a/test/ai.test.js b/test/ai.test.js
iindex 8fcf8dc..962e4d9 100644
---- a/test/ai.test.js
++++ b/test/ai.test.js
@@@ -100,6 +100,15 @@ const { boot, check, done, launchReports } = require('./helpers/boot');
assert.ok(!sent.includes('SECRET-BODY-FOR-AI'), 'no body is ever sent to the model');
assert.match(sent, /"source_type":"news.article"/);
assert.strictEqual(t.ctx.stories.get(s2.id).state, 'draft');
++ const edit = await t.get(`/edit/stories/${s2.id}`, { as: t.editor });
++ assert.strictEqual(edit.status, 200, edit.text);
++ assert.match(edit.text, /Ask OpenVibe.AI for a draft summary/);
++ assert.match(edit.text, /is AI-generated \(news.summarize_story\)\. Read it against the sources before approving/);
++ assert.match(edit.text, /What the AI draft could not support/);
++ const csrf = t.csrf(t.editor);
++ const rv = await t.get(`/edit/stories/${s2.id}/review`, { as: t.editor, form: { _csrf: csrf, revision: String(head.revision), decision: 'approved', note: '' } });
++ assert.strictEqual(rv.status, 303, rv.text);
++ assert.strictEqual(t.ctx.store.reviews.latest(s2.id, head.revision).reviewer, t.editor.subject);
});
await check('a stub-provider run is held (stub_provider) and a failed run makes no text', async () => {
ddiff --git a/test/upstream.test.js b/test/upstream.test.js
iindex f4e3067..a0d3283 100644
---- a/test/upstream.test.js
++++ b/test/upstream.test.js
@@@ -83,6 +83,21 @@ const BODY = [
assert.strictEqual(t.db().prepare("SELECT COUNT(*) AS n FROM news_editorial_flags WHERE kind = 'source_removed'").get().n, 1, 'a removal flags once');
});
++ await check('the editor desk shows the open flags, the pending revision and why it cannot be published', async () => {
++ const desk = await t.get('/edit', { as: t.editor });
++ assert.strictEqual(desk.status, 200);
++ assert.match(desk.text, /source removed \(pending revision 3\)/);
++ const edit = await t.get(`/edit/stories/${story.id}`, { as: t.editor });
++ assert.strictEqual(edit.status, 200, edit.text);
++ assert.match(edit.text, /<h2>Open flags<\/h2>/);
++ assert.match(edit.text, /was prepared by the system because a source was removed upstream/);
++ assert.match(edit.text, /<code>story.source_removed<\/code>/);
++ assert.match(edit.text, /licence withdrawn by the publisher/, 'editors see the removal reason');
++ const prev = await t.get(`/edit/stories/${story.id}/preview?revision=3`, { as: t.editor });
++ assert.strictEqual(prev.status, 200);
++ assert.match(prev.text, /Removed upstream: licence withdrawn/);
++ });
++
await check('the pending revision (still citing the removed source) cannot be published', async () => {
r = await t.api(`/stories/${story.id}/publish`, { json: { revision: 3 } });
assert.strictEqual(r.status, 409);