Skip to content

Commit

Permalink
test(checkout-core): add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
EdieLemoine committed Oct 10, 2023
1 parent 7b3bc87 commit b54d0be
Show file tree
Hide file tree
Showing 20 changed files with 388 additions and 10 deletions.
40 changes: 40 additions & 0 deletions libs/checkout/core/src/__tests__/getMockCheckoutContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {vi} from 'vitest';
import {FrontendEndpoint} from '@myparcel-pdk/checkout-common';
import {type CheckoutAppContext} from '../types';

export const getMockCheckoutContext = vi.fn(
(context?: Partial<CheckoutAppContext['checkout']>): CheckoutAppContext['checkout'] => {
return {
config: {
...context?.config,
},
settings: {
hasDeliveryOptions: true,
actions: {
baseUrl: '',
endpoints: {
[FrontendEndpoint.FetchCheckoutContext]: {
body: '',
headers: {},
method: 'GET',
parameters: {},
path: '',
property: 'context',
...context?.settings?.actions?.endpoints?.[FrontendEndpoint.FetchCheckoutContext],
},
},
...context?.settings?.actions,
},
allowedShippingMethods: [],
carriersWithTaxFields: [],
countriesWithSeparateAddressFields: [],
hiddenInputName: '',
...context?.settings,
},
strings: {
...context?.strings,
},
...context,
};
},
);
29 changes: 29 additions & 0 deletions libs/checkout/core/src/__tests__/getMockFormData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {AddressField, AddressType, PdkField} from '@myparcel-pdk/checkout-common';
import {type RecursivePartial} from '@myparcel/ts-utils';
import {type PdkCheckoutConfigInput} from '../types';

export const getMockFormData = (
formData?: RecursivePartial<PdkCheckoutConfigInput['formData']>,
): PdkCheckoutConfigInput['formData'] => {
return {
[PdkField.AddressType]: 'address-type',
[PdkField.ShippingMethod]: 'shipping-method',
[AddressType.Billing]: {
[AddressField.Address1]: 'b-address1',
[AddressField.Address2]: 'b-address2',
[AddressField.City]: 'b-city',
[AddressField.Country]: 'b-country',
[AddressField.PostalCode]: 'b-postal-code',
...formData?.[AddressType.Billing],
},
[AddressType.Shipping]: {
[AddressField.Address1]: 's-address1',
[AddressField.Address2]: 's-address2',
[AddressField.City]: 's-city',
[AddressField.Country]: 's-country',
[AddressField.PostalCode]: 's-postal-code',
...formData?.[AddressType.Shipping],
},
...formData,
} as PdkCheckoutConfigInput['formData'];
};
46 changes: 46 additions & 0 deletions libs/checkout/core/src/__tests__/getMockPdkCheckoutConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {vi} from 'vitest';
import {AddressField, AddressType, PdkField} from '@myparcel-pdk/checkout-common';
import {type PdkCheckoutConfigInput} from '../types';
import {doRequestSpy, getFormDataSpy, getFormSpy, hasAddressTypeSpy, initializeSpy, toggleFieldSpy} from './spies';
import {getMockFormData} from './getMockFormData';

export const getMockPdkCheckoutConfig = vi.fn(
(config?: Partial<PdkCheckoutConfigInput>): PdkCheckoutConfigInput => ({
doRequest: doRequestSpy,
getForm: getFormSpy,
getFormData: getFormDataSpy,
hasAddressType: hasAddressTypeSpy,
initialize: initializeSpy,
toggleField: toggleFieldSpy,

selectors: {
deliveryOptions: '#delivery-options',
deliveryOptionsWrapper: '#delivery-options-wrapper',
...config?.selectors,
},

fields: {
[PdkField.AddressType]: 'address-type',
[PdkField.ShippingMethod]: 'shipping-method',
[AddressType.Billing]: {
[AddressField.Address1]: 'b-address1',
[AddressField.Address2]: 'b-address2',
[AddressField.City]: 'b-city',
[AddressField.Country]: 'b-country',
[AddressField.PostalCode]: 'b-postal-code',
...config?.fields?.[AddressType.Billing],
},
[AddressType.Shipping]: {
[AddressField.Address1]: 's-address1',
[AddressField.Address2]: 's-address2',
[AddressField.City]: 's-city',
[AddressField.Country]: 's-country',
[AddressField.PostalCode]: 's-postal-code',
...config?.fields?.[AddressType.Shipping],
},
...config?.fields,
},

formData: getMockFormData(config?.formData),
}),
);
5 changes: 5 additions & 0 deletions libs/checkout/core/src/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './getMockFormData';
export * from './getMockPdkCheckoutConfig';
export * from './mockDeliveryOptionsElement';
export * from './mockPdkCheckout';
export * from './spies';
23 changes: 23 additions & 0 deletions libs/checkout/core/src/__tests__/mockDeliveryOptionsElement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {type CheckoutAppContext} from '../types';
import {ATTRIBUTE_CONTEXT} from '../constants';
import {getMockCheckoutContext} from './getMockCheckoutContext';

