Skip to content

Commit 36d9607

Browse files
committed
Remaining unit tests passing
Both FE and BE
1 parent 1e6b14a commit 36d9607

12 files changed

Lines changed: 491 additions & 611 deletions

File tree

app/src/docs/v1.api-spec.yaml

Lines changed: 2 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,6 @@ paths:
650650
tags:
651651
- Electrification Enquiry
652652
parameters:
653-
- $ref: '#/components/parameters/Query-IncludeDeleted'
654653
- $ref: '#/components/parameters/Query-IncludeUser'
655654
- in: query
656655
name: activityId
@@ -880,40 +879,7 @@ paths:
880879
tags:
881880
- Electrification Permit
882881
parameters:
883-
- in: path
884-
name: permitId
885-
required: true
886-
schema:
887-
type: string
888-
description: The ID of the permit to update
889-
responses:
890-
'200':
891-
description: Permit updated successfully
892-
content:
893-
application/json:
894-
schema:
895-
$ref: '#/components/schemas/DB-Permit'
896-
"401":
897-
$ref: "#/components/responses/Unauthorized"
898-
'403':
899-
$ref: '#/components/responses/Forbidden'
900-
'404':
901-
$ref: '#/components/responses/NotFound'
902-
"422":
903-
$ref: "#/components/responses/UnprocessableEntity"
904-
default:
905-
$ref: '#/components/responses/Error'
906-
put:
907-
summary: Upsert a permit
908-
operationId: upsertElectrificationPermit
909-
tags:
910-
- Electrification Permit
911-
requestBody:
912-
required: true
913-
content:
914-
application/json:
915-
schema:
916-
$ref: '#/components/schemas/Request-Permit'
882+
- $ref: '#/components/parameters/Path-PermitId'
917883
responses:
918884
'200':
919885
description: Permit updated successfully
@@ -1254,7 +1220,6 @@ paths:
12541220
tags:
12551221
- Electrification Project
12561222
parameters:
1257-
- $ref: '#/components/parameters/Query-IncludeDeleted'
12581223
- $ref: '#/components/parameters/Query-IncludeUser'
12591224
- in: query
12601225
name: activityId
@@ -1732,7 +1697,6 @@ paths:
17321697
tags:
17331698
- Housing Enquiry
17341699
parameters:
1735-
- $ref: '#/components/parameters/Query-IncludeDeleted'
17361700
- $ref: '#/components/parameters/Query-IncludeUser'
17371701
- in: query
17381702
name: activityId
@@ -1962,12 +1926,7 @@ paths:
19621926
tags:
19631927
- Housing Permit
19641928
parameters:
1965-
- in: path
1966-
name: permitId
1967-
required: true
1968-
schema:
1969-
type: string
1970-
description: The ID of the permit to update
1929+
- $ref: '#/components/parameters/Path-PermitId'
19711930
responses:
19721931
'200':
19731932
description: Permit upserted successfully
@@ -1985,34 +1944,6 @@ paths:
19851944
$ref: "#/components/responses/UnprocessableEntity"
19861945
default:
19871946
$ref: '#/components/responses/Error'
1988-
put:
1989-
summary: Upsert a permit
1990-
operationId: upsertHousingPermit
1991-
tags:
1992-
- Housing Permit
1993-
requestBody:
1994-
required: true
1995-
content:
1996-
application/json:
1997-
schema:
1998-
$ref: '#/components/schemas/Request-Permit'
1999-
responses:
2000-
'200':
2001-
description: Permit updated successfully
2002-
content:
2003-
application/json:
2004-
schema:
2005-
$ref: '#/components/schemas/DB-Permit'
2006-
"401":
2007-
$ref: "#/components/responses/Unauthorized"
2008-
'403':
2009-
$ref: '#/components/responses/Forbidden'
2010-
'404':
2011-
$ref: '#/components/responses/NotFound'
2012-
"422":
2013-
$ref: "#/components/responses/UnprocessableEntity"
2014-
default:
2015-
$ref: '#/components/responses/Error'
20161947
delete:
20171948
summary: Delete a permit
20181949
operationId: deleteHousingPermit
@@ -2336,7 +2267,6 @@ paths:
23362267
tags:
23372268
- Housing Project
23382269
parameters:
2339-
- $ref: '#/components/parameters/Query-IncludeDeleted'
23402270
- $ref: '#/components/parameters/Query-IncludeUser'
23412271
- in: query
23422272
name: activityId
@@ -2677,14 +2607,6 @@ components:
26772607
schema:
26782608
type: boolean
26792609
example: true
2680-
description: >-
2681-
Whether to include records where the related activity is flagged as deleted.
2682-
When true, both deleted and non-deleted entities are returned.
2683-
When false (default), only non-deleted entities are returned.
2684-
required: false
2685-
schema:
2686-
type: boolean
2687-
example: false
26882610
Query-SubmissionType:
26892611
in: query
26902612
name: submissionType

app/src/routes/v1/docs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { readFileSync } from 'fs';
33
import helmet from 'helmet';
44
import yaml from 'js-yaml';
55
import { join } from 'path';
6+
67
import docs from '../../docs/docs';
78

