@agents-at-scale/ark 0.1.53 → 0.1.55
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/commands/export/index.js +6 -4
- package/dist/commands/generate/generators/agent.js +2 -0
- package/dist/commands/generate/generators/marketplace.js +2 -0
- package/dist/commands/generate/generators/mcpserver.js +2 -0
- package/dist/commands/generate/generators/project.js +9 -2
- package/dist/commands/generate/generators/query.js +2 -0
- package/dist/commands/generate/generators/team.js +2 -0
- package/dist/commands/generate/templateDiscovery.js +1 -0
- package/dist/commands/generate/templateEngine.js +1 -3
- package/dist/commands/import/index.js +1 -1
- package/dist/commands/install/index.js +2 -1
- package/dist/commands/models/kubernetes/manifest-builder.js +27 -10
- package/dist/commands/models/providers/azure.d.ts +10 -7
- package/dist/commands/models/providers/azure.js +83 -21
- package/dist/commands/uninstall/index.js +1 -1
- package/dist/components/ChatUI.js +17 -16
- package/dist/components/statusChecker.js +3 -3
- package/dist/lib/arkApiClient.js +11 -9
- package/dist/lib/arkApiProxy.js +1 -0
- package/dist/lib/arkServiceProxy.js +5 -1
- package/dist/lib/chatClient.js +9 -0
- package/dist/lib/config.js +8 -3
- package/dist/lib/errors.js +3 -0
- package/dist/ui/asyncOperations/connectingToArk.js +2 -2
- package/package.json +16 -12
- package/dist/arkServices.spec.d.ts +0 -1
- package/dist/arkServices.spec.js +0 -138
- package/dist/commands/agents/index.spec.d.ts +0 -1
- package/dist/commands/agents/index.spec.js +0 -67
- package/dist/commands/cluster/get.spec.d.ts +0 -1
- package/dist/commands/cluster/get.spec.js +0 -92
- package/dist/commands/cluster/index.spec.d.ts +0 -1
- package/dist/commands/cluster/index.spec.js +0 -24
- package/dist/commands/completion/index.spec.d.ts +0 -1
- package/dist/commands/completion/index.spec.js +0 -34
- package/dist/commands/config/index.spec.d.ts +0 -1
- package/dist/commands/config/index.spec.js +0 -78
- package/dist/commands/evaluation/index.spec.d.ts +0 -1
- package/dist/commands/evaluation/index.spec.js +0 -161
- package/dist/commands/export/index.spec.d.ts +0 -1
- package/dist/commands/export/index.spec.js +0 -145
- package/dist/commands/import/index.spec.d.ts +0 -1
- package/dist/commands/import/index.spec.js +0 -46
- package/dist/commands/install/index.spec.d.ts +0 -1
- package/dist/commands/install/index.spec.js +0 -286
- package/dist/commands/marketplace/index.spec.d.ts +0 -1
- package/dist/commands/marketplace/index.spec.js +0 -88
- package/dist/commands/memory/index.spec.d.ts +0 -1
- package/dist/commands/memory/index.spec.js +0 -124
- package/dist/commands/models/create.spec.d.ts +0 -1
- package/dist/commands/models/create.spec.js +0 -167
- package/dist/commands/models/index.spec.d.ts +0 -1
- package/dist/commands/models/index.spec.js +0 -96
- package/dist/commands/models/providers/azure.spec.d.ts +0 -1
- package/dist/commands/models/providers/azure.spec.js +0 -232
- package/dist/commands/models/providers/bedrock.spec.d.ts +0 -1
- package/dist/commands/models/providers/bedrock.spec.js +0 -241
- package/dist/commands/models/providers/openai.spec.d.ts +0 -1
- package/dist/commands/models/providers/openai.spec.js +0 -180
- package/dist/commands/queries/delete.spec.d.ts +0 -1
- package/dist/commands/queries/delete.spec.js +0 -74
- package/dist/commands/queries/index.spec.d.ts +0 -1
- package/dist/commands/queries/index.spec.js +0 -167
- package/dist/commands/queries/list.spec.d.ts +0 -1
- package/dist/commands/queries/list.spec.js +0 -170
- package/dist/commands/queries/validation.spec.d.ts +0 -1
- package/dist/commands/queries/validation.spec.js +0 -27
- package/dist/commands/query/index.spec.d.ts +0 -1
- package/dist/commands/query/index.spec.js +0 -104
- package/dist/commands/targets/index.spec.d.ts +0 -1
- package/dist/commands/targets/index.spec.js +0 -154
- package/dist/commands/teams/index.spec.d.ts +0 -1
- package/dist/commands/teams/index.spec.js +0 -70
- package/dist/commands/tools/index.spec.d.ts +0 -1
- package/dist/commands/tools/index.spec.js +0 -70
- package/dist/commands/uninstall/index.spec.d.ts +0 -1
- package/dist/commands/uninstall/index.spec.js +0 -125
- package/dist/lib/arkServiceProxy.spec.d.ts +0 -1
- package/dist/lib/arkServiceProxy.spec.js +0 -100
- package/dist/lib/arkStatus.spec.d.ts +0 -1
- package/dist/lib/arkStatus.spec.js +0 -49
- package/dist/lib/chatClient.spec.d.ts +0 -1
- package/dist/lib/chatClient.spec.js +0 -108
- package/dist/lib/cluster.spec.d.ts +0 -1
- package/dist/lib/cluster.spec.js +0 -338
- package/dist/lib/commands.spec.d.ts +0 -1
- package/dist/lib/commands.spec.js +0 -146
- package/dist/lib/config.spec.d.ts +0 -1
- package/dist/lib/config.spec.js +0 -202
- package/dist/lib/duration.spec.d.ts +0 -1
- package/dist/lib/duration.spec.js +0 -13
- package/dist/lib/errors.spec.d.ts +0 -1
- package/dist/lib/errors.spec.js +0 -221
- package/dist/lib/executeQuery.spec.d.ts +0 -1
- package/dist/lib/executeQuery.spec.js +0 -325
- package/dist/lib/kubectl.spec.d.ts +0 -1
- package/dist/lib/kubectl.spec.js +0 -192
- package/dist/lib/marketplaceFetcher.spec.d.ts +0 -1
- package/dist/lib/marketplaceFetcher.spec.js +0 -225
- package/dist/lib/nextSteps.spec.d.ts +0 -1
- package/dist/lib/nextSteps.spec.js +0 -59
- package/dist/lib/output.spec.d.ts +0 -1
- package/dist/lib/output.spec.js +0 -123
- package/dist/lib/startup.spec.d.ts +0 -1
- package/dist/lib/startup.spec.js +0 -152
- package/dist/lib/stdin.spec.d.ts +0 -1
- package/dist/lib/stdin.spec.js +0 -82
- package/dist/lib/timeout.spec.d.ts +0 -1
- package/dist/lib/timeout.spec.js +0 -14
- package/dist/lib/waitForReady.spec.d.ts +0 -1
- package/dist/lib/waitForReady.spec.js +0 -104
- package/dist/marketplaceServices.spec.d.ts +0 -1
- package/dist/marketplaceServices.spec.js +0 -74
- package/dist/ui/statusFormatter.spec.d.ts +0 -1
- package/dist/ui/statusFormatter.spec.js +0 -58
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import output from '../../lib/output.js';
|
|
3
|
-
const mockExeca = jest.fn();
|
|
4
|
-
jest.unstable_mockModule('execa', () => ({
|
|
5
|
-
execa: mockExeca,
|
|
6
|
-
}));
|
|
7
|
-
const { createQueriesCommand } = await import('./index.js');
|
|
8
|
-
const { deleteQuery, BOTH_NAME_AND_ALL_ERROR, MISSING_NAME_OR_ALL_ERROR } = await import('./delete.js');
|
|
9
|
-
describe('queries delete command', () => {
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
jest.clearAllMocks();
|
|
12
|
-
console.log = jest.fn();
|
|
13
|
-
jest.spyOn(output, 'warning').mockImplementation(() => { });
|
|
14
|
-
jest.spyOn(output, 'error').mockImplementation(() => { });
|
|
15
|
-
jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
16
|
-
});
|
|
17
|
-
it('should delete a query by name', async () => {
|
|
18
|
-
mockExeca.mockResolvedValue({
|
|
19
|
-
stdout: '',
|
|
20
|
-
});
|
|
21
|
-
const command = createQueriesCommand({});
|
|
22
|
-
await command.parseAsync(['node', 'test', 'delete', 'query-1']);
|
|
23
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', 'query-1'], { stdio: 'pipe' });
|
|
24
|
-
expect(output.warning).not.toHaveBeenCalled();
|
|
25
|
-
expect(process.exit).not.toHaveBeenCalled();
|
|
26
|
-
});
|
|
27
|
-
it('should delete all queries with --all flag', async () => {
|
|
28
|
-
mockExeca.mockResolvedValue({
|
|
29
|
-
stdout: '',
|
|
30
|
-
});
|
|
31
|
-
const command = createQueriesCommand({});
|
|
32
|
-
await command.parseAsync(['node', 'test', 'delete', '--all']);
|
|
33
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', '--all'], { stdio: 'pipe' });
|
|
34
|
-
expect(output.warning).not.toHaveBeenCalled();
|
|
35
|
-
expect(process.exit).not.toHaveBeenCalled();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe('deleteQuery function', () => {
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
jest.clearAllMocks();
|
|
41
|
-
jest.spyOn(output, 'error').mockImplementation(() => { });
|
|
42
|
-
jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
43
|
-
});
|
|
44
|
-
it('should throw error when neither name nor --all flag is provided', async () => {
|
|
45
|
-
await deleteQuery(undefined, {});
|
|
46
|
-
expect(output.error).toHaveBeenCalledWith(expect.anything(), expect.stringMatching(MISSING_NAME_OR_ALL_ERROR));
|
|
47
|
-
expect(process.exit).toHaveBeenCalledWith(1);
|
|
48
|
-
});
|
|
49
|
-
it('should throw error when both name and --all flag are provided', async () => {
|
|
50
|
-
await deleteQuery('my-query', { all: true });
|
|
51
|
-
expect(output.error).toHaveBeenCalledWith(expect.anything(), expect.stringMatching(BOTH_NAME_AND_ALL_ERROR));
|
|
52
|
-
expect(process.exit).toHaveBeenCalledWith(1);
|
|
53
|
-
});
|
|
54
|
-
it('should handle deletion errors gracefully', async () => {
|
|
55
|
-
mockExeca.mockRejectedValue(new Error('query not found'));
|
|
56
|
-
await deleteQuery('nonexistent-query', {});
|
|
57
|
-
expect(output.error).toHaveBeenCalledWith('deleting query:', 'query not found');
|
|
58
|
-
expect(process.exit).toHaveBeenCalledWith(1);
|
|
59
|
-
});
|
|
60
|
-
it('should call deleteResource with query name', async () => {
|
|
61
|
-
mockExeca.mockResolvedValue({
|
|
62
|
-
stdout: '',
|
|
63
|
-
});
|
|
64
|
-
await deleteQuery('my-query', {});
|
|
65
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', 'my-query'], { stdio: 'pipe' });
|
|
66
|
-
});
|
|
67
|
-
it('should delete all queries when all option is true', async () => {
|
|
68
|
-
mockExeca.mockResolvedValue({
|
|
69
|
-
stdout: '',
|
|
70
|
-
});
|
|
71
|
-
await deleteQuery(undefined, { all: true });
|
|
72
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', '--all'], { stdio: 'pipe' });
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import output from '../../lib/output.js';
|
|
3
|
-
const mockExeca = jest.fn();
|
|
4
|
-
jest.unstable_mockModule('execa', () => ({
|
|
5
|
-
execa: mockExeca,
|
|
6
|
-
}));
|
|
7
|
-
const { createQueriesCommand } = await import('./index.js');
|
|
8
|
-
describe('queries get command', () => {
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
jest.clearAllMocks();
|
|
11
|
-
console.log = jest.fn();
|
|
12
|
-
jest.spyOn(output, 'warning').mockImplementation(() => { });
|
|
13
|
-
jest.spyOn(output, 'error').mockImplementation(() => { });
|
|
14
|
-
jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
15
|
-
});
|
|
16
|
-
it('should get query with response in JSON format', async () => {
|
|
17
|
-
const mockQuery = {
|
|
18
|
-
metadata: {
|
|
19
|
-
name: 'test-query',
|
|
20
|
-
},
|
|
21
|
-
spec: {
|
|
22
|
-
input: 'test input',
|
|
23
|
-
target: { type: 'agent', name: 'test-agent' },
|
|
24
|
-
},
|
|
25
|
-
status: {
|
|
26
|
-
phase: 'done',
|
|
27
|
-
response: {
|
|
28
|
-
content: 'This is the response',
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
mockExeca.mockResolvedValue({
|
|
33
|
-
stdout: JSON.stringify(mockQuery),
|
|
34
|
-
});
|
|
35
|
-
const command = createQueriesCommand({});
|
|
36
|
-
await command.parseAsync(['node', 'test', 'get', 'test-query']);
|
|
37
|
-
expect(console.log).toHaveBeenCalledWith(JSON.stringify(mockQuery, null, 2));
|
|
38
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', 'test-query', '-o', 'json'], { stdio: 'pipe' });
|
|
39
|
-
});
|
|
40
|
-
it('should get query with response flag in JSON format', async () => {
|
|
41
|
-
const mockQuery = {
|
|
42
|
-
metadata: {
|
|
43
|
-
name: 'test-query',
|
|
44
|
-
},
|
|
45
|
-
spec: {
|
|
46
|
-
input: 'test input',
|
|
47
|
-
target: { type: 'agent', name: 'test-agent' },
|
|
48
|
-
},
|
|
49
|
-
status: {
|
|
50
|
-
phase: 'done',
|
|
51
|
-
response: {
|
|
52
|
-
content: 'This is the response content',
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
mockExeca.mockResolvedValue({
|
|
57
|
-
stdout: JSON.stringify(mockQuery),
|
|
58
|
-
});
|
|
59
|
-
const command = createQueriesCommand({});
|
|
60
|
-
await command.parseAsync([
|
|
61
|
-
'node',
|
|
62
|
-
'test',
|
|
63
|
-
'get',
|
|
64
|
-
'test-query',
|
|
65
|
-
'--response',
|
|
66
|
-
]);
|
|
67
|
-
expect(console.log).toHaveBeenCalledWith(JSON.stringify(mockQuery.status.response, null, 2));
|
|
68
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', 'test-query', '-o', 'json'], { stdio: 'pipe' });
|
|
69
|
-
});
|
|
70
|
-
it('should get query with response flag in markdown format', async () => {
|
|
71
|
-
const mockQuery = {
|
|
72
|
-
metadata: {
|
|
73
|
-
name: 'test-query',
|
|
74
|
-
},
|
|
75
|
-
spec: {
|
|
76
|
-
input: 'test input',
|
|
77
|
-
target: { type: 'agent', name: 'test-agent' },
|
|
78
|
-
},
|
|
79
|
-
status: {
|
|
80
|
-
phase: 'done',
|
|
81
|
-
response: {
|
|
82
|
-
content: '# Heading\n\nThis is markdown content',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
mockExeca.mockResolvedValue({
|
|
87
|
-
stdout: JSON.stringify(mockQuery),
|
|
88
|
-
});
|
|
89
|
-
const command = createQueriesCommand({});
|
|
90
|
-
await command.parseAsync([
|
|
91
|
-
'node',
|
|
92
|
-
'test',
|
|
93
|
-
'get',
|
|
94
|
-
'test-query',
|
|
95
|
-
'--response',
|
|
96
|
-
'--output',
|
|
97
|
-
'markdown',
|
|
98
|
-
]);
|
|
99
|
-
expect(console.log).toHaveBeenCalled();
|
|
100
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', 'test-query', '-o', 'json'], { stdio: 'pipe' });
|
|
101
|
-
});
|
|
102
|
-
it('should get query in markdown format without response flag', async () => {
|
|
103
|
-
const mockQuery = {
|
|
104
|
-
metadata: {
|
|
105
|
-
name: 'test-query',
|
|
106
|
-
},
|
|
107
|
-
spec: {
|
|
108
|
-
input: 'test input',
|
|
109
|
-
target: { type: 'agent', name: 'test-agent' },
|
|
110
|
-
},
|
|
111
|
-
status: {
|
|
112
|
-
phase: 'done',
|
|
113
|
-
response: {
|
|
114
|
-
content: '# Response\n\nMarkdown response',
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
mockExeca.mockResolvedValue({
|
|
119
|
-
stdout: JSON.stringify(mockQuery),
|
|
120
|
-
});
|
|
121
|
-
const command = createQueriesCommand({});
|
|
122
|
-
await command.parseAsync([
|
|
123
|
-
'node',
|
|
124
|
-
'test',
|
|
125
|
-
'get',
|
|
126
|
-
'test-query',
|
|
127
|
-
'--output',
|
|
128
|
-
'markdown',
|
|
129
|
-
]);
|
|
130
|
-
expect(console.log).toHaveBeenCalled();
|
|
131
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', 'test-query', '-o', 'json'], { stdio: 'pipe' });
|
|
132
|
-
});
|
|
133
|
-
it('should warn when query has no response with response flag', async () => {
|
|
134
|
-
const mockQuery = {
|
|
135
|
-
metadata: {
|
|
136
|
-
name: 'test-query',
|
|
137
|
-
},
|
|
138
|
-
spec: {
|
|
139
|
-
input: 'test input',
|
|
140
|
-
target: { type: 'agent', name: 'test-agent' },
|
|
141
|
-
},
|
|
142
|
-
status: {
|
|
143
|
-
phase: 'running',
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
mockExeca.mockResolvedValue({
|
|
147
|
-
stdout: JSON.stringify(mockQuery),
|
|
148
|
-
});
|
|
149
|
-
const command = createQueriesCommand({});
|
|
150
|
-
await command.parseAsync([
|
|
151
|
-
'node',
|
|
152
|
-
'test',
|
|
153
|
-
'get',
|
|
154
|
-
'test-query',
|
|
155
|
-
'--response',
|
|
156
|
-
]);
|
|
157
|
-
expect(output.warning).toHaveBeenCalledWith('No response available');
|
|
158
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', 'test-query', '-o', 'json'], { stdio: 'pipe' });
|
|
159
|
-
});
|
|
160
|
-
it('should handle errors when getting query', async () => {
|
|
161
|
-
mockExeca.mockRejectedValue(new Error('Query not found'));
|
|
162
|
-
const command = createQueriesCommand({});
|
|
163
|
-
await command.parseAsync(['node', 'test', 'get', 'nonexistent-query']);
|
|
164
|
-
expect(output.error).toHaveBeenCalledWith('fetching query:', 'Query not found');
|
|
165
|
-
expect(process.exit).toHaveBeenCalled();
|
|
166
|
-
});
|
|
167
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { UNSUPPORTED_OUTPUT_FORMAT_MESSAGE } from './validation.js';
|
|
3
|
-
import output from '../../lib/output.js';
|
|
4
|
-
const mockExeca = jest.fn();
|
|
5
|
-
jest.unstable_mockModule('execa', () => ({
|
|
6
|
-
execa: mockExeca,
|
|
7
|
-
}));
|
|
8
|
-
const { createQueriesCommand } = await import('./index.js');
|
|
9
|
-
describe('queries list command', () => {
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
jest.clearAllMocks();
|
|
12
|
-
console.log = jest.fn();
|
|
13
|
-
jest.spyOn(output, 'warning').mockImplementation(() => { });
|
|
14
|
-
jest.spyOn(output, 'error').mockImplementation(() => { });
|
|
15
|
-
jest.spyOn(process, 'exit').mockImplementation(() => undefined);
|
|
16
|
-
});
|
|
17
|
-
it('should list all queries in text format by default', async () => {
|
|
18
|
-
const mockQueries = [
|
|
19
|
-
{
|
|
20
|
-
metadata: {
|
|
21
|
-
name: 'query-1',
|
|
22
|
-
creationTimestamp: '2024-01-01T00:00:00Z',
|
|
23
|
-
},
|
|
24
|
-
status: {
|
|
25
|
-
phase: 'done',
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
metadata: {
|
|
30
|
-
name: 'query-2',
|
|
31
|
-
creationTimestamp: '2024-01-02T00:00:00Z',
|
|
32
|
-
},
|
|
33
|
-
status: {
|
|
34
|
-
phase: 'running',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
];
|
|
38
|
-
mockExeca.mockResolvedValue({
|
|
39
|
-
stdout: JSON.stringify({ items: mockQueries }),
|
|
40
|
-
});
|
|
41
|
-
const command = createQueriesCommand({});
|
|
42
|
-
await command.parseAsync(['node', 'test', 'list']);
|
|
43
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/NAME.*STATUS/));
|
|
44
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/query-1/));
|
|
45
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/query-2/));
|
|
46
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '-o', 'json'], { stdio: 'pipe' });
|
|
47
|
-
});
|
|
48
|
-
it('should list all queries in JSON format', async () => {
|
|
49
|
-
const mockQueries = [
|
|
50
|
-
{
|
|
51
|
-
metadata: {
|
|
52
|
-
name: 'query-1',
|
|
53
|
-
creationTimestamp: '2024-01-01T00:00:00Z',
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
metadata: {
|
|
58
|
-
name: 'query-2',
|
|
59
|
-
creationTimestamp: '2024-01-02T00:00:00Z',
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
];
|
|
63
|
-
mockExeca.mockResolvedValue({
|
|
64
|
-
stdout: JSON.stringify({ items: mockQueries }),
|
|
65
|
-
});
|
|
66
|
-
const command = createQueriesCommand({});
|
|
67
|
-
await command.parseAsync(['node', 'test', '--output', 'json']);
|
|
68
|
-
expect(console.log).toHaveBeenCalledWith(JSON.stringify(mockQueries, null, 2));
|
|
69
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '-o', 'json'], { stdio: 'pipe' });
|
|
70
|
-
});
|
|
71
|
-
it('should support sorting by creation timestamp', async () => {
|
|
72
|
-
const mockQueries = [
|
|
73
|
-
{
|
|
74
|
-
metadata: {
|
|
75
|
-
name: 'query-1',
|
|
76
|
-
creationTimestamp: '2024-01-01T00:00:00Z',
|
|
77
|
-
},
|
|
78
|
-
status: {
|
|
79
|
-
phase: 'done',
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
metadata: {
|
|
84
|
-
name: 'query-2',
|
|
85
|
-
creationTimestamp: '2024-01-02T00:00:00Z',
|
|
86
|
-
},
|
|
87
|
-
status: {
|
|
88
|
-
phase: 'running',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
];
|
|
92
|
-
mockExeca.mockResolvedValue({
|
|
93
|
-
stdout: JSON.stringify({ items: mockQueries }),
|
|
94
|
-
});
|
|
95
|
-
const command = createQueriesCommand({});
|
|
96
|
-
await command.parseAsync([
|
|
97
|
-
'node',
|
|
98
|
-
'test',
|
|
99
|
-
'--sort-by',
|
|
100
|
-
'.metadata.creationTimestamp',
|
|
101
|
-
]);
|
|
102
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/NAME.*STATUS/));
|
|
103
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/query-1/));
|
|
104
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/query-2/));
|
|
105
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '--sort-by=.metadata.creationTimestamp', '-o', 'json'], { stdio: 'pipe' });
|
|
106
|
-
});
|
|
107
|
-
it('should display warning when no queries exist', async () => {
|
|
108
|
-
mockExeca.mockResolvedValue({
|
|
109
|
-
stdout: JSON.stringify({ items: [] }),
|
|
110
|
-
});
|
|
111
|
-
const command = createQueriesCommand({});
|
|
112
|
-
await command.parseAsync(['node', 'test', 'list']);
|
|
113
|
-
expect(output.warning).toHaveBeenCalledWith('no queries available');
|
|
114
|
-
expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '-o', 'json'], { stdio: 'pipe' });
|
|
115
|
-
});
|
|
116
|
-
it('should handle errors when listing queries', async () => {
|
|
117
|
-
mockExeca.mockRejectedValue(new Error('kubectl connection failed'));
|
|
118
|
-
const command = createQueriesCommand({});
|
|
119
|
-
await command.parseAsync(['node', 'test', 'list']);
|
|
120
|
-
expect(output.error).toHaveBeenCalled();
|
|
121
|
-
expect(process.exit).toHaveBeenCalled();
|
|
122
|
-
});
|
|
123
|
-
it('should handle invalid output format gracefully', async () => {
|
|
124
|
-
const mockQueries = [
|
|
125
|
-
{
|
|
126
|
-
metadata: {
|
|
127
|
-
name: 'query-1',
|
|
128
|
-
creationTimestamp: '2024-01-01T00:00:00Z',
|
|
129
|
-
},
|
|
130
|
-
status: {
|
|
131
|
-
phase: 'done',
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
];
|
|
135
|
-
mockExeca.mockResolvedValue({
|
|
136
|
-
stdout: JSON.stringify({ items: mockQueries }),
|
|
137
|
-
});
|
|
138
|
-
const command = createQueriesCommand({});
|
|
139
|
-
await command.parseAsync(['node', 'test', '--output', 'xml']);
|
|
140
|
-
expect(output.error).toHaveBeenCalledWith(expect.anything(), expect.stringMatching(UNSUPPORTED_OUTPUT_FORMAT_MESSAGE));
|
|
141
|
-
expect(mockExeca).not.toHaveBeenCalled();
|
|
142
|
-
expect(console.log).not.toHaveBeenCalledWith(expect.stringMatching(/query-1/));
|
|
143
|
-
expect(process.exit).toHaveBeenCalled();
|
|
144
|
-
});
|
|
145
|
-
it('should list many queries without truncation', async () => {
|
|
146
|
-
// Create 100 mock queries
|
|
147
|
-
const mockQueries = Array.from({ length: 100 }, (_, i) => ({
|
|
148
|
-
metadata: {
|
|
149
|
-
name: `query-${i + 1}`,
|
|
150
|
-
creationTimestamp: new Date(2024, 0, i + 1).toISOString(),
|
|
151
|
-
},
|
|
152
|
-
status: {
|
|
153
|
-
phase: i % 3 === 0 ? 'done' : i % 2 === 0 ? 'running' : 'initializing',
|
|
154
|
-
},
|
|
155
|
-
}));
|
|
156
|
-
mockExeca.mockResolvedValue({
|
|
157
|
-
stdout: JSON.stringify({ items: mockQueries }),
|
|
158
|
-
});
|
|
159
|
-
const command = createQueriesCommand({});
|
|
160
|
-
await command.parseAsync(['node', 'test', 'list']);
|
|
161
|
-
// Check for header and separator
|
|
162
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/NAME.*STATUS/));
|
|
163
|
-
// Verify all queries are logged
|
|
164
|
-
for (let i = 1; i <= 100; i++) {
|
|
165
|
-
expect(console.log).toHaveBeenCalledWith(expect.stringMatching(new RegExp(`query-${i}`)));
|
|
166
|
-
}
|
|
167
|
-
// Verify console.log was called: header + 100 queries
|
|
168
|
-
expect(console.log).toHaveBeenCalledTimes(101);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { InvalidArgumentError } from 'commander';
|
|
3
|
-
import { assertSupportedOutputFormat, UNSUPPORTED_OUTPUT_FORMAT_MESSAGE, } from './validation.js';
|
|
4
|
-
jest.spyOn(console, 'error').mockImplementation(() => { });
|
|
5
|
-
describe('queries validation', () => {
|
|
6
|
-
describe('assertSupportedOutputFormat', () => {
|
|
7
|
-
it('should not throw for supported formats', () => {
|
|
8
|
-
expect(() => assertSupportedOutputFormat('json')).not.toThrow();
|
|
9
|
-
expect(() => assertSupportedOutputFormat('text')).not.toThrow();
|
|
10
|
-
});
|
|
11
|
-
it('should not throw when format is undefined', () => {
|
|
12
|
-
expect(() => assertSupportedOutputFormat(undefined)).not.toThrow();
|
|
13
|
-
});
|
|
14
|
-
it('should throw InvalidArgumentError for unsupported format', () => {
|
|
15
|
-
expect(() => assertSupportedOutputFormat('xml')).toThrow(InvalidArgumentError);
|
|
16
|
-
});
|
|
17
|
-
it('should include format and supported formats in error message', () => {
|
|
18
|
-
expect(() => assertSupportedOutputFormat('xml')).toThrow(UNSUPPORTED_OUTPUT_FORMAT_MESSAGE);
|
|
19
|
-
});
|
|
20
|
-
it('should work with various invalid formats', () => {
|
|
21
|
-
const invalidFormats = ['yaml', 'csv', 'html', 'pdf'];
|
|
22
|
-
for (const format of invalidFormats) {
|
|
23
|
-
expect(() => assertSupportedOutputFormat(format)).toThrow(InvalidArgumentError);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { jest } from '@jest/globals';
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
const mockExecuteQuery = jest.fn();
|
|
4
|
-
const mockParseTarget = jest.fn();
|
|
5
|
-
jest.unstable_mockModule('../../lib/executeQuery.js', () => ({
|
|
6
|
-
executeQuery: mockExecuteQuery,
|
|
7
|
-
parseTarget: mockParseTarget,
|
|
8
|
-
}));
|
|
9
|
-
const mockOutput = {
|
|
10
|
-
error: jest.fn(),
|
|
11
|
-
};
|
|
12
|
-
jest.unstable_mockModule('../../lib/output.js', () => ({
|
|
13
|
-
default: mockOutput,
|
|
14
|
-
}));
|
|
15
|
-
const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
|
|
16
|
-
throw new Error('process.exit called');
|
|
17
|
-
}));
|
|
18
|
-
const mockConsoleError = jest
|
|
19
|
-
.spyOn(console, 'error')
|
|
20
|
-
.mockImplementation(() => { });
|
|
21
|
-
const { createQueryCommand } = await import('./index.js');
|
|
22
|
-
describe('createQueryCommand', () => {
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
jest.clearAllMocks();
|
|
25
|
-
});
|
|
26
|
-
it('should create a query command', () => {
|
|
27
|
-
const command = createQueryCommand({});
|
|
28
|
-
expect(command).toBeInstanceOf(Command);
|
|
29
|
-
expect(command.name()).toBe('query');
|
|
30
|
-
expect(command.description()).toBe('Execute a single query against a model or agent');
|
|
31
|
-
});
|
|
32
|
-
it('should parse and execute query with valid target', async () => {
|
|
33
|
-
mockParseTarget.mockReturnValue({
|
|
34
|
-
type: 'model',
|
|
35
|
-
name: 'default',
|
|
36
|
-
});
|
|
37
|
-
mockExecuteQuery.mockResolvedValue(undefined);
|
|
38
|
-
const command = createQueryCommand({});
|
|
39
|
-
await command.parseAsync(['node', 'test', 'model/default', 'Hello world']);
|
|
40
|
-
expect(mockParseTarget).toHaveBeenCalledWith('model/default');
|
|
41
|
-
expect(mockExecuteQuery).toHaveBeenCalledWith({
|
|
42
|
-
targetType: 'model',
|
|
43
|
-
targetName: 'default',
|
|
44
|
-
message: 'Hello world',
|
|
45
|
-
outputFormat: undefined,
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
it('should pass output format option to executeQuery', async () => {
|
|
49
|
-
mockParseTarget.mockReturnValue({
|
|
50
|
-
type: 'model',
|
|
51
|
-
name: 'default',
|
|
52
|
-
});
|
|
53
|
-
mockExecuteQuery.mockResolvedValue(undefined);
|
|
54
|
-
const command = createQueryCommand({});
|
|
55
|
-
await command.parseAsync([
|
|
56
|
-
'node',
|
|
57
|
-
'test',
|
|
58
|
-
'model/default',
|
|
59
|
-
'Hello world',
|
|
60
|
-
'-o',
|
|
61
|
-
'json',
|
|
62
|
-
]);
|
|
63
|
-
expect(mockParseTarget).toHaveBeenCalledWith('model/default');
|
|
64
|
-
expect(mockExecuteQuery).toHaveBeenCalledWith({
|
|
65
|
-
targetType: 'model',
|
|
66
|
-
targetName: 'default',
|
|
67
|
-
message: 'Hello world',
|
|
68
|
-
outputFormat: 'json',
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
it('should pass session-id option to executeQuery', async () => {
|
|
72
|
-
mockParseTarget.mockReturnValue({
|
|
73
|
-
type: 'agent',
|
|
74
|
-
name: 'test-agent',
|
|
75
|
-
});
|
|
76
|
-
mockExecuteQuery.mockResolvedValue(undefined);
|
|
77
|
-
const command = createQueryCommand({});
|
|
78
|
-
await command.parseAsync([
|
|
79
|
-
'node',
|
|
80
|
-
'test',
|
|
81
|
-
'agent/test-agent',
|
|
82
|
-
'Hello world',
|
|
83
|
-
'--session-id',
|
|
84
|
-
'my-session-123',
|
|
85
|
-
]);
|
|
86
|
-
expect(mockParseTarget).toHaveBeenCalledWith('agent/test-agent');
|
|
87
|
-
expect(mockExecuteQuery).toHaveBeenCalledWith({
|
|
88
|
-
targetType: 'agent',
|
|
89
|
-
targetName: 'test-agent',
|
|
90
|
-
message: 'Hello world',
|
|
91
|
-
outputFormat: undefined,
|
|
92
|
-
sessionId: 'my-session-123',
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
it('should error on invalid target format', async () => {
|
|
96
|
-
mockParseTarget.mockReturnValue(null);
|
|
97
|
-
const command = createQueryCommand({});
|
|
98
|
-
await expect(command.parseAsync(['node', 'test', 'invalid-target', 'Hello'])).rejects.toThrow('process.exit called');
|
|
99
|
-
expect(mockParseTarget).toHaveBeenCalledWith('invalid-target');
|
|
100
|
-
expect(mockExecuteQuery).not.toHaveBeenCalled();
|
|
101
|
-
expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Invalid target format'));
|
|
102
|
-
expect(mockExit).toHaveBeenCalledWith(1);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|