@mbc-cqrs-serverless/cli 0.1.69-beta.0 → 0.1.71-beta.0
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/dist/actions/generate.action.spec.js +160 -0
- package/dist/actions/start.action.spec.js +62 -0
- package/dist/actions/ui.action.spec.js +151 -0
- package/dist/runners/abstract.runner.spec.js +170 -0
- package/dist/runners/schematic.runner.spec.js +151 -0
- package/dist/schematics/schematic.option.spec.js +127 -0
- package/dist/ui/logger.spec.js +149 -0
- package/dist/utils/formatting.spec.js +110 -0
- package/dist/utils/local-binaries.spec.js +128 -0
- package/package.json +2 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const generate_action_1 = __importDefault(require("./generate.action"));
|
|
7
|
+
describe('Generate Action', () => {
|
|
8
|
+
const mockCommand = {
|
|
9
|
+
name: () => 'generate',
|
|
10
|
+
opts: () => ({
|
|
11
|
+
dryRun: false,
|
|
12
|
+
mode: 'async',
|
|
13
|
+
schema: true
|
|
14
|
+
})
|
|
15
|
+
};
|
|
16
|
+
const mockOptions = {
|
|
17
|
+
dryRun: false,
|
|
18
|
+
mode: 'async',
|
|
19
|
+
schema: true
|
|
20
|
+
};
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
describe('Overview: Schematic generation functionality', () => {
|
|
25
|
+
describe('Purpose: Test basic generate action execution', () => {
|
|
26
|
+
it('should execute generate action without errors', async () => {
|
|
27
|
+
await expect((0, generate_action_1.default)('service', 'test-service', mockOptions, mockCommand)).resolves.not.toThrow();
|
|
28
|
+
});
|
|
29
|
+
it('should handle different schematic types', async () => {
|
|
30
|
+
const schematicTypes = ['service', 'controller', 'entity', 'dto', 'module'];
|
|
31
|
+
for (const type of schematicTypes) {
|
|
32
|
+
await expect((0, generate_action_1.default)(type, `test-${type}`, mockOptions, mockCommand)).resolves.not.toThrow();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
it('should handle generate action with custom command options', async () => {
|
|
36
|
+
const customCommand = {
|
|
37
|
+
...mockCommand,
|
|
38
|
+
opts: () => ({
|
|
39
|
+
dryRun: true,
|
|
40
|
+
mode: 'sync',
|
|
41
|
+
schema: false
|
|
42
|
+
})
|
|
43
|
+
};
|
|
44
|
+
await expect((0, generate_action_1.default)('service', 'custom-service', mockOptions, customCommand)).resolves.not.toThrow();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('Purpose: Test dry-run functionality', () => {
|
|
48
|
+
it('should execute dry-run without making actual changes', async () => {
|
|
49
|
+
const dryRunCommand = {
|
|
50
|
+
...mockCommand,
|
|
51
|
+
opts: () => ({
|
|
52
|
+
dryRun: true,
|
|
53
|
+
mode: 'async',
|
|
54
|
+
schema: true
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
await expect((0, generate_action_1.default)('service', 'test-service', mockOptions, dryRunCommand)).resolves.not.toThrow();
|
|
58
|
+
});
|
|
59
|
+
it('should handle dry-run with different modes', async () => {
|
|
60
|
+
const syncDryRunCommand = {
|
|
61
|
+
...mockCommand,
|
|
62
|
+
opts: () => ({
|
|
63
|
+
dryRun: true,
|
|
64
|
+
mode: 'sync',
|
|
65
|
+
schema: false
|
|
66
|
+
})
|
|
67
|
+
};
|
|
68
|
+
await expect((0, generate_action_1.default)('controller', 'test-controller', mockOptions, syncDryRunCommand)).resolves.not.toThrow();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('Purpose: Test error handling scenarios', () => {
|
|
72
|
+
it('should handle missing schematic name', async () => {
|
|
73
|
+
await expect((0, generate_action_1.default)('service', '', mockOptions, mockCommand)).resolves.not.toThrow();
|
|
74
|
+
});
|
|
75
|
+
it('should handle undefined schematic name', async () => {
|
|
76
|
+
await expect((0, generate_action_1.default)('service', undefined, mockOptions, mockCommand)).resolves.not.toThrow();
|
|
77
|
+
});
|
|
78
|
+
it('should handle invalid schematic type', async () => {
|
|
79
|
+
await expect((0, generate_action_1.default)('invalid-type', 'test-name', mockOptions, mockCommand)).resolves.not.toThrow();
|
|
80
|
+
});
|
|
81
|
+
it('should handle undefined command', async () => {
|
|
82
|
+
await expect((0, generate_action_1.default)('service', 'test-service', mockOptions, undefined)).rejects.toThrow();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('Purpose: Test mode and schema options', () => {
|
|
86
|
+
it('should handle async mode with schema', async () => {
|
|
87
|
+
const asyncCommand = {
|
|
88
|
+
...mockCommand,
|
|
89
|
+
opts: () => ({
|
|
90
|
+
dryRun: false,
|
|
91
|
+
mode: 'async',
|
|
92
|
+
schema: true
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
await expect((0, generate_action_1.default)('service', 'async-service', mockOptions, asyncCommand)).resolves.not.toThrow();
|
|
96
|
+
});
|
|
97
|
+
it('should handle sync mode without schema', async () => {
|
|
98
|
+
const syncCommand = {
|
|
99
|
+
...mockCommand,
|
|
100
|
+
opts: () => ({
|
|
101
|
+
dryRun: false,
|
|
102
|
+
mode: 'sync',
|
|
103
|
+
schema: false
|
|
104
|
+
})
|
|
105
|
+
};
|
|
106
|
+
await expect((0, generate_action_1.default)('entity', 'sync-entity', mockOptions, syncCommand)).resolves.not.toThrow();
|
|
107
|
+
});
|
|
108
|
+
it('should handle noSchema option', async () => {
|
|
109
|
+
const noSchemaCommand = {
|
|
110
|
+
...mockCommand,
|
|
111
|
+
opts: () => ({
|
|
112
|
+
dryRun: false,
|
|
113
|
+
mode: 'async',
|
|
114
|
+
noSchema: true
|
|
115
|
+
})
|
|
116
|
+
};
|
|
117
|
+
await expect((0, generate_action_1.default)('dto', 'no-schema-dto', mockOptions, noSchemaCommand)).resolves.not.toThrow();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('Purpose: Test special characters and edge cases', () => {
|
|
121
|
+
it('should handle special characters in schematic names', async () => {
|
|
122
|
+
await expect((0, generate_action_1.default)('service', 'test-service_with-special.chars', mockOptions, mockCommand)).resolves.not.toThrow();
|
|
123
|
+
});
|
|
124
|
+
it('should handle very long schematic names', async () => {
|
|
125
|
+
const longName = 'very-long-schematic-name-that-exceeds-normal-length-limits';
|
|
126
|
+
await expect((0, generate_action_1.default)('service', longName, mockOptions, mockCommand)).resolves.not.toThrow();
|
|
127
|
+
});
|
|
128
|
+
it('should handle numeric schematic names', async () => {
|
|
129
|
+
await expect((0, generate_action_1.default)('service', '123-numeric-service', mockOptions, mockCommand)).resolves.not.toThrow();
|
|
130
|
+
});
|
|
131
|
+
it('should handle empty command options', async () => {
|
|
132
|
+
const emptyCommand = {
|
|
133
|
+
...mockCommand,
|
|
134
|
+
opts: () => ({})
|
|
135
|
+
};
|
|
136
|
+
await expect((0, generate_action_1.default)('service', 'test-service', mockOptions, emptyCommand)).resolves.not.toThrow();
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe('Purpose: Test concurrent generation scenarios', () => {
|
|
140
|
+
it('should handle multiple concurrent generation requests', async () => {
|
|
141
|
+
const promises = [
|
|
142
|
+
(0, generate_action_1.default)('service', 'service1', mockOptions, mockCommand),
|
|
143
|
+
(0, generate_action_1.default)('controller', 'controller1', mockOptions, mockCommand),
|
|
144
|
+
(0, generate_action_1.default)('entity', 'entity1', mockOptions, mockCommand)
|
|
145
|
+
];
|
|
146
|
+
await expect(Promise.all(promises)).resolves.not.toThrow();
|
|
147
|
+
});
|
|
148
|
+
it('should maintain consistency across multiple calls', async () => {
|
|
149
|
+
const results = await Promise.all([
|
|
150
|
+
(0, generate_action_1.default)('service', 'test-service', mockOptions, mockCommand),
|
|
151
|
+
(0, generate_action_1.default)('service', 'test-service', mockOptions, mockCommand),
|
|
152
|
+
(0, generate_action_1.default)('service', 'test-service', mockOptions, mockCommand)
|
|
153
|
+
]);
|
|
154
|
+
results.forEach(result => {
|
|
155
|
+
expect(result).toBeUndefined();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const start_action_1 = __importDefault(require("./start.action"));
|
|
7
|
+
describe('Start Action', () => {
|
|
8
|
+
describe('Overview: Application start functionality', () => {
|
|
9
|
+
describe('Purpose: Test basic start action execution', () => {
|
|
10
|
+
it('should execute start action without errors', async () => {
|
|
11
|
+
await expect((0, start_action_1.default)()).resolves.not.toThrow();
|
|
12
|
+
});
|
|
13
|
+
it('should handle start action consistently', async () => {
|
|
14
|
+
const result = await (0, start_action_1.default)();
|
|
15
|
+
expect(result).toBeUndefined();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe('Purpose: Test start action behavior consistency', () => {
|
|
19
|
+
it('should maintain consistent behavior across multiple calls', async () => {
|
|
20
|
+
const results = await Promise.all([
|
|
21
|
+
(0, start_action_1.default)(),
|
|
22
|
+
(0, start_action_1.default)(),
|
|
23
|
+
(0, start_action_1.default)()
|
|
24
|
+
]);
|
|
25
|
+
results.forEach(result => {
|
|
26
|
+
expect(result).toBeUndefined();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('should handle concurrent start action calls', async () => {
|
|
30
|
+
const promises = Array(5).fill(null).map(() => (0, start_action_1.default)());
|
|
31
|
+
await expect(Promise.all(promises)).resolves.not.toThrow();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('Purpose: Test start action error scenarios', () => {
|
|
35
|
+
it('should handle unexpected errors gracefully', async () => {
|
|
36
|
+
const originalConsoleError = console.error;
|
|
37
|
+
console.error = jest.fn();
|
|
38
|
+
try {
|
|
39
|
+
await (0, start_action_1.default)();
|
|
40
|
+
expect(console.error).not.toHaveBeenCalled();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
console.error = originalConsoleError;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
it('should handle multiple rapid calls', async () => {
|
|
47
|
+
for (let i = 0; i < 10; i++) {
|
|
48
|
+
await expect((0, start_action_1.default)()).resolves.not.toThrow();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
it('should handle start action in different execution contexts', async () => {
|
|
52
|
+
await expect((0, start_action_1.default)()).resolves.not.toThrow();
|
|
53
|
+
setTimeout(async () => {
|
|
54
|
+
await expect((0, start_action_1.default)()).resolves.not.toThrow();
|
|
55
|
+
}, 0);
|
|
56
|
+
setImmediate(async () => {
|
|
57
|
+
await expect((0, start_action_1.default)()).resolves.not.toThrow();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ui_action_1 = __importDefault(require("./ui.action"));
|
|
7
|
+
jest.mock('child_process');
|
|
8
|
+
jest.mock('fs');
|
|
9
|
+
jest.mock('path');
|
|
10
|
+
describe('UI Action', () => {
|
|
11
|
+
const mockCommand = {
|
|
12
|
+
name: () => 'ui-common',
|
|
13
|
+
opts: () => ({})
|
|
14
|
+
};
|
|
15
|
+
const mockOptions = {
|
|
16
|
+
pathDir: './src/common',
|
|
17
|
+
branch: 'main',
|
|
18
|
+
auth: 'SSH',
|
|
19
|
+
component: 'all',
|
|
20
|
+
alias: false,
|
|
21
|
+
token: undefined
|
|
22
|
+
};
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
jest.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
describe('Overview: UI common component installation functionality', () => {
|
|
27
|
+
describe('Purpose: Test basic UI action execution', () => {
|
|
28
|
+
it('should execute UI action without errors', async () => {
|
|
29
|
+
await expect((0, ui_action_1.default)(mockOptions, mockCommand)).resolves.not.toThrow();
|
|
30
|
+
});
|
|
31
|
+
it('should handle UI action with different command names', async () => {
|
|
32
|
+
const customCommand = { ...mockCommand, name: () => 'ui' };
|
|
33
|
+
await expect((0, ui_action_1.default)(mockOptions, customCommand)).resolves.not.toThrow();
|
|
34
|
+
});
|
|
35
|
+
it('should handle UI action with custom options', async () => {
|
|
36
|
+
const customOptions = {
|
|
37
|
+
...mockOptions,
|
|
38
|
+
component: 'appsync',
|
|
39
|
+
branch: 'develop'
|
|
40
|
+
};
|
|
41
|
+
await expect((0, ui_action_1.default)(customOptions, mockCommand)).resolves.not.toThrow();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('Purpose: Test error handling scenarios', () => {
|
|
45
|
+
it('should handle invalid component option', async () => {
|
|
46
|
+
const invalidComponentOptions = {
|
|
47
|
+
...mockOptions,
|
|
48
|
+
component: 'invalid-component'
|
|
49
|
+
};
|
|
50
|
+
await expect((0, ui_action_1.default)(invalidComponentOptions, mockCommand)).resolves.not.toThrow();
|
|
51
|
+
});
|
|
52
|
+
it('should handle missing options', async () => {
|
|
53
|
+
await expect((0, ui_action_1.default)({}, mockCommand)).resolves.not.toThrow();
|
|
54
|
+
});
|
|
55
|
+
it('should handle undefined command', async () => {
|
|
56
|
+
await expect((0, ui_action_1.default)(mockOptions, undefined)).rejects.toThrow();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('Purpose: Test authentication options', () => {
|
|
60
|
+
it('should handle HTTPS authentication', async () => {
|
|
61
|
+
const httpsOptions = {
|
|
62
|
+
...mockOptions,
|
|
63
|
+
auth: 'HTTPS',
|
|
64
|
+
token: 'user:token123'
|
|
65
|
+
};
|
|
66
|
+
await expect((0, ui_action_1.default)(httpsOptions, mockCommand)).resolves.not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
it('should handle SSH authentication', async () => {
|
|
69
|
+
const sshOptions = {
|
|
70
|
+
...mockOptions,
|
|
71
|
+
auth: 'SSH'
|
|
72
|
+
};
|
|
73
|
+
await expect((0, ui_action_1.default)(sshOptions, mockCommand)).resolves.not.toThrow();
|
|
74
|
+
});
|
|
75
|
+
it('should handle HTTPS - Token authentication', async () => {
|
|
76
|
+
const httpsTokenOptions = {
|
|
77
|
+
...mockOptions,
|
|
78
|
+
auth: 'HTTPS - Token',
|
|
79
|
+
token: 'user:token123'
|
|
80
|
+
};
|
|
81
|
+
await expect((0, ui_action_1.default)(httpsTokenOptions, mockCommand)).resolves.not.toThrow();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('Purpose: Test component installation options', () => {
|
|
85
|
+
it('should handle all components installation', async () => {
|
|
86
|
+
const allOptions = {
|
|
87
|
+
...mockOptions,
|
|
88
|
+
component: 'all'
|
|
89
|
+
};
|
|
90
|
+
await expect((0, ui_action_1.default)(allOptions, mockCommand)).resolves.not.toThrow();
|
|
91
|
+
});
|
|
92
|
+
it('should handle specific component installation', async () => {
|
|
93
|
+
const componentOptions = {
|
|
94
|
+
...mockOptions,
|
|
95
|
+
component: 'component'
|
|
96
|
+
};
|
|
97
|
+
await expect((0, ui_action_1.default)(componentOptions, mockCommand)).resolves.not.toThrow();
|
|
98
|
+
});
|
|
99
|
+
it('should handle appsync component installation', async () => {
|
|
100
|
+
const appsyncOptions = {
|
|
101
|
+
...mockOptions,
|
|
102
|
+
component: 'appsync'
|
|
103
|
+
};
|
|
104
|
+
await expect((0, ui_action_1.default)(appsyncOptions, mockCommand)).resolves.not.toThrow();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('Purpose: Test branch and path handling', () => {
|
|
108
|
+
it('should handle custom branch', async () => {
|
|
109
|
+
const customBranchOptions = {
|
|
110
|
+
...mockOptions,
|
|
111
|
+
branch: 'develop'
|
|
112
|
+
};
|
|
113
|
+
await expect((0, ui_action_1.default)(customBranchOptions, mockCommand)).resolves.not.toThrow();
|
|
114
|
+
});
|
|
115
|
+
it('should handle custom path directory', async () => {
|
|
116
|
+
const customPathOptions = {
|
|
117
|
+
...mockOptions,
|
|
118
|
+
pathDir: './custom/path'
|
|
119
|
+
};
|
|
120
|
+
await expect((0, ui_action_1.default)(customPathOptions, mockCommand)).resolves.not.toThrow();
|
|
121
|
+
});
|
|
122
|
+
it('should handle alias option', async () => {
|
|
123
|
+
const aliasOptions = {
|
|
124
|
+
...mockOptions,
|
|
125
|
+
alias: true
|
|
126
|
+
};
|
|
127
|
+
await expect((0, ui_action_1.default)(aliasOptions, mockCommand)).resolves.not.toThrow();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('Purpose: Test concurrent execution scenarios', () => {
|
|
131
|
+
it('should handle multiple concurrent UI action calls', async () => {
|
|
132
|
+
const promises = [
|
|
133
|
+
(0, ui_action_1.default)(mockOptions, mockCommand),
|
|
134
|
+
(0, ui_action_1.default)(mockOptions, mockCommand),
|
|
135
|
+
(0, ui_action_1.default)(mockOptions, mockCommand)
|
|
136
|
+
];
|
|
137
|
+
await expect(Promise.all(promises)).resolves.not.toThrow();
|
|
138
|
+
});
|
|
139
|
+
it('should maintain consistency across multiple calls', async () => {
|
|
140
|
+
const results = await Promise.all([
|
|
141
|
+
(0, ui_action_1.default)(mockOptions, mockCommand),
|
|
142
|
+
(0, ui_action_1.default)(mockOptions, mockCommand),
|
|
143
|
+
(0, ui_action_1.default)(mockOptions, mockCommand)
|
|
144
|
+
]);
|
|
145
|
+
results.forEach(result => {
|
|
146
|
+
expect(result).toBeUndefined();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const child_process_1 = require("child_process");
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
const abstract_runner_1 = require("./abstract.runner");
|
|
6
|
+
jest.mock('child_process');
|
|
7
|
+
describe('Abstract Runner', () => {
|
|
8
|
+
const mockSpawn = child_process_1.spawn;
|
|
9
|
+
let mockChildProcess;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
jest.clearAllMocks();
|
|
12
|
+
mockChildProcess = new events_1.EventEmitter();
|
|
13
|
+
mockChildProcess.stdout = new events_1.EventEmitter();
|
|
14
|
+
mockChildProcess.stderr = new events_1.EventEmitter();
|
|
15
|
+
mockSpawn.mockReturnValue(mockChildProcess);
|
|
16
|
+
});
|
|
17
|
+
describe('Overview: Base runner functionality for command execution', () => {
|
|
18
|
+
describe('Purpose: Test successful command execution', () => {
|
|
19
|
+
it('should execute command successfully with default options', async () => {
|
|
20
|
+
const runner = new abstract_runner_1.AbstractRunner('npm', ['--version']);
|
|
21
|
+
const runPromise = runner.run('install');
|
|
22
|
+
setTimeout(() => {
|
|
23
|
+
mockChildProcess.emit('close', 0);
|
|
24
|
+
}, 10);
|
|
25
|
+
await expect(runPromise).resolves.toBeNull();
|
|
26
|
+
expect(mockSpawn).toHaveBeenCalledWith('npm', ['--version', 'install'], expect.any(Object));
|
|
27
|
+
});
|
|
28
|
+
it('should execute command with custom arguments', async () => {
|
|
29
|
+
const runner = new abstract_runner_1.AbstractRunner('node', ['-v']);
|
|
30
|
+
const runPromise = runner.run('--help');
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
mockChildProcess.emit('close', 0);
|
|
33
|
+
}, 10);
|
|
34
|
+
await expect(runPromise).resolves.toBeNull();
|
|
35
|
+
expect(mockSpawn).toHaveBeenCalledWith('node', ['-v', '--help'], expect.any(Object));
|
|
36
|
+
});
|
|
37
|
+
it('should collect output when collectResult is true', async () => {
|
|
38
|
+
const runner = new abstract_runner_1.AbstractRunner('echo', ['hello']);
|
|
39
|
+
const runPromise = runner.run('world', true);
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
mockChildProcess.stdout.emit('data', Buffer.from('hello\n'));
|
|
42
|
+
}, 10);
|
|
43
|
+
const result = await runPromise;
|
|
44
|
+
expect(result).toBe('hello');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('Purpose: Test error handling scenarios', () => {
|
|
48
|
+
it('should handle command execution failure', async () => {
|
|
49
|
+
const runner = new abstract_runner_1.AbstractRunner('invalid-command', []);
|
|
50
|
+
const runPromise = runner.run('test');
|
|
51
|
+
setTimeout(() => {
|
|
52
|
+
mockChildProcess.emit('close', 1);
|
|
53
|
+
}, 10);
|
|
54
|
+
await expect(runPromise).rejects.toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
it('should handle spawn errors', async () => {
|
|
57
|
+
const runner = new abstract_runner_1.AbstractRunner('invalid-command', []);
|
|
58
|
+
const runPromise = runner.run('test');
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
mockChildProcess.emit('close', 1);
|
|
61
|
+
}, 10);
|
|
62
|
+
await expect(runPromise).rejects.toBeUndefined();
|
|
63
|
+
});
|
|
64
|
+
it('should handle stderr output as error', async () => {
|
|
65
|
+
const runner = new abstract_runner_1.AbstractRunner('test-command', []);
|
|
66
|
+
const runPromise = runner.run('test');
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
mockChildProcess.emit('close', 1);
|
|
69
|
+
}, 10);
|
|
70
|
+
await expect(runPromise).rejects.toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('Purpose: Test command string generation', () => {
|
|
74
|
+
it('should generate correct command string with binary and arguments', () => {
|
|
75
|
+
const runner = new abstract_runner_1.AbstractRunner('npm', ['install', '--save']);
|
|
76
|
+
const commandString = runner.rawFullCommand('test');
|
|
77
|
+
expect(commandString).toBe('npm install --save test');
|
|
78
|
+
});
|
|
79
|
+
it('should generate command string with empty arguments', () => {
|
|
80
|
+
const runner = new abstract_runner_1.AbstractRunner('node', []);
|
|
81
|
+
const commandString = runner.rawFullCommand('test');
|
|
82
|
+
expect(commandString).toBe('node test');
|
|
83
|
+
});
|
|
84
|
+
it('should handle arguments with spaces', () => {
|
|
85
|
+
const runner = new abstract_runner_1.AbstractRunner('echo', ['hello world', 'test']);
|
|
86
|
+
const commandString = runner.rawFullCommand('command');
|
|
87
|
+
expect(commandString).toBe('echo hello world test command');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('Purpose: Test output collection functionality', () => {
|
|
91
|
+
it('should collect stdout when collectResult is enabled', async () => {
|
|
92
|
+
const runner = new abstract_runner_1.AbstractRunner('cat', ['file.txt']);
|
|
93
|
+
const runPromise = runner.run('test', true);
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
mockChildProcess.stdout.emit('data', Buffer.from('line 1\n'));
|
|
96
|
+
}, 10);
|
|
97
|
+
const result = await runPromise;
|
|
98
|
+
expect(result).toBe('line 1');
|
|
99
|
+
});
|
|
100
|
+
it('should not collect output when collectResult is false', async () => {
|
|
101
|
+
const runner = new abstract_runner_1.AbstractRunner('echo', ['test']);
|
|
102
|
+
const runPromise = runner.run('command', false);
|
|
103
|
+
setTimeout(() => {
|
|
104
|
+
mockChildProcess.emit('close', 0);
|
|
105
|
+
}, 10);
|
|
106
|
+
const result = await runPromise;
|
|
107
|
+
expect(result).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
it('should handle empty stdout output', async () => {
|
|
110
|
+
const runner = new abstract_runner_1.AbstractRunner('true', []);
|
|
111
|
+
const runPromise = runner.run('test', false);
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
mockChildProcess.emit('close', 0);
|
|
114
|
+
}, 10);
|
|
115
|
+
const result = await runPromise;
|
|
116
|
+
expect(result).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('Purpose: Test edge cases and error scenarios', () => {
|
|
120
|
+
it('should handle process exit with signal', async () => {
|
|
121
|
+
const runner = new abstract_runner_1.AbstractRunner('test-command', []);
|
|
122
|
+
const runPromise = runner.run('test');
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
mockChildProcess.emit('close', null, 'SIGTERM');
|
|
125
|
+
}, 10);
|
|
126
|
+
await expect(runPromise).rejects.toBeUndefined();
|
|
127
|
+
});
|
|
128
|
+
it('should handle multiple stderr chunks', async () => {
|
|
129
|
+
const runner = new abstract_runner_1.AbstractRunner('test-command', []);
|
|
130
|
+
const runPromise = runner.run('test');
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
mockChildProcess.emit('close', 1);
|
|
133
|
+
}, 10);
|
|
134
|
+
await expect(runPromise).rejects.toBeUndefined();
|
|
135
|
+
});
|
|
136
|
+
it('should handle very long command arguments', async () => {
|
|
137
|
+
const longArgs = Array(100).fill('very-long-argument-name');
|
|
138
|
+
const runner = new abstract_runner_1.AbstractRunner('test-command', longArgs);
|
|
139
|
+
const commandString = runner.rawFullCommand('test');
|
|
140
|
+
expect(commandString).toContain('test-command');
|
|
141
|
+
expect(commandString.split(' ')).toHaveLength(102);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe('Purpose: Test concurrent execution scenarios', () => {
|
|
145
|
+
it('should handle multiple runner instances', async () => {
|
|
146
|
+
const runner1 = new abstract_runner_1.AbstractRunner('echo', ['test1']);
|
|
147
|
+
const runner2 = new abstract_runner_1.AbstractRunner('echo', ['test2']);
|
|
148
|
+
const promise1 = runner1.run('command1');
|
|
149
|
+
const promise2 = runner2.run('command2');
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
mockChildProcess.emit('close', 0);
|
|
152
|
+
}, 10);
|
|
153
|
+
const results = await Promise.all([promise1, promise2]);
|
|
154
|
+
expect(results).toEqual([null, null]);
|
|
155
|
+
});
|
|
156
|
+
it('should handle rapid successive runs', async () => {
|
|
157
|
+
const runner = new abstract_runner_1.AbstractRunner('echo', ['test']);
|
|
158
|
+
const promises = Array(5).fill(null).map((_, i) => {
|
|
159
|
+
const promise = runner.run(`command${i}`);
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
mockChildProcess.emit('close', 0);
|
|
162
|
+
}, 10 + i);
|
|
163
|
+
return promise;
|
|
164
|
+
});
|
|
165
|
+
const results = await Promise.all(promises);
|
|
166
|
+
expect(results).toEqual([null, null, null, null, null]);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const schematic_runner_1 = require("./schematic.runner");
|
|
4
|
+
const abstract_runner_1 = require("./abstract.runner");
|
|
5
|
+
jest.mock('./abstract.runner');
|
|
6
|
+
describe('Schematic Runner', () => {
|
|
7
|
+
const mockAbstractRunner = abstract_runner_1.AbstractRunner;
|
|
8
|
+
const mockRunnerInstance = {
|
|
9
|
+
run: jest.fn(),
|
|
10
|
+
rawFullCommand: jest.fn()
|
|
11
|
+
};
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
mockAbstractRunner.mockImplementation(() => mockRunnerInstance);
|
|
15
|
+
});
|
|
16
|
+
describe('Overview: Schematic execution runner functionality', () => {
|
|
17
|
+
describe('Purpose: Test basic schematic runner initialization', () => {
|
|
18
|
+
it('should create schematic runner without errors', () => {
|
|
19
|
+
expect(() => new schematic_runner_1.SchematicRunner()).not.toThrow();
|
|
20
|
+
});
|
|
21
|
+
it('should create schematic runner with default settings', () => {
|
|
22
|
+
expect(() => new schematic_runner_1.SchematicRunner()).not.toThrow();
|
|
23
|
+
});
|
|
24
|
+
it('should initialize AbstractRunner with correct binary path', () => {
|
|
25
|
+
new schematic_runner_1.SchematicRunner();
|
|
26
|
+
expect(mockAbstractRunner).toHaveBeenCalledWith('node', expect.arrayContaining([expect.stringContaining('schematics.js')]));
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('Purpose: Test schematic command execution', () => {
|
|
30
|
+
it('should execute schematic command successfully', async () => {
|
|
31
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
32
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
33
|
+
await runner.run('@mbc-cqrs-serverless/cli:service --name=test-service');
|
|
34
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith('@mbc-cqrs-serverless/cli:service --name=test-service');
|
|
35
|
+
});
|
|
36
|
+
it('should handle complex schematic commands with multiple options', async () => {
|
|
37
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
38
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
39
|
+
const command = '@mbc-cqrs-serverless/cli:service --name=test-service --mode=async --schema --dry-run';
|
|
40
|
+
await runner.run(command);
|
|
41
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith(command);
|
|
42
|
+
});
|
|
43
|
+
it('should handle schematic commands with quoted arguments', async () => {
|
|
44
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
45
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
46
|
+
const command = '@mbc-cqrs-serverless/cli:service --name="test service" --description="A test service"';
|
|
47
|
+
await runner.run(command);
|
|
48
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith(command);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('Purpose: Test error handling scenarios', () => {
|
|
52
|
+
it('should handle schematic execution failure', async () => {
|
|
53
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
54
|
+
mockRunnerInstance.run.mockRejectedValue(new Error('Schematic execution failed'));
|
|
55
|
+
await expect(runner.run('@mbc-cqrs-serverless/cli:service --name=test'))
|
|
56
|
+
.rejects.toThrow('Schematic execution failed');
|
|
57
|
+
});
|
|
58
|
+
it('should handle empty command string', async () => {
|
|
59
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
60
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
61
|
+
await runner.run('');
|
|
62
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith('');
|
|
63
|
+
});
|
|
64
|
+
it('should handle undefined command', async () => {
|
|
65
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
66
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
67
|
+
await runner.run(undefined);
|
|
68
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith(undefined);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('Purpose: Test collection name handling', () => {
|
|
72
|
+
it('should use node binary with schematics path', () => {
|
|
73
|
+
new schematic_runner_1.SchematicRunner();
|
|
74
|
+
expect(mockAbstractRunner).toHaveBeenCalledWith('node', expect.arrayContaining([expect.stringContaining('schematics.js')]));
|
|
75
|
+
});
|
|
76
|
+
it('should initialize with node binary and schematics path', () => {
|
|
77
|
+
new schematic_runner_1.SchematicRunner();
|
|
78
|
+
expect(mockAbstractRunner).toHaveBeenCalledWith('node', expect.arrayContaining([expect.stringContaining('schematics.js')]));
|
|
79
|
+
});
|
|
80
|
+
it('should handle binary path resolution', () => {
|
|
81
|
+
new schematic_runner_1.SchematicRunner();
|
|
82
|
+
expect(mockAbstractRunner).toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('Purpose: Test binary path resolution', () => {
|
|
86
|
+
it('should resolve schematics binary path correctly', () => {
|
|
87
|
+
new schematic_runner_1.SchematicRunner();
|
|
88
|
+
const binaryPath = mockAbstractRunner.mock.calls[0][0];
|
|
89
|
+
expect(binaryPath).toBe('node');
|
|
90
|
+
const args = mockAbstractRunner.mock.calls[0][1];
|
|
91
|
+
expect(args[0]).toContain('schematics.js');
|
|
92
|
+
});
|
|
93
|
+
it('should handle different working directories', () => {
|
|
94
|
+
const originalCwd = process.cwd;
|
|
95
|
+
process.cwd = jest.fn().mockReturnValue('/custom/working/directory');
|
|
96
|
+
new schematic_runner_1.SchematicRunner();
|
|
97
|
+
expect(mockAbstractRunner).toHaveBeenCalled();
|
|
98
|
+
process.cwd = originalCwd;
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('Purpose: Test command parsing and formatting', () => {
|
|
102
|
+
it('should handle command string correctly', async () => {
|
|
103
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
104
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
105
|
+
await runner.run('collection:schematic --option1=value1 --option2 --option3=value3');
|
|
106
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith('collection:schematic --option1=value1 --option2 --option3=value3');
|
|
107
|
+
});
|
|
108
|
+
it('should handle commands with no options', async () => {
|
|
109
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
110
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
111
|
+
await runner.run('collection:schematic');
|
|
112
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith('collection:schematic');
|
|
113
|
+
});
|
|
114
|
+
it('should handle commands with special characters', async () => {
|
|
115
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
116
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
117
|
+
await runner.run('collection:schematic --name=test-service_v2.0');
|
|
118
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledWith('collection:schematic --name=test-service_v2.0');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe('Purpose: Test concurrent execution scenarios', () => {
|
|
122
|
+
it('should handle multiple concurrent schematic runs', async () => {
|
|
123
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
124
|
+
mockRunnerInstance.run.mockResolvedValue(undefined);
|
|
125
|
+
const promises = [
|
|
126
|
+
runner.run('@mbc-cqrs-serverless/cli:service --name=service1'),
|
|
127
|
+
runner.run('@mbc-cqrs-serverless/cli:controller --name=controller1'),
|
|
128
|
+
runner.run('@mbc-cqrs-serverless/cli:entity --name=entity1')
|
|
129
|
+
];
|
|
130
|
+
await Promise.all(promises);
|
|
131
|
+
expect(mockRunnerInstance.run).toHaveBeenCalledTimes(3);
|
|
132
|
+
});
|
|
133
|
+
it('should handle partial failure in concurrent runs', async () => {
|
|
134
|
+
const runner = new schematic_runner_1.SchematicRunner();
|
|
135
|
+
mockRunnerInstance.run
|
|
136
|
+
.mockResolvedValueOnce(undefined)
|
|
137
|
+
.mockRejectedValueOnce(new Error('Execution failed'))
|
|
138
|
+
.mockResolvedValueOnce(undefined);
|
|
139
|
+
const promises = [
|
|
140
|
+
runner.run('@mbc-cqrs-serverless/cli:service --name=service1'),
|
|
141
|
+
runner.run('@mbc-cqrs-serverless/cli:controller --name=controller1'),
|
|
142
|
+
runner.run('@mbc-cqrs-serverless/cli:entity --name=entity1')
|
|
143
|
+
];
|
|
144
|
+
const results = await Promise.allSettled(promises);
|
|
145
|
+
expect(results[0].status).toBe('fulfilled');
|
|
146
|
+
expect(results[1].status).toBe('rejected');
|
|
147
|
+
expect(results[2].status).toBe('fulfilled');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const schematic_option_1 = require("./schematic.option");
|
|
4
|
+
describe('Schematic Option', () => {
|
|
5
|
+
describe('Overview: Command option handling and formatting functionality', () => {
|
|
6
|
+
describe('Purpose: Test basic option creation and formatting', () => {
|
|
7
|
+
it('should create string option and format correctly', () => {
|
|
8
|
+
const option = new schematic_option_1.SchematicOption('name', 'test-service');
|
|
9
|
+
expect(option.toCommandString()).toBe('--name=test-service');
|
|
10
|
+
});
|
|
11
|
+
it('should create boolean option and format correctly', () => {
|
|
12
|
+
const option = new schematic_option_1.SchematicOption('dry-run', true);
|
|
13
|
+
expect(option.toCommandString()).toBe('--dry-run');
|
|
14
|
+
});
|
|
15
|
+
it('should create false boolean option and format correctly', () => {
|
|
16
|
+
const option = new schematic_option_1.SchematicOption('schema', false);
|
|
17
|
+
expect(option.toCommandString()).toBe('--no-schema');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('Purpose: Test name normalization functionality', () => {
|
|
21
|
+
it('should normalize camelCase names to kebab-case', () => {
|
|
22
|
+
const option = new schematic_option_1.SchematicOption('dryRun', true);
|
|
23
|
+
expect(option.normalizedName).toBe('dry-run');
|
|
24
|
+
expect(option.toCommandString()).toBe('--dry-run');
|
|
25
|
+
});
|
|
26
|
+
it('should normalize snake_case names correctly', () => {
|
|
27
|
+
const option = new schematic_option_1.SchematicOption('spec_file_suffix', 'spec');
|
|
28
|
+
expect(option.normalizedName).toBe('spec_file_suffix');
|
|
29
|
+
});
|
|
30
|
+
it('should handle already normalized names', () => {
|
|
31
|
+
const option = new schematic_option_1.SchematicOption('dry-run', true);
|
|
32
|
+
expect(option.normalizedName).toBe('dry-run');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('Purpose: Test special option handling', () => {
|
|
36
|
+
it('should handle name option with special formatting', () => {
|
|
37
|
+
const option = new schematic_option_1.SchematicOption('name', 'TestService');
|
|
38
|
+
expect(option.toCommandString()).toBe('--name=test-service');
|
|
39
|
+
});
|
|
40
|
+
it('should handle version option without quotes', () => {
|
|
41
|
+
const option = new schematic_option_1.SchematicOption('version', '1.0.0');
|
|
42
|
+
expect(option.toCommandString()).toBe('--version=1.0.0');
|
|
43
|
+
});
|
|
44
|
+
it('should handle path option without quotes', () => {
|
|
45
|
+
const option = new schematic_option_1.SchematicOption('path', './src/services');
|
|
46
|
+
expect(option.toCommandString()).toBe('--path=./src/services');
|
|
47
|
+
});
|
|
48
|
+
it('should handle other string options with quotes', () => {
|
|
49
|
+
const option = new schematic_option_1.SchematicOption('description', 'A test service');
|
|
50
|
+
expect(option.toCommandString()).toBe('--description="A test service"');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('Purpose: Test special character escaping', () => {
|
|
54
|
+
it('should escape parentheses in name values', () => {
|
|
55
|
+
const option = new schematic_option_1.SchematicOption('name', 'test(service)');
|
|
56
|
+
expect(option.toCommandString()).toBe('--name=test\\(service\\)');
|
|
57
|
+
});
|
|
58
|
+
it('should escape brackets in name values', () => {
|
|
59
|
+
const option = new schematic_option_1.SchematicOption('name', 'test[service]');
|
|
60
|
+
expect(option.toCommandString()).toBe('--name=test\\[service\\]');
|
|
61
|
+
});
|
|
62
|
+
it('should handle mixed special characters', () => {
|
|
63
|
+
const option = new schematic_option_1.SchematicOption('name', 'test(service)[v1]');
|
|
64
|
+
expect(option.toCommandString()).toBe('--name=test\\(service\\)\\[v1\\]');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('Purpose: Test edge cases and boundary conditions', () => {
|
|
68
|
+
it('should handle empty string values', () => {
|
|
69
|
+
const option = new schematic_option_1.SchematicOption('name', '');
|
|
70
|
+
expect(option.toCommandString()).toBe('--name=');
|
|
71
|
+
});
|
|
72
|
+
it('should handle numeric values', () => {
|
|
73
|
+
const option = new schematic_option_1.SchematicOption('port', 3000);
|
|
74
|
+
expect(option.toCommandString()).toBe('--port=3000');
|
|
75
|
+
});
|
|
76
|
+
it('should handle null values', () => {
|
|
77
|
+
const option = new schematic_option_1.SchematicOption('test', null);
|
|
78
|
+
expect(option.toCommandString()).toBe('--test=null');
|
|
79
|
+
});
|
|
80
|
+
it('should handle undefined values', () => {
|
|
81
|
+
const option = new schematic_option_1.SchematicOption('test', undefined);
|
|
82
|
+
expect(option.toCommandString()).toBe('--test=undefined');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('Purpose: Test complex option scenarios', () => {
|
|
86
|
+
it('should handle options with spaces in values', () => {
|
|
87
|
+
const option = new schematic_option_1.SchematicOption('description', 'A complex service description');
|
|
88
|
+
expect(option.toCommandString()).toBe('--description="A complex service description"');
|
|
89
|
+
});
|
|
90
|
+
it('should handle options with quotes in values', () => {
|
|
91
|
+
const option = new schematic_option_1.SchematicOption('description', 'A "quoted" description');
|
|
92
|
+
expect(option.toCommandString()).toBe('--description="A "quoted" description"');
|
|
93
|
+
});
|
|
94
|
+
it('should handle very long option names', () => {
|
|
95
|
+
const longName = 'veryLongOptionNameThatExceedsNormalLengthLimits';
|
|
96
|
+
const option = new schematic_option_1.SchematicOption(longName, 'value');
|
|
97
|
+
expect(option.normalizedName).toBe('very-long-option-name-that-exceeds-normal-length-limits');
|
|
98
|
+
});
|
|
99
|
+
it('should handle very long option values', () => {
|
|
100
|
+
const longValue = 'A'.repeat(1000);
|
|
101
|
+
const option = new schematic_option_1.SchematicOption('description', longValue);
|
|
102
|
+
expect(option.toCommandString()).toBe(`--description="${longValue}"`);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('Purpose: Test option type consistency', () => {
|
|
106
|
+
it('should maintain consistent formatting across multiple calls', () => {
|
|
107
|
+
const option = new schematic_option_1.SchematicOption('dry-run', true);
|
|
108
|
+
const result1 = option.toCommandString();
|
|
109
|
+
const result2 = option.toCommandString();
|
|
110
|
+
expect(result1).toBe(result2);
|
|
111
|
+
expect(result1).toBe('--dry-run');
|
|
112
|
+
});
|
|
113
|
+
it('should handle boolean toggle scenarios', () => {
|
|
114
|
+
const trueOption = new schematic_option_1.SchematicOption('feature', true);
|
|
115
|
+
const falseOption = new schematic_option_1.SchematicOption('feature', false);
|
|
116
|
+
expect(trueOption.toCommandString()).toBe('--feature');
|
|
117
|
+
expect(falseOption.toCommandString()).toBe('--no-feature');
|
|
118
|
+
});
|
|
119
|
+
it('should handle string vs boolean distinction', () => {
|
|
120
|
+
const stringOption = new schematic_option_1.SchematicOption('value', 'true');
|
|
121
|
+
const booleanOption = new schematic_option_1.SchematicOption('value', true);
|
|
122
|
+
expect(stringOption.toCommandString()).toBe('--value="true"');
|
|
123
|
+
expect(booleanOption.toCommandString()).toBe('--value');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const logger_1 = require("./logger");
|
|
4
|
+
describe('Logger Utilities', () => {
|
|
5
|
+
let originalConsole;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
originalConsole = { ...console };
|
|
8
|
+
console.info = jest.fn();
|
|
9
|
+
console.log = jest.fn();
|
|
10
|
+
console.error = jest.fn();
|
|
11
|
+
console.warn = jest.fn();
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
console.info = originalConsole.info;
|
|
15
|
+
console.log = originalConsole.log;
|
|
16
|
+
console.error = originalConsole.error;
|
|
17
|
+
console.warn = originalConsole.warn;
|
|
18
|
+
});
|
|
19
|
+
describe('Overview: CLI logging functionality', () => {
|
|
20
|
+
describe('Purpose: Test info logging methods', () => {
|
|
21
|
+
it('should log info messages with proper formatting', () => {
|
|
22
|
+
logger_1.logger.info('Test info message');
|
|
23
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Test info message'));
|
|
24
|
+
});
|
|
25
|
+
it('should handle multiple info messages', () => {
|
|
26
|
+
logger_1.logger.info('First message');
|
|
27
|
+
logger_1.logger.info('Second message');
|
|
28
|
+
expect(console.log).toHaveBeenCalledTimes(2);
|
|
29
|
+
expect(console.log).toHaveBeenNthCalledWith(1, expect.stringContaining('First message'));
|
|
30
|
+
expect(console.log).toHaveBeenNthCalledWith(2, expect.stringContaining('Second message'));
|
|
31
|
+
});
|
|
32
|
+
it('should handle empty info messages', () => {
|
|
33
|
+
logger_1.logger.info('');
|
|
34
|
+
expect(console.log).toHaveBeenCalledWith(expect.any(String));
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('Purpose: Test error logging methods', () => {
|
|
38
|
+
it('should log error messages with proper formatting', () => {
|
|
39
|
+
logger_1.logger.error('Test error message');
|
|
40
|
+
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Test error message'));
|
|
41
|
+
});
|
|
42
|
+
it('should handle error objects', () => {
|
|
43
|
+
const error = new Error('Test error');
|
|
44
|
+
logger_1.logger.error(error.message);
|
|
45
|
+
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Test error'));
|
|
46
|
+
});
|
|
47
|
+
it('should handle multiple error messages', () => {
|
|
48
|
+
logger_1.logger.error('First error');
|
|
49
|
+
logger_1.logger.error('Second error');
|
|
50
|
+
expect(console.error).toHaveBeenCalledTimes(2);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('Purpose: Test warning logging methods', () => {
|
|
54
|
+
it('should log warning messages with proper formatting', () => {
|
|
55
|
+
logger_1.logger.warn('Test warning message');
|
|
56
|
+
expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('Test warning message'));
|
|
57
|
+
});
|
|
58
|
+
it('should handle multiple warning messages', () => {
|
|
59
|
+
logger_1.logger.warn('First warning');
|
|
60
|
+
logger_1.logger.warn('Second warning');
|
|
61
|
+
expect(console.warn).toHaveBeenCalledTimes(2);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('Purpose: Test success and status logging methods', () => {
|
|
65
|
+
it('should log success messages with proper formatting', () => {
|
|
66
|
+
logger_1.logger.success('Operation completed successfully');
|
|
67
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Operation completed successfully'));
|
|
68
|
+
});
|
|
69
|
+
it('should log title messages with proper formatting', () => {
|
|
70
|
+
logger_1.logger.title('test', 'Processing...');
|
|
71
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Processing...'));
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('Purpose: Test message formatting and special characters', () => {
|
|
75
|
+
it('should handle messages with special characters', () => {
|
|
76
|
+
const specialMessage = 'Message with @#$%^&*() characters';
|
|
77
|
+
logger_1.logger.info(specialMessage);
|
|
78
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining(specialMessage));
|
|
79
|
+
});
|
|
80
|
+
it('should handle messages with newlines', () => {
|
|
81
|
+
const multilineMessage = 'Line 1\nLine 2\nLine 3';
|
|
82
|
+
logger_1.logger.info(multilineMessage);
|
|
83
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining(multilineMessage));
|
|
84
|
+
});
|
|
85
|
+
it('should handle very long messages', () => {
|
|
86
|
+
const longMessage = 'A'.repeat(1000);
|
|
87
|
+
logger_1.logger.info(longMessage);
|
|
88
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining(longMessage));
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('Purpose: Test logging with different data types', () => {
|
|
92
|
+
it('should handle string conversion of undefined messages', () => {
|
|
93
|
+
logger_1.logger.info(String(undefined));
|
|
94
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('undefined'));
|
|
95
|
+
});
|
|
96
|
+
it('should handle string conversion of null messages', () => {
|
|
97
|
+
logger_1.logger.info(String(null));
|
|
98
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('null'));
|
|
99
|
+
});
|
|
100
|
+
it('should handle string conversion of numeric messages', () => {
|
|
101
|
+
logger_1.logger.info(String(123));
|
|
102
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('123'));
|
|
103
|
+
});
|
|
104
|
+
it('should handle string conversion of boolean messages', () => {
|
|
105
|
+
logger_1.logger.info(String(true));
|
|
106
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('true'));
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('Purpose: Test concurrent logging scenarios', () => {
|
|
110
|
+
it('should handle multiple concurrent log calls', () => {
|
|
111
|
+
const promises = [
|
|
112
|
+
Promise.resolve(logger_1.logger.info('Concurrent message 1')),
|
|
113
|
+
Promise.resolve(logger_1.logger.error('Concurrent error 1')),
|
|
114
|
+
Promise.resolve(logger_1.logger.warn('Concurrent warning 1')),
|
|
115
|
+
Promise.resolve(logger_1.logger.success('Concurrent success 1'))
|
|
116
|
+
];
|
|
117
|
+
return Promise.all(promises).then(() => {
|
|
118
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Concurrent message 1'));
|
|
119
|
+
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Concurrent error 1'));
|
|
120
|
+
expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('Concurrent warning 1'));
|
|
121
|
+
expect(console.log).toHaveBeenCalledWith(expect.stringContaining('Concurrent success 1'));
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it('should maintain message order in rapid succession', () => {
|
|
125
|
+
logger_1.logger.info('Message 1');
|
|
126
|
+
logger_1.logger.info('Message 2');
|
|
127
|
+
logger_1.logger.info('Message 3');
|
|
128
|
+
expect(console.log).toHaveBeenCalledTimes(3);
|
|
129
|
+
expect(console.log).toHaveBeenNthCalledWith(1, expect.stringContaining('Message 1'));
|
|
130
|
+
expect(console.log).toHaveBeenNthCalledWith(2, expect.stringContaining('Message 2'));
|
|
131
|
+
expect(console.log).toHaveBeenNthCalledWith(3, expect.stringContaining('Message 3'));
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe('Purpose: Test error handling in logging methods', () => {
|
|
135
|
+
it('should handle console method failures gracefully', () => {
|
|
136
|
+
console.log = jest.fn().mockImplementation(() => {
|
|
137
|
+
throw new Error('Console error');
|
|
138
|
+
});
|
|
139
|
+
expect(() => logger_1.logger.info('Test message')).toThrow('Console error');
|
|
140
|
+
});
|
|
141
|
+
it('should handle console method unavailability', () => {
|
|
142
|
+
const originalLog = console.log;
|
|
143
|
+
delete console.log;
|
|
144
|
+
expect(() => logger_1.logger.info('Test message')).not.toThrow();
|
|
145
|
+
console.log = originalLog;
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const formatting_1 = require("./formatting");
|
|
4
|
+
describe('Formatting Utilities', () => {
|
|
5
|
+
describe('Overview: String normalization functionality', () => {
|
|
6
|
+
describe('Purpose: Test normalizeToKebabOrSnakeCase with various input formats', () => {
|
|
7
|
+
it('should convert camelCase to kebab-case', () => {
|
|
8
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('camelCaseString')).toBe('camel-case-string');
|
|
9
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('myTestVariable')).toBe('my-test-variable');
|
|
10
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('XMLHttpRequest')).toBe('xmlhttp-request');
|
|
11
|
+
});
|
|
12
|
+
it('should convert PascalCase to kebab-case', () => {
|
|
13
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('PascalCaseString')).toBe('pascal-case-string');
|
|
14
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('MyTestClass')).toBe('my-test-class');
|
|
15
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('HTTPSConnection')).toBe('httpsconnection');
|
|
16
|
+
});
|
|
17
|
+
it('should handle strings with spaces', () => {
|
|
18
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('string with spaces')).toBe('string-with-spaces');
|
|
19
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('Multiple spaces here')).toBe('multiple---spaces---here');
|
|
20
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)(' leading and trailing spaces ')).toBe('-leading-and-trailing-spaces-');
|
|
21
|
+
});
|
|
22
|
+
it('should handle strings with underscores', () => {
|
|
23
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('snake_case_string')).toBe('snake_case_string');
|
|
24
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('mixed_snake_camelCase')).toBe('mixed_snake_camel-case');
|
|
25
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('__double__underscores__')).toBe('__double__underscores__');
|
|
26
|
+
});
|
|
27
|
+
it('should handle already kebab-case strings', () => {
|
|
28
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('kebab-case-string')).toBe('kebab-case-string');
|
|
29
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('already-formatted')).toBe('already-formatted');
|
|
30
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('single')).toBe('single');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('Purpose: Test edge cases and special characters', () => {
|
|
34
|
+
it('should handle empty inputs', () => {
|
|
35
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('')).toBe('');
|
|
36
|
+
});
|
|
37
|
+
it('should handle null and undefined inputs with error', () => {
|
|
38
|
+
expect(() => (0, formatting_1.normalizeToKebabOrSnakeCase)(null)).toThrow();
|
|
39
|
+
expect(() => (0, formatting_1.normalizeToKebabOrSnakeCase)(undefined)).toThrow();
|
|
40
|
+
});
|
|
41
|
+
it('should handle numeric strings', () => {
|
|
42
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('123')).toBe('123');
|
|
43
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('version2')).toBe('version2');
|
|
44
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('test123Variable')).toBe('test123-variable');
|
|
45
|
+
});
|
|
46
|
+
it('should handle special characters', () => {
|
|
47
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('test@email.com')).toBe('test@email.com');
|
|
48
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('file.name.extension')).toBe('file.name.extension');
|
|
49
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('path/to/file')).toBe('path/to/file');
|
|
50
|
+
});
|
|
51
|
+
it('should handle mixed case with numbers', () => {
|
|
52
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('HTML5Parser')).toBe('html5-parser');
|
|
53
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('CSS3Styles')).toBe('css3-styles');
|
|
54
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('API2Client')).toBe('api2-client');
|
|
55
|
+
});
|
|
56
|
+
it('should handle consecutive uppercase letters', () => {
|
|
57
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('XMLParser')).toBe('xmlparser');
|
|
58
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('HTTPSRequest')).toBe('httpsrequest');
|
|
59
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('JSONData')).toBe('jsondata');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('Purpose: Test boundary conditions', () => {
|
|
63
|
+
it('should handle very long strings', () => {
|
|
64
|
+
const longString = 'thisIsAVeryLongCamelCaseStringThatShouldBeConvertedToKebabCase';
|
|
65
|
+
const expected = 'this-is-avery-long-camel-case-string-that-should-be-converted-to-kebab-case';
|
|
66
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)(longString)).toBe(expected);
|
|
67
|
+
});
|
|
68
|
+
it('should handle single character strings', () => {
|
|
69
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('a')).toBe('a');
|
|
70
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('A')).toBe('a');
|
|
71
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('1')).toBe('1');
|
|
72
|
+
});
|
|
73
|
+
it('should handle strings with only special characters', () => {
|
|
74
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('___')).toBe('___');
|
|
75
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('---')).toBe('---');
|
|
76
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)('...')).toBe('...');
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('Purpose: Test performance with various input sizes', () => {
|
|
80
|
+
it('should handle repeated transformations consistently', () => {
|
|
81
|
+
const input = 'testCamelCaseString';
|
|
82
|
+
const expected = 'test-camel-case-string';
|
|
83
|
+
for (let i = 0; i < 100; i++) {
|
|
84
|
+
expect((0, formatting_1.normalizeToKebabOrSnakeCase)(input)).toBe(expected);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
it('should handle array of different string formats', () => {
|
|
88
|
+
const inputs = [
|
|
89
|
+
'camelCase',
|
|
90
|
+
'PascalCase',
|
|
91
|
+
'snake_case',
|
|
92
|
+
'kebab-case',
|
|
93
|
+
'UPPERCASE',
|
|
94
|
+
'lowercase',
|
|
95
|
+
'Mixed_Format-String'
|
|
96
|
+
];
|
|
97
|
+
const results = inputs.map(input => (0, formatting_1.normalizeToKebabOrSnakeCase)(input));
|
|
98
|
+
expect(results).toEqual([
|
|
99
|
+
'camel-case',
|
|
100
|
+
'pascal-case',
|
|
101
|
+
'snake_case',
|
|
102
|
+
'kebab-case',
|
|
103
|
+
'uppercase',
|
|
104
|
+
'lowercase',
|
|
105
|
+
'mixed_format-string'
|
|
106
|
+
]);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs_1 = require("fs");
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const local_binaries_1 = require("./local-binaries");
|
|
6
|
+
jest.mock('fs');
|
|
7
|
+
jest.mock('path');
|
|
8
|
+
describe('Local Binaries Utilities', () => {
|
|
9
|
+
const mockExistsSync = fs_1.existsSync;
|
|
10
|
+
const mockJoin = path_1.join;
|
|
11
|
+
const mockPosixJoin = path_1.posix.join;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
mockJoin.mockImplementation((...args) => args.join('/'));
|
|
15
|
+
mockPosixJoin.mockImplementation((...args) => args.join('/'));
|
|
16
|
+
});
|
|
17
|
+
describe('Overview: Local binary detection and loading functionality', () => {
|
|
18
|
+
describe('Purpose: Test localBinExists function', () => {
|
|
19
|
+
it('should return true when local binary exists', () => {
|
|
20
|
+
mockExistsSync.mockReturnValue(true);
|
|
21
|
+
const result = (0, local_binaries_1.localBinExists)();
|
|
22
|
+
expect(result).toBe(true);
|
|
23
|
+
expect(mockExistsSync).toHaveBeenCalledWith(expect.stringContaining('node_modules/@mbc-cqrs-serverless/cli'));
|
|
24
|
+
});
|
|
25
|
+
it('should return false when local binary does not exist', () => {
|
|
26
|
+
mockExistsSync.mockReturnValue(false);
|
|
27
|
+
const result = (0, local_binaries_1.localBinExists)();
|
|
28
|
+
expect(result).toBe(false);
|
|
29
|
+
expect(mockExistsSync).toHaveBeenCalledWith(expect.stringContaining('node_modules/@mbc-cqrs-serverless/cli'));
|
|
30
|
+
});
|
|
31
|
+
it('should handle file system errors gracefully', () => {
|
|
32
|
+
mockExistsSync.mockImplementation(() => {
|
|
33
|
+
throw new Error('File system error');
|
|
34
|
+
});
|
|
35
|
+
expect(() => (0, local_binaries_1.localBinExists)()).toThrow('File system error');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('Purpose: Test loadLocalBinCommandLoader function', () => {
|
|
39
|
+
it('should successfully load command loader when binary exists', () => {
|
|
40
|
+
const mockCommandLoader = {
|
|
41
|
+
loadCommands: jest.fn(),
|
|
42
|
+
getCommand: jest.fn()
|
|
43
|
+
};
|
|
44
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => mockCommandLoader, { virtual: true });
|
|
45
|
+
const result = (0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
46
|
+
expect(result).toBeDefined();
|
|
47
|
+
expect(mockPosixJoin).toHaveBeenCalledWith(expect.any(String), 'node_modules', '@mbc-cqrs-serverless', 'cli', 'dist', 'commands');
|
|
48
|
+
});
|
|
49
|
+
it('should handle missing command loader module', () => {
|
|
50
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => {
|
|
51
|
+
throw new Error('Module not found');
|
|
52
|
+
}, { virtual: true });
|
|
53
|
+
expect(() => (0, local_binaries_1.loadLocalBinCommandLoader)()).not.toThrow();
|
|
54
|
+
});
|
|
55
|
+
it('should handle corrupted command loader module', () => {
|
|
56
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => null, { virtual: true });
|
|
57
|
+
const result = (0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
58
|
+
expect(result).toBeDefined();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('Purpose: Test path construction and resolution', () => {
|
|
62
|
+
it('should construct correct path segments for binary detection', () => {
|
|
63
|
+
mockExistsSync.mockReturnValue(true);
|
|
64
|
+
(0, local_binaries_1.localBinExists)();
|
|
65
|
+
expect(mockJoin).toHaveBeenCalledWith(process.cwd(), 'node_modules', '@mbc-cqrs-serverless', 'cli');
|
|
66
|
+
});
|
|
67
|
+
it('should construct correct posix path for command loader', () => {
|
|
68
|
+
const mockCommandLoader = {};
|
|
69
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => mockCommandLoader, { virtual: true });
|
|
70
|
+
(0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
71
|
+
expect(mockPosixJoin).toHaveBeenCalledWith(expect.any(String), 'node_modules', '@mbc-cqrs-serverless', 'cli', 'dist', 'commands');
|
|
72
|
+
});
|
|
73
|
+
it('should handle different working directories', () => {
|
|
74
|
+
const originalCwd = process.cwd;
|
|
75
|
+
process.cwd = jest.fn().mockReturnValue('/custom/working/directory');
|
|
76
|
+
mockExistsSync.mockReturnValue(true);
|
|
77
|
+
(0, local_binaries_1.localBinExists)();
|
|
78
|
+
expect(mockJoin).toHaveBeenCalledWith(expect.any(String), 'node_modules', '@mbc-cqrs-serverless', 'cli');
|
|
79
|
+
process.cwd = originalCwd;
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('Purpose: Test error scenarios and edge cases', () => {
|
|
83
|
+
it('should handle permission denied errors', () => {
|
|
84
|
+
mockExistsSync.mockImplementation(() => {
|
|
85
|
+
throw new Error('EACCES: permission denied');
|
|
86
|
+
});
|
|
87
|
+
expect(() => (0, local_binaries_1.localBinExists)()).toThrow('EACCES: permission denied');
|
|
88
|
+
});
|
|
89
|
+
it('should handle network drive or symlink issues', () => {
|
|
90
|
+
mockExistsSync.mockImplementation(() => {
|
|
91
|
+
throw new Error('ENOTDIR: not a directory');
|
|
92
|
+
});
|
|
93
|
+
expect(() => (0, local_binaries_1.localBinExists)()).toThrow('ENOTDIR: not a directory');
|
|
94
|
+
});
|
|
95
|
+
it('should handle require cache issues in command loader', () => {
|
|
96
|
+
const mockCommandLoader = { cached: true };
|
|
97
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => mockCommandLoader, { virtual: true });
|
|
98
|
+
const result1 = (0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
99
|
+
const result2 = (0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
100
|
+
expect(result1).toBe(result2);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('Purpose: Test integration scenarios', () => {
|
|
104
|
+
it('should work correctly when binary exists and command loader is available', () => {
|
|
105
|
+
mockExistsSync.mockReturnValue(true);
|
|
106
|
+
const mockCommandLoader = {
|
|
107
|
+
loadCommands: jest.fn(),
|
|
108
|
+
getCommand: jest.fn()
|
|
109
|
+
};
|
|
110
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => mockCommandLoader, { virtual: true });
|
|
111
|
+
const binaryExists = (0, local_binaries_1.localBinExists)();
|
|
112
|
+
const commandLoader = (0, local_binaries_1.loadLocalBinCommandLoader)();
|
|
113
|
+
expect(binaryExists).toBe(true);
|
|
114
|
+
expect(commandLoader).toBeDefined();
|
|
115
|
+
expect(typeof commandLoader).toBe('object');
|
|
116
|
+
});
|
|
117
|
+
it('should handle scenario where binary exists but command loader fails', () => {
|
|
118
|
+
mockExistsSync.mockReturnValue(true);
|
|
119
|
+
jest.doMock('node_modules/@mbc-cqrs-serverless/cli/dist/commands', () => {
|
|
120
|
+
throw new Error('Command loader initialization failed');
|
|
121
|
+
}, { virtual: true });
|
|
122
|
+
const binaryExists = (0, local_binaries_1.localBinExists)();
|
|
123
|
+
expect(binaryExists).toBe(true);
|
|
124
|
+
expect(() => (0, local_binaries_1.loadLocalBinCommandLoader)()).not.toThrow();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mbc-cqrs-serverless/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.71-beta.0",
|
|
4
4
|
"description": "a CLI to get started with MBC CQRS serverless framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mbc",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"@faker-js/faker": "^8.3.1",
|
|
59
59
|
"copyfiles": "^2.4.1"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "1af676f97241bb111fc56b8435e29e9b2c62e105"
|
|
62
62
|
}
|