Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .env.local
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
DB_URI=postgres://reporting_dashboard_role:reportingdashboard123@localhost:5432/reporting_dashboard_dev
POSTGRES_HOST=0.0.0.0
POSTGRES_DB=reporting_dashboard_dev
POSTGRES_USER=reporting_dashboard_role
POSTGRES_PASSWORD=reportingdashboard123
DB_URI=postgres://postgres:[email protected]:5432/negt
POSTGRES_HOST=host.docker.internal
POSTGRES_DB=negt
POSTGRES_USER=postgres
POSTGRES_PASSWORD=root
NODE_ENV=local
ACCESS_TOKEN_SECRET=4cd7234152590dcfe77e1b6fc52e84f4d30c06fddadd0dd2fb42cbc51fa14b1bb195bbe9d72c9599ba0c6b556f9bd1607a8478be87e5a91b697c74032e0ae7af
REDIS_HOST=localhost
REDIS_HOST=host.docker.internal
REDIS_PORT=6379
12 changes: 12 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ENVIRONMENT_NAME=test
NODE_ENV=test

POSTGRES_DB=test_mock
POSTGRES_USER=test_mock
POSTGRES_PASSWORD=test123
POSTGRES_PORT=54320

DB_URI=postgres://test_mock:test123@localhost:54320/test_mock?sslmode=disable

REDIS_DOMAIN=test
REDIS_PORT=6380
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ jobs:
run: yarn lint
- name: Test
run: yarn test
- name: Run Integration Test
run: yarn test:integration
- name: Build
run: yarn build:local
- name: SonarQube Scan
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,7 @@ typings/
# DS_Store
.DS_Store
report.json
reports/test-report.xml
reports/test-report.xml

# Docker slim
slim.report.json
65 changes: 65 additions & 0 deletions __tests__/server/gql/model/address.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const { closeRedisConnection } = require('@server/services/redis');
const { getMockDBEnv, getResponse } = require('@server/utils/testUtils');
const { get } = require('lodash');

const createAddressMutation = `
mutation {
createAddress(
latitude: 123.456,
longitude: -78.90,
address1: "123 Main St",
address2: "France",
city: "Sample City",
country: "Sample Country"
) {
id
address1
address2
city
country
latitude
longitude
createdAt
updatedAt
deletedAt
}
}
`;

describe('Integration test for createAddress mutation', () => {
const OLD_ENV = process.env;

beforeEach(() => {
jest.resetModules();
jest.unmock('@database');
jest.unmock('@database/models');
jest.unmock('ioredis');
process.env = { ...OLD_ENV };
process.env = { ...process.env, ...getMockDBEnv(), REDIS_PORT: 6380 };
});

afterAll(async () => {
process.env = OLD_ENV; // Restore old environment
await closeRedisConnection(); // avoid jest open handle error
});

it('should create an address', async () => {
const response = await getResponse(createAddressMutation);

// Assuming your mutation returns the created address
const createdAddress = get(response, 'body.data.createAddress');

// Perform assertions based on the response
expect(createdAddress).toBeTruthy();
expect(createdAddress.id).toBeTruthy();
expect(createdAddress.address1).toBe('123 Main St');
expect(createdAddress.address2).toBe('France');
expect(createdAddress.city).toBe('Sample City');
expect(createdAddress.country).toBe('Sample Country');
expect(createdAddress.latitude).toBe(123.456);
expect(createdAddress.longitude).toBe(-78.9);
expect(createdAddress.createdAt).toBeTruthy();
expect(createdAddress.updatedAt).toBeTruthy();
expect(createdAddress.deletedAt).toBeNull();
});
});
54 changes: 54 additions & 0 deletions __tests__/server/gql/model/products.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const { setRedisData, getRedisData, closeRedisConnection } = require('@server/services/redis');
const { getMockDBEnv, getResponse } = require('@server/utils/testUtils');
const { get } = require('lodash');

