Skip to content

Commit a6b93ba

Browse files
authored
Merge pull request #156 from NianJiuZst/test/complete-core-coverage
test: comprehensive test coverage improvements (pure functions, SDK validation, command tests)
2 parents da44943 + f8c8f33 commit a6b93ba

14 files changed

Lines changed: 834 additions & 109 deletions

File tree

test/commands/file/upload.test.ts

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,61 @@
11
import { describe, it, expect } from 'bun:test';
22
import { default as uploadCommand } from '../../../src/commands/file/upload';
33

4+
const baseConfig = {
5+
apiKey: 'test-key',
6+
region: 'global' as const,
7+
baseUrl: 'https://api.mmx.io',
8+
output: 'text' as const,
9+
timeout: 10,
10+
verbose: false,
11+
quiet: false,
12+
noColor: true,
13+
yes: false,
14+
dryRun: false,
15+
nonInteractive: true,
16+
async: false,
17+
};
18+
19+
const baseFlags = {
20+
quiet: false,
21+
verbose: false,
22+
noColor: true,
23+
yes: false,
24+
dryRun: false,
25+
help: false,
26+
nonInteractive: true,
27+
async: false,
28+
};
29+
430
describe('file upload command', () => {
531
it('has correct name', () => {
632
expect(uploadCommand.name).toBe('file upload');
733
});
834

9-
it('requires file argument', async () => {
10-
const config = {
11-
apiKey: 'test-key',
12-
region: 'global' as const,
13-
baseUrl: 'https://api.mmx.io',
14-
output: 'text' as const,
15-
timeout: 10,
16-
verbose: false,
17-
quiet: false,
18-
noColor: true,
19-
yes: false,
20-
dryRun: true,
21-
nonInteractive: true,
22-
async: false,
23-
};
24-
35+
it('requires file argument in non-interactive mode', async () => {
2536
await expect(
26-
uploadCommand.execute(config, {
27-
quiet: false,
28-
verbose: false,
29-
noColor: true,
30-
yes: false,
31-
dryRun: true,
32-
help: false,
33-
nonInteractive: true,
34-
async: false,
35-
}),
37+
uploadCommand.execute(baseConfig, baseFlags),
3638
).rejects.toThrow('Missing required argument: --file');
3739
});
40+
41+
it('throws when file does not exist', async () => {
42+
await expect(
43+
uploadCommand.execute(baseConfig, { ...baseFlags, file: '/tmp/nonexistent-file-xxxxx.bin' }),
44+
).rejects.toThrow('File not found');
45+
});
46+
47+
it('shows dry-run output with file info', async () => {
48+
let captured = '';
49+
const origWrite = process.stdout.write;
50+
process.stdout.write = (chunk: any): any => { captured += String(chunk); return true; };
51+
52+
await uploadCommand.execute(
53+
{ ...baseConfig, dryRun: true },
54+
{ ...baseFlags, dryRun: true, file: '/dev/null', purpose: 'vision' },
55+
);
56+
57+
process.stdout.write = origWrite;
58+
expect(captured).toContain('/dev/null');
59+
expect(captured).toContain('vision');
60+
});
3861
});
Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,94 @@
11
import { describe, it, expect } from 'bun:test';
22
import { default as generateCommand } from '../../../src/commands/image/generate';
33

4+
const baseConfig = {
5+
apiKey: 'test-key',
6+
region: 'global' as const,
7+
baseUrl: 'https://api.mmx.io',
8+
output: 'text' as const,
9+
timeout: 10,
10+
verbose: false,
11+
quiet: false,
12+
noColor: true,
13+
yes: false,
14+
dryRun: false,
15+
nonInteractive: true,
16+
async: false,
17+
};
18+
19+
const baseFlags = {
20+
quiet: false,
21+
verbose: false,
22+
noColor: true,
23+
yes: false,
24+
dryRun: false,
25+
help: false,
26+
nonInteractive: true,
27+
async: false,
28+
};
29+
430
describe('image generate command', () => {
531
it('has correct name', () => {
632
expect(generateCommand.name).toBe('image generate');
733
});
834

935
it('requires prompt', async () => {
10-
const config = {
11-
apiKey: 'test-key',
12-
region: 'global' as const,
13-
baseUrl: 'https://api.mmx.io',
14-
output: 'text' as const,
15-
timeout: 10,
16-
verbose: false,
17-
quiet: false,
18-
noColor: true,
19-
yes: false,
20-
dryRun: false,
21-
nonInteractive: true,
22-
async: false,
23-
};
24-
2536
await expect(
26-
generateCommand.execute(config, {
27-
quiet: false,
28-
verbose: false,
29-
noColor: true,
30-
yes: false,
31-
dryRun: false,
32-
help: false,
33-
nonInteractive: true,
34-
async: false,
35-
}),
37+
generateCommand.execute(baseConfig, baseFlags),
3638
).rejects.toThrow('Missing required argument: --prompt');
3739
});
40+
41+
it('throws when width is provided without height', async () => {
42+
await expect(
43+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', width: 1024 }),
44+
).rejects.toThrow('--width requires --height');
45+
});
46+
47+
it('throws when height is provided without width', async () => {
48+
await expect(
49+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', height: 1024 }),
50+
).rejects.toThrow('--height requires --width');
51+
});
52+
53+
it('throws when width is below 512', async () => {
54+
await expect(
55+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', width: 256, height: 256 }),
56+
).rejects.toThrow('must be between 512 and 2048');
57+
});
58+
59+
it('throws when height is above 2048', async () => {
60+
await expect(
61+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', width: 1024, height: 4096 }),
62+
).rejects.toThrow('must be between 512 and 2048');
63+
});
64+
65+
it('throws when dimensions are not multiples of 8', async () => {
66+
await expect(
67+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', width: 1025, height: 1024 }),
68+
).rejects.toThrow('must be a multiple of 8');
69+
});
70+
71+
it('throws when --out is used with --n > 1', async () => {
72+
await expect(
73+
generateCommand.execute(baseConfig, { ...baseFlags, prompt: 'test', out: '/tmp/img.jpg', n: 3 }),
74+
).rejects.toThrow('--out cannot be used with --n > 1');
75+
});
76+
77+
it('builds correct request body in dry-run', async () => {
78+
let captured = '';
79+
const origLog = console.log;
80+
console.log = (msg: string) => { captured += msg; };
81+
try {
82+
await generateCommand.execute(
83+
{ ...baseConfig, dryRun: true, output: 'json' as const },
84+
{ ...baseFlags, dryRun: true, prompt: 'A cat', aspectRatio: '16:9', n: 2, seed: 42 },
85+
);
86+
} catch { /* dry-run may log or resolve */ }
87+
console.log = origLog;
88+
const parsed = JSON.parse(captured);
89+
expect(parsed.request.prompt).toBe('A cat');
90+
expect(parsed.request.n).toBe(2);
91+
expect(parsed.request.seed).toBe(42);
92+
expect(parsed.request.model).toBe('image-01');
93+
});
3894
});

test/commands/quota/show.test.ts

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,50 @@
11
import { describe, it, expect } from 'bun:test';
22
import { default as showCommand } from '../../../src/commands/quota/show';
33

4+
const baseConfig = {
5+
apiKey: 'test-key',
6+
region: 'global' as const,
7+
baseUrl: 'https://api.mmx.io',
8+
output: 'text' as const,
9+
timeout: 10,
10+
verbose: false,
11+
quiet: false,
12+
noColor: true,
13+
yes: false,
14+
dryRun: false,
15+
nonInteractive: true,
16+
async: false,
17+
};
18+
19+
const baseFlags = {
20+
quiet: false,
21+
verbose: false,
22+
noColor: true,
23+
yes: false,
24+
dryRun: false,
25+
help: false,
26+
nonInteractive: true,
27+
async: false,
28+
};
29+
430
describe('quota show command', () => {
531
it('has correct name', () => {
632
expect(showCommand.name).toBe('quota show');
733
});
834

935
it('handles dry run', async () => {
10-
const config = {
11-
apiKey: 'test-key',
12-
region: 'global' as const,
13-
baseUrl: 'https://api.mmx.io',
14-
output: 'text' as const,
15-
timeout: 10,
16-
verbose: false,
17-
quiet: false,
18-
noColor: true,
19-
yes: false,
20-
dryRun: true,
21-
nonInteractive: true,
22-
async: false,
23-
};
24-
25-
const originalLog = console.log;
26-
let output = '';
27-
console.log = (msg: string) => { output += msg; };
28-
36+
let captured = '';
37+
const origLog = console.log;
38+
console.log = (msg: string) => { captured += msg; };
2939
try {
30-
await showCommand.execute(config, {
31-
quiet: false,
32-
verbose: false,
33-
noColor: true,
34-
yes: false,
35-
dryRun: true,
36-
help: false,
37-
nonInteractive: true,
38-
async: false,
39-
});
40-
41-
expect(output).toContain('Would fetch quota');
40+
await showCommand.execute(
41+
{ ...baseConfig, dryRun: true },
42+
{ ...baseFlags, dryRun: true },
43+
);
44+
expect(captured).toContain('Would fetch quota');
4245
} finally {
43-
console.log = originalLog;
46+
console.log = origLog;
4447
}
4548
});
49+
4650
});

0 commit comments

Comments
 (0)