@ollie-shop/cli 0.3.4 → 1.0.1

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.
Files changed (79) hide show
  1. package/.turbo/turbo-build.log +6 -9
  2. package/CHANGELOG.md +27 -0
  3. package/dist/index.js +993 -3956
  4. package/package.json +15 -37
  5. package/src/README.md +126 -0
  6. package/src/cli.tsx +45 -0
  7. package/src/commands/help.tsx +79 -0
  8. package/src/commands/login.tsx +92 -0
  9. package/src/commands/start.tsx +411 -0
  10. package/src/index.tsx +8 -0
  11. package/src/utils/auth.ts +218 -21
  12. package/src/utils/bundle.ts +177 -0
  13. package/src/utils/config.ts +123 -0
  14. package/src/utils/esbuild.ts +541 -0
  15. package/tsconfig.json +10 -15
  16. package/tsup.config.ts +7 -7
  17. package/CLAUDE_CLI.md +0 -265
  18. package/README.md +0 -711
  19. package/__tests__/mocks/console.ts +0 -22
  20. package/__tests__/mocks/core.ts +0 -137
  21. package/__tests__/mocks/index.ts +0 -4
  22. package/__tests__/mocks/inquirer.ts +0 -16
  23. package/__tests__/mocks/progress.ts +0 -19
  24. package/dist/index.d.ts +0 -1
  25. package/src/__tests__/helpers/cli-test-helper.ts +0 -281
  26. package/src/__tests__/mocks/index.ts +0 -142
  27. package/src/actions/component.actions.ts +0 -278
  28. package/src/actions/function.actions.ts +0 -220
  29. package/src/actions/project.actions.ts +0 -131
  30. package/src/actions/version.actions.ts +0 -233
  31. package/src/commands/__tests__/component-validation.test.ts +0 -250
  32. package/src/commands/__tests__/component.test.ts +0 -318
  33. package/src/commands/__tests__/function-validation.test.ts +0 -220
  34. package/src/commands/__tests__/function.test.ts +0 -286
  35. package/src/commands/__tests__/store-version-validation.test.ts +0 -414
  36. package/src/commands/__tests__/store-version.test.ts +0 -402
  37. package/src/commands/component.ts +0 -178
  38. package/src/commands/docs.ts +0 -24
  39. package/src/commands/function.ts +0 -201
  40. package/src/commands/help.ts +0 -18
  41. package/src/commands/index.ts +0 -27
  42. package/src/commands/login.ts +0 -267
  43. package/src/commands/project.ts +0 -107
  44. package/src/commands/store-version.ts +0 -242
  45. package/src/commands/version.ts +0 -51
  46. package/src/commands/whoami.ts +0 -46
  47. package/src/index.ts +0 -116
  48. package/src/prompts/component.prompts.ts +0 -94
  49. package/src/prompts/function.prompts.ts +0 -168
  50. package/src/schemas/command.schema.ts +0 -644
  51. package/src/types/index.ts +0 -183
  52. package/src/utils/__tests__/command-parser.test.ts +0 -159
  53. package/src/utils/__tests__/command-suggestions.test.ts +0 -185
  54. package/src/utils/__tests__/console.test.ts +0 -192
  55. package/src/utils/__tests__/context-detector.test.ts +0 -258
  56. package/src/utils/__tests__/enhanced-error-handler.test.ts +0 -137
  57. package/src/utils/__tests__/error-handler.test.ts +0 -107
  58. package/src/utils/__tests__/rich-progress.test.ts +0 -181
  59. package/src/utils/__tests__/validation-error-formatter.test.ts +0 -175
  60. package/src/utils/__tests__/validation-helpers.test.ts +0 -125
  61. package/src/utils/cli-progress-reporter.ts +0 -84
  62. package/src/utils/command-builder.ts +0 -390
  63. package/src/utils/command-helpers.ts +0 -83
  64. package/src/utils/command-parser.ts +0 -245
  65. package/src/utils/command-suggestions.ts +0 -176
  66. package/src/utils/console.ts +0 -320
  67. package/src/utils/constants.ts +0 -39
  68. package/src/utils/context-detector.ts +0 -177
  69. package/src/utils/deploy-helpers.ts +0 -357
  70. package/src/utils/enhanced-error-handler.ts +0 -264
  71. package/src/utils/error-handler.ts +0 -60
  72. package/src/utils/errors.ts +0 -256
  73. package/src/utils/interactive-builder.ts +0 -325
  74. package/src/utils/rich-progress.ts +0 -331
  75. package/src/utils/store.ts +0 -23
  76. package/src/utils/validation-error-formatter.ts +0 -337
  77. package/src/utils/validation-helpers.ts +0 -325
  78. package/vitest.config.ts +0 -35
  79. package/vitest.setup.ts +0 -29
