@positronic/cli 0.0.2 → 0.0.4
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/src/cli.js +16 -1
- package/dist/src/commands/helpers.js +11 -25
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/commands/helpers.d.ts.map +1 -1
- package/package.json +11 -4
- package/dist/src/commands/brain.test.js +0 -2936
- package/dist/src/commands/helpers.test.js +0 -832
- package/dist/src/commands/project.test.js +0 -1201
- package/dist/src/commands/resources.test.js +0 -2511
- package/dist/src/commands/schedule.test.js +0 -1235
- package/dist/src/commands/secret.test.d.js +0 -1
- package/dist/src/commands/secret.test.js +0 -761
- package/dist/src/commands/server.test.js +0 -1237
- package/dist/src/commands/test-utils.js +0 -737
- package/dist/src/components/secret-sync.js +0 -303
- package/dist/src/test/mock-api-client.js +0 -371
- package/dist/src/test/test-dev-server.js +0 -1376
- package/dist/types/commands/test-utils.d.ts +0 -45
- package/dist/types/commands/test-utils.d.ts.map +0 -1
- package/dist/types/components/secret-sync.d.ts +0 -9
- package/dist/types/components/secret-sync.d.ts.map +0 -1
- package/dist/types/test/mock-api-client.d.ts +0 -25
- package/dist/types/test/mock-api-client.d.ts.map +0 -1
- package/dist/types/test/test-dev-server.d.ts +0 -129
- package/dist/types/test/test-dev-server.d.ts.map +0 -1
- package/src/cli.ts +0 -981
- package/src/commands/backend.ts +0 -63
- package/src/commands/brain.test.ts +0 -1004
- package/src/commands/brain.ts +0 -215
- package/src/commands/helpers.test.ts +0 -487
- package/src/commands/helpers.ts +0 -870
- package/src/commands/project-config-manager.ts +0 -152
- package/src/commands/project.test.ts +0 -502
- package/src/commands/project.ts +0 -109
- package/src/commands/resources.test.ts +0 -1052
- package/src/commands/resources.ts +0 -97
- package/src/commands/schedule.test.ts +0 -481
- package/src/commands/schedule.ts +0 -65
- package/src/commands/secret.test.ts +0 -210
- package/src/commands/secret.ts +0 -50
- package/src/commands/server.test.ts +0 -493
- package/src/commands/server.ts +0 -353
- package/src/commands/test-utils.ts +0 -324
- package/src/components/brain-history.tsx +0 -198
- package/src/components/brain-list.tsx +0 -105
- package/src/components/brain-rerun.tsx +0 -111
- package/src/components/brain-show.tsx +0 -92
- package/src/components/error.tsx +0 -24
- package/src/components/project-add.tsx +0 -59
- package/src/components/project-create.tsx +0 -83
- package/src/components/project-list.tsx +0 -83
- package/src/components/project-remove.tsx +0 -55
- package/src/components/project-select.tsx +0 -200
- package/src/components/project-show.tsx +0 -58
- package/src/components/resource-clear.tsx +0 -127
- package/src/components/resource-delete.tsx +0 -160
- package/src/components/resource-list.tsx +0 -177
- package/src/components/resource-sync.tsx +0 -170
- package/src/components/resource-types.tsx +0 -55
- package/src/components/resource-upload.tsx +0 -182
- package/src/components/schedule-create.tsx +0 -90
- package/src/components/schedule-delete.tsx +0 -116
- package/src/components/schedule-list.tsx +0 -186
- package/src/components/schedule-runs.tsx +0 -151
- package/src/components/secret-bulk.tsx +0 -79
- package/src/components/secret-create.tsx +0 -49
- package/src/components/secret-delete.tsx +0 -41
- package/src/components/secret-list.tsx +0 -41
- package/src/components/watch.tsx +0 -155
- package/src/hooks/useApi.ts +0 -183
- package/src/positronic.ts +0 -40
- package/src/test/data/resources/config.json +0 -1
- package/src/test/data/resources/data/config.json +0 -1
- package/src/test/data/resources/data/logo.png +0 -2
- package/src/test/data/resources/docs/api.md +0 -3
- package/src/test/data/resources/docs/readme.md +0 -3
- package/src/test/data/resources/example.md +0 -3
- package/src/test/data/resources/file with spaces.txt +0 -1
- package/src/test/data/resources/readme.md +0 -3
- package/src/test/data/resources/test.txt +0 -1
- package/src/test/mock-api-client.ts +0 -145
- package/src/test/test-dev-server.ts +0 -1003
- package/tsconfig.json +0 -11
|
@@ -1,1201 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Integration Tests - Testing Philosophy
|
|
3
|
-
*
|
|
4
|
-
* These tests are designed to be maintainable and resilient to UI changes.
|
|
5
|
-
*
|
|
6
|
-
* Key principles:
|
|
7
|
-
* 1. **Test behavior, not formatting** - Don't check for specific icons, emojis, or exact formatting
|
|
8
|
-
* 2. **Look for essential keywords only** - Focus on the minimum text that indicates success/failure
|
|
9
|
-
* 3. **Use simple assertions** - Prefer toContain() over complex regex when possible
|
|
10
|
-
* 4. **Be case-insensitive** - Use toLowerCase() to avoid breaking on capitalization changes
|
|
11
|
-
*
|
|
12
|
-
* Examples:
|
|
13
|
-
* - For success: look for "added", "switched", etc. (not specific success emojis)
|
|
14
|
-
* - For errors: look for "not found", "invalid", "already exists" (not error icons)
|
|
15
|
-
* - For data: check that project names and URLs appear, but not their exact formatting
|
|
16
|
-
*
|
|
17
|
-
* This approach ensures tests remain stable as the CLI's output formatting evolves,
|
|
18
|
-
* while still verifying that core functionality works correctly.
|
|
19
|
-
*/ // Import nock to use in tests, but configuration happens in jest.setup.js
|
|
20
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
21
|
-
try {
|
|
22
|
-
var info = gen[key](arg);
|
|
23
|
-
var value = info.value;
|
|
24
|
-
} catch (error) {
|
|
25
|
-
reject(error);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (info.done) {
|
|
29
|
-
resolve(value);
|
|
30
|
-
} else {
|
|
31
|
-
Promise.resolve(value).then(_next, _throw);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function _async_to_generator(fn) {
|
|
35
|
-
return function() {
|
|
36
|
-
var self = this, args = arguments;
|
|
37
|
-
return new Promise(function(resolve, reject) {
|
|
38
|
-
var gen = fn.apply(self, args);
|
|
39
|
-
function _next(value) {
|
|
40
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
41
|
-
}
|
|
42
|
-
function _throw(err) {
|
|
43
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
44
|
-
}
|
|
45
|
-
_next(undefined);
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function _ts_generator(thisArg, body) {
|
|
50
|
-
var f, y, t, _ = {
|
|
51
|
-
label: 0,
|
|
52
|
-
sent: function() {
|
|
53
|
-
if (t[0] & 1) throw t[1];
|
|
54
|
-
return t[1];
|
|
55
|
-
},
|
|
56
|
-
trys: [],
|
|
57
|
-
ops: []
|
|
58
|
-
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
59
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
60
|
-
return this;
|
|
61
|
-
}), g;
|
|
62
|
-
function verb(n) {
|
|
63
|
-
return function(v) {
|
|
64
|
-
return step([
|
|
65
|
-
n,
|
|
66
|
-
v
|
|
67
|
-
]);
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function step(op) {
|
|
71
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
72
|
-
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
73
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
74
|
-
if (y = 0, t) op = [
|
|
75
|
-
op[0] & 2,
|
|
76
|
-
t.value
|
|
77
|
-
];
|
|
78
|
-
switch(op[0]){
|
|
79
|
-
case 0:
|
|
80
|
-
case 1:
|
|
81
|
-
t = op;
|
|
82
|
-
break;
|
|
83
|
-
case 4:
|
|
84
|
-
_.label++;
|
|
85
|
-
return {
|
|
86
|
-
value: op[1],
|
|
87
|
-
done: false
|
|
88
|
-
};
|
|
89
|
-
case 5:
|
|
90
|
-
_.label++;
|
|
91
|
-
y = op[1];
|
|
92
|
-
op = [
|
|
93
|
-
0
|
|
94
|
-
];
|
|
95
|
-
continue;
|
|
96
|
-
case 7:
|
|
97
|
-
op = _.ops.pop();
|
|
98
|
-
_.trys.pop();
|
|
99
|
-
continue;
|
|
100
|
-
default:
|
|
101
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
102
|
-
_ = 0;
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
106
|
-
_.label = op[1];
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
if (op[0] === 6 && _.label < t[1]) {
|
|
110
|
-
_.label = t[1];
|
|
111
|
-
t = op;
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
if (t && _.label < t[2]) {
|
|
115
|
-
_.label = t[2];
|
|
116
|
-
_.ops.push(op);
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
if (t[2]) _.ops.pop();
|
|
120
|
-
_.trys.pop();
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
op = body.call(thisArg, _);
|
|
124
|
-
} catch (e) {
|
|
125
|
-
op = [
|
|
126
|
-
6,
|
|
127
|
-
e
|
|
128
|
-
];
|
|
129
|
-
y = 0;
|
|
130
|
-
} finally{
|
|
131
|
-
f = t = 0;
|
|
132
|
-
}
|
|
133
|
-
if (op[0] & 5) throw op[1];
|
|
134
|
-
return {
|
|
135
|
-
value: op[0] ? op[1] : void 0,
|
|
136
|
-
done: true
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
import * as fs from 'fs';
|
|
141
|
-
import * as path from 'path';
|
|
142
|
-
import * as os from 'os';
|
|
143
|
-
import { describe, it, expect, afterEach } from '@jest/globals';
|
|
144
|
-
import { createTestEnv, px } from './test-utils.js';
|
|
145
|
-
describe('CLI Integration: positronic server with project', function() {
|
|
146
|
-
it('runs a brain', function() {
|
|
147
|
-
return _async_to_generator(function() {
|
|
148
|
-
var env, px, waitForOutput, outputContainsRunId, outputContainsRunPrefix;
|
|
149
|
-
return _ts_generator(this, function(_state) {
|
|
150
|
-
switch(_state.label){
|
|
151
|
-
case 0:
|
|
152
|
-
return [
|
|
153
|
-
4,
|
|
154
|
-
createTestEnv()
|
|
155
|
-
];
|
|
156
|
-
case 1:
|
|
157
|
-
env = _state.sent();
|
|
158
|
-
// Setup test brain
|
|
159
|
-
env.setup(function(dir) {
|
|
160
|
-
var brainsDir = path.join(dir, 'brains');
|
|
161
|
-
fs.mkdirSync(brainsDir, {
|
|
162
|
-
recursive: true
|
|
163
|
-
});
|
|
164
|
-
// Create a simple test brain
|
|
165
|
-
fs.writeFileSync(path.join(brainsDir, 'test-brain.ts'), "\n export default function testBrain() {\n return {\n title: 'Test Brain',\n steps: [\n {\n title: 'Test Step',\n run: async () => {\n return { success: true };\n }\n }\n ]\n };\n }\n ");
|
|
166
|
-
});
|
|
167
|
-
return [
|
|
168
|
-
4,
|
|
169
|
-
env.start()
|
|
170
|
-
];
|
|
171
|
-
case 2:
|
|
172
|
-
px = _state.sent();
|
|
173
|
-
_state.label = 3;
|
|
174
|
-
case 3:
|
|
175
|
-
_state.trys.push([
|
|
176
|
-
3,
|
|
177
|
-
,
|
|
178
|
-
7,
|
|
179
|
-
9
|
|
180
|
-
]);
|
|
181
|
-
return [
|
|
182
|
-
4,
|
|
183
|
-
px([
|
|
184
|
-
'run',
|
|
185
|
-
'test-brain'
|
|
186
|
-
])
|
|
187
|
-
];
|
|
188
|
-
case 4:
|
|
189
|
-
waitForOutput = _state.sent().waitForOutput;
|
|
190
|
-
return [
|
|
191
|
-
4,
|
|
192
|
-
waitForOutput(/Run ID:/)
|
|
193
|
-
];
|
|
194
|
-
case 5:
|
|
195
|
-
outputContainsRunId = _state.sent();
|
|
196
|
-
return [
|
|
197
|
-
4,
|
|
198
|
-
waitForOutput(/run-/)
|
|
199
|
-
];
|
|
200
|
-
case 6:
|
|
201
|
-
outputContainsRunPrefix = _state.sent();
|
|
202
|
-
expect(outputContainsRunId).toBe(true);
|
|
203
|
-
expect(outputContainsRunPrefix).toBe(true);
|
|
204
|
-
return [
|
|
205
|
-
3,
|
|
206
|
-
9
|
|
207
|
-
];
|
|
208
|
-
case 7:
|
|
209
|
-
return [
|
|
210
|
-
4,
|
|
211
|
-
env.stopAndCleanup()
|
|
212
|
-
];
|
|
213
|
-
case 8:
|
|
214
|
-
_state.sent();
|
|
215
|
-
return [
|
|
216
|
-
7
|
|
217
|
-
];
|
|
218
|
-
case 9:
|
|
219
|
-
return [
|
|
220
|
-
2
|
|
221
|
-
];
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
})();
|
|
225
|
-
});
|
|
226
|
-
});
|
|
227
|
-
describe('CLI Integration: project commands', function() {
|
|
228
|
-
var tempDir;
|
|
229
|
-
var configDir;
|
|
230
|
-
beforeEach(function() {
|
|
231
|
-
// Create a temp directory for testing
|
|
232
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'positronic-project-test-'));
|
|
233
|
-
configDir = path.join(tempDir, '.positronic');
|
|
234
|
-
});
|
|
235
|
-
afterEach(function() {
|
|
236
|
-
// Clean up test directory
|
|
237
|
-
fs.rmSync(tempDir, {
|
|
238
|
-
recursive: true,
|
|
239
|
-
force: true
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
describe('project add', function() {
|
|
243
|
-
it('should add a new project successfully', function() {
|
|
244
|
-
return _async_to_generator(function() {
|
|
245
|
-
var _ref, waitForOutput, instance, isReady, output, configPath, config;
|
|
246
|
-
return _ts_generator(this, function(_state) {
|
|
247
|
-
switch(_state.label){
|
|
248
|
-
case 0:
|
|
249
|
-
return [
|
|
250
|
-
4,
|
|
251
|
-
px([
|
|
252
|
-
'project',
|
|
253
|
-
'add',
|
|
254
|
-
'My App',
|
|
255
|
-
'--url',
|
|
256
|
-
'https://my-app.positronic.sh'
|
|
257
|
-
], {
|
|
258
|
-
configDir: configDir
|
|
259
|
-
})
|
|
260
|
-
];
|
|
261
|
-
case 1:
|
|
262
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
263
|
-
return [
|
|
264
|
-
4,
|
|
265
|
-
waitForOutput(/added/i)
|
|
266
|
-
];
|
|
267
|
-
case 2:
|
|
268
|
-
isReady = _state.sent();
|
|
269
|
-
expect(isReady).toBe(true);
|
|
270
|
-
output = instance.lastFrame();
|
|
271
|
-
expect(output).toMatch(/my app/i);
|
|
272
|
-
expect(output).toContain('https://my-app.positronic.sh');
|
|
273
|
-
// Verify config file was created
|
|
274
|
-
configPath = path.join(configDir, 'config.json');
|
|
275
|
-
expect(fs.existsSync(configPath)).toBe(true);
|
|
276
|
-
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
277
|
-
expect(config.projects).toHaveLength(1);
|
|
278
|
-
expect(config.projects[0].name).toBe('My App');
|
|
279
|
-
expect(config.currentProject).toBe('My App');
|
|
280
|
-
return [
|
|
281
|
-
2
|
|
282
|
-
];
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
})();
|
|
286
|
-
});
|
|
287
|
-
it('should reject duplicate project names', function() {
|
|
288
|
-
return _async_to_generator(function() {
|
|
289
|
-
var addFirstProject, addDuplicateProject;
|
|
290
|
-
return _ts_generator(this, function(_state) {
|
|
291
|
-
switch(_state.label){
|
|
292
|
-
case 0:
|
|
293
|
-
return [
|
|
294
|
-
4,
|
|
295
|
-
px([
|
|
296
|
-
'project',
|
|
297
|
-
'add',
|
|
298
|
-
'My App',
|
|
299
|
-
'--url',
|
|
300
|
-
'https://my-app.positronic.sh'
|
|
301
|
-
], {
|
|
302
|
-
configDir: configDir
|
|
303
|
-
})
|
|
304
|
-
];
|
|
305
|
-
case 1:
|
|
306
|
-
addFirstProject = _state.sent();
|
|
307
|
-
return [
|
|
308
|
-
4,
|
|
309
|
-
addFirstProject.waitForOutput(/added/i)
|
|
310
|
-
];
|
|
311
|
-
case 2:
|
|
312
|
-
expect.apply(void 0, [
|
|
313
|
-
_state.sent()
|
|
314
|
-
]).toBe(true);
|
|
315
|
-
return [
|
|
316
|
-
4,
|
|
317
|
-
px([
|
|
318
|
-
'project',
|
|
319
|
-
'add',
|
|
320
|
-
'My App',
|
|
321
|
-
'--url',
|
|
322
|
-
'https://other.positronic.sh'
|
|
323
|
-
], {
|
|
324
|
-
configDir: configDir
|
|
325
|
-
})
|
|
326
|
-
];
|
|
327
|
-
case 3:
|
|
328
|
-
addDuplicateProject = _state.sent();
|
|
329
|
-
return [
|
|
330
|
-
4,
|
|
331
|
-
addDuplicateProject.waitForOutput(/already exists/i)
|
|
332
|
-
];
|
|
333
|
-
case 4:
|
|
334
|
-
expect.apply(void 0, [
|
|
335
|
-
_state.sent()
|
|
336
|
-
]).toBe(true);
|
|
337
|
-
return [
|
|
338
|
-
2
|
|
339
|
-
];
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
})();
|
|
343
|
-
});
|
|
344
|
-
it('should reject invalid URLs', function() {
|
|
345
|
-
return _async_to_generator(function() {
|
|
346
|
-
var waitForOutput;
|
|
347
|
-
return _ts_generator(this, function(_state) {
|
|
348
|
-
switch(_state.label){
|
|
349
|
-
case 0:
|
|
350
|
-
return [
|
|
351
|
-
4,
|
|
352
|
-
px([
|
|
353
|
-
'project',
|
|
354
|
-
'add',
|
|
355
|
-
'My App',
|
|
356
|
-
'--url',
|
|
357
|
-
'not-a-valid-url'
|
|
358
|
-
], {
|
|
359
|
-
configDir: configDir
|
|
360
|
-
})
|
|
361
|
-
];
|
|
362
|
-
case 1:
|
|
363
|
-
waitForOutput = _state.sent().waitForOutput;
|
|
364
|
-
return [
|
|
365
|
-
4,
|
|
366
|
-
waitForOutput(/invalid/i)
|
|
367
|
-
];
|
|
368
|
-
case 2:
|
|
369
|
-
expect.apply(void 0, [
|
|
370
|
-
_state.sent()
|
|
371
|
-
]).toBe(true);
|
|
372
|
-
return [
|
|
373
|
-
2
|
|
374
|
-
];
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
})();
|
|
378
|
-
});
|
|
379
|
-
it('should handle project names with spaces', function() {
|
|
380
|
-
return _async_to_generator(function() {
|
|
381
|
-
var _ref, waitForOutput, instance, config;
|
|
382
|
-
return _ts_generator(this, function(_state) {
|
|
383
|
-
switch(_state.label){
|
|
384
|
-
case 0:
|
|
385
|
-
return [
|
|
386
|
-
4,
|
|
387
|
-
px([
|
|
388
|
-
'project',
|
|
389
|
-
'add',
|
|
390
|
-
'My Production App',
|
|
391
|
-
'--url',
|
|
392
|
-
'https://prod.positronic.sh'
|
|
393
|
-
], {
|
|
394
|
-
configDir: configDir
|
|
395
|
-
})
|
|
396
|
-
];
|
|
397
|
-
case 1:
|
|
398
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
399
|
-
return [
|
|
400
|
-
4,
|
|
401
|
-
waitForOutput(/added/i)
|
|
402
|
-
];
|
|
403
|
-
case 2:
|
|
404
|
-
expect.apply(void 0, [
|
|
405
|
-
_state.sent()
|
|
406
|
-
]).toBe(true);
|
|
407
|
-
expect(instance.lastFrame()).toMatch(/my production app/i);
|
|
408
|
-
config = JSON.parse(fs.readFileSync(path.join(configDir, 'config.json'), 'utf-8'));
|
|
409
|
-
expect(config.projects[0].name).toBe('My Production App');
|
|
410
|
-
return [
|
|
411
|
-
2
|
|
412
|
-
];
|
|
413
|
-
}
|
|
414
|
-
});
|
|
415
|
-
})();
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
|
-
describe('project list', function() {
|
|
419
|
-
it('should show empty state when no projects configured', function() {
|
|
420
|
-
return _async_to_generator(function() {
|
|
421
|
-
var instance, output;
|
|
422
|
-
return _ts_generator(this, function(_state) {
|
|
423
|
-
switch(_state.label){
|
|
424
|
-
case 0:
|
|
425
|
-
return [
|
|
426
|
-
4,
|
|
427
|
-
px([
|
|
428
|
-
'project',
|
|
429
|
-
'list'
|
|
430
|
-
], {
|
|
431
|
-
configDir: configDir
|
|
432
|
-
})
|
|
433
|
-
];
|
|
434
|
-
case 1:
|
|
435
|
-
instance = _state.sent().instance;
|
|
436
|
-
output = instance.lastFrame() || '';
|
|
437
|
-
expect(output.toLowerCase()).toContain('no projects');
|
|
438
|
-
return [
|
|
439
|
-
2
|
|
440
|
-
];
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
})();
|
|
444
|
-
});
|
|
445
|
-
it('should list all projects with current indicator', function() {
|
|
446
|
-
return _async_to_generator(function() {
|
|
447
|
-
var instance, output;
|
|
448
|
-
return _ts_generator(this, function(_state) {
|
|
449
|
-
switch(_state.label){
|
|
450
|
-
case 0:
|
|
451
|
-
// Add some projects
|
|
452
|
-
return [
|
|
453
|
-
4,
|
|
454
|
-
px([
|
|
455
|
-
'project',
|
|
456
|
-
'add',
|
|
457
|
-
'Project One',
|
|
458
|
-
'--url',
|
|
459
|
-
'https://one.positronic.sh'
|
|
460
|
-
], {
|
|
461
|
-
configDir: configDir
|
|
462
|
-
})
|
|
463
|
-
];
|
|
464
|
-
case 1:
|
|
465
|
-
_state.sent();
|
|
466
|
-
return [
|
|
467
|
-
4,
|
|
468
|
-
px([
|
|
469
|
-
'project',
|
|
470
|
-
'add',
|
|
471
|
-
'Project Two',
|
|
472
|
-
'--url',
|
|
473
|
-
'https://two.positronic.sh'
|
|
474
|
-
], {
|
|
475
|
-
configDir: configDir
|
|
476
|
-
})
|
|
477
|
-
];
|
|
478
|
-
case 2:
|
|
479
|
-
_state.sent();
|
|
480
|
-
return [
|
|
481
|
-
4,
|
|
482
|
-
px([
|
|
483
|
-
'project',
|
|
484
|
-
'select',
|
|
485
|
-
'Project Two'
|
|
486
|
-
], {
|
|
487
|
-
configDir: configDir
|
|
488
|
-
})
|
|
489
|
-
];
|
|
490
|
-
case 3:
|
|
491
|
-
_state.sent();
|
|
492
|
-
return [
|
|
493
|
-
4,
|
|
494
|
-
px([
|
|
495
|
-
'project',
|
|
496
|
-
'list'
|
|
497
|
-
], {
|
|
498
|
-
configDir: configDir
|
|
499
|
-
})
|
|
500
|
-
];
|
|
501
|
-
case 4:
|
|
502
|
-
instance = _state.sent().instance;
|
|
503
|
-
output = instance.lastFrame() || '';
|
|
504
|
-
expect(output).toMatch(/project one/i);
|
|
505
|
-
expect(output).toMatch(/project two/i);
|
|
506
|
-
return [
|
|
507
|
-
2
|
|
508
|
-
];
|
|
509
|
-
}
|
|
510
|
-
});
|
|
511
|
-
})();
|
|
512
|
-
});
|
|
513
|
-
});
|
|
514
|
-
describe('project select', function() {
|
|
515
|
-
beforeEach(function() {
|
|
516
|
-
return _async_to_generator(function() {
|
|
517
|
-
return _ts_generator(this, function(_state) {
|
|
518
|
-
switch(_state.label){
|
|
519
|
-
case 0:
|
|
520
|
-
// Add some projects for selection tests
|
|
521
|
-
return [
|
|
522
|
-
4,
|
|
523
|
-
px([
|
|
524
|
-
'project',
|
|
525
|
-
'add',
|
|
526
|
-
'Project Alpha',
|
|
527
|
-
'--url',
|
|
528
|
-
'https://alpha.positronic.sh'
|
|
529
|
-
], {
|
|
530
|
-
configDir: configDir
|
|
531
|
-
})
|
|
532
|
-
];
|
|
533
|
-
case 1:
|
|
534
|
-
_state.sent();
|
|
535
|
-
return [
|
|
536
|
-
4,
|
|
537
|
-
px([
|
|
538
|
-
'project',
|
|
539
|
-
'add',
|
|
540
|
-
'Project Beta',
|
|
541
|
-
'--url',
|
|
542
|
-
'https://beta.positronic.sh'
|
|
543
|
-
], {
|
|
544
|
-
configDir: configDir
|
|
545
|
-
})
|
|
546
|
-
];
|
|
547
|
-
case 2:
|
|
548
|
-
_state.sent();
|
|
549
|
-
return [
|
|
550
|
-
4,
|
|
551
|
-
px([
|
|
552
|
-
'project',
|
|
553
|
-
'add',
|
|
554
|
-
'Project Gamma',
|
|
555
|
-
'--url',
|
|
556
|
-
'https://gamma.positronic.sh'
|
|
557
|
-
], {
|
|
558
|
-
configDir: configDir
|
|
559
|
-
})
|
|
560
|
-
];
|
|
561
|
-
case 3:
|
|
562
|
-
_state.sent();
|
|
563
|
-
return [
|
|
564
|
-
2
|
|
565
|
-
];
|
|
566
|
-
}
|
|
567
|
-
});
|
|
568
|
-
})();
|
|
569
|
-
});
|
|
570
|
-
it('should select a project by name', function() {
|
|
571
|
-
return _async_to_generator(function() {
|
|
572
|
-
var instance, output, config;
|
|
573
|
-
return _ts_generator(this, function(_state) {
|
|
574
|
-
switch(_state.label){
|
|
575
|
-
case 0:
|
|
576
|
-
return [
|
|
577
|
-
4,
|
|
578
|
-
px([
|
|
579
|
-
'project',
|
|
580
|
-
'select',
|
|
581
|
-
'Project Beta'
|
|
582
|
-
], {
|
|
583
|
-
configDir: configDir
|
|
584
|
-
})
|
|
585
|
-
];
|
|
586
|
-
case 1:
|
|
587
|
-
instance = _state.sent().instance;
|
|
588
|
-
output = instance.lastFrame() || '';
|
|
589
|
-
expect(output.toLowerCase()).toMatch(/switched|selected/);
|
|
590
|
-
expect(output).toMatch(/project beta/i);
|
|
591
|
-
// Verify config was updated
|
|
592
|
-
config = JSON.parse(fs.readFileSync(path.join(configDir, 'config.json'), 'utf-8'));
|
|
593
|
-
expect(config.currentProject).toBe('Project Beta');
|
|
594
|
-
return [
|
|
595
|
-
2
|
|
596
|
-
];
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
})();
|
|
600
|
-
});
|
|
601
|
-
it('should show error for non-existent project', function() {
|
|
602
|
-
return _async_to_generator(function() {
|
|
603
|
-
var instance, output;
|
|
604
|
-
return _ts_generator(this, function(_state) {
|
|
605
|
-
switch(_state.label){
|
|
606
|
-
case 0:
|
|
607
|
-
return [
|
|
608
|
-
4,
|
|
609
|
-
px([
|
|
610
|
-
'project',
|
|
611
|
-
'select',
|
|
612
|
-
'Non Existent'
|
|
613
|
-
], {
|
|
614
|
-
configDir: configDir
|
|
615
|
-
})
|
|
616
|
-
];
|
|
617
|
-
case 1:
|
|
618
|
-
instance = _state.sent().instance;
|
|
619
|
-
output = instance.lastFrame() || '';
|
|
620
|
-
expect(output.toLowerCase()).toContain('not found');
|
|
621
|
-
expect(output).toMatch(/project alpha/i);
|
|
622
|
-
return [
|
|
623
|
-
2
|
|
624
|
-
];
|
|
625
|
-
}
|
|
626
|
-
});
|
|
627
|
-
})();
|
|
628
|
-
});
|
|
629
|
-
it('should show interactive selection when no name provided', function() {
|
|
630
|
-
return _async_to_generator(function() {
|
|
631
|
-
var instance, output;
|
|
632
|
-
return _ts_generator(this, function(_state) {
|
|
633
|
-
switch(_state.label){
|
|
634
|
-
case 0:
|
|
635
|
-
return [
|
|
636
|
-
4,
|
|
637
|
-
px([
|
|
638
|
-
'project',
|
|
639
|
-
'select'
|
|
640
|
-
], {
|
|
641
|
-
configDir: configDir
|
|
642
|
-
})
|
|
643
|
-
];
|
|
644
|
-
case 1:
|
|
645
|
-
instance = _state.sent().instance;
|
|
646
|
-
output = instance.lastFrame() || '';
|
|
647
|
-
// In test environment, raw mode isn't supported so it shows a non-interactive list
|
|
648
|
-
expect(output).toMatch(/project alpha/i);
|
|
649
|
-
expect(output).toMatch(/project beta/i);
|
|
650
|
-
expect(output).toMatch(/project gamma/i);
|
|
651
|
-
return [
|
|
652
|
-
2
|
|
653
|
-
];
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
|
-
})();
|
|
657
|
-
});
|
|
658
|
-
});
|
|
659
|
-
describe('project show', function() {
|
|
660
|
-
it('should show no project selected when empty', function() {
|
|
661
|
-
return _async_to_generator(function() {
|
|
662
|
-
var instance, output;
|
|
663
|
-
return _ts_generator(this, function(_state) {
|
|
664
|
-
switch(_state.label){
|
|
665
|
-
case 0:
|
|
666
|
-
return [
|
|
667
|
-
4,
|
|
668
|
-
px([
|
|
669
|
-
'project',
|
|
670
|
-
'show'
|
|
671
|
-
], {
|
|
672
|
-
configDir: configDir
|
|
673
|
-
})
|
|
674
|
-
];
|
|
675
|
-
case 1:
|
|
676
|
-
instance = _state.sent().instance;
|
|
677
|
-
output = instance.lastFrame() || '';
|
|
678
|
-
expect(output.toLowerCase()).toContain('no project');
|
|
679
|
-
return [
|
|
680
|
-
2
|
|
681
|
-
];
|
|
682
|
-
}
|
|
683
|
-
});
|
|
684
|
-
})();
|
|
685
|
-
});
|
|
686
|
-
it('should show current project details', function() {
|
|
687
|
-
return _async_to_generator(function() {
|
|
688
|
-
var instance, output;
|
|
689
|
-
return _ts_generator(this, function(_state) {
|
|
690
|
-
switch(_state.label){
|
|
691
|
-
case 0:
|
|
692
|
-
return [
|
|
693
|
-
4,
|
|
694
|
-
px([
|
|
695
|
-
'project',
|
|
696
|
-
'add',
|
|
697
|
-
'My Current Project',
|
|
698
|
-
'--url',
|
|
699
|
-
'https://current.positronic.sh'
|
|
700
|
-
], {
|
|
701
|
-
configDir: configDir
|
|
702
|
-
})
|
|
703
|
-
];
|
|
704
|
-
case 1:
|
|
705
|
-
_state.sent();
|
|
706
|
-
return [
|
|
707
|
-
4,
|
|
708
|
-
px([
|
|
709
|
-
'project',
|
|
710
|
-
'show'
|
|
711
|
-
], {
|
|
712
|
-
configDir: configDir
|
|
713
|
-
})
|
|
714
|
-
];
|
|
715
|
-
case 2:
|
|
716
|
-
instance = _state.sent().instance;
|
|
717
|
-
output = instance.lastFrame() || '';
|
|
718
|
-
expect(output).toMatch(/my current project/i);
|
|
719
|
-
expect(output).toContain('https://current.positronic.sh');
|
|
720
|
-
return [
|
|
721
|
-
2
|
|
722
|
-
];
|
|
723
|
-
}
|
|
724
|
-
});
|
|
725
|
-
})();
|
|
726
|
-
});
|
|
727
|
-
it('should show other projects count when multiple exist', function() {
|
|
728
|
-
return _async_to_generator(function() {
|
|
729
|
-
var instance, output;
|
|
730
|
-
return _ts_generator(this, function(_state) {
|
|
731
|
-
switch(_state.label){
|
|
732
|
-
case 0:
|
|
733
|
-
return [
|
|
734
|
-
4,
|
|
735
|
-
px([
|
|
736
|
-
'project',
|
|
737
|
-
'add',
|
|
738
|
-
'Project 1',
|
|
739
|
-
'--url',
|
|
740
|
-
'https://one.positronic.sh'
|
|
741
|
-
], {
|
|
742
|
-
configDir: configDir
|
|
743
|
-
})
|
|
744
|
-
];
|
|
745
|
-
case 1:
|
|
746
|
-
_state.sent();
|
|
747
|
-
return [
|
|
748
|
-
4,
|
|
749
|
-
px([
|
|
750
|
-
'project',
|
|
751
|
-
'add',
|
|
752
|
-
'Project 2',
|
|
753
|
-
'--url',
|
|
754
|
-
'https://two.positronic.sh'
|
|
755
|
-
], {
|
|
756
|
-
configDir: configDir
|
|
757
|
-
})
|
|
758
|
-
];
|
|
759
|
-
case 2:
|
|
760
|
-
_state.sent();
|
|
761
|
-
return [
|
|
762
|
-
4,
|
|
763
|
-
px([
|
|
764
|
-
'project',
|
|
765
|
-
'add',
|
|
766
|
-
'Project 3',
|
|
767
|
-
'--url',
|
|
768
|
-
'https://three.positronic.sh'
|
|
769
|
-
], {
|
|
770
|
-
configDir: configDir
|
|
771
|
-
})
|
|
772
|
-
];
|
|
773
|
-
case 3:
|
|
774
|
-
_state.sent();
|
|
775
|
-
return [
|
|
776
|
-
4,
|
|
777
|
-
px([
|
|
778
|
-
'project',
|
|
779
|
-
'show'
|
|
780
|
-
], {
|
|
781
|
-
configDir: configDir
|
|
782
|
-
})
|
|
783
|
-
];
|
|
784
|
-
case 4:
|
|
785
|
-
instance = _state.sent().instance;
|
|
786
|
-
output = instance.lastFrame() || '';
|
|
787
|
-
expect(output.toLowerCase()).toContain('2 other');
|
|
788
|
-
return [
|
|
789
|
-
2
|
|
790
|
-
];
|
|
791
|
-
}
|
|
792
|
-
});
|
|
793
|
-
})();
|
|
794
|
-
});
|
|
795
|
-
});
|
|
796
|
-
describe('project rm', function() {
|
|
797
|
-
beforeEach(function() {
|
|
798
|
-
return _async_to_generator(function() {
|
|
799
|
-
return _ts_generator(this, function(_state) {
|
|
800
|
-
switch(_state.label){
|
|
801
|
-
case 0:
|
|
802
|
-
// Add some projects for removal tests
|
|
803
|
-
return [
|
|
804
|
-
4,
|
|
805
|
-
px([
|
|
806
|
-
'project',
|
|
807
|
-
'add',
|
|
808
|
-
'Project A',
|
|
809
|
-
'--url',
|
|
810
|
-
'https://a.positronic.sh'
|
|
811
|
-
], {
|
|
812
|
-
configDir: configDir
|
|
813
|
-
})
|
|
814
|
-
];
|
|
815
|
-
case 1:
|
|
816
|
-
_state.sent();
|
|
817
|
-
return [
|
|
818
|
-
4,
|
|
819
|
-
px([
|
|
820
|
-
'project',
|
|
821
|
-
'add',
|
|
822
|
-
'Project B',
|
|
823
|
-
'--url',
|
|
824
|
-
'https://b.positronic.sh'
|
|
825
|
-
], {
|
|
826
|
-
configDir: configDir
|
|
827
|
-
})
|
|
828
|
-
];
|
|
829
|
-
case 2:
|
|
830
|
-
_state.sent();
|
|
831
|
-
return [
|
|
832
|
-
4,
|
|
833
|
-
px([
|
|
834
|
-
'project',
|
|
835
|
-
'add',
|
|
836
|
-
'Project C',
|
|
837
|
-
'--url',
|
|
838
|
-
'https://c.positronic.sh'
|
|
839
|
-
], {
|
|
840
|
-
configDir: configDir
|
|
841
|
-
})
|
|
842
|
-
];
|
|
843
|
-
case 3:
|
|
844
|
-
_state.sent();
|
|
845
|
-
return [
|
|
846
|
-
2
|
|
847
|
-
];
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
})();
|
|
851
|
-
});
|
|
852
|
-
it('should remove a project successfully', function() {
|
|
853
|
-
return _async_to_generator(function() {
|
|
854
|
-
var _ref, waitForOutput, instance, isReady, output, config;
|
|
855
|
-
return _ts_generator(this, function(_state) {
|
|
856
|
-
switch(_state.label){
|
|
857
|
-
case 0:
|
|
858
|
-
return [
|
|
859
|
-
4,
|
|
860
|
-
px([
|
|
861
|
-
'project',
|
|
862
|
-
'rm',
|
|
863
|
-
'Project B'
|
|
864
|
-
], {
|
|
865
|
-
configDir: configDir
|
|
866
|
-
})
|
|
867
|
-
];
|
|
868
|
-
case 1:
|
|
869
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
870
|
-
return [
|
|
871
|
-
4,
|
|
872
|
-
waitForOutput(/removed successfully/i)
|
|
873
|
-
];
|
|
874
|
-
case 2:
|
|
875
|
-
isReady = _state.sent();
|
|
876
|
-
expect(isReady).toBe(true);
|
|
877
|
-
output = instance.lastFrame() || '';
|
|
878
|
-
expect(output).toMatch(/project b/i);
|
|
879
|
-
// Verify project was removed from config
|
|
880
|
-
config = JSON.parse(fs.readFileSync(path.join(configDir, 'config.json'), 'utf-8'));
|
|
881
|
-
expect(config.projects).toHaveLength(2);
|
|
882
|
-
expect(config.projects.find(function(p) {
|
|
883
|
-
return p.name === 'Project B';
|
|
884
|
-
})).toBeUndefined();
|
|
885
|
-
return [
|
|
886
|
-
2
|
|
887
|
-
];
|
|
888
|
-
}
|
|
889
|
-
});
|
|
890
|
-
})();
|
|
891
|
-
});
|
|
892
|
-
it('should handle removing the current project', function() {
|
|
893
|
-
return _async_to_generator(function() {
|
|
894
|
-
var _ref, waitForOutput, instance, isReady, output, config;
|
|
895
|
-
return _ts_generator(this, function(_state) {
|
|
896
|
-
switch(_state.label){
|
|
897
|
-
case 0:
|
|
898
|
-
// Select Project B as current
|
|
899
|
-
return [
|
|
900
|
-
4,
|
|
901
|
-
px([
|
|
902
|
-
'project',
|
|
903
|
-
'select',
|
|
904
|
-
'Project B'
|
|
905
|
-
], {
|
|
906
|
-
configDir: configDir
|
|
907
|
-
})
|
|
908
|
-
];
|
|
909
|
-
case 1:
|
|
910
|
-
_state.sent();
|
|
911
|
-
return [
|
|
912
|
-
4,
|
|
913
|
-
px([
|
|
914
|
-
'project',
|
|
915
|
-
'rm',
|
|
916
|
-
'Project B'
|
|
917
|
-
], {
|
|
918
|
-
configDir: configDir
|
|
919
|
-
})
|
|
920
|
-
];
|
|
921
|
-
case 2:
|
|
922
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
923
|
-
return [
|
|
924
|
-
4,
|
|
925
|
-
waitForOutput(/removed successfully/i)
|
|
926
|
-
];
|
|
927
|
-
case 3:
|
|
928
|
-
isReady = _state.sent();
|
|
929
|
-
expect(isReady).toBe(true);
|
|
930
|
-
output = instance.lastFrame() || '';
|
|
931
|
-
expect(output).toMatch(/project b/i);
|
|
932
|
-
// Verify current project was switched to another project
|
|
933
|
-
config = JSON.parse(fs.readFileSync(path.join(configDir, 'config.json'), 'utf-8'));
|
|
934
|
-
expect(config.currentProject).not.toBe('Project B');
|
|
935
|
-
expect(config.currentProject).toBeTruthy(); // Should be either Project A or Project C
|
|
936
|
-
return [
|
|
937
|
-
2
|
|
938
|
-
];
|
|
939
|
-
}
|
|
940
|
-
});
|
|
941
|
-
})();
|
|
942
|
-
});
|
|
943
|
-
it('should handle removing the last project', function() {
|
|
944
|
-
return _async_to_generator(function() {
|
|
945
|
-
var _ref, waitForOutput, instance, isReady, output, config;
|
|
946
|
-
return _ts_generator(this, function(_state) {
|
|
947
|
-
switch(_state.label){
|
|
948
|
-
case 0:
|
|
949
|
-
// Remove all but one project
|
|
950
|
-
return [
|
|
951
|
-
4,
|
|
952
|
-
px([
|
|
953
|
-
'project',
|
|
954
|
-
'rm',
|
|
955
|
-
'Project A'
|
|
956
|
-
], {
|
|
957
|
-
configDir: configDir
|
|
958
|
-
})
|
|
959
|
-
];
|
|
960
|
-
case 1:
|
|
961
|
-
_state.sent();
|
|
962
|
-
return [
|
|
963
|
-
4,
|
|
964
|
-
px([
|
|
965
|
-
'project',
|
|
966
|
-
'rm',
|
|
967
|
-
'Project B'
|
|
968
|
-
], {
|
|
969
|
-
configDir: configDir
|
|
970
|
-
})
|
|
971
|
-
];
|
|
972
|
-
case 2:
|
|
973
|
-
_state.sent();
|
|
974
|
-
return [
|
|
975
|
-
4,
|
|
976
|
-
px([
|
|
977
|
-
'project',
|
|
978
|
-
'rm',
|
|
979
|
-
'Project C'
|
|
980
|
-
], {
|
|
981
|
-
configDir: configDir
|
|
982
|
-
})
|
|
983
|
-
];
|
|
984
|
-
case 3:
|
|
985
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
986
|
-
return [
|
|
987
|
-
4,
|
|
988
|
-
waitForOutput(/removed successfully/i)
|
|
989
|
-
];
|
|
990
|
-
case 4:
|
|
991
|
-
isReady = _state.sent();
|
|
992
|
-
expect(isReady).toBe(true);
|
|
993
|
-
output = instance.lastFrame() || '';
|
|
994
|
-
expect(output.toLowerCase()).toMatch(/no active project/);
|
|
995
|
-
// Verify no projects remain and current project is null
|
|
996
|
-
config = JSON.parse(fs.readFileSync(path.join(configDir, 'config.json'), 'utf-8'));
|
|
997
|
-
expect(config.projects).toHaveLength(0);
|
|
998
|
-
expect(config.currentProject).toBeNull();
|
|
999
|
-
return [
|
|
1000
|
-
2
|
|
1001
|
-
];
|
|
1002
|
-
}
|
|
1003
|
-
});
|
|
1004
|
-
})();
|
|
1005
|
-
});
|
|
1006
|
-
it('should show error for non-existent project', function() {
|
|
1007
|
-
return _async_to_generator(function() {
|
|
1008
|
-
var _ref, waitForOutput, instance, isReady, output;
|
|
1009
|
-
return _ts_generator(this, function(_state) {
|
|
1010
|
-
switch(_state.label){
|
|
1011
|
-
case 0:
|
|
1012
|
-
return [
|
|
1013
|
-
4,
|
|
1014
|
-
px([
|
|
1015
|
-
'project',
|
|
1016
|
-
'rm',
|
|
1017
|
-
'Non Existent'
|
|
1018
|
-
], {
|
|
1019
|
-
configDir: configDir
|
|
1020
|
-
})
|
|
1021
|
-
];
|
|
1022
|
-
case 1:
|
|
1023
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
1024
|
-
return [
|
|
1025
|
-
4,
|
|
1026
|
-
waitForOutput(/failed to remove/i)
|
|
1027
|
-
];
|
|
1028
|
-
case 2:
|
|
1029
|
-
isReady = _state.sent();
|
|
1030
|
-
expect(isReady).toBe(true);
|
|
1031
|
-
output = instance.lastFrame() || '';
|
|
1032
|
-
expect(output.toLowerCase()).toMatch(/not found/);
|
|
1033
|
-
return [
|
|
1034
|
-
2
|
|
1035
|
-
];
|
|
1036
|
-
}
|
|
1037
|
-
});
|
|
1038
|
-
})();
|
|
1039
|
-
});
|
|
1040
|
-
});
|
|
1041
|
-
describe('project command interactions', function() {
|
|
1042
|
-
it('should maintain state across commands', function() {
|
|
1043
|
-
return _async_to_generator(function() {
|
|
1044
|
-
var instance, output;
|
|
1045
|
-
return _ts_generator(this, function(_state) {
|
|
1046
|
-
switch(_state.label){
|
|
1047
|
-
case 0:
|
|
1048
|
-
// Add multiple projects
|
|
1049
|
-
return [
|
|
1050
|
-
4,
|
|
1051
|
-
px([
|
|
1052
|
-
'project',
|
|
1053
|
-
'add',
|
|
1054
|
-
'First',
|
|
1055
|
-
'--url',
|
|
1056
|
-
'https://first.positronic.sh'
|
|
1057
|
-
], {
|
|
1058
|
-
configDir: configDir
|
|
1059
|
-
})
|
|
1060
|
-
];
|
|
1061
|
-
case 1:
|
|
1062
|
-
_state.sent();
|
|
1063
|
-
return [
|
|
1064
|
-
4,
|
|
1065
|
-
px([
|
|
1066
|
-
'project',
|
|
1067
|
-
'add',
|
|
1068
|
-
'Second',
|
|
1069
|
-
'--url',
|
|
1070
|
-
'https://second.positronic.sh'
|
|
1071
|
-
], {
|
|
1072
|
-
configDir: configDir
|
|
1073
|
-
})
|
|
1074
|
-
];
|
|
1075
|
-
case 2:
|
|
1076
|
-
_state.sent();
|
|
1077
|
-
return [
|
|
1078
|
-
4,
|
|
1079
|
-
px([
|
|
1080
|
-
'project',
|
|
1081
|
-
'show'
|
|
1082
|
-
], {
|
|
1083
|
-
configDir: configDir
|
|
1084
|
-
})
|
|
1085
|
-
];
|
|
1086
|
-
case 3:
|
|
1087
|
-
instance = _state.sent().instance;
|
|
1088
|
-
output = instance.lastFrame() || '';
|
|
1089
|
-
expect(output).toMatch(/first/i);
|
|
1090
|
-
// Switch projects
|
|
1091
|
-
return [
|
|
1092
|
-
4,
|
|
1093
|
-
px([
|
|
1094
|
-
'project',
|
|
1095
|
-
'select',
|
|
1096
|
-
'Second'
|
|
1097
|
-
], {
|
|
1098
|
-
configDir: configDir
|
|
1099
|
-
})
|
|
1100
|
-
];
|
|
1101
|
-
case 4:
|
|
1102
|
-
_state.sent();
|
|
1103
|
-
return [
|
|
1104
|
-
4,
|
|
1105
|
-
px([
|
|
1106
|
-
'project',
|
|
1107
|
-
'show'
|
|
1108
|
-
], {
|
|
1109
|
-
configDir: configDir
|
|
1110
|
-
})
|
|
1111
|
-
];
|
|
1112
|
-
case 5:
|
|
1113
|
-
// Verify switch worked
|
|
1114
|
-
instance = _state.sent().instance;
|
|
1115
|
-
output = instance.lastFrame() || '';
|
|
1116
|
-
expect(output).toMatch(/second/i);
|
|
1117
|
-
return [
|
|
1118
|
-
4,
|
|
1119
|
-
px([
|
|
1120
|
-
'project',
|
|
1121
|
-
'list'
|
|
1122
|
-
], {
|
|
1123
|
-
configDir: configDir
|
|
1124
|
-
})
|
|
1125
|
-
];
|
|
1126
|
-
case 6:
|
|
1127
|
-
// List should show second project
|
|
1128
|
-
instance = _state.sent().instance;
|
|
1129
|
-
output = instance.lastFrame() || '';
|
|
1130
|
-
expect(output).toMatch(/second/i);
|
|
1131
|
-
return [
|
|
1132
|
-
2
|
|
1133
|
-
];
|
|
1134
|
-
}
|
|
1135
|
-
});
|
|
1136
|
-
})();
|
|
1137
|
-
});
|
|
1138
|
-
});
|
|
1139
|
-
describe('CLI Integration: project new', function() {
|
|
1140
|
-
var tmpRoot;
|
|
1141
|
-
var originalLocalPath;
|
|
1142
|
-
beforeEach(function() {
|
|
1143
|
-
// Set POSITRONIC_LOCAL_PATH to use local template instead of npm
|
|
1144
|
-
originalLocalPath = process.env.POSITRONIC_LOCAL_PATH;
|
|
1145
|
-
process.env.POSITRONIC_LOCAL_PATH = path.resolve('.');
|
|
1146
|
-
});
|
|
1147
|
-
afterEach(function() {
|
|
1148
|
-
// Restore original environment
|
|
1149
|
-
if (originalLocalPath) {
|
|
1150
|
-
process.env.POSITRONIC_LOCAL_PATH = originalLocalPath;
|
|
1151
|
-
} else {
|
|
1152
|
-
delete process.env.POSITRONIC_LOCAL_PATH;
|
|
1153
|
-
}
|
|
1154
|
-
if (tmpRoot && fs.existsSync(tmpRoot)) {
|
|
1155
|
-
fs.rmSync(tmpRoot, {
|
|
1156
|
-
recursive: true,
|
|
1157
|
-
force: true
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
});
|
|
1161
|
-
it('should create a new project directory and output success message', function() {
|
|
1162
|
-
return _async_to_generator(function() {
|
|
1163
|
-
var projectDir, _ref, waitForOutput, instance, isReady, output;
|
|
1164
|
-
return _ts_generator(this, function(_state) {
|
|
1165
|
-
switch(_state.label){
|
|
1166
|
-
case 0:
|
|
1167
|
-
tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'positronic-new-test-'));
|
|
1168
|
-
projectDir = path.join(tmpRoot, 'my-new-project');
|
|
1169
|
-
return [
|
|
1170
|
-
4,
|
|
1171
|
-
px([
|
|
1172
|
-
'project',
|
|
1173
|
-
'new',
|
|
1174
|
-
projectDir
|
|
1175
|
-
])
|
|
1176
|
-
];
|
|
1177
|
-
case 1:
|
|
1178
|
-
_ref = _state.sent(), waitForOutput = _ref.waitForOutput, instance = _ref.instance;
|
|
1179
|
-
return [
|
|
1180
|
-
4,
|
|
1181
|
-
waitForOutput(/project created successfully/i, 200)
|
|
1182
|
-
];
|
|
1183
|
-
case 2:
|
|
1184
|
-
isReady = _state.sent();
|
|
1185
|
-
expect(isReady).toBe(true);
|
|
1186
|
-
// Validate CLI output contains the project name
|
|
1187
|
-
output = instance.lastFrame() || '';
|
|
1188
|
-
expect(output.toLowerCase()).toContain('my-new-project');
|
|
1189
|
-
// Ensure project directory and essential files exist
|
|
1190
|
-
expect(fs.existsSync(projectDir)).toBe(true);
|
|
1191
|
-
expect(fs.existsSync(path.join(projectDir, 'positronic.config.json'))).toBe(true);
|
|
1192
|
-
expect(fs.existsSync(path.join(projectDir, 'package.json'))).toBe(true);
|
|
1193
|
-
return [
|
|
1194
|
-
2
|
|
1195
|
-
];
|
|
1196
|
-
}
|
|
1197
|
-
});
|
|
1198
|
-
})();
|
|
1199
|
-
});
|
|
1200
|
-
});
|
|
1201
|
-
});
|