diff options
Diffstat (limited to 'web/test/sort-tasks.test.mjs')
| -rw-r--r-- | web/test/sort-tasks.test.mjs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/web/test/sort-tasks.test.mjs b/web/test/sort-tasks.test.mjs new file mode 100644 index 0000000..fe47702 --- /dev/null +++ b/web/test/sort-tasks.test.mjs @@ -0,0 +1,88 @@ +// sort-tasks.test.mjs — TDD contract tests for sortTasksByDate +// +// sortTasksByDate is defined inline here to establish expected behaviour. +// Once sortTasksByDate is exported from web/app.js or a shared module, +// remove the inline definition and import it instead. +// +// Run with: node --test web/test/sort-tasks.test.mjs + +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; + +// ── Implementation under contract ───────────────────────────────────────────── +// Remove this block once sortTasksByDate is available from app.js. + +function sortTasksByDate(tasks) { + return [...tasks].sort((a, b) => { + if (!a.created_at && !b.created_at) return 0; + if (!a.created_at) return 1; + if (!b.created_at) return -1; + return new Date(a.created_at) - new Date(b.created_at); + }); +} + +// ── Helpers ──────────────────────────────────────────────────────────────────── + +function makeTask(id, created_at, state = 'PENDING') { + return { id, name: `task-${id}`, state, created_at }; +} + +// ── Tests ────────────────────────────────────────────────────────────────────── + +describe('sortTasksByDate', () => { + it('sorts tasks oldest-first by created_at', () => { + const tasks = [ + makeTask('c', '2026-03-06T12:00:00Z'), + makeTask('a', '2026-03-04T08:00:00Z'), + makeTask('b', '2026-03-05T10:00:00Z'), + ]; + const result = sortTasksByDate(tasks); + assert.equal(result[0].id, 'a', 'oldest should be first'); + assert.equal(result[1].id, 'b'); + assert.equal(result[2].id, 'c', 'newest should be last'); + }); + + it('returns a new array (does not mutate input)', () => { + const tasks = [ + makeTask('b', '2026-03-05T10:00:00Z'), + makeTask('a', '2026-03-04T08:00:00Z'), + ]; + const original = [...tasks]; + const result = sortTasksByDate(tasks); + assert.notStrictEqual(result, tasks, 'should return a new array'); + assert.deepEqual(tasks, original, 'input should not be mutated'); + }); + + it('returns an empty array when given an empty array', () => { + assert.deepEqual(sortTasksByDate([]), []); + }); + + it('returns a single-element array unchanged', () => { + const tasks = [makeTask('x', '2026-03-01T00:00:00Z')]; + const result = sortTasksByDate(tasks); + assert.equal(result.length, 1); + assert.equal(result[0].id, 'x'); + }); + + it('places tasks with null created_at after tasks with a date', () => { + const tasks = [ + makeTask('no-date', null), + makeTask('has-date', '2026-03-01T00:00:00Z'), + ]; + const result = sortTasksByDate(tasks); + assert.equal(result[0].id, 'has-date', 'task with date should come first'); + assert.equal(result[1].id, 'no-date', 'task without date should come last'); + }); + + it('works with mixed states (not just PENDING)', () => { + const tasks = [ + makeTask('r', '2026-03-06T00:00:00Z', 'RUNNING'), + makeTask('p', '2026-03-04T00:00:00Z', 'PENDING'), + makeTask('q', '2026-03-05T00:00:00Z', 'QUEUED'), + ]; + const result = sortTasksByDate(tasks); + assert.equal(result[0].id, 'p'); + assert.equal(result[1].id, 'q'); + assert.equal(result[2].id, 'r'); + }); +}); |
