Skip to content

Commit

Permalink
(chore): Add tests (#8)
Browse files Browse the repository at this point in the history
* Implement tests
* Fix linting
  • Loading branch information
albertomr86 authored Sep 24, 2023
1 parent 0755b98 commit 62a0ca6
Show file tree
Hide file tree
Showing 12 changed files with 798 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
project: 'tsconfig.test.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
Expand Down
20 changes: 15 additions & 5 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: ci
on:
push:
branches:
- '**/*'
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -15,6 +16,15 @@ jobs:
with:
node-version: ${{ matrix.node }}
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run lint
- run: npm run build
- name: Install dependencies
run: npm ci
- name: Check linting
run: npm run lint
- name: Build
run: npm run build
- name: Run tests
run: npm run test
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# source
lib
tests
coverage
index.ts
package-lock.json
tslint.json
Expand All @@ -9,6 +10,8 @@ tsconfig.json
.commitlintrc.json
.eslintignore
.eslintrc.js
.nvmrc
nest-cli.json

# github
.github
Expand Down
75 changes: 75 additions & 0 deletions lib/config.module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { INestApplication } from '@nestjs/common';
import { Parameter } from '@aws-sdk/client-ssm';
import { PSConfigModule } from './config.module';
import { PSConfigParameters, PSConfigOptions } from './interfaces';
import { PS_CONFIG_PARAMETERS, PS_CONFIG_OPTIONS } from './constants';
import { createTestHarness } from '../tests/utils';
import { mockData } from '../tests/mockdata';

describe('PSConfigModule', () => {
let app: INestApplication;
const moduleOptions: PSConfigOptions = {
ssmParamStorePath: '/',
ssmDecryptParams: true,
ssmRecursive: true,
ssmClientOptions: {
region: 'us-east-1',
},
};

describe('register()', () => {
beforeEach(async () => {
const testHarness = await createTestHarness(
PSConfigModule.register(moduleOptions),
);
app = testHarness.app;
});

it('should fetch all parameters when loading', () => {
const parameters = app.get<
typeof PS_CONFIG_PARAMETERS,
PSConfigParameters
>(PS_CONFIG_PARAMETERS);
expect(parameters).toBeInstanceOf(Array<Parameter>);
expect(parameters).toHaveLength(mockData.length);
});

it('should load the module with options', () => {
expect(app.get<PSConfigOptions>(PS_CONFIG_OPTIONS)).toMatchObject(
moduleOptions,
);
});
});

describe('registerAsync()', () => {
beforeEach(async () => {
const testHarness = await createTestHarness(
PSConfigModule.registerAsync({
useFactory: () => moduleOptions,
}),
);
app = testHarness.app;
});

it('should fetch all parameters when loading', () => {
const parameters = app.get<
typeof PS_CONFIG_PARAMETERS,
PSConfigParameters
>(PS_CONFIG_PARAMETERS);
expect(parameters).toBeInstanceOf(Array<Parameter>);
expect(parameters).toHaveLength(mockData.length);
});

it('should load the module with options', () => {
expect(app.get<PSConfigOptions>(PS_CONFIG_OPTIONS)).toMatchObject(
moduleOptions,
);
});
});

afterEach(async () => {
if (app) {
await app.close();
}
});
});
40 changes: 40 additions & 0 deletions lib/providers/config-parameters.provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Test, TestingModule } from '@nestjs/testing';
import { configParametersProvider } from './config-parameters.provider';
import { createOptionsProvider } from './options.provider';
import { ParameterStoreService } from '../services';
import { PSConfigParameters } from '../interfaces';
import { PS_CONFIG_PARAMETERS } from '../constants';
import { mockData } from '../../tests/mockdata';

