clap-ts 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/parser.js +5 -5
- package/dist/types.d.ts +14 -1
- package/package.json +17 -1
- package/src/__tests__/arg-options.test.ts +687 -0
- package/src/__tests__/argfile.test.ts +127 -0
- package/src/__tests__/clap-parity.test.ts +682 -0
- package/src/__tests__/command-options.test.ts +713 -0
- package/src/__tests__/completions.test.ts +423 -0
- package/src/__tests__/config.test.ts +261 -0
- package/src/__tests__/deprecation.test.ts +104 -0
- package/src/__tests__/help.test.ts +312 -0
- package/src/__tests__/install.test.ts +120 -0
- package/src/__tests__/log.test.ts +189 -0
- package/src/__tests__/man.test.ts +135 -0
- package/src/__tests__/markdown.test.ts +114 -0
- package/src/__tests__/output.test.ts +249 -0
- package/src/__tests__/parser.test.ts +627 -0
- package/src/__tests__/plugins.test.ts +182 -0
- package/src/__tests__/progress.test.ts +221 -0
- package/src/__tests__/prompt.test.ts +265 -0
- package/src/__tests__/runner.test.ts +459 -0
- package/src/__tests__/spec.test.ts +107 -0
- package/src/__tests__/testing.test.ts +93 -0
- package/src/__tests__/validation.test.ts +267 -0
- package/src/argfile.ts +188 -0
- package/src/completions.ts +865 -0
- package/src/config.ts +184 -0
- package/src/help.ts +779 -0
- package/src/index.ts +58 -0
- package/src/install.ts +226 -0
- package/src/log.ts +225 -0
- package/src/man.ts +289 -0
- package/src/markdown.ts +210 -0
- package/src/output.ts +453 -0
- package/src/parser.ts +1240 -0
- package/src/plugins.ts +193 -0
- package/src/progress.ts +295 -0
- package/src/prompt.ts +388 -0
- package/src/runner.ts +769 -0
- package/src/spec.ts +197 -0
- package/src/testing.ts +159 -0
- package/src/types.ts +618 -0
- package/src/validation.ts +627 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for response files and the stdin conventions.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, test, expect } from 'bun:test';
|
|
6
|
+
import { parseArgFile, expandArgFiles, readPathOrStdin } from '../argfile.js';
|
|
7
|
+
|
|
8
|
+
describe('parseArgFile', () => {
|
|
9
|
+
test('splits on whitespace and newlines', () => {
|
|
10
|
+
expect(parseArgFile('--port 8080\n--host localhost')).toEqual([
|
|
11
|
+
'--port',
|
|
12
|
+
'8080',
|
|
13
|
+
'--host',
|
|
14
|
+
'localhost',
|
|
15
|
+
]);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('skips blank lines', () => {
|
|
19
|
+
expect(parseArgFile('\n\n--a\n\n \n--b\n')).toEqual(['--a', '--b']);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('treats # as a comment to end of line', () => {
|
|
23
|
+
expect(parseArgFile('# a note\n--a # trailing\n--b')).toEqual(['--a', '--b']);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('keeps a quoted run together', () => {
|
|
27
|
+
expect(parseArgFile('--msg "hello there" --other \'one two\'')).toEqual([
|
|
28
|
+
'--msg',
|
|
29
|
+
'hello there',
|
|
30
|
+
'--other',
|
|
31
|
+
'one two',
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('a quoted empty string survives', () => {
|
|
36
|
+
expect(parseArgFile('--msg ""')).toEqual(['--msg', '']);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('a hash inside a token is not a comment', () => {
|
|
40
|
+
expect(parseArgFile('--tag v1#2')).toEqual(['--tag', 'v1#2']);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('backslash escapes the next character', () => {
|
|
44
|
+
expect(parseArgFile(String.raw`--path a\ b`)).toEqual(['--path', 'a b']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('an unterminated quote is an error', () => {
|
|
48
|
+
expect(() => parseArgFile('--msg "unclosed')).toThrow('unterminated double quote');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('expandArgFiles', () => {
|
|
53
|
+
const files: Record<string, string> = {
|
|
54
|
+
'common.txt': '--verbose\n--port 8080',
|
|
55
|
+
'outer.txt': '--first\n@inner.txt',
|
|
56
|
+
'inner.txt': '--second',
|
|
57
|
+
'loop.txt': '@loop.txt',
|
|
58
|
+
};
|
|
59
|
+
const read = (path: string): string => {
|
|
60
|
+
const text = files[path];
|
|
61
|
+
if (text === undefined) {
|
|
62
|
+
throw new Error('ENOENT');
|
|
63
|
+
}
|
|
64
|
+
return text;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
test('splices a response file in place', () => {
|
|
68
|
+
expect(expandArgFiles(['--a', '@common.txt', '--b'], { read })).toEqual([
|
|
69
|
+
'--a',
|
|
70
|
+
'--verbose',
|
|
71
|
+
'--port',
|
|
72
|
+
'8080',
|
|
73
|
+
'--b',
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('leaves ordinary arguments alone', () => {
|
|
78
|
+
expect(expandArgFiles(['--a', 'b'], { read })).toEqual(['--a', 'b']);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('a response file may reference another', () => {
|
|
82
|
+
expect(expandArgFiles(['@outer.txt'], { read })).toEqual(['--first', '--second']);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('@@ escapes a literal leading at-sign', () => {
|
|
86
|
+
expect(expandArgFiles(['@@notafile'], { read })).toEqual(['@notafile']);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('a bare @ is left as itself', () => {
|
|
90
|
+
expect(expandArgFiles(['@'], { read })).toEqual(['@']);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('nothing after -- is expanded', () => {
|
|
94
|
+
expect(expandArgFiles(['--', '@common.txt'], { read })).toEqual(['--', '@common.txt']);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('a missing file names itself in the error', () => {
|
|
98
|
+
expect(() => expandArgFiles(['@nope.txt'], { read })).toThrow(
|
|
99
|
+
"cannot read response file 'nope.txt'",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('runaway nesting is caught', () => {
|
|
104
|
+
expect(() => expandArgFiles(['@loop.txt'], { read })).toThrow('nested more than');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('the prefix is configurable', () => {
|
|
108
|
+
expect(expandArgFiles(['+common.txt'], { read, prefix: '+' })).toEqual([
|
|
109
|
+
'--verbose',
|
|
110
|
+
'--port',
|
|
111
|
+
'8080',
|
|
112
|
+
]);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('readPathOrStdin', () => {
|
|
117
|
+
test('reads a path through the injected reader', async () => {
|
|
118
|
+
const text = await readPathOrStdin('some.txt', { read: () => 'contents' });
|
|
119
|
+
expect(text).toBe('contents');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test('- asks for stdin, which is a terminal under no redirection', async () => {
|
|
123
|
+
if (process.stdin.isTTY === true) {
|
|
124
|
+
await expect(readPathOrStdin('-')).rejects.toThrow('stdin is a terminal');
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|