89
const router = Router();

app/src/services/user.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import jwt from 'jsonwebtoken';
22
import { v4 as uuidv4, NIL } from 'uuid';
33

44
import { searchContacts, upsertContacts } from './contact';
5+
import { IdentityProvider as enumIDP } from '../utils/enums/application';
56
import { generateCreateStamps, generateNullUpdateStamps } from '../db/utils/utils';
7+
import { Problem } from '../utils';
68

79
import type { PrismaTransactionClient } from '../db/dataConnection';
810
import type { Contact, IdentityProvider, User } from '../types/models';
911
import type { UserSearchParameters } from '../types/stuff';
10-
import { Problem } from '../utils';
1112

1213
/**
1314
* The User DB Service
@@ -53,7 +54,7 @@ const _tokenToUser = (token: jwt.JwtPayload): JwtUser => {
5354
* @param idp The identity provider code
5455
* @returns A Promise that resolves into the created identity provider
5556
*/
56-
const createIdp = async (tx: PrismaTransactionClient, idp: string): Promise<IdentityProvider> => {
57+
export const createIdp = async (tx: PrismaTransactionClient, idp: string): Promise<IdentityProvider> => {
5758
const obj = {
5859
idp: idp,
5960
active: true,
@@ -169,11 +170,26 @@ export const login = async (tx: PrismaTransactionClient, token: jwt.JwtPayload):
169170
userId: [response.userId as string]
170171
});
171172
if (!oldContact.length) {
173+
// BCeID crams the entire name into firstName
174+
// Parse first word into first name and rest into last name
175+
// This does not guarantee name correctness, but a null last name breaks ATS
176+
let firstNameOverride: string | null = null,
177+
lastNameOverride: string | null = null;
178+
if ([enumIDP.BCEID, enumIDP.BCEIDBUSINESS].includes(newUser.idp as enumIDP)) {
179+
const split = newUser.firstName?.indexOf(' ');
180+
if (newUser.firstName && split && split > 0) {
181+
firstNameOverride = newUser.firstName.substring(0, split);
182+
lastNameOverride = newUser.firstName.substring(split + 1);
183+
} else {
184+
firstNameOverride = newUser.firstName;
185+
}
186+
}
187+
172188
const newContact: Contact = {
173189
contactId: uuidv4(),
174190
userId: response.userId as string,
175-
firstName: newUser.firstName,
176-
lastName: newUser.lastName,
191+
firstName: firstNameOverride ?? newUser.firstName,
192+
lastName: lastNameOverride ?? newUser.lastName ?? ' ', // Default blank string if no other options
177193
email: newUser.email,
178194
phoneNumber: null,
179195
contactApplicantRelationship: null,
@@ -194,7 +210,7 @@ export const login = async (tx: PrismaTransactionClient, token: jwt.JwtPayload):
194210
* @param code The identity provider code
195211
* @returns A Promise that resolves into the unique identity provider or null if not found
196212
*/
197-
const readIdp = async (tx: PrismaTransactionClient, code: string): Promise<IdentityProvider | null> => {
213+
export const readIdp = async (tx: PrismaTransactionClient, code: string): Promise<IdentityProvider | null> => {
198214
const response = await tx.identity_provider.findUnique({
199215
where: {
200216
idp: code
@@ -274,7 +290,7 @@ export const searchUsers = async (tx: PrismaTransactionClient, params: UserSearc
274290
* @param data Incoming user data
275291
* @returns A Promise that resolves into the updated user
276292
*/
277-
const updateUser = async (tx: PrismaTransactionClient, userId: string, data: JwtUser): Promise<User> => {
293+
export const updateUser = async (tx: PrismaTransactionClient, userId: string, data: JwtUser): Promise<User> => {
278294
// Check if any user values have changed
279295
const oldUser = await readUser(tx, userId);
280296
const diff = Object.entries(data).some(([key, value]) => oldUser && oldUser[key as keyof JwtUser] !== value);
Lines changed: 18 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { TEST_CURRENT_CONTEXT, TEST_IDIR_USER_1 } from '../data';
12
import { searchUsersController } from '../../../src/controllers/user';
23
import * as userService from '../../../src/services/user';
34

4-
import type { Response } from 'express';
5+
import type { Request, Response } from 'express';
6+
import type { UserSearchParameters } from '../../../src/types';
7+
import { prismaTxMock } from '../../__mocks__/prismaMock';
58

69
// Mock config library - @see {@link https://stackoverflow.com/a/64819698}
710
jest.mock('config');
@@ -23,45 +26,26 @@ afterEach(() => {
2326
jest.resetAllMocks();
2427
});
2528

26-
const CURRENT_CONTEXT = { authType: 'BEARER', tokenPayload: null };
27-
28-
const TEST_USER_LIST = [
29-
{
30-
bceidBusinessName: null,
31-
userId: '5e3f0c19-8664-4a43-ac9e-210da336e923',
32-
idp: 'IDIR',
33-
sub: 'cd90c6bf44074872a7116f4dd4f3a45b@idir',
34-
email: 'first.last@gov.bc.ca',
35-
firstName: 'First',
36-
fullName: 'Last, First',
37-
lastName: 'Last',
38-
active: true,
39-
createdAt: null,
40-
createdBy: null,
41-
updatedAt: null,
42-
updatedBy: null
43-
}
44-
];
29+
const TEST_USER_LIST = [TEST_IDIR_USER_1];
4530

4631
describe('searchUsersController', () => {
47-
const next = jest.fn();
48-
49-
// Mock service calls
5032
const searchUsersSpy = jest.spyOn(userService, 'searchUsers');
5133

52-
it('should return 200 if all good', async () => {
34+
it('should call services and respond with 200 and result', async () => {
5335
const req = {
5436
query: { userId: '5e3f0c19-8664-4a43-ac9e-210da336e923' },
55-
currentContext: CURRENT_CONTEXT
37+
currentContext: TEST_CURRENT_CONTEXT
5638
};
5739

5840
searchUsersSpy.mockResolvedValue(TEST_USER_LIST);
5941

60-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
61-
await searchUsersController(req as any, res as unknown as Response);
42+
await searchUsersController(
43+
req as unknown as Request<never, never, never, UserSearchParameters>,
44+
res as unknown as Response
45+
);
6246

6347
expect(searchUsersSpy).toHaveBeenCalledTimes(1);
64-
expect(searchUsersSpy).toHaveBeenCalledWith({
48+
expect(searchUsersSpy).toHaveBeenCalledWith(prismaTxMock, {
6549
userId: ['5e3f0c19-8664-4a43-ac9e-210da336e923']
6650
});
6751
expect(res.status).toHaveBeenCalledWith(200);
@@ -71,38 +55,19 @@ describe('searchUsersController', () => {
7155
it('adds dashes to user IDs', async () => {
7256
const req = {
7357
query: { userId: '5e3f0c1986644a43ac9e210da336e923,8b9dedd279d442c6b82f52844a8e2757' },
74-
currentContext: CURRENT_CONTEXT
58+
currentContext: TEST_CURRENT_CONTEXT
7559
};
7660

7761
searchUsersSpy.mockResolvedValue(TEST_USER_LIST);
7862

79-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
80-
await searchUsersController(req as any, res as unknown as Response);
63+
await searchUsersController(
64+
req as unknown as Request<never, never, never, UserSearchParameters>,
65+
res as unknown as Response
66+
);
8167

8268
expect(searchUsersSpy).toHaveBeenCalledTimes(1);
83-
expect(searchUsersSpy).toHaveBeenCalledWith({
69+
expect(searchUsersSpy).toHaveBeenCalledWith(prismaTxMock, {
8470
userId: ['5e3f0c19-8664-4a43-ac9e-210da336e923', '8b9dedd2-79d4-42c6-b82f-52844a8e2757']
8571
});
8672
});
87-
88-
it('calls next if the user service fails to list users', async () => {
89-
const req = {
90-
query: { userId: '5e3f0c19-8664-4a43-ac9e-210da336e923' },
91-
currentContext: CURRENT_CONTEXT
92-
};
93-
94-
searchUsersSpy.mockImplementationOnce(() => {
95-
throw new Error();
96-
});
97-
98-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99-
await searchUsersController(req as any, res as unknown as Response);
100-
101-
expect(searchUsersSpy).toHaveBeenCalledTimes(1);
102-
expect(searchUsersSpy).toHaveBeenCalledWith({
103-
userId: ['5e3f0c19-8664-4a43-ac9e-210da336e923']
104-
});
105-
expect(res.status).toHaveBeenCalledTimes(0);
106-
expect(next).toHaveBeenCalledTimes(1);
107-
});
10873
});

app/tests/unit/services/email.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ describe('logEmail tests', () => {
4949

5050
expect(prismaMock.email_log.createMany).toHaveBeenCalledWith({
5151
data: recipients.map((x) => ({
52-
email_log_id: expect.any(String),
53-
msg_id: chesResponse.messages?.[0].msgId,
52+
emailLogId: expect.any(String),
53+
msgId: chesResponse.messages?.[0].msgId,
5454
to: x,
55-
tx_id: chesResponse.txId,
56-
http_status: 201
55+
txId: chesResponse.txId,
56+
httpStatus: 201
5757
}))
5858
});
5959
});
@@ -67,11 +67,11 @@ describe('logEmail tests', () => {
6767

6868
expect(prismaMock.email_log.createMany).toHaveBeenCalledWith({
6969
data: recipients.map((x) => ({
70-
email_log_id: expect.any(String),
71-
msg_id: chesResponse.messages?.[0].msgId,
70+
emailLogId: expect.any(String),
71+
msgId: chesResponse.messages?.[0].msgId,
7272
to: x,
73-
tx_id: chesResponse.txId,
74-
http_status: statusCode
73+
txId: chesResponse.txId,
74+
httpStatus: statusCode
7575
}))
7676
});
7777
});

0 commit comments

Comments
 (0)