Skip to content

Commit

Permalink
feat(commerce-case-client): use TypeError for missing arguments, hand…
Browse files Browse the repository at this point in the history
…le void responses
  • Loading branch information
lrosenfeldt committed Aug 12, 2024
1 parent 879adab commit d815f27
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 15 deletions.
241 changes: 241 additions & 0 deletions src/endpoints/CommerceCaseApiClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import fetch from 'node-fetch';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { CommunicatorConfiguration } from '../CommunicatorConfiguration.js';
import { CommerceCaseApiClient } from '../endpoints/CommerceCaseApiClient.js';
import { createResponseMock, createEmptyErrorResponseMock } from '../testutils/mock-response.js';
import { ApiErrorResponseException } from '../errors/ApiErrorResponseException.js';
import { ApiResponseRetrievalException } from '../errors/ApiResponseRetrievalException.js';
import type { CreateCommerceCaseResponse } from '../models/CreateCommerceCaseResponse.js';
import type { ErrorResponse } from '../models/ErrorResponse.js';
import type { CommerceCaseResponse } from '../models/CommerceCaseResponse.js';
import type { Customer } from '../models/Customer.js';
import { GetCommerceCasesQuery } from '../queries/GetCommerceCasesQuery.js';

vi.mock('node-fetch', async importOriginal => {
return {
...(await importOriginal<typeof import('node-fetch')>()),
default: vi.fn(),
};
});

const mockedFetch = vi.mocked(fetch, true);

