summaryrefslogtreecommitdiff
path: root/web/test/stories.test.mjs
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-05-25 05:12:54 +0000
committerClaude <noreply@anthropic.com>2026-05-25 05:12:54 +0000
commit5669e2ca58b4a99616083eaff9f639ecce4ba809 (patch)
treea50bf5ee04f10c8dd463ffe9837d6818c5877993 /web/test/stories.test.mjs
parent42bb6432d3e53042723b43330c22eafbf553e10f (diff)
refactor(web): remove the stories dashboard from the UI (Phase 3)
The observability UI drops the stories surface: the Stories tab, the stories panel, the New/Detail story modals, and all their app.js code (STORY_STATUS_LABELS, storyStatusLabel, renderStoryCard, renderStoriesPanel, openStoryDetail, openStoryModal, renderElaboratedPlan, the story-modal init handlers, and the panel-dispatch 'stories' case) plus stories.test.mjs. The stories BACKEND (table, /api/stories* handlers, story-elaborate) is left intact for the Phase 8 cleanup pass; this only removes the UI surface. Dead CSS for the removed elements is likewise deferred to Phase 8. Verified with node --test (251 JS tests pass) and a module-import check. Not browser-verified in this environment. https://claude.ai/code/session_01SESwn7kQ7oP62trWw6pc39
Diffstat (limited to 'web/test/stories.test.mjs')
-rw-r--r--web/test/stories.test.mjs164
1 files changed, 0 insertions, 164 deletions
diff --git a/web/test/stories.test.mjs b/web/test/stories.test.mjs
deleted file mode 100644
index 263f202..0000000
--- a/web/test/stories.test.mjs
+++ /dev/null
@@ -1,164 +0,0 @@
-// stories.test.mjs — TDD tests for stories UI functions.
-//
-// Run with: node --test web/test/stories.test.mjs
-
-import { describe, it, beforeEach } from 'node:test';
-import assert from 'node:assert/strict';
-import { renderStoryCard, storyStatusLabel } from '../app.js';
-
-// ── Minimal DOM mock ──────────────────────────────────────────────────────────
-
-function makeMockDoc() {
- function createElement(tag) {
- return {
- tag,
- className: '',
- textContent: '',
- innerHTML: '',
- hidden: false,
- dataset: {},
- children: [],
- _listeners: {},
- style: {},
- appendChild(child) { this.children.push(child); return child; },
- prepend(...nodes) { this.children.unshift(...nodes); },
- append(...nodes) { nodes.forEach(n => this.children.push(n)); },
- addEventListener(ev, fn) { this._listeners[ev] = fn; },
- querySelector(sel) {
- const cls = sel.startsWith('.') ? sel.slice(1) : null;
- function search(el) {
- if (cls && el.className && el.className.split(' ').includes(cls)) return el;
- for (const c of el.children || []) {
- const found = search(c);
- if (found) return found;
- }
- return null;
- }
- return search(this);
- },
- querySelectorAll(sel) {
- const cls = sel.startsWith('.') ? sel.slice(1) : null;
- const results = [];
- function search(el) {
- if (cls && el.className && el.className.split(' ').includes(cls)) results.push(el);
- for (const c of el.children || []) search(c);
- }
- search(this);
- return results;
- },
- };
- }
- return { createElement };
-}
-
-function makeStory(overrides = {}) {
- return {
- id: 'story-1',
- name: 'Add login page',
- project_id: 'claudomator',
- branch_name: 'story/add-login-page',
- status: 'PENDING',
- created_at: '2026-03-25T10:00:00Z',
- updated_at: '2026-03-25T10:00:00Z',
- ...overrides,
- };
-}
-
-// ── storyStatusLabel ──────────────────────────────────────────────────────────
-
-describe('storyStatusLabel', () => {
- it('returns human-readable label for PENDING', () => {
- assert.equal(storyStatusLabel('PENDING'), 'Pending');
- });
-
- it('returns human-readable label for IN_PROGRESS', () => {
- assert.equal(storyStatusLabel('IN_PROGRESS'), 'In Progress');
- });
-
- it('returns human-readable label for SHIPPABLE', () => {
- assert.equal(storyStatusLabel('SHIPPABLE'), 'Shippable');
- });
-
- it('returns human-readable label for DEPLOYED', () => {
- assert.equal(storyStatusLabel('DEPLOYED'), 'Deployed');
- });
-
- it('returns human-readable label for VALIDATING', () => {
- assert.equal(storyStatusLabel('VALIDATING'), 'Validating');
- });
-
- it('returns human-readable label for REVIEW_READY', () => {
- assert.equal(storyStatusLabel('REVIEW_READY'), 'Review Ready');
- });
-
- it('returns human-readable label for NEEDS_FIX', () => {
- assert.equal(storyStatusLabel('NEEDS_FIX'), 'Needs Fix');
- });
-
- it('falls back to the raw status for unknown values', () => {
- assert.equal(storyStatusLabel('UNKNOWN_STATE'), 'UNKNOWN_STATE');
- });
-});
-
-// ── renderStoryCard ───────────────────────────────────────────────────────────
-
-describe('renderStoryCard', () => {
- let doc;
- beforeEach(() => { doc = makeMockDoc(); });
-
- it('renders the story name', () => {
- const card = renderStoryCard(makeStory(), doc);
- function findText(el, text) {
- if (el.textContent === text) return true;
- return (el.children || []).some(c => findText(c, text));
- }
- assert.ok(findText(card, 'Add login page'), 'card should contain story name');
- });
-
- it('has story-card class', () => {
- const card = renderStoryCard(makeStory(), doc);
- assert.ok(card.className.split(' ').includes('story-card'), 'root element should have story-card class');
- });
-
- it('status badge has data-status matching story status', () => {
- const card = renderStoryCard(makeStory({ status: 'IN_PROGRESS' }), doc);
- const badge = card.querySelector('.story-status-badge');
- assert.ok(badge, 'badge element should exist');
- assert.equal(badge.dataset.status, 'IN_PROGRESS');
- });
-
- it('status badge shows human-readable label', () => {
- const card = renderStoryCard(makeStory({ status: 'REVIEW_READY' }), doc);
- const badge = card.querySelector('.story-status-badge');
- assert.equal(badge.textContent, 'Review Ready');
- });
-
- it('shows project_id', () => {
- const card = renderStoryCard(makeStory({ project_id: 'nav' }), doc);
- function findText(el, text) {
- if (el.textContent === text) return true;
- return (el.children || []).some(c => findText(c, text));
- }
- assert.ok(findText(card, 'nav'), 'card should show project_id');
- });
-
- it('shows branch_name when present', () => {
- const card = renderStoryCard(makeStory({ branch_name: 'story/my-feature' }), doc);
- function findText(el, text) {
- if (el.textContent && el.textContent.includes(text)) return true;
- return (el.children || []).some(c => findText(c, text));
- }
- assert.ok(findText(card, 'story/my-feature'), 'card should show branch_name');
- });
-
- it('does not show branch section when branch_name is empty', () => {
- const card = renderStoryCard(makeStory({ branch_name: '' }), doc);
- const branchEl = card.querySelector('.story-branch');
- assert.ok(!branchEl, 'no .story-branch element when branch is empty');
- });
-
- it('card dataset.storyId is set to story id', () => {
- const card = renderStoryCard(makeStory({ id: 'abc-123' }), doc);
- assert.equal(card.dataset.storyId, 'abc-123');
- });
-});