describe('configParametersProvider#PS_CONFIG_PARAMETERS', () => {
let moduleRef: TestingModule;
let parameterStoreService: ParameterStoreService;

beforeEach(async () => {
moduleRef = await Test.createTestingModule({
providers: [
createOptionsProvider({ ssmParamStorePath: '/' }),
{
provide: ParameterStoreService,
useFactory: () => ({
getParametersByPath: jest
.spyOn(ParameterStoreService.prototype, 'getParametersByPath')
.mockImplementation(() => Promise.resolve(mockData)),
}),
},
configParametersProvider,
],
}).compile();

parameterStoreService = moduleRef.get<ParameterStoreService>(
ParameterStoreService,
);
});

it('should hold all parameters', () => {
const parameters = moduleRef.get<PSConfigParameters>(PS_CONFIG_PARAMETERS);
expect(parameters).toBeInstanceOf(Array);
expect(parameters).toHaveLength(mockData.length);
expect(parameterStoreService.getParametersByPath).toHaveBeenCalled();
});
});
67 changes: 67 additions & 0 deletions lib/services/config.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Test } from '@nestjs/testing';
import { PSConfigService } from './config.service';
import { PS_CONFIG_PARAMETERS } from '../constants';
import { mockData } from '../../tests/mockdata';

describe('PSConfigService', () => {
let psConfigService: PSConfigService;

beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
providers: [
PSConfigService,
{
provide: PS_CONFIG_PARAMETERS,
useValue: mockData,
},
],
}).compile();

psConfigService = moduleRef.get(PSConfigService);
});

describe('get()', () => {
it('should return value for existing parameter', () => {
const value = psConfigService.get('post-table', 'fake');
expect(value).toBe('ProductionPostTable');
expect(typeof value).toBe('string');
});

it('should return a default value for not found parameter', () => {
expect(psConfigService.get('unknown', null)).toBeNull();
expect(psConfigService.get('unknown', '')).toBe('');
});
});

describe('getBool()', () => {
it('should return true for truthy values', () => {
const value = psConfigService.getBool('signup-with-facebook', false);
expect(value).toBeTruthy();
expect(typeof value).toBe('boolean');
});

it('should return false for falsy values', () => {
const value = psConfigService.getBool('signup-with-google', true);
expect(value).toBeFalsy();
expect(typeof value).toBe('boolean');
});

it('should return a default value for not found parameter', () => {
expect(psConfigService.getBool('unknown', true)).toBeTruthy();
expect(psConfigService.getBool('unknown', false)).toBeFalsy();
});
});

describe('getNumber()', () => {
it('should return a number', () => {
const value = psConfigService.getNumber('port', 0);
expect(value).toBe(3000);
expect(typeof value).toBe('number');
});

it('should return a default value for not found parameter', () => {
const value = psConfigService.getNumber('unknown', 5000);
expect(value).toBe(5000);
});
});
});
52 changes: 52 additions & 0 deletions lib/services/parameter-store.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'aws-sdk-client-mock-jest';
import {
SSMClient,
Parameter,
GetParametersByPathCommand,
} from '@aws-sdk/client-ssm';
import { AwsStub } from 'aws-sdk-client-mock';
import { Test } from '@nestjs/testing';
import { ParameterStoreService } from './parameter-store.service';
import { SSM_PS_CLIENT } from '../constants';
import { createSSMClientWithTestData } from '../../tests/utils';
import { mockData } from '../../tests/mockdata';

describe('ParameterStoreService', () => {
let parameterStoreService: ParameterStoreService;
let ssmClient: AwsStub<SSMClient, unknown, unknown>;

beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
providers: [
ParameterStoreService,
{
provide: SSM_PS_CLIENT,
useFactory: () => createSSMClientWithTestData(),
},
],
}).compile();

parameterStoreService = moduleRef.get(ParameterStoreService);
ssmClient = moduleRef.get(SSM_PS_CLIENT);
});

describe('getParametersByPath()', () => {
it('should fetch all parameters with pagination', async () => {
const totalItems = mockData.length;
const totalPages = Math.ceil(totalItems / 10);

const results = await parameterStoreService.getParametersByPath(
'/',
true,
true,
);

expect(results).toBeInstanceOf(Array<Parameter>);
expect(results).toHaveLength(totalItems);
expect(ssmClient).toHaveReceivedCommandTimes(
GetParametersByPathCommand,
totalPages,
);
});
});
});
Loading

0 comments on commit 62a0ca6

Please sign in to comment.