@testim/testim-cli 3.266.0 → 3.268.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/commons/socket/baseSocketServiceSocketIO.js +25 -2
- package/commons/socket/testResultService.js +0 -1
- package/commons/testimDesiredCapabilitiesBuilder.js +14 -7
- package/commons/testimServicesApi.js +31 -5
- package/npm-shrinkwrap.json +38 -38
- package/package.json +1 -1
- package/reports/consoleReporter.js +6 -2
- package/runOptions.d.ts +4 -3
- package/runOptions.js +3 -2
- package/runner.js +1 -1
- package/runners/ParallelWorkerManager.js +66 -12
- package/runners/TestPlanRunner.js +2 -4
- package/services/gridService.js +48 -36
- package/services/gridService.test.js +11 -18
- package/testRunHandler.js +216 -235
- package/testRunStatus.js +9 -1
- package/testimNpmDriver.js +15 -18
- package/workers/BaseWorker.js +98 -44
- package/workers/BaseWorker.test.js +2 -7
- package/workers/WorkerAppium.js +64 -24
- package/workers/WorkerExtension.js +11 -5
- package/workers/WorkerExtensionSingleBrowser.js +12 -2
- package/workers/WorkerSelenium.js +29 -20
package/services/gridService.js
CHANGED
|
@@ -59,38 +59,47 @@ function getSerializableObject(grid) {
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
62
|
+
/**
|
|
63
|
+
* @template {{ status: string; code?: string; grid: * }} T
|
|
64
|
+
* @param {string} projectId
|
|
65
|
+
* @param {string} companyId
|
|
66
|
+
* @param {number} workerId
|
|
67
|
+
* @param {string} browser
|
|
68
|
+
* @param {() => Promise<T>} getFun
|
|
69
|
+
*/
|
|
70
|
+
async function handleGetGridResponse(projectId, companyId, workerId, browser, getFun) {
|
|
71
|
+
/** @type {T} */
|
|
72
|
+
let res;
|
|
73
|
+
try {
|
|
74
|
+
res = await getFun();
|
|
75
|
+
} catch (err) {
|
|
76
|
+
logger.error('failed to get grid', { projectId, companyId, err });
|
|
77
|
+
throw new Error(gridMessages.UNKNOWN);
|
|
78
|
+
}
|
|
79
|
+
logger.info('get grid info', Object.assign({}, res, { projectId, companyId }));
|
|
80
|
+
const isSuccess = () => res.status === 'success';
|
|
81
|
+
const isError = () => res.status === 'error' && res.code;
|
|
82
|
+
if (!res || (!isError() && !isSuccess())) {
|
|
83
|
+
logger.error('invalid response - get grid', { res });
|
|
84
|
+
throw new Error(gridMessages.UNKNOWN);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isSuccess()) {
|
|
88
|
+
const serGrid = getSerializableObject(res.grid);
|
|
89
|
+
module.exports.addItemToGridCache(workerId, companyId, serGrid.gridId, serGrid.slotId, browser);
|
|
90
|
+
return serGrid;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (isError() && res.code === 'not-found') {
|
|
94
|
+
throw new GridError(gridMessages.NOT_FOUND);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (isError() && res.code === 'no-available-slot') {
|
|
98
|
+
throw new GridError(`Failed to run test on ${browser} - concurrency limit reached`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
logger.error('invalid code error response - get grid', { res });
|
|
102
|
+
throw new GridError(gridMessages.UNKNOWN);
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
function addItemToGridCache(workerId, companyId, gridId, slotId, browser) {
|
|
@@ -264,7 +273,13 @@ async function getGridData(options) {
|
|
|
264
273
|
throw new GridError('Missing host or grid configuration');
|
|
265
274
|
}
|
|
266
275
|
|
|
267
|
-
|
|
276
|
+
/**
|
|
277
|
+
* @param {string} browser
|
|
278
|
+
* @param {string} executionId
|
|
279
|
+
* @param {import('../runOptions')} options
|
|
280
|
+
* @param {number} workerId
|
|
281
|
+
*/
|
|
282
|
+
async function getGridSlot(browser, executionId, options, workerId) {
|
|
268
283
|
const getGridDataFromServer = async () => {
|
|
269
284
|
const { host, project, grid, gridId, useLocalChromeDriver, useChromeLauncher, company = {} } = options;
|
|
270
285
|
const companyId = company.companyId;
|
|
@@ -284,9 +299,6 @@ async function getGridSlot(browser, executionId, testResultId, onGridSlot, optio
|
|
|
284
299
|
};
|
|
285
300
|
|
|
286
301
|
const gridInfo = await getGridDataFromServer();
|
|
287
|
-
|
|
288
|
-
await onGridSlot(executionId, testResultId, gridInfo);
|
|
289
|
-
|
|
290
302
|
return gridInfo;
|
|
291
303
|
}
|
|
292
304
|
|
|
@@ -169,14 +169,12 @@ describe('gridService', () => {
|
|
|
169
169
|
describe('getGridSlot', () => {
|
|
170
170
|
let getGridByIdStub;
|
|
171
171
|
let getGridByNameStub;
|
|
172
|
-
let onGridSlot;
|
|
173
172
|
let addItemToGridCacheStub;
|
|
174
173
|
|
|
175
174
|
beforeEach(() => {
|
|
176
175
|
getGridByIdStub = sinon.stub(servicesApi, 'getGridById').resolves({ grid: { gridId: 'gridId', type: 'gridId' }, status: 'success' });
|
|
177
176
|
getGridByNameStub = sinon.stub(servicesApi, 'getGridByName').resolves({ grid: { gridId: 'gridId', type: 'gridName' }, status: 'success' });
|
|
178
177
|
addItemToGridCacheStub = sinon.stub(gridService, 'addItemToGridCache').callThrough();
|
|
179
|
-
onGridSlot = sinon.stub().resolves();
|
|
180
178
|
});
|
|
181
179
|
afterEach(() => {
|
|
182
180
|
getGridByIdStub.restore();
|
|
@@ -185,82 +183,77 @@ describe('gridService', () => {
|
|
|
185
183
|
});
|
|
186
184
|
|
|
187
185
|
it('should not access server when using useLocalChromeDriver flag', async () => {
|
|
188
|
-
const slot = await gridService.getGridSlot('browser', 'executionId',
|
|
186
|
+
const slot = await gridService.getGridSlot('browser', 'executionId', { useLocalChromeDriver: true }, 'workerId');
|
|
189
187
|
expect(slot).to.eql({ mode: 'local' });
|
|
190
188
|
sinon.assert.notCalled(getGridByIdStub);
|
|
191
189
|
sinon.assert.notCalled(getGridByNameStub);
|
|
192
190
|
sinon.assert.notCalled(addItemToGridCacheStub);
|
|
193
|
-
sinon.assert.calledOnce(onGridSlot);
|
|
194
191
|
});
|
|
195
192
|
|
|
196
193
|
it('should not access server when using useChromeLauncher flag', async () => {
|
|
197
|
-
const slot = await gridService.getGridSlot('browser', 'executionId',
|
|
194
|
+
const slot = await gridService.getGridSlot('browser', 'executionId', { useChromeLauncher: true }, 'workerId');
|
|
198
195
|
expect(slot).to.eql({ mode: 'local' });
|
|
199
196
|
sinon.assert.notCalled(getGridByIdStub);
|
|
200
197
|
sinon.assert.notCalled(getGridByNameStub);
|
|
201
198
|
sinon.assert.notCalled(addItemToGridCacheStub);
|
|
202
|
-
sinon.assert.calledOnce(onGridSlot);
|
|
203
199
|
});
|
|
204
200
|
|
|
205
201
|
it('should return fixed grid when passing host and port', async () => {
|
|
206
|
-
const slot = await gridService.getGridSlot('browser', 'executionId',
|
|
202
|
+
const slot = await gridService.getGridSlot('browser', 'executionId', { host: 'localhost', port: 4444 }, 'workerId');
|
|
207
203
|
expect(slot).to.shallowDeepEqual({ type: 'hostAndPort', host: 'localhost', port: 4444 });
|
|
208
204
|
sinon.assert.notCalled(getGridByIdStub);
|
|
209
205
|
sinon.assert.notCalled(getGridByNameStub);
|
|
210
206
|
sinon.assert.notCalled(addItemToGridCacheStub);
|
|
211
|
-
sinon.assert.calledOnce(onGridSlot);
|
|
212
207
|
});
|
|
213
208
|
|
|
214
209
|
it('should get grid from server when passing grid id', async () => {
|
|
215
|
-
const slot = await gridService.getGridSlot('browser', 'executionId',
|
|
210
|
+
const slot = await gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId');
|
|
216
211
|
expect(slot).to.shallowDeepEqual({ type: 'gridId', gridId: 'gridId' });
|
|
217
212
|
sinon.assert.calledOnce(getGridByIdStub);
|
|
218
213
|
sinon.assert.notCalled(getGridByNameStub);
|
|
219
214
|
sinon.assert.calledOnce(addItemToGridCacheStub);
|
|
220
|
-
sinon.assert.calledOnce(onGridSlot);
|
|
221
215
|
});
|
|
222
216
|
|
|
223
217
|
it('should get grid from server when passing grid name', async () => {
|
|
224
|
-
const slot = await gridService.getGridSlot('browser', 'executionId',
|
|
218
|
+
const slot = await gridService.getGridSlot('browser', 'executionId', { grid: 'gridName' }, 'workerId');
|
|
225
219
|
expect(slot).to.shallowDeepEqual({ type: 'gridName', gridId: 'gridId' });
|
|
226
220
|
sinon.assert.calledOnce(getGridByNameStub);
|
|
227
221
|
sinon.assert.notCalled(getGridByIdStub);
|
|
228
222
|
sinon.assert.calledOnce(addItemToGridCacheStub);
|
|
229
|
-
sinon.assert.calledOnce(onGridSlot);
|
|
230
223
|
});
|
|
231
224
|
|
|
232
225
|
it('should handle grid not found error', async () => {
|
|
233
226
|
getGridByIdStub.resolves({ status: 'error', code: 'not-found' });
|
|
234
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
227
|
+
await expect(gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId'))
|
|
235
228
|
.to.eventually.be.rejectedWith('The specified grid is not available');
|
|
236
229
|
});
|
|
237
230
|
|
|
238
231
|
it('should handle no available slot error', async () => {
|
|
239
232
|
getGridByIdStub.resolves({ status: 'error', code: 'no-available-slot' });
|
|
240
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
233
|
+
await expect(gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId'))
|
|
241
234
|
.to.eventually.be.rejectedWith('Failed to run test on browser - concurrency limit reached');
|
|
242
235
|
});
|
|
243
236
|
|
|
244
237
|
it('should handle getGridSlot request error', async () => {
|
|
245
238
|
getGridByIdStub.rejects({ status: 'error', code: 'not-found' });
|
|
246
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
239
|
+
await expect(gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId'))
|
|
247
240
|
.to.eventually.be.rejectedWith('Test couldn\'t get browser - unknown error');
|
|
248
241
|
});
|
|
249
242
|
|
|
250
243
|
it('should throw when no grid selected', async () => {
|
|
251
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
244
|
+
await expect(gridService.getGridSlot('browser', 'executionId', {}, 'workerId'))
|
|
252
245
|
.to.eventually.be.rejectedWith('Missing host or grid configuration');
|
|
253
246
|
});
|
|
254
247
|
|
|
255
248
|
it('should handle unkonwn errors', async () => {
|
|
256
249
|
getGridByIdStub.resolves({ status: 'error', code: 'bla bla' });
|
|
257
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
250
|
+
await expect(gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId'))
|
|
258
251
|
.to.eventually.be.rejectedWith('Test couldn\'t get browser - unknown error');
|
|
259
252
|
});
|
|
260
253
|
|
|
261
254
|
it('should handle no status', async () => {
|
|
262
255
|
getGridByIdStub.resolves({ code: 'bla bla' });
|
|
263
|
-
await expect(gridService.getGridSlot('browser', 'executionId',
|
|
256
|
+
await expect(gridService.getGridSlot('browser', 'executionId', { gridId: 'gridId' }, 'workerId'))
|
|
264
257
|
.to.eventually.be.rejectedWith('Test couldn\'t get browser - unknown error');
|
|
265
258
|
});
|
|
266
259
|
});
|