export const mockDeliveryOptionsElement = (): void => {
const form = document.createElement('form');

const wrapper = document.createElement('div');
const element = document.createElement('div');

wrapper.id = 'delivery-options-wrapper';
element.id = 'delivery-options';

wrapper.setAttribute(
ATTRIBUTE_CONTEXT,
JSON.stringify({checkout: getMockCheckoutContext()} satisfies CheckoutAppContext),
);

wrapper.appendChild(element);
form.appendChild(wrapper);

document.body.appendChild(form);
};
21 changes: 21 additions & 0 deletions libs/checkout/core/src/__tests__/mockPdkCheckout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {usePdkCheckout} from '../usePdkCheckout';
import {type PdkCheckoutConfigInput} from '../types';
import {createPdkCheckout} from '../init';
import {mockDeliveryOptionsElement} from './mockDeliveryOptionsElement';
import {getMockPdkCheckoutConfig} from './getMockPdkCheckoutConfig';

export const mockPdkCheckout = (config?: Partial<PdkCheckoutConfigInput>, includeElements = true): Promise<void> => {
return new Promise((resolve, reject) => {
if (includeElements) {
mockDeliveryOptionsElement();
}

createPdkCheckout(getMockPdkCheckoutConfig(config));

usePdkCheckout().onInitialize(() => resolve());

setTimeout(() => {
reject(new Error('Timeout: mockPdkCheckout'));
}, 1000);
});
};
30 changes: 30 additions & 0 deletions libs/checkout/core/src/__tests__/spies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {vi} from 'vitest';
import {AddressType} from '@myparcel-pdk/checkout-common';

export const doRequestSpy = vi.fn();

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
export const getFormSpy = vi.fn(() => document.querySelector<HTMLFormElement>('form')!);

export const getFormDataSpy = vi.fn(
(): Record<string, string> => ({
'address-type': AddressType.Billing,
'b-address1': 'Straatnaam 12e',
'b-address2': '',
'b-city': 'Amsterdam',
'b-country': 'NL',
'b-postal-code': '1234AB',
's-address1': 'Straatnaam 12e',
's-address2': '',
's-city': 'Amsterdam',
's-country': 'NL',
's-postal-code': '1234AB',
'shipping-method': 'shipping-method',
}),
);

export const hasAddressTypeSpy = vi.fn(() => true);

export const initializeSpy = vi.fn(() => Promise.resolve());

export const toggleFieldSpy = vi.fn();
1 change: 1 addition & 0 deletions libs/checkout/core/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ATTRIBUTE_CONTEXT = 'data-context';
3 changes: 3 additions & 0 deletions libs/checkout/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import './globals';

export * from './__tests__';

export * from './config';
export * from './constants';
export * from './data';
export * from './events';
export * from './init';
Expand Down
5 changes: 3 additions & 2 deletions libs/checkout/core/src/listeners/updateCheckoutForm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {type AddressField, AddressType, type PdkField} from '@myparcel-pdk/checkout-common';
import {useCheckoutStore} from '../utils';
import {getAddressType, type PdkCheckoutForm, useConfig} from '../index';
import {getAddressType, useCheckoutStore} from '../utils';
import {type PdkCheckoutForm} from '../types';
import {useConfig} from '../config';

