Skip to content

Commit

Permalink
fix: support another error and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
EdieLemoine committed Apr 15, 2024
1 parent d718873 commit 3c6bf36
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 17 deletions.
4 changes: 3 additions & 1 deletion apps/delivery-options/src/composables/useLanguage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ const translate = useMemoize((translatable: AnyTranslatable): string => {
const replacers = translation.match(/\{(.+?)}/g);

if (replacers?.length && isOfType<TranslatableWithArgs>(translatable, 'args')) {
return replacers.toReversed().reduce((string, match) => {
replacers.reverse();

return replacers.reduce((string, match) => {
const argKey = match.slice(1, -1);
const matchingArg = translatable?.args?.[argKey];

Expand Down
101 changes: 101 additions & 0 deletions libs/shared/src/composables/useApiExceptions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {describe, it, expect, beforeEach} from 'vitest';
import {ApiException} from '@myparcel/sdk';
import {type TranslatableWithArgs} from '../types';
import {ERROR_INVALID_POSTAL_CODE, IGNORED_ERRORS, ERROR_MISSING_REQUIRED_PARAMETER, ERROR_REPLACE_MAP} from '../data';
import {useApiExceptions} from './useApiExceptions';

const createException = (code: string | number, message = 'error'): ApiException => {
return new ApiException({
message: 'error',
request_id: '...',
errors: [{code: Number(code), message}],
});
};

describe('useApiExceptions', () => {
beforeEach(() => {
useApiExceptions().clear();
});

it('adds exceptions', () => {
const {addException, exceptions, hasExceptions} = useApiExceptions();
const exception = createException(ERROR_INVALID_POSTAL_CODE);

addException(['test'], exception);

expect(hasExceptions.value).toBe(true);
expect(exceptions.value).toEqual([
{
code: ERROR_INVALID_POSTAL_CODE,
label: `error${ERROR_INVALID_POSTAL_CODE}`,
},
]);

addException(['test'], createException(ERROR_INVALID_POSTAL_CODE));

// Expect no duplicates
expect(exceptions.value).toHaveLength(1);
});

it.each(IGNORED_ERRORS)('ignores exceptions with code %s', (code) => {
const {addException, exceptions, hasExceptions} = useApiExceptions();
const exception = createException(code);

addException(['someRequest'], exception);

expect(hasExceptions.value).toBe(false);
expect(exceptions.value).toEqual([]);
});

it.each(Object.entries(ERROR_REPLACE_MAP))(`replaces error code %d with %d`, (code, replacement) => {
const {addException, exceptions, hasExceptions} = useApiExceptions();
const exception = createException(code);

addException(['test'], exception);

expect(hasExceptions.value).toBe(true);
expect(exceptions.value).toEqual([
{
code: replacement,
label: `error${replacement}`,
},
]);
});

it('can clear exceptions', () => {
const {addException, clear, hasExceptions, exceptions} = useApiExceptions();
const exception = createException(ERROR_INVALID_POSTAL_CODE);

addException(['test'], exception);

expect(hasExceptions.value).toBe(true);

clear();

expect(hasExceptions.value).toBe(false);
expect(exceptions.value).toEqual([]);
});

it(`adds arguments to exception with code ${ERROR_MISSING_REQUIRED_PARAMETER}`, () => {
const {addException, exceptions, hasExceptions} = useApiExceptions();
const exception = createException(ERROR_MISSING_REQUIRED_PARAMETER, 'city is required');

addException(['test'], exception);

expect(hasExceptions.value).toBe(true);
expect(exceptions.value).toEqual([
{
code: ERROR_MISSING_REQUIRED_PARAMETER,
label: {
key: `error${ERROR_MISSING_REQUIRED_PARAMETER}`,
args: {
field: {
key: 'city',
plain: true,
},
},
} satisfies TranslatableWithArgs,
},
]);
});
});
33 changes: 17 additions & 16 deletions libs/shared/src/composables/useApiExceptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {ref, type Ref, computed, type ComputedRef} from 'vue';
import {useMemoize} from '@vueuse/core';
import {type ApiException, type ErrorResponse} from '@myparcel/sdk';
import {type RequestKey, type AnyTranslatable} from '../types';
import {IGNORED_ERRORS, ERROR_MISSING_REQUIRED_PARAMETER} from '../data';
import {IGNORED_ERRORS, ERROR_MISSING_REQUIRED_PARAMETER, ERROR_REPLACE_MAP} from '../data';

const exceptions = ref<ParsedError[]>([]);

Expand All @@ -19,27 +19,28 @@ interface UseErrors {
}

const parseError = (error: ErrorResponse['errors'][number]): ParsedError => {
if (error.code === ERROR_MISSING_REQUIRED_PARAMETER) {
const strings = error.message.split(' ');
const resolvedCode = ERROR_REPLACE_MAP[error.code] ?? error.code;

return {
code: error.code,
label: {
key: `error${error.code}`,
args: {
field: {
key: strings?.[0],
plain: true,
},
const resolvedError: ParsedError = {
code: resolvedCode,
label: `error${resolvedCode}`,
};

if (resolvedCode === ERROR_MISSING_REQUIRED_PARAMETER) {
const words = error.message.split(' ');

resolvedError.label = {
key: `error${resolvedCode}`,
args: {
field: {
key: words[0],
plain: true,
},
},
};
}

return {
code: error.code,
label: `error${error.code}`,
};
return resolvedError;
};

export const useApiExceptions = useMemoize((): UseErrors => {
Expand Down
6 changes: 6 additions & 0 deletions libs/shared/src/data/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export const ERROR_NO_DELIVERY_OPTIONS_FOUND = 3721;

export const ERROR_UNSUPPORTED_CARRIER = 3728;

export const ERROR_ADDRESS_CAN_NOT_BE_SPLIT = 3731;

export const ERROR_WADDEN_ISLANDS = 3753;

/**
Expand All @@ -31,3 +33,7 @@ export const IGNORED_ERRORS = Object.freeze([
ERROR_INVALID_COUNTRY_CODE,
ERROR_INVALID_CARRIER_PLATFORM_COMBINATION,
]);

export const ERROR_REPLACE_MAP: Record<number, number> = Object.freeze({
[ERROR_ADDRESS_CAN_NOT_BE_SPLIT]: ERROR_ADDRESS_UNKNOWN,
});

0 comments on commit 3c6bf36

Please sign in to comment.