describe('CheckoutApiClient', () => {
let commerceCaseApiClient: CommerceCaseApiClient;

beforeEach(() => {
commerceCaseApiClient = new CommerceCaseApiClient(
new CommunicatorConfiguration('apiKey', 'apiSecret', 'https://test.com'),
);
});

describe('createCommerceCaseRequest', () => {
test('given request was successful, then return response', async () => {
const expectedResponse: CreateCommerceCaseResponse = {
commerceCaseId: 'id-5513',
customer: {
businessRelation: 'B2C',
billingAddress: {
countryCode: 'DE',
zip: '40474',
city: 'Düsseldorf',
street: 'Cecilienallee',
houseNumber: '2',
},
},
checkout: {
checkoutId: 'checkout-101',
amountOfMoney: { currencyCode: 'EUR', amount: 1445 },
},
};

mockedFetch.mockResolvedValueOnce(createResponseMock(200, expectedResponse));

const payload: CreateCommerceCaseResponse = {
merchantReference: 'id-from-shop-45',
customer: {
businessRelation: 'B2C',
billingAddress: {
countryCode: 'DE',
zip: '40474',
city: 'Düsseldorf',
street: 'Cecilienallee',
houseNumber: '2',
},
},
};
const res = await commerceCaseApiClient.createCommerceCaseRequest('merchantId', payload);

expect(res).toEqual(expectedResponse);
});
test('given request was not successful (400), then return errorresponse', async () => {
const expectedResponse: ErrorResponse = { errorId: 'error-id' };

mockedFetch.mockResolvedValueOnce(createResponseMock<ErrorResponse>(400, expectedResponse));

expect.assertions(1);
try {
await commerceCaseApiClient.createCommerceCaseRequest('merchantId', {});
} catch (error) {
expect(error).toEqual(new ApiErrorResponseException(400, JSON.stringify(expectedResponse)));
}
});
test('given request was not successful (500), throw ApiResponseRetrievalException', async () => {
mockedFetch.mockResolvedValueOnce(createEmptyErrorResponseMock(500));

expect.assertions(1);
try {
await commerceCaseApiClient.createCommerceCaseRequest('merchantId', {});
} catch (error) {
expect(error).toEqual(new ApiResponseRetrievalException(500, ''));
}
});
test('a required params is empty, throw an error', () => {
expect(() => commerceCaseApiClient.createCommerceCaseRequest('', {})).rejects.toThrow('Merchant ID is required');
});
});
describe('getCommerceCaseRequest', () => {
test('given request was successful, then return response', async () => {
const expectedResponse: CommerceCaseResponse = {
commerceCaseId: 'id-4499',
customer: {
businessRelation: 'B2B',
billingAddress: {
countryCode: 'DE',
zip: '24113',
city: 'Kiel',
street: 'Krummbogen',
houseNumber: '82a',
},
},
checkouts: [],
};

mockedFetch.mockResolvedValueOnce(createResponseMock(200, expectedResponse));

const res = await commerceCaseApiClient.getCommerceCaseRequest('merchantId', 'commerceCaseId');

expect(res).toEqual(expectedResponse);
});
test('given request was not successful (400), then return errorresponse', async () => {
const expectedResponse: ErrorResponse = { errorId: 'error-id' };

mockedFetch.mockResolvedValueOnce(createResponseMock<ErrorResponse>(400, expectedResponse));

expect.assertions(1);
try {
await commerceCaseApiClient.getCommerceCaseRequest('merchantId', 'commerceCaseId');
} catch (error) {
expect(error).toEqual(new ApiErrorResponseException(400, JSON.stringify(expectedResponse)));
}
});
test('given request was not successful (500), throw ApiResponseRetrievalException', async () => {
mockedFetch.mockResolvedValueOnce(createEmptyErrorResponseMock(500));

expect.assertions(1);
try {
await commerceCaseApiClient.getCommerceCaseRequest('merchantId', 'commerceCaseId');
} catch (error) {
expect(error).toEqual(new ApiResponseRetrievalException(500, ''));
}
});
test('a required params is empty, throw an error', () => {
expect(() => commerceCaseApiClient.getCommerceCaseRequest('', 'commerceCaseId')).rejects.toThrow(
'Merchant ID is required',
);
expect(() => commerceCaseApiClient.getCommerceCaseRequest('merchantId', '')).rejects.toThrow(
'Commerce Case ID is required',
);
});
});
describe('getCommerceCasesRequest', () => {
test('given request was successful, then return response', async () => {
const expectedResponse: CommerceCaseResponse[] = [
{
commerceCaseId: 'id-4499',
checkouts: [
{
commerceCaseId: 'id-4499',
creationDateTime: '2024-12-24T12:34:56Z',
},
],
},
];

mockedFetch.mockResolvedValueOnce(createResponseMock(200, expectedResponse));

const queryParams = new GetCommerceCasesQuery();
queryParams.setOffset(0);
queryParams.setSize(10);
queryParams.setCommerceCaseId('commerceCaseId');
const res = await commerceCaseApiClient.getCommerceCasesRequest('merchantId', queryParams);

expect(res).toEqual(expectedResponse);
});
test('given request was not successful (400), then return errorresponse', async () => {
const expectedResponse: ErrorResponse = { errorId: 'error-id' };

mockedFetch.mockResolvedValueOnce(createResponseMock<ErrorResponse>(400, expectedResponse));

expect.assertions(1);
try {
await commerceCaseApiClient.getCommerceCasesRequest('merchantId');
} catch (error) {
expect(error).toEqual(new ApiErrorResponseException(400, JSON.stringify(expectedResponse)));
}
});
test('given request was not successful (500), throw ApiResponseRetrievalException', async () => {
mockedFetch.mockResolvedValueOnce(createEmptyErrorResponseMock(500));

expect.assertions(1);
try {
await commerceCaseApiClient.getCommerceCasesRequest('merchantId');
} catch (error) {
expect(error).toEqual(new ApiResponseRetrievalException(500, ''));
}
});
test('a required params is empty, throw an error', () => {
expect(() => commerceCaseApiClient.getCommerceCasesRequest('')).rejects.toThrow('Merchant ID is required');
});
});
describe('updateCommerceCaseRequest', () => {
test('given request was successful, then return response', async () => {
mockedFetch.mockResolvedValueOnce(createResponseMock(204));

const customer: Customer = {
locale: '',
};
await commerceCaseApiClient.updateCommerceCaseRequest('merchantId', 'commerceCaseId', customer);
});
test('given request was not successful (400), then return errorresponse', async () => {
const expectedResponse: ErrorResponse = { errorId: 'error-id' };

mockedFetch.mockResolvedValueOnce(createResponseMock<ErrorResponse>(400, expectedResponse));

expect.assertions(1);
try {
await commerceCaseApiClient.updateCommerceCaseRequest('merchantId', 'commerceCaseId', {});
} catch (error) {
expect(error).toEqual(new ApiErrorResponseException(400, JSON.stringify(expectedResponse)));
}
});
test('given request was not successful (500), throw ApiResponseRetrievalException', async () => {
mockedFetch.mockResolvedValueOnce(createEmptyErrorResponseMock(500));

expect.assertions(1);
try {
await commerceCaseApiClient.updateCommerceCaseRequest('merchantId', 'commerceCaseId', {});
} catch (error) {
expect(error).toEqual(new ApiResponseRetrievalException(500, ''));
}
});
test('a required params is empty, throw an error', () => {
expect(() => commerceCaseApiClient.updateCommerceCaseRequest('', 'commerceCaseId', {})).rejects.toThrow(
'Merchant ID is required',
);
expect(() => commerceCaseApiClient.updateCommerceCaseRequest('merchantId', '', {})).rejects.toThrow(
'Commerce Case ID is required',
);
});
});
});
23 changes: 8 additions & 15 deletions src/endpoints/CommerceCaseApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
Customer,
} from '../models/index.js';
import { GetCommerceCasesQuery } from '../queries/GetCommerceCasesQuery.js';
import { BaseApiClient } from './BaseApiClient.js';
import { BaseApiClient, COMMERCE_CASE_ID_REQUIRED_ERROR, MERCHANT_ID_REQUIRED_ERROR } from './BaseApiClient.js';

