Refactor errors util to TypeScript, minor typing fixes (https://github.com/woocommerce/woocommerce-blocks/pull/10754)
This commit is contained in:
parent
2d89f4892d
commit
44f48e41e9
|
@ -117,6 +117,9 @@ const restrictedImports = [
|
|||
];
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
root: true,
|
||||
extends: [
|
||||
'plugin:@woocommerce/eslint-plugin/recommended',
|
||||
|
|
|
@ -9,7 +9,7 @@ import isShallowEqual from '@wordpress/is-shallow-equal';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getReviews } from '../../blocks/reviews/utils';
|
||||
import { formatError } from '../utils/errors.js';
|
||||
import { formatError } from '../utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries reviews for a component.
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* Given a JS error or a fetch response error, parse and format it, so it can be displayed to the user.
|
||||
*
|
||||
* @param {Object} error Error object.
|
||||
* @param {Function} [error.json] If a json method is specified, it will try parsing the error first.
|
||||
* @param {string} [error.message] If a message is specified, it will be shown to the user.
|
||||
* @param {string} [error.type] The context in which the error was triggered.
|
||||
* @return {Promise<{message:string;type:string;}>} Error object containing a message and type.
|
||||
*/
|
||||
export const formatError = async ( error ) => {
|
||||
if ( typeof error.json === 'function' ) {
|
||||
try {
|
||||
const parsedError = await error.json();
|
||||
return {
|
||||
message: parsedError.message,
|
||||
type: parsedError.type || 'api',
|
||||
};
|
||||
} catch ( e ) {
|
||||
return {
|
||||
message: e.message,
|
||||
type: 'general',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
message: error.message,
|
||||
type: error.type || 'general',
|
||||
};
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
export interface ErrorObject {
|
||||
/**
|
||||
* Human-readable error message to display.
|
||||
*/
|
||||
message: string;
|
||||
/**
|
||||
* Context in which the error was triggered. That will determine how the error is displayed to the user.
|
||||
*/
|
||||
type: 'api' | 'general' | string;
|
||||
}
|
||||
|
||||
type SimpleError = {
|
||||
message: string;
|
||||
type?: string;
|
||||
};
|
||||
|
||||
export const formatError = async (
|
||||
error: SimpleError | Response
|
||||
): Promise< ErrorObject > => {
|
||||
if ( 'json' in error ) {
|
||||
try {
|
||||
const parsedError = await error.json();
|
||||
return {
|
||||
message: parsedError.message,
|
||||
type: parsedError.type || 'api',
|
||||
};
|
||||
} catch ( e ) {
|
||||
return {
|
||||
// We could only return this if e is instanceof Error but, to avoid changing runtime
|
||||
// behaviour, we'll just cast it instead.
|
||||
message: ( e as Error ).message,
|
||||
type: 'general',
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
message: error.message,
|
||||
type: error.type || 'general',
|
||||
};
|
||||
}
|
||||
};
|
|
@ -4,6 +4,9 @@
|
|||
import { formatError } from '../errors';
|
||||
|
||||
describe( 'formatError', () => {
|
||||
const mockResponseBody = JSON.stringify( { message: 'Lorem Ipsum' } );
|
||||
const mockMalformedJson = '{ "message": "Lorem Ipsum"';
|
||||
|
||||
test( 'should format general errors', async () => {
|
||||
const error = await formatError( {
|
||||
message: 'Lorem Ipsum',
|
||||
|
@ -17,9 +20,9 @@ describe( 'formatError', () => {
|
|||
} );
|
||||
|
||||
test( 'should format API errors', async () => {
|
||||
const error = await formatError( {
|
||||
json: () => Promise.resolve( { message: 'Lorem Ipsum' } ),
|
||||
} );
|
||||
const mockResponse = new Response( mockResponseBody, { status: 400 } );
|
||||
|
||||
const error = await formatError( mockResponse );
|
||||
const expectedError = {
|
||||
message: 'Lorem Ipsum',
|
||||
type: 'api',
|
||||
|
@ -29,11 +32,12 @@ describe( 'formatError', () => {
|
|||
} );
|
||||
|
||||
test( 'should format JSON parse errors', async () => {
|
||||
const error = await formatError( {
|
||||
json: () => Promise.reject( { message: 'Lorem Ipsum' } ),
|
||||
} );
|
||||
const mockResponse = new Response( mockMalformedJson, { status: 400 } );
|
||||
|
||||
const error = await formatError( mockResponse );
|
||||
const expectedError = {
|
||||
message: 'Lorem Ipsum',
|
||||
message:
|
||||
'invalid json response body at reason: Unexpected end of JSON input',
|
||||
type: 'general',
|
||||
};
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ const ProductControl = (
|
|||
} else if ( showVariations ) {
|
||||
return renderItemWithVariations;
|
||||
}
|
||||
return undefined;
|
||||
return () => null;
|
||||
};
|
||||
|
||||
if ( error ) {
|
||||
|
|
|
@ -124,7 +124,9 @@ export interface SearchListControlProps< T extends object = object > {
|
|||
// Callback fired when the search field is used.
|
||||
onSearch?: ( ( search: string ) => void ) | undefined;
|
||||
// Callback to render each item in the selection list, allows any custom object-type rendering.
|
||||
renderItem?: ( ( args: renderItemArgs< T > ) => JSX.Element ) | undefined;
|
||||
renderItem?:
|
||||
| ( ( args: renderItemArgs< T > ) => JSX.Element | null )
|
||||
| undefined;
|
||||
// The list of currently selected items.
|
||||
selected: SearchListItem< T >[];
|
||||
// Whether to show a text field or a token field as search
|
||||
|
|
|
@ -7,7 +7,7 @@ import { getAttributes, getTerms } from '@woocommerce/editor-components/utils';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* Get attribute data (name, taxonomy etc) from server data.
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getCategories } from '@woocommerce/editor-components/utils';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries categories for a component.
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getCategory } from '@woocommerce/editor-components/utils';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries a category for a component.
|
||||
|
|
|
@ -10,7 +10,7 @@ import { getProductVariations } from '@woocommerce/editor-components/utils';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries variations for a component.
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getProduct } from '@woocommerce/editor-components/utils';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
/**
|
||||
* HOC that queries a product for a component.
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatError } from '../base/utils/errors.js';
|
||||
import { formatError } from '../base/utils/errors';
|
||||
|
||||
interface WithSearchedProductProps {
|
||||
selected: number[];
|
||||
|
|
Loading…
Reference in New Issue