Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FN-3163): MDM endpoints for automatically creating new DTFS customers in Salesforce #1057

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
4cf255c
feat: add DnB behaviour ready for use in customers service
Nov 8, 2024
7719a61
refactor: newlines
Dec 3, 2024
abd3707
feat: dummy customer creation endpoint
Sep 13, 2024
da44fcf
feat: wip add salesforce service and module bypassing self-signed iss…
Sep 13, 2024
f2b08c7
feat: dummy post request
Sep 16, 2024
1b50b81
feat: wip post request
Sep 16, 2024
bdce5fb
feat: wip post request
Sep 16, 2024
59a71c8
feat: minimal sf post
Sep 17, 2024
6619c4d
refactor: cleanup
Sep 17, 2024
500c96b
feat: use custom create customer reopnse dto
Sep 17, 2024
3c3d836
feat: use isarray in dto
Sep 17, 2024
2774465
feat: redact sensitive salesforce api data
Sep 17, 2024
03aacc5
feat: add custom sf error objects
Sep 17, 2024
6d6b6dc
test: update old test suites
Sep 19, 2024
b055538
feat: add unrestricted mvp fields
Sep 24, 2024
c4fd4f5
feat: prepare for DnB integration
Sep 24, 2024
57d389d
feat: continue mocking full customer creation
Oct 4, 2024
bdf2b4c
feat: add direct salesforce GET as agreed with data team
Oct 7, 2024
d4a7b56
feat: return 404 when no customer found
Oct 8, 2024
b0a9e34
feat: update customer service tests
Oct 8, 2024
468f47f
feat: update customer controller tests
Oct 8, 2024
46f8dda
feat: add create test to customer controller tests
Oct 8, 2024
caaaaaf
feat: add salesforce exception test
Oct 8, 2024
1d8aa6f
feat: update salesforce response descriptions
Oct 9, 2024
2aa8972
feat: add salesforce service tests
Oct 9, 2024
daf37c5
feat: typos
Oct 9, 2024
def50ad
feat: add salesforce create tests
Oct 10, 2024
f87ee47
feat: use minimum fieldset for account creation
Oct 14, 2024
9ccf0bc
feat: update snapshot
Oct 14, 2024
ed9be19
feat: update config behaviour and tests
Oct 14, 2024
79c0d3f
feat: post customer name to SF with D&B number
Oct 16, 2024
0a87635
feta: update tests
Oct 16, 2024
a98f57c
feat: add companies house number to POST
Oct 22, 2024
a393023
feat: update direct get dtos
Oct 22, 2024
bb55e5e
feat: update tests
Oct 22, 2024
b02e3d1
feat: mock salesforce response correctly
Oct 22, 2024
c82bd8a
feat: update snapshot
Oct 22, 2024
9c8891c
feat: return created customer after creation and update error handling
Oct 24, 2024
48b0edd
feat: generate PartyURN before POSTing
Oct 24, 2024
5fad347
comment: add comment
Oct 24, 2024
03ad79c
feat: update error handling and add sql validation
Oct 25, 2024
f73c9e0
feat: continue on noncritical errors and return efficiently
Oct 28, 2024
e5c9cf4
feat: update tests and error handling
Oct 28, 2024
2b5c215
feat: update api tests
Oct 28, 2024
53086eb
feat: add minimal DnB GET DUNS endpoint
Oct 29, 2024
3f792e1
feat: update tests
Oct 29, 2024
c1a1c42
feat: update customers service tests
Oct 29, 2024
5f6e849
feat: update error throwing mock behaviour
Oct 30, 2024
1c632ad
feat: remove redundant companies endpoint built for testing
Oct 30, 2024
7ec4996
feat: add d&b service and exception tests
Oct 30, 2024
554254d
feat: rename endpoint direct -> sf
Nov 7, 2024
ace44a6
feat: comment out rejectUnauthorized for prod
Nov 11, 2024
2dc5c01
docs: update readme
Nov 11, 2024
647035e
docs: update comments
Nov 11, 2024
fd0a1a2
docs: update comments
Nov 11, 2024
291cb59
refactor: rename SF_ -> SALESFORCE_
Nov 19, 2024
3baeb63
feat: use informatica get in creation (legacy behaviour commented out)
Nov 28, 2024
e7cc52a
feat: update tests
Nov 28, 2024
820f5e0
refactor: cleanup
Nov 28, 2024
6086fcb
feat: add customer service tests
Nov 28, 2024
2f748cb
feat: add informatica failure tests
Nov 28, 2024
ea1101a
refactor: cleanup
Nov 29, 2024
b687b90
feat: add legacy behaviour and tests
Dec 2, 2024
eb5c15b
docs: update sf numgen comment
Dec 2, 2024
d85449d
feat: update duplicate error message
Dec 4, 2024
8679311
feat: specify dynamic success status code for getOrCreate
Dec 5, 2024
d8bdcb7
test: update controller tests
Dec 5, 2024
71005ed
test: update controller tests
Dec 5, 2024
575d456
refactor: remove logging
Dec 5, 2024
a67eec3
feat: update customer service tests
Dec 5, 2024
0d08a88
lint: formatting
Dec 5, 2024
ac7d5a5
refactor: lint
Dec 5, 2024
7ba76fd
refactor: lint
Dec 5, 2024
cf2f3a7
feat: dummy customer creation endpoint
Sep 13, 2024
b49d5d6
feat: wip add salesforce service and module bypassing self-signed iss…
Sep 13, 2024
cea3496
feat: dummy post request
Sep 16, 2024
381b57c
feat: wip post request
Sep 16, 2024
5f7c397
feat: wip post request
Sep 16, 2024
75f7e44
feat: minimal sf post
Sep 17, 2024
61f6e04
refactor: cleanup
Sep 17, 2024
c6c4f42
feat: use custom create customer reopnse dto
Sep 17, 2024
0cd765a
feat: use isarray in dto
Sep 17, 2024
7535b94
feat: redact sensitive salesforce api data
Sep 17, 2024
24e22cd
feat: add custom sf error objects
Sep 17, 2024
08929cb
test: update old test suites
Sep 19, 2024
50d8514
feat: add unrestricted mvp fields
Sep 24, 2024
c8dbf58
feat: prepare for DnB integration
Sep 24, 2024
0d45e93
feat: continue mocking full customer creation
Oct 4, 2024
d5c183f
feat: add direct salesforce GET as agreed with data team
Oct 7, 2024
014824e
feat: return 404 when no customer found
Oct 8, 2024
d0b9e66
feat: update customer service tests
Oct 8, 2024
63d59d2
feat: update customer controller tests
Oct 8, 2024
96aa2c1
feat: add create test to customer controller tests
Oct 8, 2024
38ff5b2
feat: add salesforce exception test
Oct 8, 2024
a9b7265
feat: update salesforce response descriptions
Oct 9, 2024
593f426
feat: add salesforce service tests
Oct 9, 2024
2e49612
feat: typos
Oct 9, 2024
3a744a4
feat: add salesforce create tests
Oct 10, 2024
b294e34
feat: use minimum fieldset for account creation
Oct 14, 2024
f8171e4
feat: update snapshot
Oct 14, 2024
c135e73
feat: update config behaviour and tests
Oct 14, 2024
fe7a255
feat: post customer name to SF with D&B number
Oct 16, 2024
3b3833f
feta: update tests
Oct 16, 2024
88f8bbf
feat: add companies house number to POST
Oct 22, 2024
f48497d
feat: update direct get dtos
Oct 22, 2024
fee5b2c
feat: update tests
Oct 22, 2024
17d3d0c
feat: mock salesforce response correctly
Oct 22, 2024
1e08809
feat: update snapshot
Oct 22, 2024
b644796
feat: return created customer after creation and update error handling
Oct 24, 2024
79f4a90
feat: generate PartyURN before POSTing
Oct 24, 2024
78aaeb5
comment: add comment
Oct 24, 2024
592cbba
feat: update error handling and add sql validation
Oct 25, 2024
bd4d4a0
feat: continue on noncritical errors and return efficiently
Oct 28, 2024
52825a0
feat: update tests and error handling
Oct 28, 2024
900a435
feat: update api tests
Oct 28, 2024
e9802d8
feat: add minimal DnB GET DUNS endpoint
Oct 29, 2024
277be6d
feat: update tests
Oct 29, 2024
336f194
feat: update customers service tests
Oct 29, 2024
2828a0b
feat: update error throwing mock behaviour
Oct 30, 2024
3ab3e65
feat: remove redundant companies endpoint built for testing
Oct 30, 2024
b08be74
feat: add d&b service and exception tests
Oct 30, 2024
d7a489f
feat: rename endpoint direct -> sf
Nov 7, 2024
c6a27f9
feat: comment out rejectUnauthorized for prod
Nov 11, 2024
49c89b2
docs: update readme
Nov 11, 2024
13e410a
docs: update comments
Nov 11, 2024
32e0ca2
docs: update comments
Nov 11, 2024
aee6f99
refactor: rename SF_ -> SALESFORCE_
Nov 19, 2024
b961ed8
feat: use informatica get in creation (legacy behaviour commented out)
Nov 28, 2024
36824b8
feat: update tests
Nov 28, 2024
b91b2c9
refactor: cleanup
Nov 28, 2024
aaf73f0
feat: add customer service tests
Nov 28, 2024
4b303c9
feat: add informatica failure tests
Nov 28, 2024
b0ab9e1
refactor: cleanup
Nov 29, 2024
1fef264
feat: add legacy behaviour and tests
Dec 2, 2024
6ccdcdd
docs: update sf numgen comment
Dec 2, 2024
54fb187
feat: update duplicate error message
Dec 4, 2024
3490970
feat: specify dynamic success status code for getOrCreate
Dec 5, 2024
50ff093
test: update controller tests
Dec 5, 2024
6e77f83
test: update controller tests
Dec 5, 2024
27f7a63
refactor: remove logging
Dec 5, 2024
52eeff8
feat: update customer service tests
Dec 5, 2024
7e014f9
refactor: lint
Dec 5, 2024
3a2c84e
refactor: lint
Dec 5, 2024
482b193
Merge branch 'create-customer-endpoint' of https://github.com/UK-Expo…
Dec 5, 2024
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ MDM micro-service provides endpoints for internal UKEF applications ranging from
## Install 💻

