managarten/apps/api/src/modules/articles/consent-wall.test.ts
Till JS e8774fc233 test(articles): worker rollup + field-meta + consent-wall + recovery UI (#6,#14)
#6 — Worker test coverage on the deterministic helpers
   Three new bun-test files in apps/api/src/modules/articles/:
     - field-meta.test.ts (6 tests): pins down the legacy-vs-F3 fix
       so it can never regress silently — including the regression
       check from the live-test-found bug (string vs object compare
       across both shapes evaluates correctly).
     - consent-wall.test.ts (8 tests): the heuristic we extracted
       in #4. German + English vocab, wordcount threshold + the
       boundary case, case-insensitivity.
     - import-worker.test.ts (5 tests): countByState rollup. Pins
       down the consent-wall-counts-as-saved semantics so the
       progress bar doesn't off-by-one and allTerminal stays correct.
   Total 19 bun tests, all green.
   countByState + StateCounts exported (test-only access).

#14 — Consent-wall recovery UI in JobDetailView
   Bulk-import items that hit a cookie-wand land as state='consent-wall'
   with the teaser saved. Before this commit there was no UX path to
   "rescue" them other than navigating to the article and re-saving
   manually. Now:
     - Job-level hint banner appears when warningCount > 0,
       explaining the cookie-wand semantics + linking to
       /articles/settings (where the v2 bookmarklet lives).
     - Per-item action group on consent-wall rows: "Teaser ansehen"
       (open existing article) + "Erneut speichern" (deep-link to
       /articles/add?source=bookmarklet&url=… so the bookmarklet's
       postMessage handshake has the URL pre-populated).

Plan: docs/plans/articles-bulk-import.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 01:30:04 +02:00

47 lines
1.7 KiB
TypeScript

import { describe, it, expect } from 'bun:test';
import { looksLikeConsentWall } from './consent-wall';
describe('looksLikeConsentWall', () => {
it('flags short text containing German consent vocabulary', () => {
const text =
'Cookies zustimmen — Wir und unsere Partner speichern Informationen auf einem Endgerät.';
expect(looksLikeConsentWall(text, 14)).toBe(true);
});
it('flags short English consent dialogs', () => {
const text = 'Please accept all cookies to continue using this website.';
expect(looksLikeConsentWall(text, 9)).toBe(true);
});
it('flags JavaScript-disabled walls', () => {
const text = 'JavaScript is disabled. Please enable JavaScript to continue.';
expect(looksLikeConsentWall(text, 7)).toBe(true);
});
it('does NOT flag long articles even if they mention cookies', () => {
// Long-form article that happens to mention cookies in body. The
// heuristic only fires below the wordcount threshold (300) so a
// real article about cookies isn't misclassified.
const text = 'cookie consent ' + 'lorem '.repeat(400);
expect(looksLikeConsentWall(text, 800)).toBe(false);
});
it('does NOT flag short text without consent vocabulary', () => {
const text = 'A short blog post about hiking trails in the Black Forest.';
expect(looksLikeConsentWall(text, 11)).toBe(false);
});
it('is case-insensitive', () => {
const text = 'COOKIES ZUSTIMMEN — KLICKE HIER';
expect(looksLikeConsentWall(text, 4)).toBe(true);
});
it('returns false on empty content', () => {
expect(looksLikeConsentWall('', 0)).toBe(false);
});
it('returns false at exactly the wordcount threshold (boundary check)', () => {
const text = 'cookie consent ' + 'lorem '.repeat(300);
expect(looksLikeConsentWall(text, 300)).toBe(false);
});
});