const getProductsQueryWhere = `
query products{
products(limit: 10, offset: 1){
edges{
node{
id
name
}
}
}
}
`;

describe('Integration test for products', () => {
const OLD_ENV = process.env;

beforeEach(() => {
jest.resetModules();
jest.unmock('@database');
jest.unmock('@database/models');
jest.unmock('ioredis');
process.env = { ...OLD_ENV };
process.env = { ...process.env, ...getMockDBEnv(), REDIS_PORT: 6380 };
});

afterAll(async () => {
process.env = OLD_ENV; // Restore old environment
await closeRedisConnection(); // avoid jest open handle error
const actualRedis = jest.requireActual('@server/services/redis').redis;
await actualRedis.quit();
});

it('should check and get products', async () => {
const response = await getResponse(getProductsQueryWhere);
const productResult = get(response, 'body.data.products.edges');
expect(productResult?.length).toBeGreaterThan(0);
expect(productResult[0].node).toMatchObject({
id: expect.anything(),
name: expect.any(String)
});
});

it('should set and get data from redis', async () => {
const testKey = 'product';
const testValue = 'test';
await setRedisData(testKey, testValue);
const result = await getRedisData(testKey);
expect(result).toBe(testValue);
});
});
44 changes: 44 additions & 0 deletions jest.config.integration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"testEnvironment": "node",
"setupFilesAfterEnv": ["./jest.setup.integration.js"],
"roots": ["__tests__"],
"reporters": [
"default",
[
"jest-sonar",
{
"outputDirectory": "reports",
"outputName": "test-report.xml",
"relativeRootDir": "./",
"reportedFilePath": "relative"
}
]
],
"collectCoverageFrom": [
"**/server/**",
"!**/node_modules/**",
"!**/dist/**",
"!**/server/database/models/**",
"!**/server/utils/testUtils/**",
"!**/server/utils/configureEnv.js",
"!**server/middleware/logger/index.js"
],
"coverageReporters": ["json-summary", "text", "lcov"],
"testPathIgnorePatterns": ["<rootDir>/dist/"],
"moduleNameMapper": {
"@server(.*)$": "<rootDir>/server/$1",
"@(database|services|gql|middleware|daos|utils)(.*)$": "<rootDir>/server/$1/$2",
"@config(.*)$": "<rootDir>/config/$1",
"slack-notify": "<rootDir>/node_modules/slack-notify/src/cjs/index.js"
},
"coverageThreshold": {
"global": {
"statements": 82,
"branches": 82,
"functions": 82,
"lines": 82
}
},
"globalSetup": "./test_setup/global-setup.js",
"globalTeardown": "./test_setup/global-teardown.js"
}
2 changes: 1 addition & 1 deletion jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"!**server/middleware/logger/index.js"
],
"coverageReporters": ["json-summary", "text", "lcov"],
"testPathIgnorePatterns": ["<rootDir>/dist/"],
"testPathIgnorePatterns": ["<rootDir>/dist/", "<rootDir>/__tests__/"],
"moduleNameMapper": {
"@server(.*)$": "<rootDir>/server/$1",
"@(database|services|gql|middleware|daos|utils)(.*)$": "<rootDir>/server/$1/$2",
Expand Down
17 changes: 17 additions & 0 deletions jest.setup.integration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DB_ENV } from '@utils/testUtils/mockData';

require('dotenv').config({
path: '.env.test'
});

process.env.ENVIRONMENT_NAME = 'test';

beforeEach(() => {
process.env = { ...process.env, ...DB_ENV, ENVIRONMENT_NAME: 'test' };
});

afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
jest.resetModules();
});
3 changes: 2 additions & 1 deletion jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"@daos/*": ["server/daos/*"],
"@database/*": ["server/database/*"],
"@gql/*": ["server/gql/*"],
"@config/*": ["config/*"]
"@config/*": ["config/*"],
"@test_setup/*": ["test_setup/*"]
},
"moduleResolution": "Node"
},
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"prettify": "prettier --write",
"precommit": "lint:staged",
"test": "export ENVIRONMENT_NAME=test && npx jest --silent --forceExit --detectOpenHandles --ci --coverage --testLocationInResults --json --outputFile=\"report.json\"",
"test:integration": "export ENVIRONMENT_NAME=test && npx jest --silent --forceExit --ci --coverage --testLocationInResults --json --outputFile=\"report.json\" --config ./jest.config.integration.json",
"test:badges": "npm run test && jest-coverage-badges --output './badges'",
"postinstall": "link-module-alias",
"preinstall": "command -v link-module-alias && link-module-alias clean || true"
Expand All @@ -54,6 +55,7 @@
"cors": "^2.8.5",
"crypto": "^1.0.1",
"deep-map-keys": "^2.0.1",
"docker-compose": "^0.24.3",
"dotenv": "^10.0.0",
"eslint-loader": "^4.0.2",
"express": "^4.17.1",
Expand All @@ -68,6 +70,7 @@
"html-webpack-plugin": "^4.5.0",
"http": "^0.0.1-security",
"ioredis": "^5.2.2",
"is-port-reachable": "3.0.0",
"jsonwebtoken": "^8.5.1",
"loadash": "^1.0.0",
"lodash": "^4.17.21",
Expand Down
27 changes: 25 additions & 2 deletions seeders/01_products.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
const products = [
{
id: 1,
name: 'test1',
category: 'category1',
amount: 10
},
{
id: 2,
name: 'test2',
category: 'category2',
amount: 20
},
{
id: 3,
name: 'test3',
category: 'category3',
amount: 30
}
];

module.exports = {
up: queryInterface => {
const faker = require('faker');
const range = require('lodash/range');
const arr = range(1, 2000).map((value, index) => ({
const arr = range(4, 2000).map((value, index) => ({
id: value,
name: faker.commerce.productName(),
category: faker.commerce.department(),
amount: parseFloat(faker.commerce.price()) * 100
}));
return queryInterface.bulkInsert('products', arr, {});
const newArr = products.concat(arr);
return queryInterface.bulkInsert('products', newArr, {});
},
down: queryInterface => queryInterface.bulkDelete('products', null, {})
};
15 changes: 15 additions & 0 deletions server/services/redis.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
import Redis from 'ioredis';

export const redis = new Redis(process.env.REDIS_PORT, process.env.REDIS_HOST);

export const setRedisData = async (key, value) => {
const data = await redis.set(key, value);
return data;
};

export const getRedisData = async key => {
const data = await redis.get(key);
return data;
};

// Add a function to close the Redis connection
export const closeRedisConnection = async () => {
await redis.quit();
};
9 changes: 9 additions & 0 deletions server/utils/testUtils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ export function mockDBClient(config = { total: 10 }) {
};
}

export const getMockDBEnv = () => ({
DB_URI: 'postgres://test_mock:test123@localhost:54320/test_mock?sslmode=disable',
DB_PORT: 54320,
DB_HOST: 'localhost',
DB_NAME: 'test_mock',
DB_USER: 'test_mock',
DB_PASSWORD: 'test123'
});

export async function connectToMockDB() {
const client = mockDBClient();
try {
Expand Down
22 changes: 22 additions & 0 deletions test_setup/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3'

services:
postgres: #1
image: postgres:12-alpine #1.1
command: postgres -c fsync=off -c synchronous_commit=off -c full_page_writes=off -c random_page_cost=1.0 #1.2
environment: #1.3
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- '${POSTGRES_PORT}:5432' #1.4
tmpfs: /var/lib/postgresql/data #.15

redis: #2
image: redis:6.2-alpine
ports:
- '${REDIS_PORT}:6379'

networks: #3
default:
name: 'test-server-network'
Loading