Skip to content

Instantly share code, notes, and snippets.

@jfhector
Last active February 19, 2022 20:23
Show Gist options
  • Save jfhector/883b03b2886645d6596d77f734330db7 to your computer and use it in GitHub Desktop.
Save jfhector/883b03b2886645d6596d77f734330db7 to your computer and use it in GitHub Desktop.
wrapInSynchronousTryCatch
Feature: wrapInSynchronousTryCatch
Scenario: The function returned by wrapInSynchronousTryCatch calls the function provided to wrapInSynchronousTryCatch with the same arguments
Given wrapInSynchronousTryCatch is called with a synchronous function that does not throw
When the function returned by wrapInSynchronousTryCatch is called with some arguments
Then the function provided to wrapInSynchronousTryCatch gets called with the same arguments
And the function returned by wrapInSynchronousTryCatch returns the same thing as the provided function
Scenario: It catches any error that the provided function throws
Given wrapInSynchronousTryCatch is called with a synchronous function that throws when called with some arguments
When the function returned by wrapInSynchronousTryCatch is called with the same arguments
Then the error gets logged to the console
And the function returned by wrapInSynchronousTryCatch does not throw
/* eslint-disable no-console */
type WrapInSynchronousTryCatch = {
<Args extends any[], ReturnType>(fn: (...args: Args) => ReturnType): (
...args: Args
) => ReturnType | undefined;
};
/**
* Use this if you have a function that may throw an error, and you want that error handled so it doesn't propagate further.
*
* Important note: If the function you're providing is asynchronous (or returns a promise), use `wrapInAsyncTryCatch` instead.
*
* @param syncFnToWrapInTryCatch a synchronous function that you want called inside a try/catch block
* @returns a synchronous function which, when called, calls `fn` with the arguments it's given. `fn` will be called inside `try { ... } catch(err) { logs the err and returns }`
*/
const wrapInSynchronousTryCatch: WrapInSynchronousTryCatch = syncFnToWrapInTryCatch => {
return function todoName(...args) {
try {
return syncFnToWrapInTryCatch(...args);
} catch (err) {
console.error(err);
return;
}
};
};
export { wrapInSynchronousTryCatch };
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-console */
import { defineFeature, loadFeature } from 'jest-cucumber';
import { wrapInSynchronousTryCatch } from '..';
// Syncing with .feature Cucumber file
const feature = loadFeature('../definition.feature', {
loadRelativePath: true,
});
defineFeature(feature, test => {
afterEach(() => {
jest.clearAllMocks();
});
test('The function returned by wrapInSynchronousTryCatch calls the function provided to wrapInSynchronousTryCatch with the same arguments', ({
given,
when,
then,
and,
}) => {
const functionToProvideToWithErrorBoundary = jest
.fn()
.mockImplementation((a, b) => a + ' ' + b);
let functionReturnedByWithErrorBoundary: any;
let valueReturnedByTheFunctionReturnedByWithErrorBoundary: any;
given(
'wrapInSynchronousTryCatch is called with a synchronous function that does not throw',
() => {
functionReturnedByWithErrorBoundary = wrapInSynchronousTryCatch(
functionToProvideToWithErrorBoundary
);
}
);
when(
'the function returned by wrapInSynchronousTryCatch is called with some arguments',
() => {
valueReturnedByTheFunctionReturnedByWithErrorBoundary = functionReturnedByWithErrorBoundary(
'Hello',
'World'
);
}
);
then(
'the function provided to wrapInSynchronousTryCatch gets called with the same arguments',
() => {
expect(functionToProvideToWithErrorBoundary).toHaveBeenCalledWith(
'Hello',
'World'
);
}
);
and(
'the function returned by wrapInSynchronousTryCatch returns the same thing as the provided function',
() => {
expect(valueReturnedByTheFunctionReturnedByWithErrorBoundary).toBe(
functionToProvideToWithErrorBoundary('Hello', 'World')
);
}
);
});
test('It catches any error that the provided function throws', ({
given,
when,
then,
and,
}) => {
const MOCK_ERROR = new Error('mock error');
const functionToProvideToWithErrorBoundary = jest
.fn()
.mockImplementation(() => {
throw MOCK_ERROR;
});
let functionReturnedByWithErrorBoundary: any;
const consoleErrorSpy = jest.spyOn(console, 'error');
given(
'wrapInSynchronousTryCatch is called with a synchronous function that throws when called with some arguments',
() => {
functionReturnedByWithErrorBoundary = wrapInSynchronousTryCatch(
functionToProvideToWithErrorBoundary
);
}
);
when(
'the function returned by wrapInSynchronousTryCatch is called with the same arguments',
() => {
functionReturnedByWithErrorBoundary();
}
);
then('the error gets logged to the console', () => {
expect(consoleErrorSpy).toHaveBeenCalledWith(MOCK_ERROR);
});
and(
'the function returned by wrapInSynchronousTryCatch does not throw',
() => {
console.log(
'If this gets executed, it means there has been no unhandled exception, and this test is successful'
);
}
);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment