-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcli-config.integration.test.ts
More file actions
236 lines (190 loc) · 7.33 KB
/
Copy pathcli-config.integration.test.ts
File metadata and controls
236 lines (190 loc) · 7.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/**
* Integration Tests for Config CLI Commands
* Tests the full config command flow with real file persistence
*/
import { execSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import { createTestConfigDir, makeRunCLI } from '../helpers';
describe('Config CLI Integration', () => {
const testConfig = createTestConfigDir('test-config');
const testConfigDir = testConfig.path;
const configPath = path.join(testConfigDir, 'config.json');
const { runCLI } = makeRunCLI(testConfig.path);
afterAll(() => {
testConfig.cleanup();
});
beforeEach(() => {
// Create default config for each test
const defaultConfig = {
auth: { apiKey: undefined },
api: {
baseUrl: 'https://api-free.deepl.com/v2',
},
defaults: {
sourceLang: undefined,
targetLangs: [],
formality: 'default',
preserveFormatting: true,
},
cache: {
enabled: true,
maxSize: 1073741824,
ttl: 2592000,
},
output: {
format: 'text',
color: true,
verbose: false,
},
watch: {
debounceMs: 500,
autoCommit: false,
pattern: '**/*',
},
};
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
});
describe('deepl config list', () => {
it('should list all configuration values as JSON', () => {
const output = runCLI('deepl config list');
// Parse JSON output
const config = JSON.parse(output);
// Verify structure
expect(config).toHaveProperty('auth');
expect(config).toHaveProperty('api');
expect(config).toHaveProperty('defaults');
expect(config).toHaveProperty('cache');
expect(config).toHaveProperty('output');
expect(config).toHaveProperty('watch');
});
it('should show formatted JSON', () => {
const output = runCLI('deepl config list');
// Should be pretty-printed JSON
expect(output).toContain('{\n');
expect(output).toContain(' "auth"');
});
});
describe('deepl config get', () => {
it('should get specific nested config value', () => {
const output = runCLI('deepl config get cache.enabled');
const value = JSON.parse(output);
expect(value).toBe(true);
});
it('should get top-level config section', () => {
const output = runCLI('deepl config get cache');
const cache = JSON.parse(output);
expect(cache).toHaveProperty('enabled');
expect(cache).toHaveProperty('maxSize');
expect(cache).toHaveProperty('ttl');
});
it('should return null for non-existent key', () => {
const output = runCLI('deepl config get nonexistent.key');
const value = JSON.parse(output);
expect(value).toBeNull();
});
});
describe('deepl config set', () => {
it('should set a boolean value', () => {
runCLI('deepl config set cache.enabled false');
// Verify it was set
const output = runCLI('deepl config get cache.enabled');
const value = JSON.parse(output);
expect(value).toBe(false);
});
it('should set a number value', () => {
runCLI('deepl config set cache.maxSize 2048');
// Verify it was set
const output = runCLI('deepl config get cache.maxSize');
const value = JSON.parse(output);
expect(value).toBe(2048);
});
it('should set a string value', () => {
runCLI('deepl config set output.format json');
// Verify it was set
const output = runCLI('deepl config get output.format');
const value = JSON.parse(output);
expect(value).toBe('json');
});
it('should set array values from comma-separated string', () => {
runCLI('deepl config set defaults.targetLangs es,fr,de');
// Verify it was set
const output = runCLI('deepl config get defaults.targetLangs');
const value = JSON.parse(output);
expect(value).toEqual(['es', 'fr', 'de']);
});
it('should persist changes to config file', () => {
runCLI('deepl config set cache.enabled false');
// Read config file directly
const configContent = fs.readFileSync(configPath, 'utf-8');
const config = JSON.parse(configContent);
expect(config.cache.enabled).toBe(false);
});
});
describe('deepl config reset', () => {
it('should reset configuration to defaults with --yes flag', () => {
// Change a value
runCLI('deepl config set cache.enabled false');
// Reset (success message goes to stderr via Logger.success, so just verify it runs)
runCLI('deepl config reset --yes');
// Verify defaults restored
const cacheEnabled = runCLI('deepl config get cache.enabled');
expect(JSON.parse(cacheEnabled)).toBe(true);
});
it('should remove config file on reset', () => {
runCLI('deepl config reset --yes');
// Config file should be removed or reset
// (implementation may vary - either delete or reset to defaults)
// This test validates the reset command executes successfully
expect(true).toBe(true);
});
it('should abort without --yes in non-TTY mode', () => {
// Change a value
runCLI('deepl config set cache.enabled false');
// Reset without --yes (non-TTY should abort)
const output = execSync('deepl config reset 2>&1', {
encoding: 'utf-8',
env: { ...process.env, DEEPL_CONFIG_DIR: testConfigDir },
shell: '/bin/sh',
});
expect(output).toContain('Aborted');
// Value should still be changed
const cacheEnabled = runCLI('deepl config get cache.enabled');
expect(JSON.parse(cacheEnabled)).toBe(false);
});
it('should accept -y short flag', () => {
runCLI('deepl config set cache.enabled false');
runCLI('deepl config reset -y');
const cacheEnabled = runCLI('deepl config get cache.enabled');
expect(JSON.parse(cacheEnabled)).toBe(true);
});
});
describe('output.color disables chalk colors', () => {
// ANSI escape code pattern: ESC[ followed by color/style codes
// eslint-disable-next-line no-control-regex
const ANSI_REGEX = /\x1b\[/;
// Success messages go to stderr via Logger.success, so redirect stderr to stdout
const runCLIWithStderr = (command: string, extraEnv?: Record<string, string>): string => {
return execSync(`${command} 2>&1`, {
encoding: 'utf-8',
env: { ...process.env, DEEPL_CONFIG_DIR: testConfigDir, ...extraEnv },
shell: '/bin/sh',
});
};
it('should produce no ANSI codes in output when output.color is false', () => {
runCLI('deepl config set output.color false');
// Run a command that normally produces colored output (config set emits chalk.green via Logger.success on stderr)
const output = runCLIWithStderr('deepl config set cache.enabled true');
expect(output).not.toMatch(ANSI_REGEX);
});
it('should produce ANSI codes when output.color is true (default)', () => {
// Ensure color is enabled (default)
runCLI('deepl config set output.color true');
// Run a command that produces colored output
// Force color output by setting FORCE_COLOR=1 (chalk respects this)
// Capture stderr where Logger.success writes
const output = runCLIWithStderr('deepl config set cache.enabled true', { FORCE_COLOR: '1' });
expect(output).toMatch(ANSI_REGEX);
});
});
});