@@ -1,286 +0,0 @@
1
- import type { Command } from "@commander-js/extra-typings";
2
- import {
3
- createTestProgram,
4
- executeCLI,
5
- resetCLIMocks,
6
- } from "@tests/helpers/cli-test-helper";
7
- import { createMockCore } from "@tests/mocks";
8
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
9
- import { registerFunctionCommands } from "../function";
10
-
11
- // Mock the function actions module
12
- vi.mock("../../actions/function.actions", () => ({
13
- createFunction: vi.fn(),
14
- listFunctions: vi.fn(),
15
- deployFunction: vi.fn(),
16
- buildFunction: vi.fn(),
17
- testFunction: vi.fn(),
18
- validateFunction: vi.fn(),
19
- }));
20
-
21
- // Import mocked actions
22
- import * as functionActions from "../../actions/function.actions";
23
-
24
- describe("Function Command", () => {
25
- let program: Command;
26
- let _mockCore: ReturnType<typeof createMockCore>;
27
-
28
- beforeEach(() => {
29
- const testSetup = createTestProgram();
30
- program = testSetup.program;
31
- _mockCore = createMockCore();
32
-
33
- // Register the function commands
34
- registerFunctionCommands(program);
35
-
36
- // Reset all mocks
37
- vi.clearAllMocks();
38
- });
39
-
40
- afterEach(() => {
41
- resetCLIMocks();
42
- });
43
-
44
- describe("list subcommand", () => {
45
- it("should list functions successfully", async () => {
46
- // Arrange
47
- vi.mocked(functionActions.listFunctions).mockResolvedValue();
48
-
49
- // Act
50
- const result = await executeCLI(program, ["function", "list"]);
51
-
52
- // Assert
53
- expect(result.exitCode).toBe(0);
54
- expect(functionActions.listFunctions).toHaveBeenCalled();
55
- });
56
-
57
- it("should handle list errors gracefully", async () => {
58
- // Arrange
59
- const error = new Error("Failed to fetch functions");
60
- vi.mocked(functionActions.listFunctions).mockRejectedValue(error);
61
-
62
- // Act
63
- const result = await executeCLI(program, ["function", "list"]);
64
-
65
- // Assert
66
- expect(result.exitCode).toBe(1);
67
- });
68
- });
69
-
70
- describe("create subcommand", () => {
71
- it("should create function with options", async () => {
72
- // Arrange
73
- vi.mocked(functionActions.createFunction).mockResolvedValue();
74
-
75
- // Act
76
- const result = await executeCLI(program, [
77
- "function",
78
- "create",
79
- "--name",
80
- "my-function",
81
- "--invocation",
82
- "request",
83
- ]);
84
-
85
- // Assert
86
- expect(result.exitCode).toBe(0);
87
- expect(functionActions.createFunction).toHaveBeenCalledWith(
88
- expect.objectContaining({
89
- name: "my-function",
90
- invocation: "request",
91
- tests: true,
92
- }),
93
- expect.any(Object),
94
- );
95
- });
96
-
97
- it("should create function with default values", async () => {
98
- // Arrange
99
- vi.mocked(functionActions.createFunction).mockResolvedValue();
100
-
101
- // Act
102
- const result = await executeCLI(program, [
103
- "function",
104
- "create",
105
- "--name",
106
- "my-function",
107
- ]);
108
-
109
- // Assert
110
- expect(result.exitCode).toBe(0);
111
- expect(functionActions.createFunction).toHaveBeenCalledWith(
112
- expect.objectContaining({
113
- name: "my-function",
114
- invocation: "request",
115
- tests: true,
116
- }),
117
- expect.any(Object),
118
- );
119
- });
120
-
121
- it("should handle JavaScript language option", async () => {
122
- // Arrange
123
- vi.mocked(functionActions.createFunction).mockResolvedValue();
124
-
125
- // Act
126
- const result = await executeCLI(program, [
127
- "function",
128
- "create",
129
- "--name",
130
- "my-function",
131
- ]);
132
-
133
- // Assert
134
- expect(result.exitCode).toBe(0);
135
- expect(functionActions.createFunction).toHaveBeenCalledWith(
136
- expect.objectContaining({
137
- name: "my-function",
138
- invocation: "request",
139
- tests: true,
140
- }),
141
- expect.any(Object),
142
- );
143
- });
144
-
145
- it("should handle action errors", async () => {
146
- // Arrange
147
- const error = new Error("Creation failed");
148
- vi.mocked(functionActions.createFunction).mockRejectedValue(error);
149
-
150
- // Act
151
- const result = await executeCLI(program, [
152
- "function",
153
- "create",
154
- "--name",
155
- "MyFunction",
156
- ]);
157
-
158
- // Assert
159
- expect(result.exitCode).toBe(1);
160
- });
161
- });
162
-
163
- describe("validate subcommand", () => {
164
- it("should validate a function at path", async () => {
165
- // Arrange
166
- vi.mocked(functionActions.validateFunction).mockResolvedValue();
167
-
168
- // Act
169
- const result = await executeCLI(program, [
170
- "function",
171
- "validate",
172
- "--path",
173
- "./my-function",
174
- ]);
175
-
176
- // Assert
177
- expect(result.exitCode).toBe(0);
178
- expect(functionActions.validateFunction).toHaveBeenCalledWith(
179
- expect.objectContaining({
180
- path: "./my-function",
181
- }),
182
- expect.any(Object),
183
- );
184
- });
185
- });
186
-
187
- describe("test subcommand", () => {
188
- it("should test a function", async () => {
189
- // Arrange
190
- vi.mocked(functionActions.testFunction).mockResolvedValue();
191
-
192
- // Act
193
- const result = await executeCLI(program, [
194
- "function",
195
- "test",
196
- "--path",
197
- "./my-function",
198
- ]);
199
-
200
- // Assert
201
- expect(result.exitCode).toBe(0);
202
- expect(functionActions.testFunction).toHaveBeenCalledWith(
203
- expect.objectContaining({
204
- path: "./my-function",
205
- }),
206
- expect.any(Object),
207
- );
208
- });
209
-
210
- it("should handle test failures", async () => {
211
- // Arrange
212
- const error = new Error("Function test failed");
213
- vi.mocked(functionActions.testFunction).mockRejectedValue(error);
214
-
215
- // Act
216
- const result = await executeCLI(program, [
217
- "function",
218
- "test",
219
- "--path",
220
- "./my-function",
221
- ]);
222
-
223
- // Assert
224
- expect(result.exitCode).toBe(1);
225
- });
226
- });
227
-
228
- describe("deploy subcommand", () => {
229
- it("should deploy a function", async () => {
230
- // Arrange
231
- vi.mocked(functionActions.deployFunction).mockResolvedValue();
232
-
233
- // Act
234
- const result = await executeCLI(program, [
235
- "function",
236
- "deploy",
237
- "--path",
238
- "./my-function",
239
- "--id",
240
- "123e4567-e89b-12d3-a456-426614174000",
241
- ]);
242
-
243
- // Assert
244
- expect(result.exitCode).toBe(0);
245
- expect(functionActions.deployFunction).toHaveBeenCalledWith(
246
- expect.objectContaining({
247
- path: "./my-function",
248
- }),
249
- expect.any(Object),
250
- );
251
- });
252
- });
253
-
254
- describe("error handling", () => {
255
- it("should handle validation errors gracefully", async () => {
256
- // Arrange
257
- const error = new Error("Validation failed");
258
- vi.mocked(functionActions.validateFunction).mockRejectedValue(error);
259
-
260
- // Act
261
- const result = await executeCLI(program, [
262
- "function",
263
- "validate",
264
- "--path",
265
- "./my-function",
266
- ]);
267
-
268
- // Assert
269
- expect(result.exitCode).toBe(1);
270
- });
271
- });
272
-
273
- describe("alias support", () => {
274
- it("should work with func alias", async () => {
275
- // Arrange
276
- vi.mocked(functionActions.listFunctions).mockResolvedValue();
277
-
278
- // Act
279
- const result = await executeCLI(program, ["func", "list"]);
280
-
281
- // Assert
282
- expect(result.exitCode).toBe(0);
283
- expect(functionActions.listFunctions).toHaveBeenCalled();
284
- });
285
- });
286
- });
@@ -1,414 +0,0 @@
1
- import type { Command } from "@commander-js/extra-typings";
2
- import {
3
- createTestProgram,
4
- executeCLI,
5
- resetCLIMocks,
6
- } from "@tests/helpers/cli-test-helper";
7
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
8
- import { registerStoreVersionCommands } from "../store-version";
9
-
10
- // Mock the version actions module
11
- vi.mock("../../actions/version.actions", () => ({
12
- create: vi.fn(),
13
- list: vi.fn(),
14
- get: vi.fn(),
15
- setDefault: vi.fn(),
16
- activate: vi.fn(),
17
- deactivate: vi.fn(),
18
- clone: vi.fn(),
19
- deleteVersion: vi.fn(),
20
- }));
21
-
22
- import * as versionActions from "../../actions/version.actions";
23
-
24
- describe("Store Version Command Validation and DX", () => {
25
- let program: Command;
26
- let testSetup: ReturnType<typeof createTestProgram>;
27
-
28
- beforeEach(() => {
29
- testSetup = createTestProgram();
30
- program = testSetup.program;
31
- registerStoreVersionCommands(program);
32
- vi.clearAllMocks();
33
- });
34
-
35
- afterEach(() => {
36
- resetCLIMocks();
37
- });
38
-
39
- describe("store ID validation", () => {
40
- it("should reject invalid UUID format for store ID", async () => {
41
- const result = await executeCLI(program, [
42
- "store-version",
43
- "create",
44
- "--store",
45
- "invalid-uuid",
46
- "--name",
47
- "v2.0",
48
- ]);
49
-
50
- const consoleOutput = testSetup.mocks.console.error.mock.calls
51
- .map((call) => call.join(" "))
52
- .join("\n");
53
-
54
- expect(result.exitCode).toBe(1);
55
- expect(consoleOutput).toContain("Validation failed");
56
- expect(consoleOutput.toLowerCase()).toContain("must be a valid uuid");
57
- expect(versionActions.create).not.toHaveBeenCalled();
58
- });
59
-
60
- it("should reject malformed UUIDs", async () => {
61
- const malformedUUIDs = [
62
- "123",
63
- "123e4567-e89b-12d3-a456",
64
- "123e4567e89b12d3a456426614174000",
65
- "not-a-uuid-at-all",
66
- "123e4567-e89b-12d3-a456-42661417400g", // 'g' is not valid hex
67
- ];
68
-
69
- for (const uuid of malformedUUIDs) {
70
- const result = await executeCLI(program, [
71
- "store-version",
72
- "create",
73
- "--store",
74
- uuid,
75
- "--name",
76
- "v2.0",
77
- ]);
78
-
79
- const consoleOutput = testSetup.mocks.console.error.mock.calls
80
- .map((call) => call.join(" "))
81
- .join("\n");
82
-
83
- expect(result.exitCode).toBe(1);
84
- expect(consoleOutput).toContain("Validation failed");
85
- expect(versionActions.create).not.toHaveBeenCalled();
86
- }
87
- });
88
-
89
- it("should accept valid UUID format", async () => {
90
- vi.mocked(versionActions.create).mockResolvedValue();
91
-
92
- const validUUID = "123e4567-e89b-12d3-a456-426614174000";
93
- const result = await executeCLI(program, [
94
- "store-version",
95
- "create",
96
- "--store",
97
- validUUID,
98
- "--name",
99
- "v2.0",
100
- ]);
101
-
102
- expect(result.exitCode).toBe(0);
103
- expect(versionActions.create).toHaveBeenCalledWith(
104
- expect.objectContaining({
105
- store: validUUID,
106
- name: "v2.0",
107
- }),
108
- );
109
- });
110
-
111
- it("should require store ID", async () => {
112
- const result = await executeCLI(program, [
113
- "store-version",
114
- "create",
115
- "--name",
116
- "v2.0",
117
- ]);
118
-
119
- expect(result.exitCode).toBe(1);
120
- expect(versionActions.create).not.toHaveBeenCalled();
121
- });
122
- });
123
-
124
- describe("version name validation", () => {
125
- it("should reject empty version names", async () => {
126
- const result = await executeCLI(program, [
127
- "store-version",
128
- "create",
129
- "--store",
130
- "123e4567-e89b-12d3-a456-426614174000",
131
- "--name",
132
- "",
133
- ]);
134
-
135
- const consoleOutput = testSetup.mocks.console.error.mock.calls
136
- .map((call) => call.join(" "))
137
- .join("\n");
138
-
139
- expect(result.exitCode).toBe(1);
140
- expect(consoleOutput).toContain("Validation failed");
141
- expect(versionActions.create).not.toHaveBeenCalled();
142
- });
143
-
144
- it("should reject version names over 50 characters", async () => {
145
- const longName = "a".repeat(51);
146
- const result = await executeCLI(program, [
147
- "store-version",
148
- "create",
149
- "--store",
150
- "123e4567-e89b-12d3-a456-426614174000",
151
- "--name",
152
- longName,
153
- ]);
154
-
155
- // The schema doesn't enforce a max length, so a 51 character name should be accepted
156
- expect(result.exitCode).toBe(0);
157
- expect(versionActions.create).toHaveBeenCalled();
158
- });
159
-
160
- it("should accept various valid version name formats", async () => {
161
- vi.mocked(versionActions.create).mockResolvedValue();
162
-
163
- const validNames = [
164
- "v1.0.0",
165
- "summer-sale-2024",
166
- "black-friday",
167
- "test_version",
168
- "VERSION-2",
169
- "v2.1.0-beta",
170
- ];
171
-
172
- for (const name of validNames) {
173
- vi.clearAllMocks();
174
-
175
- const result = await executeCLI(program, [
176
- "store-version",
177
- "create",
178
- "--store",
179
- "123e4567-e89b-12d3-a456-426614174000",
180
- "--name",
181
- name,
182
- ]);
183
-
184
- expect(result.exitCode).toBe(0);
185
- expect(versionActions.create).toHaveBeenCalledWith(
186
- expect.objectContaining({
187
- name,
188
- }),
189
- );
190
- }
191
- });
192
-
193
- it("should require version name", async () => {
194
- const result = await executeCLI(program, [
195
- "store-version",
196
- "create",
197
- "--store",
198
- "123e4567-e89b-12d3-a456-426614174000",
199
- ]);
200
-
201
- expect(result.exitCode).toBe(1);
202
- expect(versionActions.create).not.toHaveBeenCalled();
203
- });
204
- });
205
-
206
- describe("template validation", () => {
207
- it("should accept default template", async () => {
208
- vi.mocked(versionActions.create).mockResolvedValue();
209
-
210
- const result = await executeCLI(program, [
211
- "store-version",
212
- "create",
213
- "--store",
214
- "123e4567-e89b-12d3-a456-426614174000",
215
- "--name",
216
- "v2.0",
217
- "--template",
218
- "default",
219
- ]);
220
-
221
- expect(result.exitCode).toBe(0);
222
- expect(versionActions.create).toHaveBeenCalledWith(
223
- expect.objectContaining({
224
- template: "default",
225
- }),
226
- );
227
- });
228
-
229
- it("should use default template when not specified", async () => {
230
- vi.mocked(versionActions.create).mockResolvedValue();
231
-
232
- const result = await executeCLI(program, [
233
- "store-version",
234
- "create",
235
- "--store",
236
- "123e4567-e89b-12d3-a456-426614174000",
237
- "--name",
238
- "v2.0",
239
- ]);
240
-
241
- expect(result.exitCode).toBe(0);
242
- expect(versionActions.create).toHaveBeenCalledWith(
243
- expect.objectContaining({
244
- template: "default",
245
- }),
246
- );
247
- });
248
- });
249
-
250
- describe("active flag validation", () => {
251
- it("should create active version by default", async () => {
252
- vi.mocked(versionActions.create).mockResolvedValue();
253
-
254
- const result = await executeCLI(program, [
255
- "store-version",
256
- "create",
257
- "--store",
258
- "123e4567-e89b-12d3-a456-426614174000",
259
- "--name",
260
- "v2.0",
261
- ]);
262
-
263
- expect(result.exitCode).toBe(0);
264
- expect(versionActions.create).toHaveBeenCalledWith(
265
- expect.objectContaining({
266
- active: true,
267
- }),
268
- );
269
- });
270
-
271
- it("should create inactive version with --no-active", async () => {
272
- vi.mocked(versionActions.create).mockResolvedValue();
273
-
274
- const result = await executeCLI(program, [
275
- "store-version",
276
- "create",
277
- "--store",
278
- "123e4567-e89b-12d3-a456-426614174000",
279
- "--name",
280
- "v2.0",
281
- "--no-active",
282
- ]);
283
-
284
- expect(result.exitCode).toBe(0);
285
- expect(versionActions.create).toHaveBeenCalledWith(
286
- expect.objectContaining({
287
- active: false,
288
- }),
289
- );
290
- });
291
- });
292
-
293
- describe("positional argument validation", () => {
294
- it("should validate version ID in get command", async () => {
295
- const result = await executeCLI(program, [
296
- "store-version",
297
- "get",
298
- "invalid-uuid",
299
- ]);
300
-
301
- expect(result.exitCode).toBe(1);
302
- expect(versionActions.get).not.toHaveBeenCalled();
303
- });
304
-
305
- it("should validate version ID in set-default command", async () => {
306
- const result = await executeCLI(program, [
307
- "store-version",
308
- "set-default",
309
- "not-a-uuid",
310
- ]);
311
-
312
- expect(result.exitCode).toBe(1);
313
- expect(versionActions.setDefault).not.toHaveBeenCalled();
314
- });
315
-
316
- it("should fail with invalid UUID", async () => {
317
- const result = await executeCLI(program, [
318
- "store-version",
319
- "get",
320
- "invalid",
321
- ]);
322
-
323
- expect(result.exitCode).toBe(1);
324
- expect(versionActions.get).not.toHaveBeenCalled();
325
- });
326
- });
327
-
328
- describe("clone command validation", () => {
329
- it("should validate both version ID and name", async () => {
330
- const result = await executeCLI(program, [
331
- "store-version",
332
- "clone",
333
- "invalid-uuid",
334
- "--name",
335
- "v2.0",
336
- ]);
337
-
338
- expect(result.exitCode).toBe(1);
339
- expect(versionActions.clone).not.toHaveBeenCalled();
340
- });
341
-
342
- it("should require name for clone", async () => {
343
- const result = await executeCLI(program, [
344
- "store-version",
345
- "clone",
346
- "123e4567-e89b-12d3-a456-426614174000",
347
- ]);
348
-
349
- expect(result.exitCode).toBe(1);
350
- expect(versionActions.clone).not.toHaveBeenCalled();
351
- });
352
-
353
- it("should validate name length in clone", async () => {
354
- const longName = "a".repeat(101); // Exceed the 100-character limit
355
- const result = await executeCLI(program, [
356
- "store-version",
357
- "clone",
358
- "123e4567-e89b-12d3-a456-426614174000",
359
- "--name",
360
- longName,
361
- ]);
362
-
363
- expect(result.exitCode).toBe(1);
364
- expect(result.stderr.join("")).toContain("Version name is too long");
365
- expect(versionActions.clone).not.toHaveBeenCalled();
366
- });
367
- });
368
-
369
- describe("help command", () => {
370
- it("should show examples in create help", async () => {
371
- const result = await executeCLI(program, [
372
- "store-version",
373
- "create",
374
- "--help",
375
- ]);
376
-
377
- const output = result.stdout.join("") + result.stderr.join("");
378
- expect(output).toContain("Examples:");
379
- expect(output).toContain("Create an active version:");
380
- expect(output).toContain("$ ollieshop store-version create --store");
381
- expect(output).toContain("Create version with grocery template:");
382
- expect(output).toContain("Create inactive version for testing:");
383
- });
384
-
385
- it("should show examples in clone help", async () => {
386
- const result = await executeCLI(program, [
387
- "store-version",
388
- "clone",
389
- "--help",
390
- ]);
391
-
392
- const output = result.stdout.join("") + result.stderr.join("");
393
- expect(output).toContain("Examples:");
394
- expect(output).toContain("Clone a version:");
395
- expect(output).toContain("Clone for A/B testing:");
396
- });
397
- });
398
-
399
- describe("alias support", () => {
400
- it("should work with sv alias", async () => {
401
- vi.mocked(versionActions.list).mockResolvedValue();
402
-
403
- const result = await executeCLI(program, [
404
- "sv",
405
- "list",
406
- "--store",
407
- "123e4567-e89b-12d3-a456-426614174000",
408
- ]);
409
-
410
- expect(result.exitCode).toBe(0);
411
- expect(versionActions.list).toHaveBeenCalled();
412
- });
413
- });
414
- });