export class CommerceCaseApiClient extends BaseApiClient {
constructor(config: CommunicatorConfiguration) {
Expand All @@ -20,12 +20,8 @@ export class CommerceCaseApiClient extends BaseApiClient {
payload: CreateCommerceCaseRequest,
): Promise<CreateCommerceCaseResponse> {
if (!merchantId) {
throw new Error('Merchant ID is required');
throw new TypeError(MERCHANT_ID_REQUIRED_ERROR);
}
if (!payload) {
throw new Error('Payload is required');
}
console.log(payload);
const url = new URL(`/v1/${merchantId}/commerce-cases`, this.getConfig().getHost());

const requestInit: RequestInit = {
Expand All @@ -41,10 +37,10 @@ export class CommerceCaseApiClient extends BaseApiClient {

public async getCommerceCaseRequest(merchantId: string, commerceCaseId: string): Promise<CommerceCaseResponse> {
if (!merchantId) {
throw new Error('Merchant ID is required');
throw new TypeError(MERCHANT_ID_REQUIRED_ERROR);
}
if (!commerceCaseId) {
throw new Error('Commerce Case ID is required');
throw new TypeError(COMMERCE_CASE_ID_REQUIRED_ERROR);
}

const url = new URL(`/v1/${merchantId}/commerce-cases/${commerceCaseId}`, this.getConfig().getHost());
Expand All @@ -62,7 +58,7 @@ export class CommerceCaseApiClient extends BaseApiClient {
queryParams?: GetCommerceCasesQuery,
): Promise<CommerceCaseResponse[]> {
if (!merchantId) {
throw new Error('Merchant ID is required');
throw new TypeError(MERCHANT_ID_REQUIRED_ERROR);
}

const url = new URL(`/v1/${merchantId}/commerce-cases`, this.getConfig().getHost());
Expand All @@ -86,13 +82,10 @@ export class CommerceCaseApiClient extends BaseApiClient {
customer: Customer,
): Promise<void> {
if (!merchantId) {
throw new Error('Merchant ID is required');
throw new TypeError(MERCHANT_ID_REQUIRED_ERROR);
}
if (!commerceCaseId) {
throw new Error('Commerce Case ID is required');
}
if (!customer) {
throw new Error('Customer is required');
throw new TypeError(COMMERCE_CASE_ID_REQUIRED_ERROR);
}

const url = new URL(`/v1/${merchantId}/commerce-cases/${commerceCaseId}`, this.getConfig().getHost());
Expand All @@ -105,6 +98,6 @@ export class CommerceCaseApiClient extends BaseApiClient {
body: JSON.stringify({ customer }),
};

await this.makeApiCall(url.toString(), requestInit);
await this.makeApiCall(url.toString(), requestInit, BaseApiClient.parseVoid);
}
}

0 comments on commit d815f27

Please sign in to comment.