Skip to content

Commit

Permalink
Merge pull request #64 from GovTechSG/MOL-13533
Browse files Browse the repository at this point in the history
add regadd option for mock params
  • Loading branch information
gnzhen authored Aug 14, 2023
2 parents 8dcfd40 + 134fce2 commit 86817be
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 86 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelogs

## 8.1.0

- Add `regadd` as mock param options for fake profile
- Add `mrSGFromBedok`

## 7.4.0

- Update `proxy-agent` from `5.0.0` to `6.3.0`
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@govtechsg/singpass-myinfo-oidc-helper",
"version": "8.0.0",
"version": "8.1.0",
"description": "Helper for building a Relying Party to integrate with Singpass OIDC and MyInfo person basic API",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
116 changes: 113 additions & 3 deletions src/myinfo/fake/__tests__/fake-helper.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { MyInfoComponents, MyInfoLifeStatusCode, MyInfoResidentialCode, MyInfoSexCode } from "../../domain";
import { ChildrenBirthRecord, CpfContributionHistory, FakeMyInfoHelper, OverrideMode, transformChildBirthRecord, transformItems, transformItemsWithAdditionalMock } from "../fake-helper";
import { MyInfoLifeStatusCode, MyInfoSexCode } from "../../domain";
import { FakeMyInfoHelper, transformChildBirthRecord, transformItems, transformItemsWithAdditionalMock } from "../fake-helper";
import { ProfileArchetype } from "../profiles/fake-profile";
import { mrSGFatherNormalChildrenOnly } from "../profiles/sponsored-children/mrSGFatherNormalChildrenOnly";
import { mrSGDaddyPerfect } from "../profiles/mrSGDaddyPerfect";
import { mrSGNoLocalAddress } from "../profiles/mrSGNoLocalAddress ";
import { mrSGFatherNormalChildrenOnly } from "../profiles/sponsored-children/mrSGFatherNormalChildrenOnly";
import { ChildrenBirthRecord, CpfContributionHistory, OverrideMode } from "../types";

