mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Add better support for non-native errors
This commit is contained in:
@@ -45,7 +45,7 @@ describe('EmailPasswordUtil', (): void => {
|
||||
const error = 'Error!';
|
||||
expect((): never => throwIdpInteractionError(error, prefilled)).toThrow(expect.objectContaining({
|
||||
statusCode: 500,
|
||||
message: 'Unknown Error',
|
||||
message: 'Unknown error: Error!',
|
||||
prefilled,
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('A ResetPasswordHandler', (): void => {
|
||||
});
|
||||
|
||||
it('has a default error for non-native errors.', async(): Promise<void> => {
|
||||
const errorMessage = 'An unknown error occurred';
|
||||
const errorMessage = 'Unknown error: not native';
|
||||
request = createPostFormRequest({ recordId, password: 'password!', confirmPassword: 'password!' });
|
||||
(accountStore.getForgotPasswordRecord as jest.Mock).mockRejectedValueOnce('not native');
|
||||
await expect(handler.handle({ request, response })).resolves.toBeUndefined();
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('An IdpRouteController', (): void => {
|
||||
expect(renderHandler.handleSafe).toHaveBeenCalledTimes(1);
|
||||
expect(renderHandler.handleSafe).toHaveBeenLastCalledWith({
|
||||
response,
|
||||
props: { errorMessage: 'An unknown error occurred', prefilled: {}},
|
||||
props: { errorMessage: 'Unknown error: apple!', prefilled: {}},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -22,19 +22,13 @@ describe('FetchUtil', (): void => {
|
||||
|
||||
it('errors if there was an issue fetching.', async(): Promise<void> => {
|
||||
fetchMock.mockRejectedValueOnce(new Error('Invalid webId!'));
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Cannot fetch ${url}: Invalid webId!`);
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Cannot fetch ${url}`);
|
||||
expect(fetchMock).toHaveBeenCalledWith(url);
|
||||
|
||||
fetchMock.mockRejectedValueOnce('apple');
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Cannot fetch ${url}: Unknown error`);
|
||||
});
|
||||
|
||||
it('errors if there was an issue parsing the returned RDF.', async(): Promise<void> => {
|
||||
(datasetResponse.dataset as jest.Mock).mockRejectedValueOnce(new Error('Invalid RDF!'));
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Could not parse RDF in ${url}: Invalid RDF!`);
|
||||
|
||||
(datasetResponse.dataset as jest.Mock).mockRejectedValueOnce('apple');
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Could not parse RDF in ${url}: Unknown error`);
|
||||
await expect(fetchDataset(url)).rejects.toThrow(`Cannot fetch ${url}`);
|
||||
});
|
||||
|
||||
it('returns the resulting Dataset.', async(): Promise<void> => {
|
||||
|
||||
@@ -25,12 +25,13 @@ describe('A BasicResponseWriter', (): void => {
|
||||
});
|
||||
|
||||
it('requires the input to be a binary ResponseDescription.', async(): Promise<void> => {
|
||||
await expect(writer.canHandle({ response, result: new Error('error') }))
|
||||
.rejects.toThrow(NotImplementedHttpError);
|
||||
const metadata = new RepresentationMetadata(INTERNAL_QUADS);
|
||||
await expect(writer.canHandle({ response, result: { statusCode: 201, metadata }}))
|
||||
.rejects.toThrow(NotImplementedHttpError);
|
||||
await expect(writer.canHandle({ response, result }))
|
||||
metadata.contentType = 'text/turtle';
|
||||
await expect(writer.canHandle({ response, result: { statusCode: 201, metadata }}))
|
||||
.resolves.toBeUndefined();
|
||||
await expect(writer.canHandle({ response, result: { statusCode: 201 }}))
|
||||
.resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ describe('A BaseHttpServerFactory', (): void => {
|
||||
handler.handleSafe.mockRejectedValueOnce('apple');
|
||||
|
||||
const res = await request(server).get('/').expect(500);
|
||||
expect(res.text).toContain('Unknown error.');
|
||||
expect(res.text).toContain('Unknown error: apple.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('A BaseHttpServerFactory', (): void => {
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('throws unknown errors if its handler throw non-Error objects.', async(): Promise<void> => {
|
||||
it('does not print the stack if that option is disabled.', async(): Promise<void> => {
|
||||
const error = new Error('dummyError');
|
||||
handler.handleSafe.mockRejectedValueOnce(error);
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import { NotImplementedHttpError } from '../../../src/util/errors/NotImplemented
|
||||
import type { Guarded } from '../../../src/util/GuardedStream';
|
||||
import { SingleRootIdentifierStrategy } from '../../../src/util/identifiers/SingleRootIdentifierStrategy';
|
||||
import { trimTrailingSlashes } from '../../../src/util/PathUtil';
|
||||
import * as quadUtil from '../../../src/util/QuadUtil';
|
||||
import { guardedStreamFrom } from '../../../src/util/StreamUtil';
|
||||
import { CONTENT_TYPE, SOLID_HTTP, LDP, PIM, RDF } from '../../../src/util/Vocabularies';
|
||||
import quad = DataFactory.quad;
|
||||
@@ -236,16 +235,6 @@ describe('A DataAccessorBasedStore', (): void => {
|
||||
await expect(store.addResource(resourceID, representation)).rejects.toThrow(BadRequestHttpError);
|
||||
});
|
||||
|
||||
it('passes the result along if the MetadataController throws a non-Error.', async(): Promise<void> => {
|
||||
const resourceID = { path: root };
|
||||
const mock = jest.spyOn(quadUtil, 'parseQuads').mockImplementationOnce(async(): Promise<any> => {
|
||||
throw 'apple';
|
||||
});
|
||||
representation.metadata.add(RDF.type, LDP.terms.Container);
|
||||
await expect(store.addResource(resourceID, representation)).rejects.toBe('apple');
|
||||
mock.mockRestore();
|
||||
});
|
||||
|
||||
it('can write resources.', async(): Promise<void> => {
|
||||
const resourceID = { path: root };
|
||||
representation.metadata.removeAll(RDF.type);
|
||||
@@ -584,7 +573,7 @@ describe('A DataAccessorBasedStore', (): void => {
|
||||
expect(accessor.data[`${root}resource.dummy`]).not.toBeUndefined();
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error).toHaveBeenLastCalledWith(
|
||||
'Problem deleting auxiliary resource http://test.com/resource.dummy: auxiliary error!',
|
||||
'Error deleting auxiliary resource http://test.com/resource.dummy: auxiliary error!',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -607,7 +596,7 @@ describe('A DataAccessorBasedStore', (): void => {
|
||||
expect(accessor.data[`${root}resource.dummy`]).not.toBeUndefined();
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error).toHaveBeenLastCalledWith(
|
||||
'Problem deleting auxiliary resource http://test.com/resource.dummy: auxiliary error!',
|
||||
'Error deleting auxiliary resource http://test.com/resource.dummy: Unknown error: auxiliary error!',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
getBestPreference,
|
||||
getConversionTarget,
|
||||
getTypeWeight,
|
||||
getWeightedPreferences,
|
||||
getWeightedPreferences, isInternalContentType,
|
||||
matchesMediaPreferences,
|
||||
matchesMediaType,
|
||||
} from '../../../../src/storage/conversion/ConversionUtil';
|
||||
@@ -144,4 +144,13 @@ describe('ConversionUtil', (): void => {
|
||||
expect(matchesMediaType('text/plain', 'text/turtle')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isInternalContentType', (): void => {
|
||||
it('only returns true on internal types.', async(): Promise<void> => {
|
||||
expect(isInternalContentType('internal/quads')).toBeTruthy();
|
||||
|
||||
expect(isInternalContentType()).toBeFalsy();
|
||||
expect(isInternalContentType('text/turtle')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,24 +1,42 @@
|
||||
import { assertNativeError, getStatusCode, isNativeError } from '../../../../src/util/errors/ErrorUtil';
|
||||
import { assertError, createErrorMessage, getStatusCode, isError } from '../../../../src/util/errors/ErrorUtil';
|
||||
import { NotFoundHttpError } from '../../../../src/util/errors/NotFoundHttpError';
|
||||
|
||||
describe('ErrorUtil', (): void => {
|
||||
describe('#isNativeError', (): void => {
|
||||
describe('#isError', (): void => {
|
||||
it('returns true on native errors.', async(): Promise<void> => {
|
||||
expect(isNativeError(new Error('error'))).toBe(true);
|
||||
expect(isError(new Error('error'))).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true on error-like objects.', async(): Promise<void> => {
|
||||
expect(isError({ name: 'name', message: 'message', stack: 'stack' })).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true on errors without a stack.', async(): Promise<void> => {
|
||||
expect(isError({ name: 'name', message: 'message' })).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false on other values.', async(): Promise<void> => {
|
||||
expect(isNativeError('apple')).toBe(false);
|
||||
expect(isError('apple')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#assertNativeError', (): void => {
|
||||
describe('#assertError', (): void => {
|
||||
it('returns undefined on native errors.', async(): Promise<void> => {
|
||||
expect(assertNativeError(new Error('error'))).toBeUndefined();
|
||||
expect(assertError(new Error('error'))).toBeUndefined();
|
||||
});
|
||||
|
||||
it('throws on other values.', async(): Promise<void> => {
|
||||
expect((): void => assertNativeError('apple')).toThrow('apple');
|
||||
expect((): void => assertError('apple')).toThrow('apple');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createErrorMessage', (): void => {
|
||||
it('returns the given message for normal Errors.', async(): Promise<void> => {
|
||||
expect(createErrorMessage(new Error('error msg'))).toBe('error msg');
|
||||
});
|
||||
|
||||
it('tries to put the object in a string .', async(): Promise<void> => {
|
||||
expect(createErrorMessage('apple')).toBe('Unknown error: apple');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ describe('A WaterfallHandler', (): void => {
|
||||
};
|
||||
const handler = new WaterfallHandler([ handlerFalse, handlerFalse ]);
|
||||
|
||||
await expect(handler.canHandle(null)).rejects.toThrow('[Unknown error, Unknown error]');
|
||||
await expect(handler.canHandle(null)).rejects.toThrow('[Unknown error: apple, Unknown error: apple]');
|
||||
});
|
||||
|
||||
it('handles data if a handler supports it.', async(): Promise<void> => {
|
||||
|
||||
Reference in New Issue
Block a user