```bash
npm install
npm install --legacy-peer-deps
```

## Run 💡
Expand Down
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ services:
COMPANIES_HOUSE_KEY:
COMPANIES_HOUSE_MAX_REDIRECTS:
COMPANIES_HOUSE_TIMEOUT:
DUN_AND_BRADSTREET_URL:
DUN_AND_BRADSTREET_KEY:
DUN_AND_BRADSTREET_MAX_REDIRECTS:
DUN_AND_BRADSTREET_TIMEOUT:
SALESFORCE_CLIENT_ID:
SALESFORCE_CLIENT_SECRET:
SALESFORCE_USERNAME:
SALESFORCE_PASSWORD:
SALESFORCE_INSTANCE_URL:
SALESFORCE_ACCESS_URL:
SALESFORCE_MAX_REDIRECTS:
SALESFORCE_TIMEOUT:
API_KEY:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:${PORT}"]
Expand Down
20 changes: 20 additions & 0 deletions src/config/dun-and-bradstreet.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { registerAs } from '@nestjs/config';
import { DUN_AND_BRADSTREET } from '@ukef/constants';
import { getIntConfig } from '@ukef/helpers/get-int-config';

export interface DunAndBradstreetConfig {
baseUrl: string;
key: string;
maxRedirects: number;
timeout: number;
}