// tslint:disable-next-line: no-big-function
describe("FakeMyInfoHelper", () => {
Expand Down Expand Up @@ -74,6 +76,114 @@ describe("FakeMyInfoHelper", () => {
expect(person).toHaveProperty("drivinglicence.lastupdated");
});

describe("regadd", () => {
it("should return base profile regadd if no override provided", () => {
const fakeHelper = new FakeMyInfoHelper();

const person = fakeHelper.getPersonBasic({
archetype: ProfileArchetype.MR_SG_DADDY_PERFECT,
});

expect(person.regadd).toStrictEqual(mrSGDaddyPerfect.generate().regadd);
});

describe("SG Address", () => {
it("should merge archetype SG address with override", () => {
const fakeHelper = new FakeMyInfoHelper();
const person = fakeHelper.getPersonBasic({
archetype: ProfileArchetype.MR_SG_DADDY_PERFECT,
regadd: {
type: "SG",
postal: "123456",
street: "Some street",
unit: "111"
}
});

expect(person.regadd).toStrictEqual({
...mrSGDaddyPerfect.generate().regadd,
postal: { value: "123456" },
street: { value: "Some street" },
unit: { value: "111" }
});
});

it("should override with SG address if archetype has unformatted", () => {
const fakeHelper = new FakeMyInfoHelper();
const person = fakeHelper.getPersonBasic({
archetype: ProfileArchetype.MR_SG_NO_LOCAL_ADDRESS,
regadd: {
type: "SG",
block: "123",
building: "Some building",
floor: "11",
postal: "123456",
street: "Some street",
unit: "111"
}
});

const baseRegAdd = mrSGNoLocalAddress.generate().regadd;
expect(person.regadd).toStrictEqual({
type: "SG",
country: {
code: "SG",
desc: "SINGAPORE"
},
block: { value: "123" },
building: { value: "Some building" },
floor: { value: "11" },
postal: { value: "123456" },
street: { value: "Some street" },
unit: { value: "111" },
classification: baseRegAdd.classification,
lastupdated: baseRegAdd.lastupdated,
source: baseRegAdd.source,
});
});
});

describe("Unformatted Address", () => {
it("should merge archetype unformatted address with override", () => {
const fakeHelper = new FakeMyInfoHelper();
const person = fakeHelper.getPersonBasic({
archetype: ProfileArchetype.MR_SG_NO_LOCAL_ADDRESS,
regadd: {
type: "UNFORMATTED",
line1: "Line 1 address",
}
});

expect(person.regadd).toStrictEqual({
...mrSGNoLocalAddress.generate().regadd,
line1: { value: "Line 1 address" },
});
});

it("should override with unformatted address if archetype has SG", () => {
const fakeHelper = new FakeMyInfoHelper();
const person = fakeHelper.getPersonBasic({
archetype: ProfileArchetype.MR_SG_DADDY_PERFECT,
regadd: {
type: "UNFORMATTED",
line1: "Line 1 address",
line2: "Line 2 address",
}
});

const baseRegAdd = mrSGDaddyPerfect.generate().regadd;
expect(person.regadd).toStrictEqual({
type: "UNFORMATTED",
line1: { value: "Line 1 address" },
line2: { value: "Line 2 address" },
classification: baseRegAdd.classification,
lastupdated: baseRegAdd.lastupdated,
source: baseRegAdd.source,
});
});
});
});

describe("childrenbirthrecords", () => {
const mockChildrenbirthrecords: ChildrenBirthRecord[] = [
{
Expand Down
120 changes: 41 additions & 79 deletions src/myinfo/fake/fake-helper.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,9 @@
import { get, isEmpty, map, partition, set } from "lodash";
import { get, isEmpty, map, omit, partition, set } from "lodash";
// tslint:disable-next-line: max-line-length
import { MyInfoComponents, MyInfoComStatusCode, MyInfoCountryPlaceCode, MyInfoDrivingLicenceValidityCode, MyInfoHDBTypeCode, MyInfoHousingTypeCode, MyInfoLifeStatusCode, MyInfoMaritalStatusCode, MyInfoMerdekaGenerationMessageCode, MyInfoRaceCode, MyInfoResidentialCode, MyInfoSexCode, MyInfoVehicleStatus } from "../domain";
import { ProfileArchetype } from "./profiles/fake-profile";
import { MyInfoComponents, MyInfoComStatusCode, MyInfoCountryPlaceCode, MyInfoDrivingLicenceValidityCode, MyInfoHDBTypeCode, MyInfoHousingTypeCode, MyInfoLifeStatusCode, MyInfoMaritalStatusCode, MyInfoRaceCode, MyInfoResidentialCode, MyInfoSexCode, MyInfoVehicleStatus } from "../domain";
import { profiles } from "./profiles/fake-profiles";
import { ChildrenBirthRecord, CpfBalanceExtension, GVS, MockParams, MockParamsPerson, NoaBasicExtension, OverrideMode, UniqueAddressSgKeys, UniqueAddressUnformattedKeys } from "./types";

enum GVS {
true = "true",
false = "false",
}

export enum OverrideMode {
partial = "partial",
full = "full",
appendToExisting = "append",
}
export interface ChildrenBirthRecord {
birthcertno: string;
name?: string;
dob?: string;
tob?: string;
sex?: MyInfoSexCode;
lifestatus?: MyInfoLifeStatusCode;
}

export interface CpfContributionHistory {
date: string;
amount: number;
month: string;
employer: string;
}

export interface CpfBalance {
ma: number;
oa: number;
sa: number;
ra: number;
}

export interface NoaBasic {
amount: number;
yearofassessment: string;
}

export interface MockParams {
archetype: ProfileArchetype;
userdisplayname?: string;
race?: MyInfoRaceCode;
marital?: MyInfoMaritalStatusCode;
marriagedate?: string;
divorcedate?: string;
marriagecertno?: string;
countryofmarriage?: MyInfoCountryPlaceCode;
childrenbirthrecords?: ChildrenBirthRecord[];
childrenoverridemode?: OverrideMode;
residentialstatus?: MyInfoResidentialCode;
occupationfreeform?: string;
dob?: string;
gstvyear?: string;
gvs?: GVS;
merdekageneligible?: boolean;
merdekagenquantum?: number;
merdekagenmessagecode?: MyInfoMerdekaGenerationMessageCode;
hdbtype?: MyInfoHDBTypeCode;
housingtype?: MyInfoHousingTypeCode;
drivingqdlvalidity?: MyInfoDrivingLicenceValidityCode;
vehiclestatus?: MyInfoVehicleStatus;
employment?: string;
}
export interface MockFinanceParams {
cpfcontributionhistoryoverridemode?: OverrideMode;
cpfcontributions?: CpfContributionHistory[];
cpfbalances?: CpfBalance;
noabasic?: NoaBasic;
}

export interface DefaultParams { lastupdated: string; classification: "C"; source: '1'; unavailable: boolean; }
type MockParamsPerson = MockParams & MockFinanceParams;

type NoaBasicExtension = MyInfoComponents.Schemas.NOABasic & MyInfoComponents.Schemas.DataFieldProperties;
type CpfBalanceExtension = MyInfoComponents.Schemas.Cpfbalances & MyInfoComponents.Schemas.DataFieldProperties;
type PersonBasic = MyInfoComponents.Schemas.PersonBasic;
type Person = MyInfoComponents.Schemas.Person;

Expand Down Expand Up @@ -185,6 +110,43 @@ export class FakeMyInfoHelper implements IFakeMyInfoHelper {
myinfoPerson.merdekagen.quantum = { value: mockParams.merdekagenquantum };
}

if (!isEmpty(mockParams.regadd)) {
const sgProps: UniqueAddressSgKeys[] = ["block", "building", "country", "floor", "postal", "street", "unit"];
const unformattedProps: UniqueAddressUnformattedKeys[] = ["line1", "line2"];

if (mockParams.regadd.type === "SG") {
const regadd = myinfoPerson.regadd as MyInfoComponents.Schemas.DataitemAddressSg;
myinfoPerson.regadd = {
...myinfoPerson.regadd,
type: "SG",
country: {
code: MyInfoCountryPlaceCode.SINGAPORE,
desc: MyInfoCountryPlaceCode.fn.toEnumDesc(MyInfoCountryPlaceCode.SINGAPORE),
},
block: { value: !isEmpty(mockParams.regadd.block) ? mockParams.regadd.block : regadd.block.value },
building: { value: !isEmpty(mockParams.regadd.building) ? mockParams.regadd.building : regadd.building.value },
floor: { value: !isEmpty(mockParams.regadd.floor) ? mockParams.regadd.floor : regadd.floor.value },
postal: { value: !isEmpty(mockParams.regadd.postal) ? mockParams.regadd.postal : regadd.postal.value },
street: { value: !isEmpty(mockParams.regadd.street) ? mockParams.regadd.street : regadd.street.value },
unit: { value: !isEmpty(mockParams.regadd.unit) ? mockParams.regadd.unit : regadd.unit.value },
};

myinfoPerson.regadd = omit(myinfoPerson.regadd, unformattedProps) as PersonBasic["regadd"];
}

if (mockParams.regadd.type === "UNFORMATTED") {
const regadd = myinfoPerson.regadd as MyInfoComponents.Schemas.DataitemAddressUnformatted;
myinfoPerson.regadd = {
...myinfoPerson.regadd,
type: "UNFORMATTED",
line1: { value: !isEmpty(mockParams.regadd.line1) ? mockParams.regadd.line1 : regadd.line1.value },
line2: { value: !isEmpty(mockParams.regadd.line2) ? mockParams.regadd.line2 : regadd.line2.value },
};

myinfoPerson.regadd = omit(myinfoPerson.regadd, sgProps) as PersonBasic["regadd"];
}
}

if (!isEmpty(mockParams.hdbtype)) {
myinfoPerson.hdbtype = {
lastupdated: "2018-06-01",
Expand Down Expand Up @@ -448,7 +410,7 @@ export class FakeMyInfoHelper implements IFakeMyInfoHelper {
}

if (!isEmpty(mockParams.race)) {
myinfoPerson.race.code = mockParams.race;
myinfoPerson.race.code = mockParams.race;
myinfoPerson.race.desc = MyInfoRaceCode.fn.toEnumDesc(mockParams.race);
}

Expand Down
3 changes: 2 additions & 1 deletion src/myinfo/fake/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as factory from "./factory/person-basic-factory";
export { factory };
export { FakeMyInfoHelper as Helper, IFakeMyInfoHelper as IHelper, MockParams } from "./fake-helper";
export { FakeMyInfoHelper as Helper, IFakeMyInfoHelper as IHelper } from "./fake-helper";
export { FakeMyInfoRequest as Request } from "./fake-request";
export * from "./profiles/fake-profiles";
export { ProfileArchetype } from "./profiles/fake-profile";
export { MockParams } from "./types";
1 change: 1 addition & 0 deletions src/myinfo/fake/profiles/fake-profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export enum ProfileArchetype {
MR_MY_DAD_JOBLESS = "Mr MY Dad Jobless",
MRS_MY_MOM_JOBLESS = "Mrs MY Mom Jobless",
MR_SG_JOBLESS = "Mr SG Jobless",
MR_SG_FROM_BEDOK = "Mr SG From Bedok",
MR_SG_NO_LOCAL_ADDRESS = "Mr SG No Local Address",
MR_SG_NO_ADDRESS = "Mr SG No Address",
MR_PR_NO_LOCAL_ADDRESS = "Mr PR No Local Address",
Expand Down
2 changes: 2 additions & 0 deletions src/myinfo/fake/profiles/fake-profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { mrsMYMommyPerfect } from "./mrsMYMommyPerfect";
import { mrsSGMommyPerfect } from "./mrsSGMommyPerfect";
import { mrSGFatherNormalChildrenOnly } from "./sponsored-children/mrSGFatherNormalChildrenOnly";
import { msSGMotherBothChildren } from "./sponsored-children/msSGMotherBothChildren";
import { mrSGFromBedok } from "./mrSGFromBedok";
import { mrSGNoLocalAddress } from "./mrSGNoLocalAddress ";
import { mrSGNoAddress } from "./mrSGNoAddress";
import { mrPRNoLocalAddress } from "./mrPRNoLocalAddress";
Expand Down Expand Up @@ -80,6 +81,7 @@ export const profiles = [
msSGMotherBothChildren,
mrSGDaddyPerfect,
mrsSGMommyPerfect,
mrSGFromBedok,
mrSGNoLocalAddress,
mrSGNoAddress,
mrPRNoLocalAddress,
Expand Down
30 changes: 30 additions & 0 deletions src/myinfo/fake/profiles/mrSGFromBedok.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as _ from "lodash";
import { FakeProfile, ProfileArchetype } from "./fake-profile";
import { mrSGDaddyPerfect } from "./mrSGDaddyPerfect";

const id = "S8752571F";
const name = ProfileArchetype.MR_SG_FROM_BEDOK;

export const mrSGFromBedok: FakeProfile = {
id,
name,
generate: (profileName) => {
profileName = _.isEmpty(profileName) ? name : profileName;

const profile = mrSGDaddyPerfect.generate(profileName);
profile.regadd = {
...profile.regadd,
block: { value: "634" },
street: { value: "BEDOK STREET" },
postal: { value: "458634" }
};
profile.dob = {
"lastupdated": "2018-06-01",
"source": "1",
"classification": "C",
"value": "1983-10-06",
};

return profile;
},
};
Loading

0 comments on commit 86817be

Please sign in to comment.