Skip to content

Commit

Permalink
feat: added additional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marnixdessing committed Mar 23, 2023
1 parent 817a86f commit 4cb79a5
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .eslintrc.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Testing
5 changes: 1 addition & 4 deletions src/app/code/YiviApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,20 @@ export class YiviApi {
}

private async doSignedPostRequest(path: string, data: any, errorMsg: string) {
console.debug('Starting signed POST request:', path);

try {
const client = this.getSigningClient();
const resp = await client.post(path, data);
if (resp.data) {
console.debug('Response data:', resp.data);
return resp.data;
}
throw Error(errorMsg);
} catch (error: any) {
console.error('Error while doing signed post request for endpoint', path);
if (axios.isAxiosError(error)) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(`http status for ${path}: ${error.response?.status}`);
console.debug(error.response.data);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
Expand Down
3 changes: 2 additions & 1 deletion src/app/issue/issueRequestHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ async function handleLoggedinRequest(session: Session, brpApi: BrpApi, yiviApi:
// Start YIVI session
let yiviFullSession = undefined;
if (!error) {
console.debug('Starting YIVI session...');
const loa = session.getValue('loa');
const yiviResponse = await yiviApi.startSession(brpData, loa);
console.debug('YIVI session: ', yiviResponse);
Expand All @@ -73,7 +74,7 @@ async function handleLoggedinRequest(session: Session, brpApi: BrpApi, yiviApi:
error: error,
yiviFullSession: yiviFullSession,
};
console.debug('Rendering page with data:', data);
console.log('Rendering page with data:', data);
const html = await render(data, template.default);
return Response.html(html, 200, session.getCookie());
}
Expand Down
89 changes: 89 additions & 0 deletions test/app/TestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { DynamoDBClient, GetItemCommand, GetItemCommandOutput, ServiceInputTypes, ServiceOutputTypes } from "@aws-sdk/client-dynamodb";
import { AwsStub } from "aws-sdk-client-mock";
import { DigidLoa } from "../../src/app/code/DigiDLoa";


export class TestUtils {

static getSessionStoreMock(
ddMock: AwsStub<ServiceInputTypes, ServiceOutputTypes>,
loggedin: boolean = true,
bsn: string = '900026236',
state: string = '12345',
loa: DigidLoa = DigidLoa.Midden
) {
const dynamoDBClient = new DynamoDBClient({ region: 'us-east-1' });

const getItemOutput: Partial<GetItemCommandOutput> = {
Item: {
data: {
M: {
loggedin: { BOOL: loggedin },
bsn: { S: bsn },
state: { S: state },
loa: { S: loa },
},
},
},
};
ddMock.on(GetItemCommand).resolves(getItemOutput);
return dynamoDBClient;
}

static getYiviSessionExampleResponse() {

const sessionResponse = {
sessionPtr: {
u: 'https://gw-test.nijmegen.nl/yivi/session/anothertoken',
yiviqr: 'issuing'
},
token: 'sometoken',
frontendRequest: {
authorization: 'blabla',
pairingHint: true,
minProtocolVersion: '1.0',
maxProtocolVersion: '1.1'
}
}
return sessionResponse;
}

static getBrpExampleData() {
const brpData = {
"Persoon": {
"BSN": {
"BSN": "900026236"
},
"Persoonsgegevens": {
"Voorletters": "H.",
"Voornamen": "Hans",
"Voorvoegsel": "de",
"Geslachtsnaam": "Jong",
"Achternaam": "de Jong",
"Naam": "H. de Jong",
"Geboortedatum": "01-01-1956",
"Geslacht": "M",
"NederlandseNationaliteit": "Ja",
"Geboorteplaats": "Nijmegen",
"Geboorteland": "Nederland"
},
"Adres": {
"Straat": "Kelfkensbos",
"Huisnummer": "80",
"Gemeente": "Nijmegen",
"Postcode": "6511 RN",
"Woonplaats": "Nijmegen"
},
"ageLimits": {
"over12": "Yes",
"over16": "Yes",
"over18": "Yes",
"over21": "Yes",
"over65": "Yes"
}
}
}
return brpData;
}

}
12 changes: 10 additions & 2 deletions test/app/irma.test.ts → test/app/YiviApi.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { YiviApi } from '../../src/app/code/YiviApi';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import {AWS } from '@gemeentenijmegen/utils';
import { AWS } from '@gemeentenijmegen/utils';
import * as dotenv from 'dotenv'
import { DigidLoa, loaToNumber } from '../../src/app/code/DigiDLoa';
dotenv.config()
Expand All @@ -16,7 +16,7 @@ jest.mock('@gemeentenijmegen/utils/lib/AWS', () => ({
}));

beforeAll(() => {
// console.log = jest.fn();
console.log = jest.fn();
console.info = jest.fn();
console.debug = jest.fn();
console.error = jest.fn();
Expand Down Expand Up @@ -51,6 +51,14 @@ test('Check if yivi api adds aws4-singature and irma-authorization header and ri
expect(data?.credentials[1]?.attributes?.digidlevel).toBe(loa);
});

test('Check timeout Yivi API', async () => {
axiosMock.onPost('/session').timeout()
const client = new YiviApi();
client.manualInit('gw-test.nijmegen.nl', true, 'someid', 'somesecretkey', 'irma-autharizaiton-header');
await client.startSession(brpData, DigidLoa.Substantieel);
expect(console.error).toHaveBeenCalledWith('timeout of 2000ms exceeded');
});

test('Initialization', async () => {
process.env.YIVI_API_ACCESS_KEY_ID_ARN = 'key-id-arn';
process.env.YIVI_API_SECRET_KEY_ARN = 'secret-arn';
Expand Down
92 changes: 92 additions & 0 deletions test/app/issue.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { BrpApi } from '../../src/app/issue/BrpApi';
import { issueRequestHandler } from '../../src/app/issue/issueRequestHandler';
import { ApiClient } from '@gemeentenijmegen/apiclient';
import { YiviApi } from '../../src/app/code/YiviApi';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { mockClient } from 'aws-sdk-client-mock';
import { DigidLoa } from '../../src/app/code/DigiDLoa';
import { TestUtils } from './TestUtils';

const ddbMock = mockClient(DynamoDBClient);
const axiosMock = new MockAdapter(axios);

const brpApi = new BrpApi(new ApiClient('cert', 'key', 'ca'));
const yiviApi = new YiviApi();

// Mock SSM and Secrets manager utility (cannot be moved to TestUtils)
jest.mock('@gemeentenijmegen/utils/lib/AWS', () => ({
AWS: {
getParameter: jest.fn().mockImplementation((name) => `${name}`),
getSecret: jest.fn().mockImplementation((arn) => `${arn}`),
}
}));

beforeAll(async () => {
// Mock the logging functions (can be used to check for precense of logging)
console.log = jest.fn();
console.info = jest.fn();
console.debug = jest.fn();
console.error = jest.fn();
console.time = jest.fn();

// Setup BRP and Yivi client
process.env.BRP_API_URL = 'https://example.com/brp/api/test';
await brpApi.init();
yiviApi.manualInit('yivi-server-test.nijmegen.nl', true, 'someid', 'somesecretkey', 'irma-autharizaiton-header');
});

beforeEach(() => {
axiosMock.reset();
ddbMock.reset();
});

test('Issue page loads successfull', async () => {

// Mocks
const dynamoDBClient = TestUtils.getSessionStoreMock(ddbMock);
axiosMock.onPost('https://yivi-server-test.nijmegen.nl/session').reply(200, TestUtils.getYiviSessionExampleResponse());
axiosMock.onPost('https://example.com/brp/api/test').reply(200, TestUtils.getBrpExampleData());

// Call issue request handler
const response = await issueRequestHandler('session=12345', brpApi, yiviApi, dynamoDBClient);

// Check if the session resonse is encoded in the html
const data = await brpApi.getBrpData('900026236');
const manuallyObtainedSessionResponse = await yiviApi.startSession(data, DigidLoa.Midden);
const base64SessionResponse = Buffer.from(JSON.stringify(manuallyObtainedSessionResponse), 'utf-8').toString('base64');
expect(response.body).toContain(base64SessionResponse)
});

test('Issue page not logged in', async () => {
// Session store not logged in
const dynamoDBClient = TestUtils.getSessionStoreMock(ddbMock, false);

const response = await issueRequestHandler('session=12345', brpApi, yiviApi, dynamoDBClient);
expect(response.statusCode).toBe(302);
expect(response.headers?.Location).toBe('/login');
expect(response.body).toBe('');
});

test('Yivi API timeout', async () => {
// Mocks
const dynamoDBClient = TestUtils.getSessionStoreMock(ddbMock);
axiosMock.onPost('https://yivi-server-test.nijmegen.nl/session').timeout();
axiosMock.onPost('https://example.com/brp/api/test').reply(200, TestUtils.getBrpExampleData());

// Call issue request handler
await issueRequestHandler('session=12345', brpApi, yiviApi, dynamoDBClient);
expect(console.error).toHaveBeenCalledWith('timeout of 2000ms exceeded');
});


test('BRP API timeout', async () => {
// Mocks
const dynamoDBClient = TestUtils.getSessionStoreMock(ddbMock);
axiosMock.onPost('https://example.com/brp/api/test').timeout();

// Call issue request handler
await issueRequestHandler('session=12345', brpApi, yiviApi, dynamoDBClient);
expect(console.error).toHaveBeenCalledWith('timeout of 2000ms exceeded');
});

0 comments on commit 4cb79a5

Please sign in to comment.