Skip to content

Commit 4ea6f1c

Browse files
committed
Add tests for ArgumentProcessor, VaultDeleteCommand, and EnvRemoveCommand
- ArgumentProcessor: 24 tests covering argument mapping, flags, options, collect mode, import/copy flags, and unknown commands - VaultDeleteCommand: 7 tests covering deletion, default vault protection, error handling, and confirmation behavior - EnvRemoveCommand: 10 tests covering removal, system env protection, error handling, and confirmation behavior
1 parent 3b7e2df commit 4ea6f1c

3 files changed

Lines changed: 546 additions & 0 deletions

File tree

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
<?php
2+
3+
use STS\Keep\Data\Settings;
4+
5+
describe('EnvRemoveCommand', function () {
6+
7+
beforeEach(function () {
8+
$this->tempDir = createTempKeepDir();
9+
10+
mkdir('.keep');
11+
mkdir('.keep/vaults');
12+
13+
$settings = [
14+
'app_name' => 'test-app',
15+
'namespace' => 'test-app',
16+
'default_vault' => 'test',
17+
'envs' => ['local', 'staging', 'production', 'custom-env', 'qa'],
18+
'created_at' => date('c'),
19+
'version' => '1.0',
20+
];
21+
22+
file_put_contents('.keep/settings.json', json_encode($settings, JSON_PRETTY_PRINT));
23+
24+
$vaultConfig = [
25+
'driver' => 'test',
26+
'name' => 'Test Vault',
27+
'namespace' => 'test-app',
28+
];
29+
30+
file_put_contents('.keep/vaults/test.json', json_encode($vaultConfig, JSON_PRETTY_PRINT));
31+
});
32+
33+
afterEach(function () {
34+
if (isset($this->tempDir)) {
35+
cleanupTempDir($this->tempDir);
36+
}
37+
});
38+
39+
describe('removing custom environments', function () {
40+
41+
it('removes a custom environment with --force', function () {
42+
$initialSettings = Settings::load();
43+
expect($initialSettings->envs())->toContain('custom-env');
44+
45+
$commandTester = runCommand('env:remove', [
46+
'name' => 'custom-env',
47+
'--force' => true,
48+
]);
49+
50+
expect($commandTester->getStatusCode())->toBe(0);
51+
52+
$updatedSettings = Settings::load();
53+
expect($updatedSettings->envs())->not->toContain('custom-env');
54+
});
55+
56+
it('preserves other environments when removing one', function () {
57+
$commandTester = runCommand('env:remove', [
58+
'name' => 'custom-env',
59+
'--force' => true,
60+
]);
61+
62+
expect($commandTester->getStatusCode())->toBe(0);
63+
64+
$updatedSettings = Settings::load();
65+
expect($updatedSettings->envs())->toContain('local');
66+
expect($updatedSettings->envs())->toContain('staging');
67+
expect($updatedSettings->envs())->toContain('production');
68+
expect($updatedSettings->envs())->toContain('qa');
69+
});
70+
71+
it('shows success message after removal', function () {
72+
$commandTester = runCommand('env:remove', [
73+
'name' => 'custom-env',
74+
'--force' => true,
75+
]);
76+
77+
$output = stripAnsi($commandTester->getDisplay());
78+
expect($output)->toContain('custom-env');
79+
expect($output)->toContain('removed');
80+
});
81+
});
82+
83+
describe('system environment protection', function () {
84+
85+
it('prevents removing local environment', function () {
86+
$commandTester = runCommand('env:remove', [
87+
'name' => 'local',
88+
'--force' => true,
89+
]);
90+
91+
expect($commandTester->getStatusCode())->toBe(1);
92+
93+
$output = stripAnsi($commandTester->getDisplay());
94+
expect($output)->toContain('Cannot remove system environment');
95+
96+
$settings = Settings::load();
97+
expect($settings->envs())->toContain('local');
98+
});
99+
100+
it('prevents removing staging environment', function () {
101+
$commandTester = runCommand('env:remove', [
102+
'name' => 'staging',
103+
'--force' => true,
104+
]);
105+
106+
expect($commandTester->getStatusCode())->toBe(1);
107+
108+
$settings = Settings::load();
109+
expect($settings->envs())->toContain('staging');
110+
});
111+
112+
it('prevents removing production environment', function () {
113+
$commandTester = runCommand('env:remove', [
114+
'name' => 'production',
115+
'--force' => true,
116+
]);
117+
118+
expect($commandTester->getStatusCode())->toBe(1);
119+
120+
$settings = Settings::load();
121+
expect($settings->envs())->toContain('production');
122+
});
123+
});
124+
125+
describe('error handling', function () {
126+
127+
it('shows error for non-existent environment', function () {
128+
$commandTester = runCommand('env:remove', [
129+
'name' => 'nonexistent',
130+
'--force' => true,
131+
]);
132+
133+
expect($commandTester->getStatusCode())->toBe(1);
134+
135+
$output = stripAnsi($commandTester->getDisplay());
136+
expect($output)->toContain('not found');
137+
});
138+
139+
it('handles no custom environments gracefully', function () {
140+
$settings = [
141+
'app_name' => 'test-app',
142+
'namespace' => 'test-app',
143+
'default_vault' => 'test',
144+
'envs' => ['local', 'staging', 'production'],
145+
'created_at' => date('c'),
146+
'version' => '1.0',
147+
];
148+
file_put_contents('.keep/settings.json', json_encode($settings, JSON_PRETTY_PRINT));
149+
150+
$commandTester = runCommand('env:remove', [
151+
'--force' => true,
152+
]);
153+
154+
expect($commandTester->getStatusCode())->toBe(0);
155+
156+
$output = stripAnsi($commandTester->getDisplay());
157+
expect($output)->toContain('No custom environments');
158+
});
159+
});
160+
161+
describe('confirmation behavior', function () {
162+
163+
it('cancels removal without --force in non-interactive mode', function () {
164+
$commandTester = runCommand('env:remove', [
165+
'name' => 'custom-env',
166+
]);
167+
168+
// Non-interactive mode auto-declines confirmation
169+
$settings = Settings::load();
170+
expect($settings->envs())->toContain('custom-env');
171+
});
172+
173+
it('skips confirmation with --force flag', function () {
174+
$commandTester = runCommand('env:remove', [
175+
'name' => 'custom-env',
176+
'--force' => true,
177+
]);
178+
179+
expect($commandTester->getStatusCode())->toBe(0);
180+
181+
$settings = Settings::load();
182+
expect($settings->envs())->not->toContain('custom-env');
183+
});
184+
});
185+
});
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
describe('VaultDeleteCommand', function () {
4+
5+
beforeEach(function () {
6+
$this->tempDir = createTempKeepDir();
7+
8+
mkdir('.keep');
9+
mkdir('.keep/vaults');
10+
11+
$settings = [
12+
'app_name' => 'test-app',
13+
'namespace' => 'test-app',
14+
'default_vault' => 'primary',
15+
'envs' => ['testing', 'production'],
16+
'created_at' => date('c'),
17+
'version' => '1.0',
18+
];
19+
20+
file_put_contents('.keep/settings.json', json_encode($settings, JSON_PRETTY_PRINT));
21+
22+
$primaryVault = [
23+
'driver' => 'test',
24+
'name' => 'Primary Vault',
25+
'namespace' => 'test-app',
26+
];
27+
28+
$secondaryVault = [
29+
'driver' => 'test',
30+
'name' => 'Secondary Vault',
31+
'namespace' => 'test-app',
32+
];
33+
34+
file_put_contents('.keep/vaults/primary.json', json_encode($primaryVault, JSON_PRETTY_PRINT));
35+
file_put_contents('.keep/vaults/secondary.json', json_encode($secondaryVault, JSON_PRETTY_PRINT));
36+
});
37+
38+
afterEach(function () {
39+
if (isset($this->tempDir)) {
40+
cleanupTempDir($this->tempDir);
41+
}
42+
});
43+
44+
describe('deleting a vault', function () {
45+
46+
it('deletes a non-default vault with --force', function () {
47+
expect(file_exists('.keep/vaults/secondary.json'))->toBeTrue();
48+
49+
$commandTester = runCommand('vault:delete', [
50+
'vault' => 'secondary',
51+
'--force' => true,
52+
]);
53+
54+
expect($commandTester->getStatusCode())->toBe(0);
55+
expect(file_exists('.keep/vaults/secondary.json'))->toBeFalse();
56+
});
57+
58+
it('shows success message after deletion', function () {
59+
$commandTester = runCommand('vault:delete', [
60+
'vault' => 'secondary',
61+
'--force' => true,
62+
]);
63+
64+
$output = stripAnsi($commandTester->getDisplay());
65+
expect($output)->toContain('secondary');
66+
expect($output)->toContain('deleted');
67+
});
68+
69+
it('shows vault details before deletion', function () {
70+
$commandTester = runCommand('vault:delete', [
71+
'vault' => 'secondary',
72+
'--force' => true,
73+
]);
74+
75+
$output = stripAnsi($commandTester->getDisplay());
76+
expect($output)->toContain('Secondary Vault');
77+
});
78+
});
79+
80+
describe('protection against deleting default vault', function () {
81+
82+
it('prevents deleting the default vault', function () {
83+
$commandTester = runCommand('vault:delete', [
84+
'vault' => 'primary',
85+
'--force' => true,
86+
]);
87+
88+
expect($commandTester->getStatusCode())->toBe(1);
89+
expect(file_exists('.keep/vaults/primary.json'))->toBeTrue();
90+
91+
$output = stripAnsi($commandTester->getDisplay());
92+
expect($output)->toContain('Cannot delete the default vault');
93+
});
94+
});
95+
96+
describe('error handling', function () {
97+
98+
it('shows error for non-existent vault', function () {
99+
$commandTester = runCommand('vault:delete', [
100+
'vault' => 'nonexistent',
101+
'--force' => true,
102+
]);
103+
104+
expect($commandTester->getStatusCode())->toBe(1);
105+
106+
$output = stripAnsi($commandTester->getDisplay());
107+
expect($output)->toContain('not found');
108+
});
109+
110+
it('handles no configured vaults', function () {
111+
unlink('.keep/vaults/primary.json');
112+
unlink('.keep/vaults/secondary.json');
113+
114+
$commandTester = runCommand('vault:delete', [
115+
'vault' => 'anything',
116+
'--force' => true,
117+
]);
118+
119+
$output = stripAnsi($commandTester->getDisplay());
120+
expect($output)->toContain('No vaults');
121+
});
122+
});
123+
124+
describe('confirmation behavior', function () {
125+
126+
it('cancels deletion without --force in non-interactive mode', function () {
127+
$commandTester = runCommand('vault:delete', [
128+
'vault' => 'secondary',
129+
]);
130+
131+
// Non-interactive mode auto-declines confirmation
132+
expect(file_exists('.keep/vaults/secondary.json'))->toBeTrue();
133+
});
134+
135+
it('skips confirmation with --force flag', function () {
136+
$commandTester = runCommand('vault:delete', [
137+
'vault' => 'secondary',
138+
'--force' => true,
139+
]);
140+
141+
expect($commandTester->getStatusCode())->toBe(0);
142+
expect(file_exists('.keep/vaults/secondary.json'))->toBeFalse();
143+
});
144+
});
145+
});

0 commit comments

Comments
 (0)