Skip to content

Commit 72bc931

Browse files
PaulJPhilpclaude
andcommitted
test: add unit tests for scaffold-test-project and make logic testable
Export pure functions (makePackageJson, templateFiles, TEMPLATES, TOOLS, TSCONFIG, GITIGNORE) and guard CLI runner with import.meta.main so the module can be imported without side effects. Add @effect/experimental to http-server template deps to fix missing transitive dependency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3fc8622 commit 72bc931

2 files changed

Lines changed: 541 additions & 147 deletions

File tree

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* Scaffold Test Project Tests
3+
*
4+
* Tests for the pure/extractable logic in scaffold-test-project.ts:
5+
* makePackageJson, templateFiles, TEMPLATES, and TOOLS constants.
6+
*/
7+
8+
import { describe, expect, it } from 'vitest';
9+
import {
10+
GITIGNORE,
11+
makePackageJson,
12+
templateFiles,
13+
TEMPLATES,
14+
TOOLS,
15+
TSCONFIG,
16+
} from '../scaffold-test-project.js';
17+
18+
// ---------------------------------------------------------------------------
19+
// TEMPLATES & TOOLS constants
20+
// ---------------------------------------------------------------------------
21+
22+
describe('TEMPLATES', () => {
23+
it('should contain exactly the four expected templates', () => {
24+
expect(TEMPLATES).toEqual(['basic', 'service', 'cli', 'http-server']);
25+
});
26+
});
27+
28+
describe('TOOLS', () => {
29+
it('should contain exactly the four expected tools', () => {
30+
expect(TOOLS).toEqual(['agents', 'cursor', 'vscode', 'windsurf']);
31+
});
32+
});
33+
34+
// ---------------------------------------------------------------------------
35+
// makePackageJson
36+
// ---------------------------------------------------------------------------
37+
38+
describe('makePackageJson', () => {
39+
it('basic: should have effect in deps and no vitest', () => {
40+
const pkg = JSON.parse(makePackageJson('test-basic', 'basic'));
41+
42+
expect(pkg.name).toBe('test-basic');
43+
expect(pkg.dependencies.effect).toBe('latest');
44+
expect(pkg.devDependencies.vitest).toBeUndefined();
45+
expect(pkg.scripts.test).toBeUndefined();
46+
});
47+
48+
it('basic: should have standard devDeps (typescript, tsx, @types/node)', () => {
49+
const pkg = JSON.parse(makePackageJson('test-basic', 'basic'));
50+
51+
expect(pkg.devDependencies.typescript).toBe('latest');
52+
expect(pkg.devDependencies.tsx).toBe('latest');
53+
expect(pkg.devDependencies['@types/node']).toBe('latest');
54+
});
55+
56+
it('service: should have effect in deps and vitest in devDeps with test script', () => {
57+
const pkg = JSON.parse(makePackageJson('test-svc', 'service'));
58+
59+
expect(pkg.dependencies.effect).toBe('latest');
60+
expect(pkg.devDependencies.vitest).toBe('latest');
61+
expect(pkg.scripts.test).toBe('vitest run');
62+
});
63+
64+
it('cli: should have @effect/cli, @effect/platform, @effect/platform-node in deps', () => {
65+
const pkg = JSON.parse(makePackageJson('test-cli', 'cli'));
66+
67+
expect(pkg.dependencies['@effect/cli']).toBe('latest');
68+
expect(pkg.dependencies['@effect/platform']).toBe('latest');
69+
expect(pkg.dependencies['@effect/platform-node']).toBe('latest');
70+
});
71+
72+
it('http-server: should have @effect/platform, @effect/platform-node, and @effect/experimental in deps', () => {
73+
const pkg = JSON.parse(makePackageJson('test-http', 'http-server'));
74+
75+
expect(pkg.dependencies['@effect/platform']).toBe('latest');
76+
expect(pkg.dependencies['@effect/platform-node']).toBe('latest');
77+
expect(pkg.dependencies['@effect/experimental']).toBe('latest');
78+
expect(pkg.dependencies['@effect/cli']).toBeUndefined();
79+
});
80+
81+
it('all templates should have type: module and standard scripts', () => {
82+
for (const template of TEMPLATES) {
83+
const pkg = JSON.parse(makePackageJson(`test-${template}`, template));
84+
85+
expect(pkg.type).toBe('module');
86+
expect(pkg.scripts.dev).toBe('tsx src/index.ts');
87+
expect(pkg.scripts.build).toBe('tsc');
88+
expect(pkg.scripts.start).toBe('node dist/index.js');
89+
}
90+
});
91+
});
92+
93+
// ---------------------------------------------------------------------------
94+
// templateFiles
95+
// ---------------------------------------------------------------------------
96+
97+
describe('templateFiles', () => {
98+
it('should have an entry for every template', () => {
99+
for (const template of TEMPLATES) {
100+
expect(templateFiles[template]).toBeDefined();
101+
}
102+
});
103+
104+
it('every template should include src/index.ts', () => {
105+
for (const template of TEMPLATES) {
106+
expect(templateFiles[template]['src/index.ts']).toBeDefined();
107+
}
108+
});
109+
110+
it('service template should have src/service.ts and src/service.test.ts', () => {
111+
const files = Object.keys(templateFiles.service);
112+
113+
expect(files).toContain('src/service.ts');
114+
expect(files).toContain('src/service.test.ts');
115+
});
116+
117+
it('cli template should have src/commands.ts', () => {
118+
const files = Object.keys(templateFiles.cli);
119+
120+
expect(files).toContain('src/commands.ts');
121+
});
122+
123+
it('http-server template should have src/routes.ts', () => {
124+
const files = Object.keys(templateFiles['http-server']);
125+
126+
expect(files).toContain('src/routes.ts');
127+
});
128+
129+
it('basic template should only have src/index.ts', () => {
130+
const files = Object.keys(templateFiles.basic);
131+
132+
expect(files).toEqual(['src/index.ts']);
133+
});
134+
});
135+
136+
// ---------------------------------------------------------------------------
137+
// TSCONFIG & GITIGNORE
138+
// ---------------------------------------------------------------------------
139+
140+
describe('TSCONFIG', () => {
141+
it('should be valid JSON with expected compiler options', () => {
142+
const tsconfig = JSON.parse(TSCONFIG);
143+
144+
expect(tsconfig.compilerOptions.strict).toBe(true);
145+
expect(tsconfig.compilerOptions.module).toBe('NodeNext');
146+
expect(tsconfig.compilerOptions.outDir).toBe('dist');
147+
expect(tsconfig.compilerOptions.rootDir).toBe('src');
148+
expect(tsconfig.include).toEqual(['src']);
149+
});
150+
});
151+
152+
describe('GITIGNORE', () => {
153+
it('should ignore node_modules and dist', () => {
154+
expect(GITIGNORE).toContain('node_modules/');
155+
expect(GITIGNORE).toContain('dist/');
156+
});
157+
});

0 commit comments

Comments
 (0)