export default registerAs(
DUN_AND_BRADSTREET.CONFIG.KEY,
(): DunAndBradstreetConfig => ({
baseUrl: process.env.DUN_AND_BRADSTREET_URL,
key: process.env.DUN_AND_BRADSTREET_KEY,
maxRedirects: getIntConfig(process.env.DUN_AND_BRADSTREET_MAX_REDIRECTS, 5),
timeout: getIntConfig(process.env.DUN_AND_BRADSTREET_TIMEOUT, 30000),
}),
);
4 changes: 3 additions & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import AppConfig from './app.config';
import CompaniesHouseConfig from './companies-house.config';
import DatabaseConfig from './database.config';
import DocConfig from './doc.config';
import DunAndBradstreetConfig from './dun-and-bradstreet.config';
import InformaticaConfig from './informatica.config';
import OrdnanceSurveyConfig from './ordnance-survey.config';
import SalesforceConfig from './salesforce.config';

export default [AppConfig, CompaniesHouseConfig, DocConfig, DatabaseConfig, InformaticaConfig, OrdnanceSurveyConfig];
export default [AppConfig, CompaniesHouseConfig, DocConfig, DatabaseConfig, DunAndBradstreetConfig, InformaticaConfig, OrdnanceSurveyConfig, SalesforceConfig];
56 changes: 56 additions & 0 deletions src/config/salesforce.config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { withEnvironmentVariableParsingUnitTests } from '@ukef-test/common-tests/environment-variable-parsing-unit-tests';

