Skip to content

Commit

Permalink
[RND-513] Jest is taking too long (#222)
Browse files Browse the repository at this point in the history
* Adding debug configuration for extension

* Adding missing config values for tests

* Update dependencies

* Restore jest mongo db

* Add fastify mocks to close connection

* Fixing mock that was doing an actual db connection

* Refactor of get test to avoid multiple setup and multiple connections

* Fixing post test to mock db connection

* Fixing mock on test for Put

* Fix typo

* Adding method to get successful frontend response for tests

* Fix mocking on frontend facade

* Using specific tsconfig file for spec files to have a simpler compilation

* Test workers

* Fixing jest config import

* Moving maxWorkers to default config

* Adding max workers explicitly on action

* Adding jest cache

* Adding script for unit tests on CI
  • Loading branch information
andonyns committed Mar 17, 2023
1 parent 0141edc commit 9db1d62
Show file tree
Hide file tree
Showing 26 changed files with 707 additions and 404 deletions.
21 changes: 16 additions & 5 deletions .github/workflows/on-pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,10 @@ jobs:
matrix:
tests:
[
{
type: "Unit",
command: "npm run test:unit:coverage -- --ci",
},
{ type: "Unit", command: "npm run test:unit:coverage:ci" },
{
type: "Integration",
command: "npm run test:integration -- --ci ",
command: "npm run test:integration -- --ci",
},
]

Expand Down Expand Up @@ -190,6 +187,13 @@ jobs:
if: ${{ steps.modules-cache.outputs.cache-hit != 'true' }}
run: npm install

- name: Jest cache
id: cache-jest
uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 #v3.0.11
with:
path: /tmp/jest_rt
key: ${{ runner.os }}-jest-${{ hashFiles('**/package-lock.json') }}

- name: Configure postgres
if: ${{ matrix.tests.type != 'Unit' }}
run: |
Expand Down Expand Up @@ -251,6 +255,13 @@ jobs:
- name: Install required dependencies
run: npm install -D cross-env

- name: Jest cache
id: cache-jest
uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 #v3.0.11
with:
path: /tmp/jest_rt
key: ${{ runner.os }}-jest-${{ hashFiles('**/package-lock.json') }}

- name: Create .env file
run: |
touch .env
Expand Down
11 changes: 11 additions & 0 deletions Meadowlark-js/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@
"console": "integratedTerminal",
"sourceMaps": true
},
{
"type": "node",
"name": "vscode-jest-tests",
"request": "launch",
"console": "integratedTerminal",
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js",
"args": [
"jest",
"--runInBand",
]
},
{
"type": "node",
"name": "MongoDb Integration Tests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

import { FrontendRequest, FrontendResponse, newFrontendRequest, newFrontendResponse } from '@edfi/meadowlark-core';
import { FrontendRequest, FrontendResponse, newFrontendRequest, newFrontendResponseSuccess } from '@edfi/meadowlark-core';
import { newFrontendRequestMiddleware } from '@edfi/meadowlark-core/src/handler/FrontendRequest';
import { newPathComponents } from '@edfi/meadowlark-core/src/model/PathComponents';
import { securityMiddleware } from '../../src/security/SecurityMiddleware';
Expand All @@ -13,7 +13,7 @@ jest.setTimeout(40000);

describe('given the upsert where response already posted', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};

const frontendRequest: FrontendRequest = {
...newFrontendRequest(),
Expand All @@ -24,13 +24,10 @@ describe('given the upsert where response already posted', () => {
},
};

const frontendResponse: FrontendResponse = {
...newFrontendResponse(),
statusCode: 200,
};
const frontendResponse: FrontendResponse = newFrontendResponseSuccess();

beforeAll(async () => {
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should return the original arguments without modification', async () => {
Expand All @@ -49,7 +46,7 @@ describe('given the upsert where response already posted', () => {

describe('given the upsert where authorization strategy type is different than OWNERSHIP_BASED', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};
const frontendResponse: any = null;

const frontendRequest: FrontendRequest = {
Expand All @@ -62,7 +59,7 @@ describe('given the upsert where authorization strategy type is different than O
};

beforeAll(async () => {
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should return the original arguments without modification', async () => {
Expand All @@ -81,7 +78,7 @@ describe('given the upsert where authorization strategy type is different than O

describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHIP_BASED and SecurityResult equal to ACCESS_APPROVED', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};
const frontendResponse: any = null;

const frontendRequest: FrontendRequest = {
Expand All @@ -102,7 +99,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI
beforeAll(async () => {
jest.spyOn(OwnershipSecurity, 'rejectByOwnershipSecurity').mockResolvedValueOnce('ACCESS_APPROVED');

result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should return the original arguments without modification', async () => {
Expand All @@ -126,7 +123,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI

describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHIP_BASED and SecurityResult equal to NOT_APPLICABLE', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};
const frontendResponse: any = null;

const frontendRequest: FrontendRequest = {
Expand All @@ -147,7 +144,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI
beforeAll(async () => {
jest.spyOn(OwnershipSecurity, 'rejectByOwnershipSecurity').mockResolvedValueOnce('NOT_APPLICABLE');

result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should return the original arguments without modification', async () => {
Expand All @@ -171,7 +168,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI

describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHIP_BASED and SecurityResult equal to UNKNOWN_FAILURE', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};
const frontendResponse: any = null;

const frontendRequest: FrontendRequest = {
Expand All @@ -192,7 +189,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI
beforeAll(async () => {
jest.spyOn(OwnershipSecurity, 'rejectByOwnershipSecurity').mockResolvedValueOnce('UNKNOWN_FAILURE');

result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should respond with an internal server error code', async () => {
Expand Down Expand Up @@ -220,7 +217,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI

describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHIP_BASED and SecurityResult equal to ACCESS_DENIED', () => {
let result;
const mongoClienttMock = {};
const mongoClientMock = {};
const frontendResponse: any = null;

const frontendRequest: FrontendRequest = {
Expand All @@ -241,7 +238,7 @@ describe('given the upsert where AuthorizationStrategy type is equal to OWNERSHI
beforeAll(async () => {
jest.spyOn(OwnershipSecurity, 'rejectByOwnershipSecurity').mockResolvedValueOnce('ACCESS_DENIED');

result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClienttMock as any);
result = await securityMiddleware({ frontendRequest, frontendResponse }, mongoClientMock as any);
});

it('should respond with a Forbidden error code', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jest.setTimeout(40000);

describe('given a transaction on a resource', () => {
const retryNumberOfTimes = 2;
let mongoClienttMock = {};
let mongoClientMock = {};
let deleteOneMock = jest.fn();
const error = {
codeName: 'WriteConflict',
Expand All @@ -20,7 +20,7 @@ describe('given a transaction on a resource', () => {
deleteOne: deleteOneMock,
} as any);

mongoClienttMock = {
mongoClientMock = {
startSession: jest.fn().mockReturnValue({
withTransaction: async (cb: any) => {
await cb();
Expand All @@ -44,7 +44,7 @@ describe('given a transaction on a resource', () => {
describe('given that a number of retries greater than zero has been configured', () => {
beforeAll(async () => {
jest.spyOn(utilities.Config, 'get').mockReturnValue(retryNumberOfTimes);
result = await deleteDocumentById(newDeleteRequest(), mongoClienttMock as any);
result = await deleteDocumentById(newDeleteRequest(), mongoClientMock as any);
});

it('returns error', async () => {
Expand All @@ -63,7 +63,7 @@ describe('given a transaction on a resource', () => {
describe('given that a number of retries equal to zero has been configured', () => {
beforeAll(async () => {
jest.spyOn(utilities.Config, 'get').mockReturnValue(0);
result = await deleteDocumentById(newDeleteRequest(), mongoClienttMock as any);
result = await deleteDocumentById(newDeleteRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand All @@ -77,7 +77,7 @@ describe('given a transaction on a resource', () => {

describe('given that a number of retries was not configured', () => {
beforeAll(async () => {
result = await deleteDocumentById(newDeleteRequest(), mongoClienttMock as any);
result = await deleteDocumentById(newDeleteRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.setTimeout(40000);

describe('given a transaction on a resource', () => {
const retryNumberOfTimes = 2;
let mongoClienttMock = {};
let mongoClientMock = {};
let replaceOneMock = jest.fn();
const error = {
codeName: 'WriteConflict',
Expand All @@ -29,7 +29,7 @@ describe('given a transaction on a resource', () => {
updateMany: jest.fn(),
} as any);

mongoClienttMock = {
mongoClientMock = {
startSession: jest.fn().mockReturnValue({
withTransaction: async (cb: any) => {
await cb();
Expand Down Expand Up @@ -57,7 +57,7 @@ describe('given a transaction on a resource', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
jest.spyOn(utilities.Config, 'get').mockReturnValue(retryNumberOfTimes);
result = await updateDocumentById(newUpdateRequest(), mongoClienttMock as any);
result = await updateDocumentById(newUpdateRequest(), mongoClientMock as any);
});

it('returns error', async () => {
Expand All @@ -77,7 +77,7 @@ describe('given a transaction on a resource', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
jest.spyOn(utilities.Config, 'get').mockReturnValue(0);
result = await updateDocumentById(newUpdateRequest(), mongoClienttMock as any);
result = await updateDocumentById(newUpdateRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand All @@ -92,7 +92,7 @@ describe('given a transaction on a resource', () => {
describe('given that a number of retries was not configured', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
result = await updateDocumentById(newUpdateRequest(), mongoClienttMock as any);
result = await updateDocumentById(newUpdateRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jest.setTimeout(40000);

describe('given a transaction on a resource', () => {
const retryNumberOfTimes = 2;
let mongoClienttMock = {};
let mongoClientMock = {};
let replaceOneMock = jest.fn();
const error = {
codeName: 'WriteConflict',
Expand All @@ -22,7 +22,7 @@ describe('given a transaction on a resource', () => {
updateMany: jest.fn(),
} as any);

mongoClienttMock = {
mongoClientMock = {
startSession: jest.fn().mockReturnValue({
withTransaction: async (cb: any) => {
await cb();
Expand All @@ -49,7 +49,7 @@ describe('given a transaction on a resource', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
jest.spyOn(utilities.Config, 'get').mockReturnValue(retryNumberOfTimes);
result = await upsertDocument(newUpsertRequest(), mongoClienttMock as any);
result = await upsertDocument(newUpsertRequest(), mongoClientMock as any);
});

it('returns error', async () => {
Expand All @@ -69,7 +69,7 @@ describe('given a transaction on a resource', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
jest.spyOn(utilities.Config, 'get').mockReturnValue(0);
result = await upsertDocument(newUpsertRequest(), mongoClienttMock as any);
result = await upsertDocument(newUpsertRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand All @@ -84,7 +84,7 @@ describe('given a transaction on a resource', () => {
describe('given that a number of retries was not configured', () => {
beforeAll(async () => {
jest.spyOn(DB, 'writeLockReferencedDocuments').mockImplementationOnce(async () => Promise.resolve());
result = await upsertDocument(newUpsertRequest(), mongoClienttMock as any);
result = await upsertDocument(newUpsertRequest(), mongoClientMock as any);
});

it('should not retry', () => {
Expand Down
2 changes: 0 additions & 2 deletions Meadowlark-js/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const { defaults: tsjPreset } = require('ts-jest/presets');

module.exports = {
projects: [
'<rootDir>/tests/config/unit/jest.config.js',
Expand Down

0 comments on commit 9db1d62

Please sign in to comment.