Skip to content

Commit 0e52ca6

Browse files
author
Peter Hauge
committed
Fix up tests for making --cli-package parameter optional
1 parent 50c141d commit 0e52ca6

3 files changed

Lines changed: 117 additions & 34 deletions

File tree

tests/unit/cli/init-command.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,13 @@ describe('init-command', () => {
5151
expect(envOpt?.defaultValue).toBe('dev,prod');
5252
});
5353

54-
it('should have --cli-package required option', () => {
54+
it('should have --cli-package optional option', () => {
5555
const cmd = createInitCommand();
5656
const opts = cmd.options;
5757
const cliPkgOpt = opts.find((o) => o.long === '--cli-package');
5858
expect(cliPkgOpt).toBeDefined();
59-
expect(cliPkgOpt?.required).toBe(true);
59+
// The option itself is not mandatory, but when present it requires a value
60+
expect(cliPkgOpt?.mandatory).toBe(false);
6061
});
6162

6263
it('should have --force option defaulting to false', () => {
@@ -67,11 +68,11 @@ describe('init-command', () => {
6768
expect(forceOpt?.defaultValue).toBe(false);
6869
});
6970

70-
it('should have all required options for non-interactive mode', () => {
71+
it('should have all expected options for non-interactive mode', () => {
7172
const cmd = createInitCommand();
72-
const requiredOptions = ['--ci', '--non-interactive', '--artifact-dir', '--environments', '--cli-package', '--force'];
73+
const expectedOptions = ['--ci', '--non-interactive', '--artifact-dir', '--environments', '--cli-package', '--force'];
7374

74-
requiredOptions.forEach((optName) => {
75+
expectedOptions.forEach((optName) => {
7576
const opt = cmd.options.find((o) => o.long === optName);
7677
expect(opt).toBeDefined();
7778
});

tests/unit/services/init-service.test.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ describe('init-service', () => {
378378
);
379379
});
380380

381-
it('should generate package.json with file: dependency to tarball', async () => {
381+
it('should generate package.json with file: dependency to tarball in local mode', async () => {
382382
const config: InitConfig = {
383383
ciProvider: 'github-actions',
384384
nonInteractive: true,
@@ -402,6 +402,49 @@ describe('init-service', () => {
402402
expect(pkg.dependencies.apiops).toContain('apiops-0.1.0.tgz');
403403
});
404404

405+
it('should generate package.json with npm dependency when cliPackage not provided', async () => {
406+
const config: InitConfig = {
407+
ciProvider: 'github-actions',
408+
nonInteractive: true,
409+
artifactDir: './apim-artifacts',
410+
environments: ['dev'],
411+
outputDir: '/test',
412+
// cliPackage is omitted — npm mode
413+
force: false,
414+
};
415+
416+
const result = await initService.run(config);
417+
418+
expect(result.configs).toContain('package.json');
419+
const pkgCalls = vi.mocked(fs.writeFile).mock.calls.filter(
420+
(call) => call[0] === path.join('/test', 'package.json')
421+
);
422+
expect(pkgCalls).toHaveLength(1);
423+
const content = pkgCalls[0][1] as string;
424+
const pkg = JSON.parse(content);
425+
expect(pkg.dependencies['@peterhauge/apiops-cli']).toBe('latest');
426+
expect(pkg.dependencies.apiops).toBeUndefined();
427+
});
428+
429+
it('should NOT copy tarball or create .apiops directory in npm mode', async () => {
430+
const config: InitConfig = {
431+
ciProvider: 'github-actions',
432+
nonInteractive: true,
433+
artifactDir: './apim-artifacts',
434+
environments: ['dev'],
435+
outputDir: '/test',
436+
// cliPackage is omitted — npm mode
437+
force: false,
438+
};
439+
440+
const result = await initService.run(config);
441+
442+
// .apiops should NOT be in generated directories
443+
expect(result.directories).not.toContain('.apiops');
444+
// copyFile should NOT have been called
445+
expect(vi.mocked(fs.copyFile)).not.toHaveBeenCalled();
446+
});
447+
405448
it('should throw if CLI package tarball does not exist', async () => {
406449
vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
407450

tests/unit/templates/configs/package-json.test.ts

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,79 @@ import { generatePackageJson } from '../../../../src/templates/configs/package-j
77

88
describe('configs/package-json', () => {
99
describe('generatePackageJson', () => {
10-
it('should generate valid JSON', () => {
11-
const content = generatePackageJson({ tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
12-
expect(() => JSON.parse(content)).not.toThrow();
13-
});
10+
describe('local mode', () => {
11+
it('should generate valid JSON', () => {
12+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
13+
expect(() => JSON.parse(content)).not.toThrow();
14+
});
1415

15-
it('should include file: dependency for the tarball', () => {
16-
const content = generatePackageJson({ tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
17-
const pkg = JSON.parse(content);
18-
expect(pkg.dependencies.apiops).toBe('file:.apiops/apiops-0.1.0.tgz');
19-
});
16+
it('should include file: dependency for the tarball', () => {
17+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
18+
const pkg = JSON.parse(content);
19+
expect(pkg.dependencies.apiops).toBe('file:.apiops/apiops-0.1.0.tgz');
20+
});
2021

21-
it('should set private to true', () => {
22-
const content = generatePackageJson({ tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
23-
const pkg = JSON.parse(content);
24-
expect(pkg.private).toBe(true);
25-
});
22+
it('should set private to true', () => {
23+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
24+
const pkg = JSON.parse(content);
25+
expect(pkg.private).toBe(true);
26+
});
2627

27-
it('should include name and version', () => {
28-
const content = generatePackageJson({ tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
29-
const pkg = JSON.parse(content);
30-
expect(pkg.name).toBeTruthy();
31-
expect(pkg.version).toBeTruthy();
32-
});
28+
it('should include name and version', () => {
29+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
30+
const pkg = JSON.parse(content);
31+
expect(pkg.name).toBeTruthy();
32+
expect(pkg.version).toBeTruthy();
33+
});
34+
35+
it('should use forward slashes in dependency path', () => {
36+
// Even if path.join produces backslashes on Windows, the output should use /
37+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops\\apiops-0.1.0.tgz' });
38+
const pkg = JSON.parse(content);
39+
expect(pkg.dependencies.apiops).toBe('file:.apiops/apiops-0.1.0.tgz');
40+
});
3341

34-
it('should use forward slashes in dependency path', () => {
35-
// Even if path.join produces backslashes on Windows, the output should use /
36-
const content = generatePackageJson({ tarballRelPath: '.apiops\\apiops-0.1.0.tgz' });
37-
const pkg = JSON.parse(content);
38-
expect(pkg.dependencies.apiops).toBe('file:.apiops/apiops-0.1.0.tgz');
42+
it('should end with a newline', () => {
43+
const content = generatePackageJson({ mode: 'local', tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
44+
expect(content.endsWith('\n')).toBe(true);
45+
});
3946
});
4047

41-
it('should end with a newline', () => {
42-
const content = generatePackageJson({ tarballRelPath: '.apiops/apiops-0.1.0.tgz' });
43-
expect(content.endsWith('\n')).toBe(true);
48+
describe('npm mode', () => {
49+
it('should generate valid JSON', () => {
50+
const content = generatePackageJson({ mode: 'npm' });
51+
expect(() => JSON.parse(content)).not.toThrow();
52+
});
53+
54+
it('should include @peterhauge/apiops-cli dependency', () => {
55+
const content = generatePackageJson({ mode: 'npm' });
56+
const pkg = JSON.parse(content);
57+
expect(pkg.dependencies['@peterhauge/apiops-cli']).toBe('latest');
58+
});
59+
60+
it('should NOT include apiops dependency', () => {
61+
const content = generatePackageJson({ mode: 'npm' });
62+
const pkg = JSON.parse(content);
63+
expect(pkg.dependencies.apiops).toBeUndefined();
64+
});
65+
66+
it('should set private to true', () => {
67+
const content = generatePackageJson({ mode: 'npm' });
68+
const pkg = JSON.parse(content);
69+
expect(pkg.private).toBe(true);
70+
});
71+
72+
it('should include name and version', () => {
73+
const content = generatePackageJson({ mode: 'npm' });
74+
const pkg = JSON.parse(content);
75+
expect(pkg.name).toBeTruthy();
76+
expect(pkg.version).toBeTruthy();
77+
});
78+
79+
it('should end with a newline', () => {
80+
const content = generatePackageJson({ mode: 'npm' });
81+
expect(content.endsWith('\n')).toBe(true);
82+
});
4483
});
4584
});
4685
});

0 commit comments

Comments
 (0)