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
Changes
@@@ -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 () => {@@@ -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);
@@ -100,6 +100,15 @@ const { boot, check, done, launchReports } = require('./helpers/boot');
@@ -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.ok(!sent.includes('SECRET-BODY-FOR-AI'), 'no body is ever sent to the model');
assert.match(sent, /"source_type":"news.article"/);
assert.match(sent, /"source_type":"news.article"/);
assert.strictEqual(t.ctx.stories.get(s2.id).state, 'draft');
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 () => {
await check('a stub-provider run is held (stub_provider) and a failed run makes no text', async () => {
@@ -83,6 +83,21 @@ const BODY = [
@@ -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');
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 () => {
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 } });
r = await t.api(`/stories/${story.id}/publish`, { json: { revision: 3 } });
assert.strictEqual(r.status, 409);
assert.strictEqual(r.status, 409);