import salesforceConfig, { SalesforceConfig } from './salesforce.config';

describe('salesforceConfig', () => {
const configDirectlyFromEnvironmentVariables: { configPropertyName: keyof SalesforceConfig; environmentVariableName: string }[] = [
{
configPropertyName: 'baseUrl',
environmentVariableName: 'SALESFORCE_INSTANCE_URL',
},
{
configPropertyName: 'clientId',
environmentVariableName: 'SALESFORCE_CLIENT_ID',
},

{
configPropertyName: 'clientSecret',
environmentVariableName: 'SALESFORCE_CLIENT_SECRET',
},
{
configPropertyName: 'username',
environmentVariableName: 'SALESFORCE_USERNAME',
},
{
configPropertyName: 'password',
environmentVariableName: 'SALESFORCE_PASSWORD',
},
{
configPropertyName: 'accessUrl',
environmentVariableName: 'SALESFORCE_ACCESS_URL',
},
];

const configParsedAsIntFromEnvironmentVariablesWithDefault: {
configPropertyName: keyof SalesforceConfig;
environmentVariableName: string;
defaultConfigValue: number;
}[] = [
{
configPropertyName: 'maxRedirects',
environmentVariableName: 'SALESFORCE_MAX_REDIRECTS',
defaultConfigValue: 5,
},
{
configPropertyName: 'timeout',
environmentVariableName: 'SALESFORCE_TIMEOUT',
defaultConfigValue: 30000, // in milliseconds
},
];

withEnvironmentVariableParsingUnitTests({
configDirectlyFromEnvironmentVariables,
configParsedAsIntFromEnvironmentVariablesWithDefault,
getConfig: () => salesforceConfig(),
});
});
29 changes: 29 additions & 0 deletions src/config/salesforce.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { registerAs } from '@nestjs/config';
import { getIntConfig } from '@ukef/helpers/get-int-config';

export const KEY = 'salesforce';

export interface SalesforceConfig {
baseUrl: string;
clientId: string;
clientSecret: string;
username: string;
password: string;
accessUrl: string;
maxRedirects: number;
timeout: number;
}

export default registerAs(
KEY,
(): SalesforceConfig => ({
baseUrl: process.env.SALESFORCE_INSTANCE_URL,
clientId: process.env.SALESFORCE_CLIENT_ID,
clientSecret: process.env.SALESFORCE_CLIENT_SECRET,
username: process.env.SALESFORCE_USERNAME,
password: process.env.SALESFORCE_PASSWORD,
accessUrl: process.env.SALESFORCE_ACCESS_URL,
maxRedirects: getIntConfig(process.env.SALESFORCE_MAX_REDIRECTS, 5),
timeout: getIntConfig(process.env.SALESFORCE_TIMEOUT, 30000), // in milliseconds
}),
);
5 changes: 5 additions & 0 deletions src/constants/dun-and-bradstreet.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const DUN_AND_BRADSTREET = {
CONFIG: {
KEY: 'dunAndBradstreet',
},
};
1 change: 1 addition & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export * from './companies-house.constant';
export * from './customers.constant';
export * from './database-name.constant';
export * from './date.constant';
export * from './dun-and-bradstreet.constant';
export * from './enums';
export * from './geospatial.constant';
export * from './govuk-notify.constant';
Expand Down
27 changes: 27 additions & 0 deletions src/helper-modules/dun-and-bradstreet/dun-and-bradstreet.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DunAndBradstreetConfig } from '@ukef/config/dun-and-bradstreet.config';
import { DUN_AND_BRADSTREET } from '@ukef/constants';
import { HttpModule } from '@ukef/modules/http/http.module';

