@testrevolution/bugbug-cli 8.14.6 → 8.16.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@testrevolution/bugbug-cli",
3
3
  "description": "BugBug CLI",
4
- "version": "8.14.6",
4
+ "version": "8.16.0",
5
5
  "keywords": [
6
6
  "automation",
7
7
  "cli",
@@ -41,6 +41,12 @@ module.exports = {
41
41
  webappUrl: 'http://localhost:3000/organizations/ed67dc98-16be-48d5-97fe-2f579ca6a62a/projects/cli-cc3abe1c-4540-4451-8bdc-41ac893e5720/runs-history/tests/cabe0d21-7693-4953-8851-581554a70368/',
42
42
  },
43
43
  },
44
+ stopTestRunRunSuccess: {
45
+ data: {
46
+ id: '95a37d6a-a7a5-42ae-8fe3-336a120b807b',
47
+ status: 'stopped',
48
+ },
49
+ },
44
50
  getResultTestRunSuccess: {
45
51
  data: {
46
52
  details: [{
@@ -21,13 +21,12 @@ beforeAll(() => {
21
21
  afterAll(() => {
22
22
  config.__RewireAPI__.__ResetDependency__('readConfig');
23
23
  });
24
+ jest.mock('axios');
24
25
 
25
26
  afterEach(() => {
26
27
  jest.restoreAllMocks();
27
28
  });
28
29
 
29
- jest.mock('axios');
30
-
31
30
  describe('commands module', () => {
32
31
  describe('help', () => {
33
32
  it('should console log main help menu', async () => {
@@ -0,0 +1,95 @@
1
+ const axios = require('axios');
2
+
3
+ const {
4
+ remote: remoteCommand,
5
+ } = require('../commands');
6
+ const settings = require('../settings');
7
+ const config = require('../utils/config');
8
+ // eslint-disable-next-line jest/no-mocks-import
9
+ const apiMocks = require('../__mocks__/api');
10
+
11
+ const configValue = { item: 'value', token: '1337' };
12
+
13
+ beforeAll(() => {
14
+ // rewire discussion
15
+ // https://github.com/facebook/jest/issues/936#issuecomment-545080082
16
+ config.__RewireAPI__.__Rewire__('readConfig', jest.fn().mockReturnValue(configValue));
17
+ });
18
+
19
+ afterAll(() => {
20
+ config.__RewireAPI__.__ResetDependency__('readConfig');
21
+ });
22
+ jest.mock('axios');
23
+
24
+ afterEach(() => {
25
+ jest.restoreAllMocks();
26
+ });
27
+
28
+ describe('commands stop module', () => {
29
+ beforeAll(() => {
30
+ settings.API_POLLING_INTERVAL = 1;
31
+ settings.API_POLLING_MAX_RETRY_TIMES = 5;
32
+ settings.API_URL = 'https://bugbug.io/test-api/';
33
+ });
34
+
35
+ it('should return error when testRunId is missing', async () => {
36
+ const consoleLogSpy = jest.spyOn(console, 'error').mockImplementation();
37
+ const args = {
38
+ _: ['remote', 'stop', 'test'],
39
+ noprogress: true,
40
+ };
41
+ await remoteCommand(args);
42
+
43
+ expect(consoleLogSpy).toHaveBeenNthCalledWith(1, 'Missing testRun id.');
44
+ });
45
+
46
+ it('stop test command should call API', async () => {
47
+ const consoleLogSpy = jest.spyOn(console, 'error').mockImplementation();
48
+ axios.mockResolvedValueOnce(apiMocks.stopTestRunRunSuccess);
49
+ const id = '95a37d6a-a7a5-42ae-8fe3-336a120b807b';
50
+ const args = {
51
+ _: ['remote', 'stop', 'test', id],
52
+ noprogress: true,
53
+ };
54
+ await remoteCommand(args);
55
+
56
+ expect(consoleLogSpy).toHaveBeenNthCalledWith(1, `Status: ${apiMocks.stopTestRunRunSuccess.data.status}`);
57
+ expect(axios).toHaveBeenCalledWith({
58
+ method: 'POST',
59
+ url: `https://bugbug.io/test-api/v1/testruns/${id}/stop/`,
60
+ data: { triggeredBy: 'cli' },
61
+ params: {},
62
+ headers: { Authorization: `Token ${configValue.token}`, 'User-Agent': settings.USER_AGENT },
63
+ });
64
+ });
65
+
66
+ it('stop test action should call stopTestRun function', async () => {
67
+ const stopMock = jest.fn();
68
+ remoteCommand.__RewireAPI__.__Rewire__('stopTestRun', stopMock);
69
+
70
+ const id = '95a37d6a-a7a5-42ae-8fe3-336a120b807b';
71
+ const args = {
72
+ _: ['remote', 'stop', 'test', id],
73
+ noprogress: true,
74
+ };
75
+ await remoteCommand(args);
76
+ expect(stopMock).toHaveBeenCalledWith(id, {
77
+ noprogress: true, nowait: false, outputPath: 'test-report.xml', reporter: 'inline', triggeredBy: 'cli', withDetails: false,
78
+ });
79
+ });
80
+
81
+ it('stop suite action should call stopSuiteRun function', async () => {
82
+ const stopMock = jest.fn();
83
+ remoteCommand.__RewireAPI__.__Rewire__('stopSuiteRun', stopMock);
84
+
85
+ const id = '95a37d6a-a7a5-42ae-8fe3-336a120b807b';
86
+ const args = {
87
+ _: ['remote', 'stop', 'suite', id],
88
+ noprogress: true,
89
+ };
90
+ await remoteCommand(args);
91
+ expect(stopMock).toHaveBeenCalledWith(id, {
92
+ noprogress: true, nowait: false, outputPath: 'test-report.xml', reporter: 'inline', triggeredBy: 'cli', withDetails: false,
93
+ });
94
+ });
95
+ });
@@ -23,6 +23,7 @@ const help = {
23
23
  * run [test|suite] <string:testId|suiteId> [--no-wait] [--no-progress] [--debug] [--with-details] [--profile] [--variable] [--result-timeout <int>]
24
24
  * status [test|suite] <string:testRunId|suiteRunId> [--no-progress] [--debug]
25
25
  * result [test|suite] <string:testRunId|suiteRunId> [--no-progress] [--debug] [--with-details] [--result-timeout <int>]
26
+ * stop [test|suite] <string:testRunId|suiteRunId> [--no-progress] [--debug] [--result-timeout <int>]
26
27
 
27
28
  optional flags:
28
29
  * --debug - show more data (like raw API response)
@@ -128,6 +128,33 @@ const run = async (type, data, extraParams) => {
128
128
  return getExitCode(false);
129
129
  };
130
130
 
131
+ const stop = async (type, { id }, extraParams) => {
132
+ const { noprogress } = extraParams;
133
+ const route = settings.API_ROUTING[`${type}Stop`];
134
+ const spinner = getSpinner(noprogress);
135
+
136
+ if (!id) {
137
+ spinner.fail(`Missing ${type}Run id.`);
138
+ return getExitCode(false);
139
+ }
140
+
141
+ const path = format(route.path, id);
142
+
143
+ try {
144
+ const response = await apiCall(path, route.method, {}, {}, extraParams.triggeredBy);
145
+ printStatus(spinner, response.data.status);
146
+
147
+ return getExitCode(true);
148
+ } catch (error) {
149
+ if (error.response?.status === 404) {
150
+ spinner.fail(`No ${type}Run with id ${id} found.`);
151
+ } else {
152
+ await printErrorResponse(spinner, error);
153
+ }
154
+ }
155
+ return getExitCode(false);
156
+ };
157
+
131
158
  const runTest = async (testId, profileName, variables, extraParams) => run(settings.TYPE_TEST, {
132
159
  test_id: testId, profile_name: profileName, variables,
133
160
  }, extraParams);
@@ -136,6 +163,14 @@ const runSuite = async (suiteId, profileName, variables, extraParams) => run(set
136
163
  suite_id: suiteId, profile_name: profileName, variables,
137
164
  }, extraParams);
138
165
 
166
+ const stopTestRun = async (testRunId, extraParams) => stop(settings.TYPE_TEST, {
167
+ id: testRunId,
168
+ }, extraParams);
169
+
170
+ const stopSuiteRun = async (suiteRunId, extraParams) => stop(settings.TYPE_SUITE, {
171
+ id: suiteRunId,
172
+ }, extraParams);
173
+
139
174
  const checkTokenConfig = async () => {
140
175
  try {
141
176
  if (await getConfigValue('token') === undefined) {
@@ -223,6 +258,13 @@ module.exports = async (args) => {
223
258
  case settings.ACTION_STATUS:
224
259
  exitCode = await checkStatus(objectType, id, extraParams);
225
260
  break;
261
+ case settings.ACTION_STOP:
262
+ if (objectType === settings.TYPE_TEST) {
263
+ exitCode = await stopTestRun(id, extraParams);
264
+ } else if (objectType === settings.TYPE_SUITE) {
265
+ exitCode = await stopSuiteRun(id, extraParams);
266
+ }
267
+ break;
226
268
  case settings.ACTION_RESULT:
227
269
  exitCode = await getResult(objectType, id, extraParams);
228
270
  break;
package/src/settings.js CHANGED
@@ -25,6 +25,7 @@ const ACTION_HELP = 'help';
25
25
  const ACTION_SET_TOKEN = 'set-token';
26
26
  const ACTION_LIST = 'list';
27
27
  const ACTION_RUN = 'run';
28
+ const ACTION_STOP = 'stop';
28
29
  const ACTION_STATUS = 'status';
29
30
  const ACTION_RESULT = 'result';
30
31
 
@@ -35,10 +36,12 @@ const API_ROUTING = {
35
36
  suiteResult: { method: 'GET', path: `${API_VERSION}/suiteruns/%s/` },
36
37
  suiteRun: { method: 'POST', path: `${API_VERSION}/suiteruns/` },
37
38
  suiteStatus: { method: 'GET', path: `${API_VERSION}/suiteruns/%s/status/` },
39
+ suiteStop: { method: 'POST', path: `${API_VERSION}/suiteruns/%s/stop/` },
38
40
  testList: { method: 'GET', path: `${API_VERSION}/tests/` },
39
41
  testResult: { method: 'GET', path: `${API_VERSION}/testruns/%s/` },
40
42
  testRun: { method: 'POST', path: `${API_VERSION}/testruns/` },
41
43
  testStatus: { method: 'GET', path: `${API_VERSION}/testruns/%s/status/` },
44
+ testStop: { method: 'POST', path: `${API_VERSION}/testruns/%s/stop/` },
42
45
  };
43
46
 
44
47
  const API_POLLING_MODIFIED_INTERVAL = 120000; // 120 seconds
@@ -81,6 +84,7 @@ module.exports = {
81
84
  ACTION_RUN,
82
85
  ACTION_SET_TOKEN,
83
86
  ACTION_STATUS,
87
+ ACTION_STOP,
84
88
  API_CALL_RETRIES,
85
89
  API_CALL_RETRY_DELAY,
86
90
  API_ERROR_QUOTA_EXCEEDED,