summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/app.js1
-rw-r--r--web/test/ready-subtasks.test.mjs72
2 files changed, 73 insertions, 0 deletions
diff --git a/web/app.js b/web/app.js
index 77a2d9d..8d78f90 100644
--- a/web/app.js
+++ b/web/app.js
@@ -171,6 +171,7 @@ function createTaskCard(task) {
});
footer.appendChild(btn);
} else if (task.state === 'READY') {
+ renderSubtaskRollup(task.id, footer);
const acceptBtn = document.createElement('button');
acceptBtn.className = 'btn-accept';
acceptBtn.textContent = 'Accept';
diff --git a/web/test/ready-subtasks.test.mjs b/web/test/ready-subtasks.test.mjs
new file mode 100644
index 0000000..1516c35
--- /dev/null
+++ b/web/test/ready-subtasks.test.mjs
@@ -0,0 +1,72 @@
+// ready-subtasks.test.mjs — subtask rollup visibility for READY tasks
+//
+// Run with: node --test web/test/ready-subtasks.test.mjs
+
+import { describe, it } from 'node:test';
+import assert from 'node:assert/strict';
+
+// ── Logic under test ──────────────────────────────────────────────────────────
+//
+// READY tasks (awaiting user approval) that have subtasks should display a
+// subtask rollup identical to BLOCKED tasks. The rollup fetches from:
+// GET /api/tasks/{id}/subtasks
+//
+// States that show the subtask rollup:
+// - BLOCKED (when task.question is absent)
+// - READY (always — mirrors BLOCKED without question)
+
+function shouldShowSubtaskRollup(state, hasQuestion) {
+ if (state === 'BLOCKED' && !hasQuestion) return true;
+ if (state === 'READY') return true;
+ return false;
+}
+
+function getSubtasksEndpoint(taskId) {
+ return `/api/tasks/${taskId}/subtasks`;
+}
+
+// ── Tests ─────────────────────────────────────────────────────────────────────
+
+describe('subtask rollup visibility', () => {
+ it('READY tasks show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('READY', false), true);
+ });
+
+ it('READY tasks show subtask rollup even when question is absent', () => {
+ assert.equal(shouldShowSubtaskRollup('READY', true), true);
+ });
+
+ it('BLOCKED tasks without a question show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('BLOCKED', false), true);
+ });
+
+ it('BLOCKED tasks with a question do NOT show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('BLOCKED', true), false);
+ });
+
+ it('RUNNING tasks do not show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('RUNNING', false), false);
+ });
+
+ it('PENDING tasks do not show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('PENDING', false), false);
+ });
+
+ it('COMPLETED tasks do not show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('COMPLETED', false), false);
+ });
+
+ it('FAILED tasks do not show subtask rollup', () => {
+ assert.equal(shouldShowSubtaskRollup('FAILED', false), false);
+ });
+});
+
+describe('subtask rollup API endpoint', () => {
+ it('uses correct subtasks endpoint for a READY task', () => {
+ assert.equal(getSubtasksEndpoint('task-abc'), '/api/tasks/task-abc/subtasks');
+ });
+
+ it('uses correct subtasks endpoint for a BLOCKED task', () => {
+ assert.equal(getSubtasksEndpoint('task-xyz'), '/api/tasks/task-xyz/subtasks');
+ });
+});