init.test.ts86 lines · main
| 1 | import assert from 'node:assert/strict'; |
| 2 | import { describe, test } from 'node:test'; |
| 3 | |
| 4 | import { parseInitArgs, TEMPLATES } from './init.js'; |
| 5 | |
| 6 | describe('parseInitArgs', () => { |
| 7 | test('defaults to blank template + no name + no force', () => { |
| 8 | const args = parseInitArgs([]); |
| 9 | assert.equal(args.template, 'blank'); |
| 10 | assert.equal(args.name, undefined); |
| 11 | assert.equal(args.force, false); |
| 12 | }); |
| 13 | |
| 14 | test('positional name', () => { |
| 15 | assert.equal(parseInitArgs(['my-project']).name, 'my-project'); |
| 16 | }); |
| 17 | |
| 18 | test('--name overrides positional', () => { |
| 19 | assert.equal(parseInitArgs(['ignored', '--name', 'real']).name, 'real'); |
| 20 | }); |
| 21 | |
| 22 | test('--template <name> picks a known template', () => { |
| 23 | assert.equal(parseInitArgs(['--template', 'todo-app']).template, 'todo-app'); |
| 24 | assert.equal(parseInitArgs(['--template', 'chat']).template, 'chat'); |
| 25 | }); |
| 26 | |
| 27 | test('--template=<name> shorthand', () => { |
| 28 | assert.equal(parseInitArgs(['--template=todo-app']).template, 'todo-app'); |
| 29 | }); |
| 30 | |
| 31 | test('--template carries unknown names through (rejected at runtime)', () => { |
| 32 | // Defer reject to runInit so the error message can list available |
| 33 | // templates. parseInitArgs returns the literal so the caller can |
| 34 | // detect the mismatch. |
| 35 | assert.equal(parseInitArgs(['--template', 'mystery']).template, 'mystery'); |
| 36 | }); |
| 37 | |
| 38 | test('--force flag', () => { |
| 39 | assert.equal(parseInitArgs(['--force']).force, true); |
| 40 | }); |
| 41 | |
| 42 | test('--list-templates', () => { |
| 43 | assert.equal(parseInitArgs(['--list-templates']).list, true); |
| 44 | }); |
| 45 | }); |
| 46 | |
| 47 | describe('TEMPLATES', () => { |
| 48 | test('every template has a briven/schema.ts and at least one function', () => { |
| 49 | for (const [name, tpl] of Object.entries(TEMPLATES)) { |
| 50 | assert.match(tpl.description, /.+/); |
| 51 | assert.ok(tpl.files['briven/schema.ts'], `${name} should have briven/schema.ts`); |
| 52 | const fnFiles = Object.keys(tpl.files).filter((p) => p.startsWith('briven/functions/')); |
| 53 | assert.ok(fnFiles.length >= 1, `${name} should have functions`); |
| 54 | } |
| 55 | }); |
| 56 | |
| 57 | test('todo-app template ships the expected four mutations + listing', () => { |
| 58 | const t = TEMPLATES['todo-app']; |
| 59 | assert.ok(t.files['briven/functions/listTodos.ts']); |
| 60 | assert.ok(t.files['briven/functions/createTodo.ts']); |
| 61 | assert.ok(t.files['briven/functions/toggleTodo.ts']); |
| 62 | assert.ok(t.files['briven/functions/deleteTodo.ts']); |
| 63 | }); |
| 64 | |
| 65 | test('chat template ships rooms + messages + the four functions', () => { |
| 66 | const t = TEMPLATES.chat; |
| 67 | const schema = t.files['briven/schema.ts']; |
| 68 | assert.ok(schema); |
| 69 | assert.match(schema, /rooms/); |
| 70 | assert.match(schema, /messages/); |
| 71 | assert.ok(t.files['briven/functions/listRooms.ts']); |
| 72 | assert.ok(t.files['briven/functions/listMessages.ts']); |
| 73 | assert.ok(t.files['briven/functions/createRoom.ts']); |
| 74 | assert.ok(t.files['briven/functions/sendMessage.ts']); |
| 75 | }); |
| 76 | |
| 77 | test('every function source imports from @briven/cli/server', () => { |
| 78 | for (const tpl of Object.values(TEMPLATES)) { |
| 79 | for (const [path, src] of Object.entries(tpl.files)) { |
| 80 | if (path.startsWith('briven/functions/') && src) { |
| 81 | assert.match(src, /@briven\/cli\/server/, `${path} should import @briven/cli/server`); |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | }); |
| 86 | }); |