@nestbox-ai/cli 1.0.18 → 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.
@@ -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
+ });
package/test/setup.ts ADDED
@@ -0,0 +1,121 @@
1
+ import { vi } from 'vitest';
2
+
3
+ // Mock external dependencies that are commonly used across all test files
4
+
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
+ }));
package/tsconfig.json CHANGED
@@ -112,5 +112,7 @@
112
112
  "declaration": true,
113
113
  "sourceMap": true,
114
114
  "resolveJsonModule": true
115
- }
115
+ },
116
+ "include": ["src/**/*"],
117
+ "exclude": ["node_modules", "dist", "test", "**/*.test.ts", "**/*.spec.ts", "vitest.config.ts"]
116
118
  }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_1 = require("vitest/config");
4
+ exports.default = (0, config_1.defineConfig)({
5
+ test: {
6
+ environment: 'node',
7
+ globals: true,
8
+ setupFiles: ['./test/setup.ts'],
9
+ coverage: {
10
+ provider: 'v8',
11
+ reporter: ['text', 'json', 'html'],
12
+ exclude: [
13
+ 'node_modules/',
14
+ 'dist/',
15
+ 'templates/',
16
+ 'test/',
17
+ '**/*.test.ts',
18
+ '**/*.spec.ts'
19
+ ]
20
+ }
21
+ }
22
+ });
23
+ //# sourceMappingURL=vitest.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.config.js","sourceRoot":"","sources":["vitest.config.ts"],"names":[],"mappings":";;AAAA,0CAA4C;AAE5C,kBAAe,IAAA,qBAAY,EAAC;IAC1B,IAAI,EAAE;QACJ,WAAW,EAAE,MAAM;QACnB,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,CAAC,iBAAiB,CAAC;QAC/B,QAAQ,EAAE;YACR,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAClC,OAAO,EAAE;gBACP,eAAe;gBACf,OAAO;gBACP,YAAY;gBACZ,OAAO;gBACP,cAAc;gBACd,cAAc;aACf;SACF;KACF;CACF,CAAC,CAAA"}
@@ -0,0 +1,21 @@
1
+ import { defineConfig } from 'vitest/config'
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: 'node',
6
+ globals: true,
7
+ setupFiles: ['./test/setup.ts'],
8
+ coverage: {
9
+ provider: 'v8',
10
+ reporter: ['text', 'json', 'html'],
11
+ exclude: [
12
+ 'node_modules/',
13
+ 'dist/',
14
+ 'templates/',
15
+ 'test/',
16
+ '**/*.test.ts',
17
+ '**/*.spec.ts'
18
+ ]
19
+ }
20
+ }
21
+ })