import { DunAndBradstreetService } from './dun-and-bradstreet.service';

@Module({
imports: [
HttpModule.registerAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const { baseUrl, maxRedirects, timeout } = configService.get<DunAndBradstreetConfig>(DUN_AND_BRADSTREET.CONFIG.KEY);
return {
baseURL: baseUrl,
maxRedirects,
timeout,
};
},
}),
],
providers: [DunAndBradstreetService],
exports: [DunAndBradstreetService],
})
export class DunAndBradstreetModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { resetAllWhenMocks, when } from 'jest-when';
import { of, throwError } from 'rxjs';

import { DunAndBradstreetService } from './dun-and-bradstreet.service';
import { DunAndBradstreetException } from './exception/dun-and-bradstreet.exception';
import { RandomValueGenerator } from '@ukef-test/support/generator/random-value-generator';
import { AxiosError } from 'axios';

describe('CompaniesHouseService', () => {
let httpServiceGet: jest.Mock;
let configServiceGet: jest.Mock;
let service: DunAndBradstreetService;

const valueGenerator = new RandomValueGenerator();

const testRegistrationNumber = '0' + valueGenerator.stringOfNumericCharacters({ length: 7 });
const expectedAccessToken = 'TEST_ACCESS_TOKEN';
const getAccessTokenMethodMock = jest
.spyOn(DunAndBradstreetService.prototype as any, 'getAccessToken')
.mockImplementation(() => Promise.resolve(expectedAccessToken));

const dunAndBradstreetpath = `/v1/match/cleanseMatch?countryISOAlpha2Code=GB&registrationNumber=${testRegistrationNumber}`;
const expectedDunsNumber = '123456789';
const getDunsNumberDunAndBradstreetResponse = {
matchCandidates: [
{
organization: {
duns: expectedDunsNumber,
},
},
],
};

const expectedHttpServiceGetArguments: [string, object] = [
dunAndBradstreetpath,
{
headers: {
Authorization: `Bearer ${expectedAccessToken}`,
},
},
];

const expectedHttpServiceGetResponse = of({
data: getDunsNumberDunAndBradstreetResponse,
status: 200,
statusText: 'OK',
config: undefined,
headers: undefined,
});

beforeAll(() => {
const httpService = new HttpService();
httpServiceGet = jest.fn();
httpService.get = httpServiceGet;

const configService = new ConfigService();
configServiceGet = jest.fn().mockReturnValue({ key: 'TEST API_KEY' });
configService.get = configServiceGet;

service = new DunAndBradstreetService(httpService, configService);
});

beforeEach(() => {
resetAllWhenMocks();
});

afterEach(() => {
jest.clearAllMocks();
});

describe('getDunAndBradstreetNumberByRegistrationNumber', () => {
it('calls the Dun and Bradstreet API with the correct arguments', async () => {
when(httpServiceGet)
.calledWith(...expectedHttpServiceGetArguments)
.mockReturnValueOnce(expectedHttpServiceGetResponse);

await service.getDunAndBradstreetNumberByRegistrationNumber(testRegistrationNumber);

expect(getAccessTokenMethodMock).toHaveBeenCalledTimes(1);
expect(httpServiceGet).toHaveBeenCalledTimes(1);
expect(httpServiceGet).toHaveBeenCalledWith(...expectedHttpServiceGetArguments);
});

it('returns the results when the Dun and Bradstreet API returns a 200 response with results', async () => {
when(httpServiceGet)
.calledWith(...expectedHttpServiceGetArguments)
.mockReturnValueOnce(expectedHttpServiceGetResponse);

const response = await service.getDunAndBradstreetNumberByRegistrationNumber(testRegistrationNumber);

expect(getAccessTokenMethodMock).toHaveBeenCalledTimes(1);
expect(response).toBe(expectedDunsNumber);
});

it('throws a DunAndBradstreetException if the Dun and Bradstreet API returns an unknown error response', async () => {
const axiosError = new AxiosError();
when(httpServiceGet)
.calledWith(...expectedHttpServiceGetArguments)
.mockReturnValueOnce(throwError(() => axiosError));

const getDunsNumberPromise = service.getDunAndBradstreetNumberByRegistrationNumber(testRegistrationNumber);

expect(getAccessTokenMethodMock).toHaveBeenCalledTimes(1);
await expect(getDunsNumberPromise).rejects.toBeInstanceOf(DunAndBradstreetException);
await expect(getDunsNumberPromise).rejects.toThrow('Failed to get response from Dun and Bradstreet API');
await expect(getDunsNumberPromise).rejects.toHaveProperty('innerError', axiosError);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { DUN_AND_BRADSTREET } from '@ukef/constants';
import { HttpClient } from '@ukef/modules/http/http.client';

import { DunAndBradstreetConfig } from '@ukef/config/dun-and-bradstreet.config';
import { createWrapDunAndBradstreetHttpGetErrorCallback } from './wrap-dun-and-bradstreet-http-error-callback';

@Injectable()
export class DunAndBradstreetService {
private readonly httpClient: HttpClient;
private readonly encoded_key: string;

constructor(httpService: HttpService, configService: ConfigService) {
this.httpClient = new HttpClient(httpService);
const { key } = configService.get<DunAndBradstreetConfig>(DUN_AND_BRADSTREET.CONFIG.KEY);
this.encoded_key = key;
}

async getDunAndBradstreetNumberByRegistrationNumber(registrationNumber: string): Promise<string> {
const path = `/v1/match/cleanseMatch?countryISOAlpha2Code=GB&registrationNumber=${registrationNumber}`;
const access_token = await this.getAccessToken();
const { data } = await this.httpClient.get<any>({
path,
headers: {
Authorization: 'Bearer ' + access_token,
},
onError: createWrapDunAndBradstreetHttpGetErrorCallback({
messageForUnknownError: 'Failed to get response from Dun and Bradstreet API',
knownErrors: [],
}),
});
return data?.matchCandidates[0]?.organization?.duns;
}

private async getAccessToken(): Promise<string> {
const path = '/v3/token';
const response = await this.httpClient.post<any, any>({
path,
body: {
grant_type: 'client_credentials',
},
headers: {
Authorization: 'Basic ' + this.encoded_key,
'Content-Type': 'application/x-www-form-urlencoded',
},
onError: createWrapDunAndBradstreetHttpGetErrorCallback({
messageForUnknownError: 'Failed to get access token',
knownErrors: [],
}),
});
return response.data.access_token;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { RandomValueGenerator } from '@ukef-test/support/generator/random-value-generator';

import { DunAndBradstreetException } from './dun-and-bradstreet.exception';

describe('CompaniesHouseException', () => {
const valueGenerator = new RandomValueGenerator();
const message = valueGenerator.string();

it('exposes the message it was created with', () => {
const exception = new DunAndBradstreetException(message);

expect(exception.message).toBe(message);
});

it('exposes the name of the exception', () => {
const exception = new DunAndBradstreetException(message);

expect(exception.name).toBe('DunAndBradstreetException');
});

it('exposes the inner error it was created with', () => {
const innerError = new Error();

const exception = new DunAndBradstreetException(message, innerError);

expect(exception.innerError).toBe(innerError);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class DunAndBradstreetException extends Error {
constructor(
message: string,
public readonly innerError?: Error,
) {
super(message);
this.name = this.constructor.name;
}
}
Loading