function getEntry(data: Record<string, FormDataEntryValue>, value: undefined | string): string {
return (data[value as string] as string | undefined) ?? '';
Expand Down
5 changes: 2 additions & 3 deletions libs/checkout/core/src/utils/getFrontendContext.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import {type CheckoutAppContext} from '../types';
import {ATTRIBUTE_CONTEXT} from '../constants';
import {useConfig} from '../config';
import {getElement} from './global';

const ATTRIBUTE_CONTEXT = 'data-context';

export const getFrontendContext = (): CheckoutAppContext['checkout'] => {
const config = useConfig();

const wrapper = getElement(config.selectors.deliveryOptionsWrapper);
const wrapper = getElement(config.selectors.deliveryOptionsWrapper, false);
const context = wrapper?.getAttribute(ATTRIBUTE_CONTEXT);

if (!wrapper || !context) {
Expand Down
18 changes: 18 additions & 0 deletions libs/checkout/core/src/utils/global/doRequest.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {beforeEach, describe, expect, it} from 'vitest';
import {FrontendEndpoint} from '@myparcel-pdk/checkout-common';
import {doRequestSpy, mockPdkCheckout} from '../../__tests__';
import {doRequest} from './doRequest';

describe('doRequest', () => {
beforeEach(async () => {
await mockPdkCheckout();
});

it('should call doRequest', async () => {
expect.assertions(1);

await doRequest(FrontendEndpoint.FetchCheckoutContext, {shippingMethod: 'shipping-method'});

expect(doRequestSpy).toHaveBeenCalled();
});
});
83 changes: 83 additions & 0 deletions libs/checkout/core/src/utils/global/fieldsEqual.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {beforeEach, describe, expect, it} from 'vitest';
import {AddressField, AddressType, PdkField} from '@myparcel-pdk/checkout-common';
import {getMockFormData, mockPdkCheckout} from '../../__tests__';
import {fieldsEqual} from './fieldsEqual';

describe('fieldsEqual', () => {
beforeEach(async () => {
await mockPdkCheckout();
});

it('should return true if the fields are equal', () => {
const result = fieldsEqual(
getMockFormData({[AddressType.Billing]: {[AddressField.Address1]: 'appelboom'}}),
getMockFormData({[AddressType.Billing]: {[AddressField.Address1]: 'appelboom'}}),
AddressField.Address1,
);

expect(result).toBe(true);
});

it('should return false if the fields are not equal', () => {
const result = fieldsEqual(
getMockFormData({[AddressType.Billing]: {[AddressField.Address1]: 'appelboom'}}),
getMockFormData({[AddressType.Billing]: {[AddressField.Address1]: 'perenboom'}}),
AddressField.Address1,
);

expect(result).toBe(false);
});

it('should return true if the fields are equal for a specific address type', () => {
const result = fieldsEqual(
getMockFormData({
[AddressType.Billing]: {
[AddressField.Address1]: 'ruurd',
},
[AddressType.Shipping]: {
[AddressField.Address1]: 'appelboom',
},
}),
getMockFormData({
[AddressType.Billing]: {
[AddressField.Address1]: 'jan-piet',
},
[AddressType.Shipping]: {
[AddressField.Address1]: 'appelboom',
},
}),
AddressField.Address1,
AddressType.Shipping,
);

expect(result).toBe(true);
});

it('can check if pdk fields match', () => {
const result = fieldsEqual(
getMockFormData({
[PdkField.ShippingMethod]: 'ruurd',
}),
getMockFormData({
[PdkField.ShippingMethod]: 'ruurd',
}),
PdkField.ShippingMethod,
);

expect(result).toBe(true);
});

it('can check if pdk fields do not match', () => {
const result = fieldsEqual(
getMockFormData({
[PdkField.ShippingMethod]: 'ruurd',
}),
getMockFormData({
[PdkField.ShippingMethod]: 'barend',
}),
PdkField.ShippingMethod,
);

expect(result).toBe(false);
});
});
3 changes: 2 additions & 1 deletion libs/checkout/core/src/utils/global/fieldsEqual.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {type AddressField, type AddressFields, type AddressType, PdkField} from '@myparcel-pdk/checkout-common';
import {isEnumValue} from '@myparcel/ts-utils';
import {getAddressType, type PdkCheckoutForm} from '../../index';
import {type PdkCheckoutForm} from '../../types';
import {getAddressType} from './getAddressType';

type FieldsEqual = {
(
Expand Down
3 changes: 2 additions & 1 deletion libs/checkout/core/src/utils/global/getAddressField.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {type AddressField, type AddressType} from '@myparcel-pdk/checkout-common';
import {useUtil, Util} from '../useUtil';
import {useCheckoutStore} from '../useCheckoutStore';
import {useConfig, useUtil, Util} from '../../index';
import {useConfig} from '../../config';

/**
* Get field by name. Will return element with selector: "#<billing|shipping>_<name>".
Expand Down
28 changes: 28 additions & 0 deletions libs/checkout/core/src/utils/global/getElement.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {afterEach, describe, expect, it, vi} from 'vitest';
import {getElement} from './getElement';

describe('getElement', () => {
afterEach(() => {
document.body.innerHTML = '';
});

it('should return null if the element is not found', () => {
expect(getElement('#foo', false)).toBeNull();
});

it('should return the element if it is found', () => {
document.body.innerHTML = `
<div id="foo"></div>
`;

expect(getElement('#foo')).toEqual(document.querySelector('#foo'));
});

it('should warn if the element is not found', () => {
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});

getElement('#foo', true);

expect(consoleWarnSpy).toHaveBeenCalledWith('Element not found: "#foo"');
});
});
2 changes: 1 addition & 1 deletion libs/checkout/core/src/utils/global/getFieldValue.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {type AddressField, type AddressType, PdkField} from '@myparcel-pdk/checkout-common';
import {isEnumValue} from '@myparcel/ts-utils';
import {useCheckoutStore} from '../useCheckoutStore';
import {type PdkCheckoutForm} from '../../index';
import {type PdkCheckoutForm} from '../../types';

type GetFieldValue = {
(field: AddressField | string, addressType?: AddressType, fields?: PdkCheckoutForm): undefined | string;
Expand Down
Loading

0 comments on commit b54d0be

Please sign in to comment.