@nestbox-ai/cli 1.0.19 → 1.0.21
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/.github/workflows/generate-client.yml +34 -6
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/agent.d.ts +0 -1
- package/dist/utils/agent.js +0 -48
- package/dist/utils/agent.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +9 -2
- package/src/utils/agent.ts +0 -57
- package/test/README.md +52 -0
- package/test/agent.test.ts +140 -0
- package/test/auth.test.ts +71 -0
- package/test/compute.test.ts +135 -0
- package/test/document.test.ts +217 -0
- package/test/image.test.ts +107 -0
- package/test/mocks.ts +122 -0
- package/test/projects.test.ts +108 -0
- package/test/setup.ts +121 -0
- package/tsconfig.json +3 -1
- package/vitest.config.d.ts +2 -0
- package/vitest.config.js +23 -0
- package/vitest.config.js.map +1 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { registerComputeProgram } from '../src/commands/compute';
|
|
4
|
+
|
|
5
|
+
describe('Compute Commands', () => {
|
|
6
|
+
let program: Command;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
program = new Command();
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('registerComputeProgram', () => {
|
|
14
|
+
it('should register compute command group', () => {
|
|
15
|
+
registerComputeProgram(program);
|
|
16
|
+
|
|
17
|
+
const commands = program.commands;
|
|
18
|
+
const computeCommand = commands.find(cmd => cmd.name() === 'compute');
|
|
19
|
+
|
|
20
|
+
expect(computeCommand).toBeDefined();
|
|
21
|
+
expect(computeCommand?.description()).toBe('Manage Nestbox computes');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should register compute list subcommand', () => {
|
|
25
|
+
registerComputeProgram(program);
|
|
26
|
+
|
|
27
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
28
|
+
const subCommands = computeCommand?.commands || [];
|
|
29
|
+
const listCommand = subCommands.find(cmd => cmd.name() === 'list');
|
|
30
|
+
|
|
31
|
+
expect(listCommand).toBeDefined();
|
|
32
|
+
expect(listCommand?.description()).toBe('List all compute instances');
|
|
33
|
+
|
|
34
|
+
// Check options
|
|
35
|
+
const options = listCommand?.options || [];
|
|
36
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
37
|
+
expect(projectOption).toBeDefined();
|
|
38
|
+
expect(projectOption?.description).toBe('Project ID or name (defaults to the current project)');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should register compute create subcommand', () => {
|
|
42
|
+
registerComputeProgram(program);
|
|
43
|
+
|
|
44
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
45
|
+
const subCommands = computeCommand?.commands || [];
|
|
46
|
+
const createCommand = subCommands.find(cmd => cmd.name() === 'create');
|
|
47
|
+
|
|
48
|
+
expect(createCommand).toBeDefined();
|
|
49
|
+
expect(createCommand?.description()).toBe('Create a new compute instance');
|
|
50
|
+
|
|
51
|
+
// Check options
|
|
52
|
+
const options = createCommand?.options || [];
|
|
53
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
54
|
+
const imageOption = options.find(opt => opt.long === '--image');
|
|
55
|
+
|
|
56
|
+
expect(projectOption).toBeDefined();
|
|
57
|
+
expect(imageOption).toBeDefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should register compute delete subcommand', () => {
|
|
61
|
+
registerComputeProgram(program);
|
|
62
|
+
|
|
63
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
64
|
+
const subCommands = computeCommand?.commands || [];
|
|
65
|
+
const deleteCommand = subCommands.find(cmd => cmd.name() === 'delete');
|
|
66
|
+
|
|
67
|
+
expect(deleteCommand).toBeDefined();
|
|
68
|
+
expect(deleteCommand?.description()).toBe('Delete one or more compute instances');
|
|
69
|
+
|
|
70
|
+
// Check options
|
|
71
|
+
const options = deleteCommand?.options || [];
|
|
72
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
73
|
+
const forceOption = options.find(opt => opt.long === '--force');
|
|
74
|
+
|
|
75
|
+
expect(projectOption).toBeDefined();
|
|
76
|
+
expect(forceOption).toBeDefined();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should have all expected compute subcommands', () => {
|
|
80
|
+
registerComputeProgram(program);
|
|
81
|
+
|
|
82
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
83
|
+
const subCommandNames = computeCommand?.commands.map(cmd => cmd.name()) || [];
|
|
84
|
+
|
|
85
|
+
expect(subCommandNames).toContain('list');
|
|
86
|
+
expect(subCommandNames).toContain('create');
|
|
87
|
+
expect(subCommandNames).toContain('delete');
|
|
88
|
+
expect(subCommandNames).toHaveLength(3);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should have proper action functions for all subcommands', () => {
|
|
92
|
+
registerComputeProgram(program);
|
|
93
|
+
|
|
94
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
95
|
+
const subCommands = computeCommand?.commands || [];
|
|
96
|
+
|
|
97
|
+
subCommands.forEach(cmd => {
|
|
98
|
+
expect(typeof cmd.action).toBe('function');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should register compute list command with correct structure', () => {
|
|
103
|
+
registerComputeProgram(program);
|
|
104
|
+
|
|
105
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
106
|
+
const listCommand = computeCommand?.commands.find(cmd => cmd.name() === 'list');
|
|
107
|
+
|
|
108
|
+
expect(listCommand?.name()).toBe('list');
|
|
109
|
+
expect(listCommand?.description()).toBe('List all compute instances');
|
|
110
|
+
expect(typeof listCommand?.action).toBe('function');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should register compute create command with correct structure', () => {
|
|
114
|
+
registerComputeProgram(program);
|
|
115
|
+
|
|
116
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
117
|
+
const createCommand = computeCommand?.commands.find(cmd => cmd.name() === 'create');
|
|
118
|
+
|
|
119
|
+
expect(createCommand?.name()).toBe('create');
|
|
120
|
+
expect(createCommand?.description()).toBe('Create a new compute instance');
|
|
121
|
+
expect(typeof createCommand?.action).toBe('function');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should register compute delete command with correct structure', () => {
|
|
125
|
+
registerComputeProgram(program);
|
|
126
|
+
|
|
127
|
+
const computeCommand = program.commands.find(cmd => cmd.name() === 'compute');
|
|
128
|
+
const deleteCommand = computeCommand?.commands.find(cmd => cmd.name() === 'delete');
|
|
129
|
+
|
|
130
|
+
expect(deleteCommand?.name()).toBe('delete');
|
|
131
|
+
expect(deleteCommand?.description()).toBe('Delete one or more compute instances');
|
|
132
|
+
expect(typeof deleteCommand?.action).toBe('function');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { registerDocumentCommands } from '../src/commands/document';
|
|
4
|
+
|
|
5
|
+
describe('Document Commands', () => {
|
|
6
|
+
let program: Command;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
program = new Command();
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('registerDocumentCommands', () => {
|
|
14
|
+
it('should register document command group', () => {
|
|
15
|
+
registerDocumentCommands(program);
|
|
16
|
+
|
|
17
|
+
const commands = program.commands;
|
|
18
|
+
const documentCommand = commands.find(cmd => cmd.name() === 'document');
|
|
19
|
+
|
|
20
|
+
expect(documentCommand).toBeDefined();
|
|
21
|
+
expect(documentCommand?.description()).toBe('Manage Nestbox documents');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should register doc subcommand group', () => {
|
|
25
|
+
registerDocumentCommands(program);
|
|
26
|
+
|
|
27
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
28
|
+
const subCommands = documentCommand?.commands || [];
|
|
29
|
+
const docCommand = subCommands.find(cmd => cmd.name() === 'doc');
|
|
30
|
+
|
|
31
|
+
expect(docCommand).toBeDefined();
|
|
32
|
+
expect(docCommand?.description()).toBe('Manage individual documents');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should register collection subcommand group', () => {
|
|
36
|
+
registerDocumentCommands(program);
|
|
37
|
+
|
|
38
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
39
|
+
const subCommands = documentCommand?.commands || [];
|
|
40
|
+
const collectionCommand = subCommands.find(cmd => cmd.name() === 'collection');
|
|
41
|
+
|
|
42
|
+
expect(collectionCommand).toBeDefined();
|
|
43
|
+
expect(collectionCommand?.description()).toBe('Manage document collections');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should register doc list subcommand', () => {
|
|
47
|
+
registerDocumentCommands(program);
|
|
48
|
+
|
|
49
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
50
|
+
const collectionCommand = documentCommand?.commands.find(cmd => cmd.name() === 'collection');
|
|
51
|
+
const collectionSubCommands = collectionCommand?.commands || [];
|
|
52
|
+
const listCommand = collectionSubCommands.find(cmd => cmd.name() === 'list');
|
|
53
|
+
|
|
54
|
+
expect(listCommand).toBeDefined();
|
|
55
|
+
expect(listCommand?.description()).toBe('List document collections for a specific instance');
|
|
56
|
+
|
|
57
|
+
// Check options
|
|
58
|
+
const options = listCommand?.options || [];
|
|
59
|
+
const instanceOption = options.find(opt => opt.long === '--instance');
|
|
60
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
61
|
+
|
|
62
|
+
expect(instanceOption).toBeDefined();
|
|
63
|
+
expect(projectOption).toBeDefined();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should register doc create subcommand', () => {
|
|
67
|
+
registerDocumentCommands(program);
|
|
68
|
+
|
|
69
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
70
|
+
const collectionCommand = documentCommand?.commands.find(cmd => cmd.name() === 'collection');
|
|
71
|
+
const collectionSubCommands = collectionCommand?.commands || [];
|
|
72
|
+
const createCommand = collectionSubCommands.find(cmd => cmd.name() === 'create');
|
|
73
|
+
|
|
74
|
+
expect(createCommand).toBeDefined();
|
|
75
|
+
expect(createCommand?.description()).toBe('Create a new document collection for a specific instance');
|
|
76
|
+
|
|
77
|
+
// Check options
|
|
78
|
+
const options = createCommand?.options || [];
|
|
79
|
+
const instanceOption = options.find(opt => opt.long === '--instance');
|
|
80
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
81
|
+
|
|
82
|
+
expect(instanceOption).toBeDefined();
|
|
83
|
+
expect(projectOption).toBeDefined();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should register doc get subcommand', () => {
|
|
87
|
+
registerDocumentCommands(program);
|
|
88
|
+
|
|
89
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
90
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
91
|
+
const docSubCommands = docCommand?.commands || [];
|
|
92
|
+
const getCommand = docSubCommands.find(cmd => cmd.name() === 'get');
|
|
93
|
+
|
|
94
|
+
expect(getCommand).toBeDefined();
|
|
95
|
+
expect(getCommand?.description()).toBe('Get a document from a collection');
|
|
96
|
+
|
|
97
|
+
// Arguments are part of the command definition, not in args array
|
|
98
|
+
expect(getCommand?.name()).toBe('get');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should register doc delete subcommand', () => {
|
|
102
|
+
registerDocumentCommands(program);
|
|
103
|
+
|
|
104
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
105
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
106
|
+
const docSubCommands = docCommand?.commands || [];
|
|
107
|
+
const deleteCommand = docSubCommands.find(cmd => cmd.name() === 'delete');
|
|
108
|
+
|
|
109
|
+
expect(deleteCommand).toBeDefined();
|
|
110
|
+
expect(deleteCommand?.description()).toBe('Delete a document from a collection');
|
|
111
|
+
|
|
112
|
+
// Arguments are part of the command definition, not in args array
|
|
113
|
+
expect(deleteCommand?.name()).toBe('delete');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should register doc update subcommand', () => {
|
|
117
|
+
registerDocumentCommands(program);
|
|
118
|
+
|
|
119
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
120
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
121
|
+
const docSubCommands = docCommand?.commands || [];
|
|
122
|
+
const updateCommand = docSubCommands.find(cmd => cmd.name() === 'update');
|
|
123
|
+
|
|
124
|
+
expect(updateCommand).toBeDefined();
|
|
125
|
+
expect(updateCommand?.description()).toBe('Update a document in a collection');
|
|
126
|
+
|
|
127
|
+
// Arguments are part of the command definition, not in args array
|
|
128
|
+
expect(updateCommand?.name()).toBe('update');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should register collection add subcommand', () => {
|
|
132
|
+
registerDocumentCommands(program);
|
|
133
|
+
|
|
134
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
135
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
136
|
+
const docSubCommands = docCommand?.commands || [];
|
|
137
|
+
const addCommand = docSubCommands.find(cmd => cmd.name() === 'add');
|
|
138
|
+
|
|
139
|
+
expect(addCommand).toBeDefined();
|
|
140
|
+
expect(addCommand?.description()).toBe('Add a new document to a collection');
|
|
141
|
+
|
|
142
|
+
// Check options
|
|
143
|
+
const options = addCommand?.options || [];
|
|
144
|
+
const instanceOption = options.find(opt => opt.long === '--instance');
|
|
145
|
+
const collectionOption = options.find(opt => opt.long === '--collection');
|
|
146
|
+
|
|
147
|
+
expect(instanceOption).toBeDefined();
|
|
148
|
+
expect(collectionOption).toBeDefined();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should register collection search subcommand', () => {
|
|
152
|
+
registerDocumentCommands(program);
|
|
153
|
+
|
|
154
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
155
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
156
|
+
const docSubCommands = docCommand?.commands || [];
|
|
157
|
+
const searchCommand = docSubCommands.find(cmd => cmd.name() === 'search');
|
|
158
|
+
|
|
159
|
+
expect(searchCommand).toBeDefined();
|
|
160
|
+
expect(searchCommand?.description()).toBe('Search for documents in a collection');
|
|
161
|
+
|
|
162
|
+
// Check arguments and options
|
|
163
|
+
expect(searchCommand?.name()).toBe('search');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should have all expected doc subcommands', () => {
|
|
167
|
+
registerDocumentCommands(program);
|
|
168
|
+
|
|
169
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
170
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
171
|
+
const docSubCommandNames = docCommand?.commands.map(cmd => cmd.name()) || [];
|
|
172
|
+
|
|
173
|
+
expect(docSubCommandNames).toContain('add');
|
|
174
|
+
expect(docSubCommandNames).toContain('get');
|
|
175
|
+
expect(docSubCommandNames).toContain('delete');
|
|
176
|
+
expect(docSubCommandNames).toContain('update');
|
|
177
|
+
expect(docSubCommandNames).toContain('upload-file');
|
|
178
|
+
expect(docSubCommandNames).toContain('search');
|
|
179
|
+
expect(docSubCommandNames).toHaveLength(6);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should have all expected collection subcommands', () => {
|
|
183
|
+
registerDocumentCommands(program);
|
|
184
|
+
|
|
185
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
186
|
+
const collectionCommand = documentCommand?.commands.find(cmd => cmd.name() === 'collection');
|
|
187
|
+
const collectionSubCommandNames = collectionCommand?.commands.map(cmd => cmd.name()) || [];
|
|
188
|
+
|
|
189
|
+
expect(collectionSubCommandNames).toContain('list');
|
|
190
|
+
expect(collectionSubCommandNames).toContain('create');
|
|
191
|
+
expect(collectionSubCommandNames).toContain('get');
|
|
192
|
+
expect(collectionSubCommandNames).toContain('delete');
|
|
193
|
+
expect(collectionSubCommandNames).toContain('update');
|
|
194
|
+
expect(collectionSubCommandNames).toHaveLength(5);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should have proper action functions for all subcommands', () => {
|
|
198
|
+
registerDocumentCommands(program);
|
|
199
|
+
|
|
200
|
+
const documentCommand = program.commands.find(cmd => cmd.name() === 'document');
|
|
201
|
+
const docCommand = documentCommand?.commands.find(cmd => cmd.name() === 'doc');
|
|
202
|
+
const collectionCommand = documentCommand?.commands.find(cmd => cmd.name() === 'collection');
|
|
203
|
+
|
|
204
|
+
// Check doc subcommands
|
|
205
|
+
const docSubCommands = docCommand?.commands || [];
|
|
206
|
+
docSubCommands.forEach(cmd => {
|
|
207
|
+
expect(typeof cmd.action).toBe('function');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Check collection subcommands
|
|
211
|
+
const collectionSubCommands = collectionCommand?.commands || [];
|
|
212
|
+
collectionSubCommands.forEach(cmd => {
|
|
213
|
+
expect(typeof cmd.action).toBe('function');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { registerImageCommands } from '../src/commands/image';
|
|
4
|
+
|
|
5
|
+
describe('Image Commands', () => {
|
|
6
|
+
let program: Command;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
program = new Command();
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('registerImageCommands', () => {
|
|
14
|
+
it('should register image command group', () => {
|
|
15
|
+
registerImageCommands(program);
|
|
16
|
+
|
|
17
|
+
const commands = program.commands;
|
|
18
|
+
const imageCommand = commands.find(cmd => cmd.name() === 'image');
|
|
19
|
+
|
|
20
|
+
expect(imageCommand).toBeDefined();
|
|
21
|
+
expect(imageCommand?.description()).toBe('Manage Nestbox images');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should register image list subcommand', () => {
|
|
25
|
+
registerImageCommands(program);
|
|
26
|
+
|
|
27
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
28
|
+
const subCommands = imageCommand?.commands || [];
|
|
29
|
+
const listCommand = subCommands.find(cmd => cmd.name() === 'list');
|
|
30
|
+
|
|
31
|
+
expect(listCommand).toBeDefined();
|
|
32
|
+
expect(listCommand?.description()).toBe('List images for a project');
|
|
33
|
+
|
|
34
|
+
// Check options
|
|
35
|
+
const options = listCommand?.options || [];
|
|
36
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
37
|
+
expect(projectOption).toBeDefined();
|
|
38
|
+
expect(projectOption?.description).toBe('Project ID or name (defaults to the current project)');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should have all expected image subcommands', () => {
|
|
42
|
+
registerImageCommands(program);
|
|
43
|
+
|
|
44
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
45
|
+
const subCommandNames = imageCommand?.commands.map(cmd => cmd.name()) || [];
|
|
46
|
+
|
|
47
|
+
expect(subCommandNames).toContain('list');
|
|
48
|
+
expect(subCommandNames).toHaveLength(1);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should have proper action functions for all subcommands', () => {
|
|
52
|
+
registerImageCommands(program);
|
|
53
|
+
|
|
54
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
55
|
+
const subCommands = imageCommand?.commands || [];
|
|
56
|
+
|
|
57
|
+
subCommands.forEach(cmd => {
|
|
58
|
+
expect(typeof cmd.action).toBe('function');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should register image list command with correct structure', () => {
|
|
63
|
+
registerImageCommands(program);
|
|
64
|
+
|
|
65
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
66
|
+
const listCommand = imageCommand?.commands.find(cmd => cmd.name() === 'list');
|
|
67
|
+
|
|
68
|
+
expect(listCommand?.name()).toBe('list');
|
|
69
|
+
expect(listCommand?.description()).toBe('List images for a project');
|
|
70
|
+
expect(typeof listCommand?.action).toBe('function');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should have project option with correct configuration', () => {
|
|
74
|
+
registerImageCommands(program);
|
|
75
|
+
|
|
76
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
77
|
+
const listCommand = imageCommand?.commands.find(cmd => cmd.name() === 'list');
|
|
78
|
+
const options = listCommand?.options || [];
|
|
79
|
+
const projectOption = options.find(opt => opt.long === '--project');
|
|
80
|
+
|
|
81
|
+
expect(projectOption).toBeDefined();
|
|
82
|
+
expect(projectOption?.description).toBe('Project ID or name (defaults to the current project)');
|
|
83
|
+
expect(projectOption?.long).toBe('--project');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should properly initialize when auth token is available', () => {
|
|
87
|
+
// This test verifies that the command registration doesn't fail when auth token is available
|
|
88
|
+
expect(() => {
|
|
89
|
+
registerImageCommands(program);
|
|
90
|
+
}).not.toThrow();
|
|
91
|
+
|
|
92
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
93
|
+
expect(imageCommand).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should handle the case when createApis function is called within command actions', () => {
|
|
97
|
+
registerImageCommands(program);
|
|
98
|
+
|
|
99
|
+
const imageCommand = program.commands.find(cmd => cmd.name() === 'image');
|
|
100
|
+
const listCommand = imageCommand?.commands.find(cmd => cmd.name() === 'list');
|
|
101
|
+
|
|
102
|
+
// Verify that the action function exists and is callable
|
|
103
|
+
expect(listCommand?.action).toBeDefined();
|
|
104
|
+
expect(typeof listCommand?.action).toBe('function');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
package/test/mocks.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
// Mock external dependencies that are commonly used across all test files
|
|
4
|
+
export const setupCommonMocks = () => {
|
|
5
|
+
// Mock utils/error
|
|
6
|
+
vi.mock('../src/utils/error', () => ({
|
|
7
|
+
withTokenRefresh: vi.fn(),
|
|
8
|
+
handle401Error: vi.fn()
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
// Mock utils/auth
|
|
12
|
+
vi.mock('../src/utils/auth', () => ({
|
|
13
|
+
getAuthToken: vi.fn().mockReturnValue({
|
|
14
|
+
token: 'mock-token',
|
|
15
|
+
serverUrl: 'http://localhost:3000'
|
|
16
|
+
}),
|
|
17
|
+
listCredentials: vi.fn(),
|
|
18
|
+
removeCredentials: vi.fn()
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
// Mock @nestbox-ai/admin
|
|
22
|
+
vi.mock('@nestbox-ai/admin', () => ({
|
|
23
|
+
Configuration: vi.fn(),
|
|
24
|
+
AuthApi: vi.fn(),
|
|
25
|
+
ProjectsApi: vi.fn(),
|
|
26
|
+
MachineAgentApi: vi.fn(),
|
|
27
|
+
MachineInstancesApi: vi.fn(),
|
|
28
|
+
MiscellaneousApi: vi.fn(),
|
|
29
|
+
DocumentsApi: vi.fn(),
|
|
30
|
+
OAuthLoginRequestDTOTypeEnum: {}
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
// Mock utils/project
|
|
34
|
+
vi.mock('../src/utils/project', () => ({
|
|
35
|
+
resolveProject: vi.fn()
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
// Mock utils/agent
|
|
39
|
+
vi.mock('../src/utils/agent', () => ({
|
|
40
|
+
createNestboxConfig: vi.fn(),
|
|
41
|
+
createZipFromDirectory: vi.fn(),
|
|
42
|
+
extractZip: vi.fn(),
|
|
43
|
+
findProjectRoot: vi.fn(),
|
|
44
|
+
isTypeScriptProject: vi.fn(),
|
|
45
|
+
loadNestboxConfig: vi.fn(),
|
|
46
|
+
runPredeployScripts: vi.fn()
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
// Mock utils/user
|
|
50
|
+
vi.mock('../src/utils/user', () => ({
|
|
51
|
+
userData: vi.fn()
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
// Mock chalk
|
|
55
|
+
vi.mock('chalk', () => ({
|
|
56
|
+
default: {
|
|
57
|
+
green: vi.fn((text) => text),
|
|
58
|
+
red: vi.fn((text) => text),
|
|
59
|
+
yellow: vi.fn((text) => text),
|
|
60
|
+
blue: vi.fn((text) => text)
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
// Mock ora
|
|
65
|
+
vi.mock('ora', () => ({
|
|
66
|
+
default: vi.fn(() => ({
|
|
67
|
+
start: vi.fn().mockReturnThis(),
|
|
68
|
+
succeed: vi.fn().mockReturnThis(),
|
|
69
|
+
fail: vi.fn().mockReturnThis(),
|
|
70
|
+
text: ''
|
|
71
|
+
}))
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
// Mock cli-table3
|
|
75
|
+
vi.mock('cli-table3', () => ({
|
|
76
|
+
default: vi.fn()
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
// Mock inquirer
|
|
80
|
+
vi.mock('inquirer', () => ({
|
|
81
|
+
default: {
|
|
82
|
+
prompt: vi.fn()
|
|
83
|
+
}
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
// Mock fs
|
|
87
|
+
vi.mock('fs', () => ({
|
|
88
|
+
default: {
|
|
89
|
+
existsSync: vi.fn(),
|
|
90
|
+
readFileSync: vi.fn(),
|
|
91
|
+
writeFileSync: vi.fn()
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
// Mock yaml
|
|
96
|
+
vi.mock('yaml', () => ({
|
|
97
|
+
default: {
|
|
98
|
+
load: vi.fn()
|
|
99
|
+
}
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
// Mock axios
|
|
103
|
+
vi.mock('axios', () => ({
|
|
104
|
+
default: {
|
|
105
|
+
get: vi.fn(),
|
|
106
|
+
post: vi.fn()
|
|
107
|
+
}
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
// Mock open
|
|
111
|
+
vi.mock('open', () => ({
|
|
112
|
+
default: vi.fn()
|
|
113
|
+
}));
|
|
114
|
+
|
|
115
|
+
// Mock path
|
|
116
|
+
vi.mock('path', () => ({
|
|
117
|
+
default: {
|
|
118
|
+
join: vi.fn(),
|
|
119
|
+
resolve: vi.fn()
|
|
120
|
+
}
|
|
121
|
+
}));
|
|
122
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { registerProjectCommands } from '../src/commands/projects';
|
|
4
|
+
|
|
5
|
+
describe('Project Commands', () => {
|
|
6
|
+
let program: Command;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
program = new Command();
|
|
10
|
+
vi.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
describe('registerProjectCommands', () => {
|
|
14
|
+
it('should register project command group', () => {
|
|
15
|
+
registerProjectCommands(program);
|
|
16
|
+
|
|
17
|
+
const commands = program.commands;
|
|
18
|
+
const projectCommand = commands.find(cmd => cmd.name() === 'project');
|
|
19
|
+
|
|
20
|
+
expect(projectCommand).toBeDefined();
|
|
21
|
+
expect(projectCommand?.description()).toBe('Manage Nestbox projects');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should register project use subcommand', () => {
|
|
25
|
+
registerProjectCommands(program);
|
|
26
|
+
|
|
27
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
28
|
+
const subCommands = projectCommand?.commands || [];
|
|
29
|
+
const useCommand = subCommands.find(cmd => cmd.name() === 'use');
|
|
30
|
+
|
|
31
|
+
expect(useCommand).toBeDefined();
|
|
32
|
+
expect(useCommand?.description()).toBe('Set default project for all commands');
|
|
33
|
+
|
|
34
|
+
// The command uses a required argument <project-name> which is part of the command definition
|
|
35
|
+
expect(useCommand?.name()).toBe('use');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should register project add subcommand', () => {
|
|
39
|
+
registerProjectCommands(program);
|
|
40
|
+
|
|
41
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
42
|
+
const subCommands = projectCommand?.commands || [];
|
|
43
|
+
const addCommand = subCommands.find(cmd => cmd.name() === 'add');
|
|
44
|
+
|
|
45
|
+
expect(addCommand).toBeDefined();
|
|
46
|
+
expect(addCommand?.description()).toBe('Add a project with optional alias');
|
|
47
|
+
|
|
48
|
+
// The command uses required and optional arguments which are part of the command definition
|
|
49
|
+
expect(addCommand?.name()).toBe('add');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should register project list subcommand', () => {
|
|
53
|
+
registerProjectCommands(program);
|
|
54
|
+
|
|
55
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
56
|
+
const subCommands = projectCommand?.commands || [];
|
|
57
|
+
const listCommand = subCommands.find(cmd => cmd.name() === 'list');
|
|
58
|
+
|
|
59
|
+
expect(listCommand).toBeDefined();
|
|
60
|
+
expect(listCommand?.description()).toBe('List all projects');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should have all expected project subcommands', () => {
|
|
64
|
+
registerProjectCommands(program);
|
|
65
|
+
|
|
66
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
67
|
+
const subCommandNames = projectCommand?.commands.map(cmd => cmd.name()) || [];
|
|
68
|
+
|
|
69
|
+
expect(subCommandNames).toContain('use');
|
|
70
|
+
expect(subCommandNames).toContain('add');
|
|
71
|
+
expect(subCommandNames).toContain('list');
|
|
72
|
+
expect(subCommandNames).toHaveLength(3);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should have proper action functions for all commands', () => {
|
|
76
|
+
registerProjectCommands(program);
|
|
77
|
+
|
|
78
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
79
|
+
const subCommands = projectCommand?.commands || [];
|
|
80
|
+
|
|
81
|
+
subCommands.forEach(cmd => {
|
|
82
|
+
expect(typeof cmd.action).toBe('function');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should register project use command with correct structure', () => {
|
|
87
|
+
registerProjectCommands(program);
|
|
88
|
+
|
|
89
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
90
|
+
const useCommand = projectCommand?.commands.find(cmd => cmd.name() === 'use');
|
|
91
|
+
|
|
92
|
+
expect(useCommand?.name()).toBe('use');
|
|
93
|
+
expect(useCommand?.description()).toBe('Set default project for all commands');
|
|
94
|
+
expect(typeof useCommand?.action).toBe('function');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should register project add command with correct structure', () => {
|
|
98
|
+
registerProjectCommands(program);
|
|
99
|
+
|
|
100
|
+
const projectCommand = program.commands.find(cmd => cmd.name() === 'project');
|
|
101
|
+
const addCommand = projectCommand?.commands.find(cmd => cmd.name() === 'add');
|
|
102
|
+
|
|
103
|
+
expect(addCommand?.name()).toBe('add');
|
|
104
|
+
expect(addCommand?.description()).toBe('Add a project with optional alias');
|
|
105
|
+
expect(typeof addCommand?.action).toBe('function');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|