@vida-global/core 1.1.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/README.md +9 -0
- package/index.js +17 -0
- package/lib/active_record/README.md +205 -0
- package/lib/active_record/baseRecord.js +112 -0
- package/lib/active_record/db/connection.js +128 -0
- package/lib/active_record/db/connectionConfiguration.js +114 -0
- package/lib/active_record/db/importSchema.js +4 -0
- package/lib/active_record/db/migration.js +132 -0
- package/lib/active_record/db/migrationTemplate.js +8 -0
- package/lib/active_record/db/migrationVersion.js +68 -0
- package/lib/active_record/db/migrator.js +169 -0
- package/lib/active_record/db/queryInterface.js +47 -0
- package/lib/active_record/db/schema.js +113 -0
- package/lib/active_record/index.js +6 -0
- package/lib/active_record/utils.js +43 -0
- package/lib/http/README.md +32 -0
- package/lib/http/client.js +129 -0
- package/lib/http/error.js +34 -0
- package/lib/logger/README.md +2 -0
- package/lib/logger/index.js +16 -0
- package/lib/release/develop.js +27 -0
- package/lib/release/git.js +86 -0
- package/lib/release/increment.js +56 -0
- package/lib/release/index.js +10 -0
- package/lib/release/release.js +30 -0
- package/lib/release/utils.js +44 -0
- package/lib/server/README.md +37 -0
- package/lib/server/index.js +9 -0
- package/lib/server/server.js +359 -0
- package/lib/server/serverController.js +344 -0
- package/lib/server/systemController.js +23 -0
- package/package.json +37 -0
- package/scripts/active_record/migrate.js +30 -0
- package/scripts/release.js +62 -0
- package/test/active_record/baseRecord.test.js +179 -0
- package/test/active_record/db/connection.test.js +221 -0
- package/test/active_record/db/connectionConfiguration.test.js +184 -0
- package/test/active_record/db/migrator.test.js +266 -0
- package/test/active_record/db/queryInterface.test.js +66 -0
- package/test/http/client.test.js +271 -0
- package/test/http/error.test.js +71 -0
- package/test/release/develop.test.js +57 -0
- package/test/release/git.test.js +189 -0
- package/test/release/increment.test.js +145 -0
- package/test/release/release.test.js +72 -0
- package/test/release/utils.test.js +148 -0
- package/test/server/helpers/controllers/barController.js +9 -0
- package/test/server/helpers/controllers/fooController.js +48 -0
- package/test/server/helpers/controllers/sub/bazController.js +10 -0
- package/test/server/helpers/server.js +14 -0
- package/test/server/server.test.js +188 -0
- package/test/server/serverController.test.js +251 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
const { HttpClient } = require('../../lib/http/client');
|
|
2
|
+
const TestHelpers = require('@vida-global/test-helpers');
|
|
3
|
+
const { logger } = require('../../lib/logger');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const urlRoot = `https://${TestHelpers.Faker.Text.randomString()}.com`.toLowerCase();
|
|
7
|
+
const apiEndpoint = `/${TestHelpers.Faker.Text.randomString()}`
|
|
8
|
+
const apiUrl = `${urlRoot}${apiEndpoint}`;
|
|
9
|
+
const requestReturnValue = {
|
|
10
|
+
[TestHelpers.Faker.Text.randomString()]: Math.random()
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ClientWithUrlRoot extends HttpClient {
|
|
15
|
+
get urlRoot() { return urlRoot; }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
global.fetch = jest.fn().mockReturnValue({
|
|
20
|
+
json: () => requestReturnValue,
|
|
21
|
+
status: 200
|
|
22
|
+
});
|
|
23
|
+
logger.info = jest.fn();
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
jest.clearAllMocks();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
describe('HttpClient#urlRoot', () => {
|
|
32
|
+
it ('prepends the url root when overriden', async () => {
|
|
33
|
+
const client = new ClientWithUrlRoot();
|
|
34
|
+
await client.post(apiEndpoint);
|
|
35
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expect.any(Object));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/***************************************************************************************************
|
|
41
|
+
* POST
|
|
42
|
+
***************************************************************************************************/
|
|
43
|
+
describe('HttpClient#post', () => {
|
|
44
|
+
const client = new HttpClient();
|
|
45
|
+
|
|
46
|
+
it ('returns the result of the API request', async () => {
|
|
47
|
+
const res = await client.post(apiUrl);
|
|
48
|
+
expect(res).toEqual({data: requestReturnValue, status: 200});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it ('calls fetch with the provided url and default params', async () => {
|
|
52
|
+
const expectedRequestParams = {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
body: "{}",
|
|
55
|
+
headers: {
|
|
56
|
+
Accept: "application/json",
|
|
57
|
+
"Content-Type": "application/json",
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
await client.post(apiUrl);
|
|
62
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
63
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it ('includes the provided body in the request', async () => {
|
|
67
|
+
const body = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
68
|
+
await client.post(apiUrl, { body });
|
|
69
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expect.objectContaining({
|
|
70
|
+
body: JSON.stringify(body)
|
|
71
|
+
}));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it ('includes additional headers', async () => {
|
|
75
|
+
const headers = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
76
|
+
const expectedRequestParams = {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
body: "{}",
|
|
79
|
+
headers: {
|
|
80
|
+
Accept: "application/json",
|
|
81
|
+
"Content-Type": "application/json",
|
|
82
|
+
...headers
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
await client.post(apiUrl, { headers });
|
|
87
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it ('logs api requests', async () => {
|
|
91
|
+
await client.post(apiUrl);
|
|
92
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
93
|
+
expect(logger.info).toHaveBeenCalledWith(`API CALL: POST ${apiUrl}`);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/***************************************************************************************************
|
|
99
|
+
* PUT
|
|
100
|
+
***************************************************************************************************/
|
|
101
|
+
describe('HttpClient#put', () => {
|
|
102
|
+
const client = new HttpClient();
|
|
103
|
+
|
|
104
|
+
it ('returns the result of the API request', async () => {
|
|
105
|
+
const res = await client.put(apiUrl);
|
|
106
|
+
expect(res).toEqual({data: requestReturnValue, status: 200});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it ('calls fetch with the provided url and default params', async () => {
|
|
110
|
+
const expectedRequestParams = {
|
|
111
|
+
method: 'PUT',
|
|
112
|
+
body: "{}",
|
|
113
|
+
headers: {
|
|
114
|
+
Accept: "application/json",
|
|
115
|
+
"Content-Type": "application/json",
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
await client.put(apiUrl);
|
|
120
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
121
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it ('includes the provided body in the request', async () => {
|
|
125
|
+
const body = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
126
|
+
await client.put(apiUrl, { body });
|
|
127
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expect.objectContaining({
|
|
128
|
+
body: JSON.stringify(body)
|
|
129
|
+
}));
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it ('includes additional headers', async () => {
|
|
133
|
+
const headers = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
134
|
+
const expectedRequestParams = {
|
|
135
|
+
method: 'PUT',
|
|
136
|
+
body: "{}",
|
|
137
|
+
headers: {
|
|
138
|
+
Accept: "application/json",
|
|
139
|
+
"Content-Type": "application/json",
|
|
140
|
+
...headers
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
await client.put(apiUrl, { headers });
|
|
145
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it ('logs api requests', async () => {
|
|
149
|
+
await client.put(apiUrl);
|
|
150
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
151
|
+
expect(logger.info).toHaveBeenCalledWith(`API CALL: PUT ${apiUrl}`);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
/***************************************************************************************************
|
|
157
|
+
* GET
|
|
158
|
+
***************************************************************************************************/
|
|
159
|
+
describe('HttpClient#get', () => {
|
|
160
|
+
const client = new HttpClient();
|
|
161
|
+
it ('returns the result of the API request', async () => {
|
|
162
|
+
const res = await client.get(apiUrl);
|
|
163
|
+
expect(res).toEqual({data: requestReturnValue, status: 200});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it ('calls fetch with the provided url and default params', async () => {
|
|
167
|
+
const expectedRequestParams = {
|
|
168
|
+
method: 'GET',
|
|
169
|
+
headers: {
|
|
170
|
+
Accept: "application/json",
|
|
171
|
+
"Content-Type": "application/json",
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await client.get(apiUrl);
|
|
176
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
177
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it ('includes the provided params in the url', async () => {
|
|
181
|
+
const param1Name = TestHelpers.Faker.Text.randomString();
|
|
182
|
+
const param1Value = TestHelpers.Faker.Text.randomString();
|
|
183
|
+
const param2Name = TestHelpers.Faker.Text.randomString();
|
|
184
|
+
const param2Value = TestHelpers.Faker.Text.randomString();
|
|
185
|
+
const requestParams = {[param1Name]: param1Value, [param2Name]: param2Value};
|
|
186
|
+
const expectedUrl = `${apiUrl}?${param1Name}=${param1Value}&${param2Name}=${param2Value}`;
|
|
187
|
+
await client.get(apiUrl, {requestParams });
|
|
188
|
+
|
|
189
|
+
expect(fetch).toHaveBeenCalledWith(expectedUrl, expect.any(Object));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it ('includes additional headers', async () => {
|
|
193
|
+
const headers = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
194
|
+
const expectedRequestParams = {
|
|
195
|
+
method: 'GET',
|
|
196
|
+
headers: {
|
|
197
|
+
Accept: "application/json",
|
|
198
|
+
"Content-Type": "application/json",
|
|
199
|
+
...headers
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
await client.get(apiUrl, { headers });
|
|
204
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it ('logs api requests', async () => {
|
|
208
|
+
await client.get(apiUrl);
|
|
209
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
210
|
+
expect(logger.info).toHaveBeenCalledWith(`API CALL: GET ${apiUrl}`);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
/***************************************************************************************************
|
|
216
|
+
* DELETE
|
|
217
|
+
***************************************************************************************************/
|
|
218
|
+
describe('HttpClient#delete', () => {
|
|
219
|
+
const client = new HttpClient();
|
|
220
|
+
it ('returns the result of the API request', async () => {
|
|
221
|
+
const res = await client.delete(apiUrl);
|
|
222
|
+
expect(res).toEqual({data: requestReturnValue, status: 200});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it ('calls fetch with the provided url and default params', async () => {
|
|
226
|
+
const expectedRequestParams = {
|
|
227
|
+
method: 'DELETE',
|
|
228
|
+
headers: {
|
|
229
|
+
Accept: "application/json",
|
|
230
|
+
"Content-Type": "application/json",
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await client.delete(apiUrl);
|
|
235
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
236
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it ('includes the provided params in the url', async () => {
|
|
240
|
+
const param1Name = TestHelpers.Faker.Text.randomString();
|
|
241
|
+
const param1Value = TestHelpers.Faker.Text.randomString();
|
|
242
|
+
const param2Name = TestHelpers.Faker.Text.randomString();
|
|
243
|
+
const param2Value = TestHelpers.Faker.Text.randomString();
|
|
244
|
+
const requestParams = {[param1Name]: param1Value, [param2Name]: param2Value};
|
|
245
|
+
const expectedUrl = `${apiUrl}?${param1Name}=${param1Value}&${param2Name}=${param2Value}`;
|
|
246
|
+
await client.delete(apiUrl, {requestParams });
|
|
247
|
+
|
|
248
|
+
expect(fetch).toHaveBeenCalledWith(expectedUrl, expect.any(Object));
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it ('includes additional headers', async () => {
|
|
252
|
+
const headers = {[TestHelpers.Faker.Text.randomString()]: Math.random()};
|
|
253
|
+
const expectedRequestParams = {
|
|
254
|
+
method: 'DELETE',
|
|
255
|
+
headers: {
|
|
256
|
+
Accept: "application/json",
|
|
257
|
+
"Content-Type": "application/json",
|
|
258
|
+
...headers
|
|
259
|
+
},
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await client.delete(apiUrl, { headers });
|
|
263
|
+
expect(fetch).toHaveBeenCalledWith(apiUrl, expectedRequestParams);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it ('logs api requests', async () => {
|
|
267
|
+
await client.delete(apiUrl);
|
|
268
|
+
expect(logger.info).toHaveBeenCalledTimes(1);
|
|
269
|
+
expect(logger.info).toHaveBeenCalledWith(`API CALL: DELETE ${apiUrl}`);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const { HttpError } = require('../../lib/http/error');
|
|
2
|
+
const TestHelpers = require('@vida-global/test-helpers');
|
|
3
|
+
|
|
4
|
+
const key1 = TestHelpers.Faker.Text.randomString()
|
|
5
|
+
const key2 = TestHelpers.Faker.Text.randomString()
|
|
6
|
+
const key3 = TestHelpers.Faker.Text.randomString()
|
|
7
|
+
const key4 = TestHelpers.Faker.Text.randomString()
|
|
8
|
+
const key5 = TestHelpers.Faker.Text.randomString()
|
|
9
|
+
const val1 = TestHelpers.Faker.Text.randomString()
|
|
10
|
+
const val2 = TestHelpers.Faker.Text.randomString()
|
|
11
|
+
const val3 = TestHelpers.Faker.Text.randomString()
|
|
12
|
+
const val4 = TestHelpers.Faker.Text.randomString()
|
|
13
|
+
const val5 = TestHelpers.Faker.Text.randomString()
|
|
14
|
+
|
|
15
|
+
const response = {
|
|
16
|
+
headers: {
|
|
17
|
+
[key1]: val1,
|
|
18
|
+
[key2]: val2,
|
|
19
|
+
},
|
|
20
|
+
status: Math.random(),
|
|
21
|
+
statusText: TestHelpers.Faker.Text.randomString(),
|
|
22
|
+
url: TestHelpers.Faker.Text.randomString(),
|
|
23
|
+
};
|
|
24
|
+
const requestPayload = {
|
|
25
|
+
[key3]: val3,
|
|
26
|
+
[key4]: {[key5]: val5}
|
|
27
|
+
};
|
|
28
|
+
const error = new HttpError(response, requestPayload);
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
describe('HttpError', () => {
|
|
32
|
+
it ('returns the status code in the message', () => {
|
|
33
|
+
expect(error.message).toEqual(`HTTP Error: ${response.status}`);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it ('returns the response status code as the status', () => {
|
|
37
|
+
expect(error.status).toEqual(response.status);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it ('passes through the status text', () => {
|
|
41
|
+
expect(error.statusText).toEqual(response.statusText);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it ('passes through the url', () => {
|
|
45
|
+
expect(error.url).toEqual(response.url);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it ('passes through a copy of the response headers', () => {
|
|
49
|
+
expect(error.responseHeaders).toEqual(response.headers);
|
|
50
|
+
expect(error.responseHeaders).not.toBe(response.headers);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it ('passes through a copy of the request payload', () => {
|
|
54
|
+
expect(error.requestPayload).toEqual(requestPayload);
|
|
55
|
+
expect(error.requestPayload).not.toBe(requestPayload);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it ('converts the response body to JSON if possible', async () => {
|
|
59
|
+
response.text = () => `{"${key1}": "${val1}", "${key2}": {"${key3}": "${val3}"}}`;
|
|
60
|
+
const data = await error.data();
|
|
61
|
+
const expected = {[key1]: val1, [key2]: {[key3]: val3}};
|
|
62
|
+
expect(data).toEqual(expected);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it ('returns text when the body is not JSON', async () => {
|
|
66
|
+
const text = TestHelpers.Faker.Text.randomString();
|
|
67
|
+
response.text = () => text;
|
|
68
|
+
const data = await error.data();
|
|
69
|
+
expect(data).toEqual(text);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const { develop } = require('../../lib/release/develop');
|
|
2
|
+
const Git = require('../../lib/release/git');
|
|
3
|
+
const TestHelpers = require('@vida-global/test-helpers');
|
|
4
|
+
const utils = require('../../lib/release/utils');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
jest.mock('../../lib/release/git', () => {
|
|
8
|
+
return { createBranch: jest.fn(), getCurrentUser: jest.fn() }
|
|
9
|
+
});
|
|
10
|
+
jest.mock('../../lib/release/utils', () => {
|
|
11
|
+
return { confirmContinue: jest.fn() };
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
let branchType;
|
|
16
|
+
let description;
|
|
17
|
+
let firstName;
|
|
18
|
+
let issueNumber;
|
|
19
|
+
let lastName;
|
|
20
|
+
let sourceBranch;
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.resetAllMocks();
|
|
23
|
+
utils.confirmContinue.mockImplementation(() => true);
|
|
24
|
+
|
|
25
|
+
firstName = TestHelpers.Faker.User.randomFirstName();
|
|
26
|
+
lastName = TestHelpers.Faker.User.randomLastName();
|
|
27
|
+
Git.getCurrentUser.mockImplementation(() => `${firstName} ${lastName}`);
|
|
28
|
+
|
|
29
|
+
branchType = TestHelpers.Faker.Text.randomString();
|
|
30
|
+
sourceBranch = TestHelpers.Faker.Text.randomString();
|
|
31
|
+
description = TestHelpers.Faker.Text.randomSentence();
|
|
32
|
+
issueNumber = TestHelpers.Faker.Math.randomNumber();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
describe('develop', () => {
|
|
37
|
+
it ('confirms and creates a branch once', async () => {
|
|
38
|
+
await develop(branchType, issueNumber, description, sourceBranch);
|
|
39
|
+
expect(utils.confirmContinue).toHaveBeenCalledTimes(1);
|
|
40
|
+
expect(Git.createBranch).toHaveBeenCalledTimes(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it ('generates the correct branch name', async () => {
|
|
44
|
+
const initials = `${firstName[0]}${lastName[0]}`.toLowerCase();
|
|
45
|
+
const branchName = `${branchType}/${issueNumber}/${initials}/${description.replace(/\s+/g, '-').toLowerCase().replace(/[^a-z0-9-]/g, '')}`;
|
|
46
|
+
await develop(branchType, issueNumber, description, sourceBranch);
|
|
47
|
+
|
|
48
|
+
expect(utils.confirmContinue).toHaveBeenCalledWith(`Do you want to create branch ${branchName}?`);
|
|
49
|
+
expect(Git.createBranch).toHaveBeenCalledWith(branchName, sourceBranch);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it ('does not create a branch if the user does not confirm', async () => {
|
|
53
|
+
utils.confirmContinue.mockImplementation(() => false);
|
|
54
|
+
await develop(branchType, issueNumber, description, sourceBranch);
|
|
55
|
+
expect(Git.createBranch).not.toHaveBeenCalled();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const Git = require('../../lib/release/git');
|
|
3
|
+
const TestHelpers = require('@vida-global/test-helpers');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
jest.mock('child_process', () => {
|
|
7
|
+
const execSync = jest.fn();
|
|
8
|
+
return { execSync };
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.resetAllMocks();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
describe('Git.add', () => {
|
|
18
|
+
it ('calls git add with the file name', () => {
|
|
19
|
+
const fileName = TestHelpers.Faker.Text.randomString();
|
|
20
|
+
Git.add(fileName);
|
|
21
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
22
|
+
expect(execSync).toHaveBeenCalledWith(`git add ${fileName}`);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
describe('Git.branches', () => {
|
|
28
|
+
it ('calls git branch and returns an array of the resulting strings', () => {
|
|
29
|
+
const b1 = TestHelpers.Faker.Text.randomString();
|
|
30
|
+
const b2 = TestHelpers.Faker.Text.randomString();
|
|
31
|
+
const b3 = TestHelpers.Faker.Text.randomString();
|
|
32
|
+
const branchStr = ` ${b1} \n ${b2}\n${b3} `;
|
|
33
|
+
execSync.mockImplementation(() => branchStr);
|
|
34
|
+
|
|
35
|
+
const branches = Git.branches();
|
|
36
|
+
|
|
37
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
38
|
+
expect(branches).toEqual([b1, b2, b3]);
|
|
39
|
+
expect(execSync).toHaveBeenCalledWith(`git branch -r`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it ('does not include the remote option when needed', () => {
|
|
43
|
+
execSync.mockImplementation(() => '');
|
|
44
|
+
const branches = Git.branches(false);
|
|
45
|
+
expect(execSync).toHaveBeenCalledWith(`git branch`);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
describe('Git.checkout', () => {
|
|
51
|
+
it ('calls git checkout with the branch name', () => {
|
|
52
|
+
const branchName = TestHelpers.Faker.Text.randomString();
|
|
53
|
+
Git.checkout(branchName);
|
|
54
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(execSync).toHaveBeenCalledWith(`git checkout ${branchName}`);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
describe('Git.commit', () => {
|
|
61
|
+
it ('calls git commit with comment', () => {
|
|
62
|
+
const comment = TestHelpers.Faker.Text.randomString();
|
|
63
|
+
Git.commit(comment);
|
|
64
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
65
|
+
expect(execSync).toHaveBeenCalledWith(`git commit -m '${comment}'`);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
describe('Git.createBranch', () => {
|
|
71
|
+
it ('creates a branch and switches to it', () => {
|
|
72
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
73
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
74
|
+
|
|
75
|
+
Git.createBranch(branch1, branch2);
|
|
76
|
+
|
|
77
|
+
expect(execSync).toHaveBeenCalledTimes(2);
|
|
78
|
+
expect(execSync).toHaveBeenNthCalledWith(1, `git branch ${branch1} ${branch2}`);
|
|
79
|
+
expect(execSync).toHaveBeenNthCalledWith(2, `git checkout ${branch1}`);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it ('defaults to the primary branch', () => {
|
|
83
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
84
|
+
|
|
85
|
+
execSync.mockImplementation(() => 'origin/main');
|
|
86
|
+
|
|
87
|
+
Git.createBranch(branch1);
|
|
88
|
+
|
|
89
|
+
expect(execSync).toHaveBeenCalledTimes(3);
|
|
90
|
+
expect(execSync).toHaveBeenNthCalledWith(2, `git branch ${branch1} origin/main`);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
describe('Git.forceRemotePush', () => {
|
|
96
|
+
it ('calls git push with the origin', () => {
|
|
97
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
98
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
99
|
+
|
|
100
|
+
Git.forceRemotePush(branch1, branch2);
|
|
101
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
102
|
+
expect(execSync).toHaveBeenCalledWith(`git push origin origin/${branch1}:${branch2} --force`)
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
describe('Git.getCurrentUser', () => {
|
|
108
|
+
it ('returns the result of git config.name', () => {
|
|
109
|
+
const name = TestHelpers.Faker.User.randomName();
|
|
110
|
+
execSync.mockImplementation(() => name);
|
|
111
|
+
|
|
112
|
+
const response = Git.getCurrentUser();
|
|
113
|
+
|
|
114
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
115
|
+
expect(execSync).toHaveBeenCalledWith(`git config user.name`);
|
|
116
|
+
expect(response).toEqual(name);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
describe('Git.getPrimaryBranch', () => {
|
|
122
|
+
it ('returns master when that is the primary branch', () => {
|
|
123
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
124
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
125
|
+
const branchStr = ` origin/${branch1}\n origin/master \n origin/${branch2}`;
|
|
126
|
+
execSync.mockImplementation(() => branchStr);
|
|
127
|
+
|
|
128
|
+
const branch = Git.getPrimaryBranch();
|
|
129
|
+
|
|
130
|
+
expect(branch).toEqual('origin/master');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it ('returns main when that is the primary branch', () => {
|
|
134
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
135
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
136
|
+
const branchStr = `origin/${branch1}\norigin/${branch2}\n origin/main `;
|
|
137
|
+
execSync.mockImplementation(() => branchStr);
|
|
138
|
+
|
|
139
|
+
const branch = Git.getPrimaryBranch();
|
|
140
|
+
|
|
141
|
+
expect(branch).toEqual('origin/main');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it ('returns undefined when it cannot determine the primary branch', () => {
|
|
145
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
146
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
147
|
+
const branch3 = TestHelpers.Faker.Text.randomString();
|
|
148
|
+
const branchStr = `origin/${branch1}\norigin/${branch2}\n origin/${branch3} `;
|
|
149
|
+
execSync.mockImplementation(() => branchStr);
|
|
150
|
+
|
|
151
|
+
const branch = Git.getPrimaryBranch();
|
|
152
|
+
|
|
153
|
+
expect(branch).toBeUndefined();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
describe('Git.getCurrentBranch', () => {
|
|
159
|
+
it ('returns the branch with the *', () => {
|
|
160
|
+
const branch1 = TestHelpers.Faker.Text.randomString();
|
|
161
|
+
const branch2 = TestHelpers.Faker.Text.randomString();
|
|
162
|
+
const branch3 = TestHelpers.Faker.Text.randomString();
|
|
163
|
+
const branchStr = ` origin/${branch1}\n * ${branch3} \n origin/${branch2}`;
|
|
164
|
+
execSync.mockImplementation(() => branchStr);
|
|
165
|
+
|
|
166
|
+
const branch = Git.getCurrentBranch();
|
|
167
|
+
|
|
168
|
+
expect(branch).toEqual(branch3);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
describe('Git.pull', () => {
|
|
174
|
+
it ('calls git pull with the prune option', () => {
|
|
175
|
+
Git.pull();
|
|
176
|
+
expect(execSync).toHaveBeenCalledTimes(1);
|
|
177
|
+
expect(execSync).toHaveBeenCalledWith(`git pull --prune`);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
describe('Git.push', () => {
|
|
183
|
+
it ('pushes to the current branch', () => {
|
|
184
|
+
const branch = TestHelpers.Faker.Text.randomString();
|
|
185
|
+
execSync.mockImplementation(() => `* ${branch}`);
|
|
186
|
+
Git.push();
|
|
187
|
+
expect(execSync).toHaveBeenCalledWith(`git push -u origin ${branch}`);
|
|
188
|
+
});
|
|
189
|
+
});
|