Skip to content

Commit 5528fcf

Browse files
Add E2E Cypress negative cases tests for github activity and repositories
Signed-off-by: Lukasz Gryglicki <[email protected]> Assisted by [OpenAI](https://platform.openai.com/) Assisted by [GitHub Copilot](https://github.com/features/copilot)
1 parent a6c0b92 commit 5528fcf

File tree

2 files changed

+173
-33
lines changed

2 files changed

+173
-33
lines changed

tests/functional/cypress/e2e/v4/github-repositories.cy.ts

Lines changed: 172 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
validateApiResponse,
33
validate_200_Status,
4+
validate_401_Status,
45
getTokenKey,
56
getAPIBaseURL,
67
getXACLHeader,
@@ -199,18 +200,19 @@ describe('To Validate github-repositories API call', function () {
199200
// Use the same project SFID and repository ID as the working tests
200201
const projectSfidOrg = appConfig.childProjectSFID;
201202
const repositoryID = 'f577ae5d-5616-453f-a77e-9a76ff2910ec';
203+
const local = Cypress.env('LOCAL') ? true : false;
204+
const timeout = 180000;
202205

203-
const defaultHeaders = getXACLHeader();
204206
const claBaseEndpoint = getAPIBaseURL('v4');
205207

206208
const requests = [
209+
// GET /project/{projectSFID}/github/repositories
207210
{
208-
title: 'GET /project/.../github/repositories without token',
209211
method: 'GET',
210212
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories`,
211213
},
214+
// POST /project/{projectSFID}/github/repositories
212215
{
213-
title: 'POST /project/.../github/repositories without token',
214216
method: 'POST',
215217
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories`,
216218
body: {
@@ -220,18 +222,18 @@ describe('To Validate github-repositories API call', function () {
220222
repository_github_ids: ['12345'],
221223
},
222224
},
225+
// DELETE /project/{projectSFID}/github/repositories/{repositoryID}
223226
{
224-
title: 'DELETE /project/.../github/repositories/... without token',
225227
method: 'DELETE',
226228
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${repositoryID}`,
227229
},
230+
// GET /project/{projectSFID}/github/repositories/{repositoryID}/branch-protection
228231
{
229-
title: 'GET /project/.../github/repositories/.../branch-protection without token',
230232
method: 'GET',
231233
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${repositoryID}/branch-protection`,
232234
},
235+
// POST /project/{projectSFID}/github/repositories/{repositoryID}/branch-protection
233236
{
234-
title: 'POST /project/.../github/repositories/.../branch-protection without token',
235237
method: 'POST',
236238
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${repositoryID}/branch-protection`,
237239
body: {
@@ -242,22 +244,33 @@ describe('To Validate github-repositories API call', function () {
242244
},
243245
];
244246

245-
requests.forEach((request) => {
246-
cy.request({
247-
method: request.method,
248-
url: request.url,
249-
body: request.body,
250-
failOnStatusCode: false,
251-
}).then((response) => {
252-
validate_expected_status(response, 401, undefined, undefined, undefined);
253-
});
247+
cy.wrap(requests).each((req: any) => {
248+
return cy
249+
.request({
250+
method: req.method as any,
251+
url: req.url,
252+
body: req.body,
253+
failOnStatusCode: false, // expect 401
254+
timeout,
255+
})
256+
.then((response) => {
257+
return cy.logJson('401 response (github-repositories)', response).then(() => {
258+
validate_expected_status(response, 401, undefined, undefined, undefined);
259+
});
260+
});
254261
});
255262
});
256263

257264
it('Returns errors due to missing or malformed parameters for GitHub Repositories APIs', function () {
258-
// Use the same project SFID and repository ID as the working tests
259265
const projectSfidOrg = appConfig.childProjectSFID;
260266
const repositoryID = 'f577ae5d-5616-453f-a77e-9a76ff2910ec';
267+
const badUUID = 'aa';
268+
const badUUID2 = 'd9428888-122b-4b20-8c4a-0c9a1a6z9b8e';
269+
const badSFID = 'bad';
270+
const badSFID2 = '001000000000-00AAA';
271+
const exampleSFID = '001000000000000AAA';
272+
const local = Cypress.env('LOCAL') ? true : false;
273+
const timeout = 180000;
261274

262275
const defaultHeaders = getXACLHeader();
263276
const defaultAuth = { bearer: bearerToken };
@@ -285,6 +298,124 @@ describe('To Validate github-repositories API call', function () {
285298
expectedMessage?: string;
286299
expectedMessageContains?: boolean;
287300
}> = [
301+
// --- POST /project/{projectSFID}/github/repositories (missing required fields) ---
302+
{
303+
title: 'POST /project/.../github/repositories with missing cla_group_id',
304+
method: 'POST',
305+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories`,
306+
body: {
307+
github_organization_name: 'test-org',
308+
repository_github_id: '12345',
309+
repository_github_ids: ['12345'],
310+
},
311+
expectedStatus: 422,
312+
expectedCode: 602,
313+
expectedMessage: 'cla_group_id in body is required',
314+
expectedMessageContains: false,
315+
},
316+
{
317+
title: 'POST /project/.../github/repositories with missing github_organization_name',
318+
method: 'POST',
319+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories`,
320+
body: {
321+
cla_group_id: 'd9428888-122b-4b20-8c4a-0c9a1a6f9b8e',
322+
repository_github_id: '12345',
323+
repository_github_ids: ['12345'],
324+
},
325+
expectedStatus: 422,
326+
expectedCode: 602,
327+
expectedMessage: 'github_organization_name in body is required',
328+
expectedMessageContains: false,
329+
},
330+
{
331+
title: 'POST /project/.../github/repositories with missing repository_github_id',
332+
method: 'POST',
333+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories`,
334+
body: {
335+
cla_group_id: 'd9428888-122b-4b20-8c4a-0c9a1a6f9b8e',
336+
github_organization_name: 'test-org',
337+
repository_github_ids: ['12345'],
338+
},
339+
expectedStatus: 400,
340+
expectedCode: 400,
341+
expectedMessage: 'provided cla group id d9428888-122b-4b20-8c4a-0c9a1a6f9b8e is not linked to project sfid',
342+
expectedMessageContains: true,
343+
},
344+
345+
// --- POST /project/{projectSFID}/github/repositories/{repositoryID}/branch-protection (missing required fields) ---
346+
{
347+
title: 'POST /project/.../github/repositories/.../branch-protection with missing branch_name',
348+
method: 'POST',
349+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${repositoryID}/branch-protection`,
350+
body: {
351+
enforce_admin: true,
352+
status_checks: [{ enabled: true, name: 'EasyCLA' }],
353+
},
354+
expectedStatus: 200,
355+
// API seems to handle missing branch_name gracefully by using default branch
356+
},
357+
358+
// --- Path parameter validation ---
359+
{
360+
title: 'GET /project/.../github/repositories with malformed projectSFID (too short)',
361+
method: 'GET',
362+
url: `${claBaseEndpoint}project/${badSFID}/github/repositories`,
363+
expectedStatus: 404,
364+
expectedCode: 404,
365+
expectedMessage: 'unable to locate project with ID: bad',
366+
expectedMessageContains: true,
367+
},
368+
{
369+
title: 'GET /project/.../github/repositories with malformed projectSFID (bad format)',
370+
method: 'GET',
371+
url: `${claBaseEndpoint}project/${badSFID2}/github/repositories`,
372+
expectedStatus: 404,
373+
expectedCode: 404,
374+
expectedMessage: 'unable to locate project with ID',
375+
expectedMessageContains: true,
376+
},
377+
{
378+
title: 'DELETE /project/.../github/repositories/... with malformed repositoryID (too short)',
379+
method: 'DELETE',
380+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${badUUID}`,
381+
expectedStatus: 404,
382+
expectedCode: 404,
383+
expectedMessage: 'repository not found for projectSFID',
384+
expectedMessageContains: true,
385+
},
386+
{
387+
title: 'DELETE /project/.../github/repositories/... with malformed repositoryID (bad format)',
388+
method: 'DELETE',
389+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${badUUID2}`,
390+
expectedStatus: 404,
391+
expectedCode: 404,
392+
expectedMessage: 'repository not found for projectSFID',
393+
expectedMessageContains: true,
394+
},
395+
{
396+
title: 'GET /project/.../github/repositories/.../branch-protection with malformed repositoryID (too short)',
397+
method: 'GET',
398+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${badUUID}/branch-protection`,
399+
expectedStatus: 404,
400+
expectedCode: 404,
401+
expectedMessage: 'unable to locatate branch protection projectSFID',
402+
expectedMessageContains: true,
403+
},
404+
{
405+
title: 'POST /project/.../github/repositories/.../branch-protection with malformed repositoryID (bad format)',
406+
method: 'POST',
407+
url: `${claBaseEndpoint}project/${projectSfidOrg}/github/repositories/${badUUID2}/branch-protection`,
408+
body: {
409+
branch_name: 'main',
410+
enforce_admin: true,
411+
status_checks: [{ enabled: true, name: 'EasyCLA' }],
412+
},
413+
expectedStatus: 404,
414+
expectedCode: 404,
415+
expectedMessage: 'unable to update branch protection for projectSFID',
416+
expectedMessageContains: true,
417+
},
418+
288419
// (Sanity) valid-looking parameters should succeed (or at least get past validation)
289420
{
290421
title: 'GET /project/.../github/repositories with valid projectSFID',
@@ -300,26 +431,34 @@ describe('To Validate github-repositories API call', function () {
300431
},
301432
];
302433

303-
cases.forEach((testCase) => {
304-
cy.request({
305-
method: testCase.method,
306-
url: testCase.url,
434+
cy.wrap(cases).each((c: any) => {
435+
cy.task('log', `--> ${c.title} | ${c.method} ${c.url}`);
436+
const opts: any = {
437+
method: c.method,
438+
url: c.url,
307439
headers: defaultHeaders,
308440
auth: defaultAuth,
309-
body: testCase.body,
310441
failOnStatusCode: false,
311-
}).then((response) => {
312-
cy.task(
313-
'log',
314-
`--> expected ${testCase.expectedStatus}, ${testCase.expectedCode}, '${testCase.expectedMessage}' (contains? ${testCase.expectedMessageContains})`,
315-
);
316-
validate_expected_status(
317-
response,
318-
testCase.expectedStatus,
319-
testCase.expectedCode,
320-
testCase.expectedMessage,
321-
testCase.expectedMessageContains,
322-
);
442+
timeout,
443+
};
444+
if (c.body) opts.body = c.body;
445+
446+
cy.request(opts).then((response) => {
447+
return cy.logJson('response', response).then(() => {
448+
const es = local
449+
? (c.expectedStatusLocal ?? c.expectedStatus)
450+
: (c.expectedStatusRemote ?? c.expectedStatus);
451+
const ec = local ? (c.expectedCodeLocal ?? c.expectedCode) : (c.expectedCodeRemote ?? c.expectedCode);
452+
const em = local
453+
? (c.expectedMessageLocal ?? c.expectedMessage)
454+
: (c.expectedMessageRemote ?? c.expectedMessage);
455+
const emc = local
456+
? (c.expectedMessageContainsLocal ?? c.expectedMessageContains)
457+
: (c.expectedMessageContainsRemote ?? c.expectedMessageContains);
458+
459+
cy.task('log', ` --> expected ${es}, ${ec}, '${em}' (contains? ${emc})`);
460+
validate_expected_status(response, es, ec, em, emc);
461+
});
323462
});
324463
});
325464
});

tests/functional/cypress/e2e/v4/githubActivity.cy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
validate_200_Status,
3+
validate_401_Status,
34
getTokenKey,
45
getAPIBaseURL,
56
getXACLHeader,

0 commit comments

Comments
 (0)