Skip to content

Commit

Permalink
refactor(testing): react testing, handler context wrappers
Browse files Browse the repository at this point in the history
* jest, expand handlers to apply context on results
* scansContext, test adjust for updated handler
  • Loading branch information
cdcabrera committed Jul 19, 2023
1 parent 5443987 commit 43d473b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 27 deletions.
63 changes: 49 additions & 14 deletions config/jest.setupTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ global.screenRender = {
*
* @param {React.ReactNode} testComponent
* @param {object} options
* @param {boolean} options.includeInstanceRef The component includes an instance ref for class components. If the component instance
* includes functions, they are wrapped in "act" for convenience.
* @returns {HTMLElement}
*/
global.renderComponent = (testComponent, options = {}) => {
Expand Down Expand Up @@ -111,7 +113,25 @@ global.renderComponent = (testComponent, options = {}) => {

if (updatedTestComponent?.type?.prototype?.isReactComponent && updatedOptions.includeInstanceRef === true) {
updatedTestComponent.ref = element => {
elementInstance = element;
const updatedElement = element;

if (element) {
Object.entries(element).forEach(([key, value]) => {
if (typeof value === 'function') {
updatedElement[key] = (...args) => {
let output;
act(() => {
output = value.call(element, ...args);
});
return output;
};
} else {
updatedElement[key] = value;
}
});

elementInstance = updatedElement;
}
};
}

Expand Down Expand Up @@ -160,12 +180,12 @@ global.renderComponent = (testComponent, options = {}) => {
*
* @param {Function} useHook
* @param {object} options
* @param {Function} options.callback A result callback fired after the hook in the same context.
* An alternative to using the "result" response.
* @param {boolean} options.includeInstanceContext The hook result, if it includes functions, is wrapped in "act" for convenience.
* @param {object} options.state An object representing a mock Redux store's state.
* @returns {*}
*/
global.renderHook = async (useHook = Function.prototype, { callback, state } = {}) => {
global.renderHook = async (useHook = Function.prototype, options = {}) => {
const updatedOptions = { includeInstanceContext: true, ...options };
let result;
let spyUseSelector;
let unmountHook;
Expand All @@ -180,22 +200,36 @@ global.renderHook = async (useHook = Function.prototype, { callback, state } = {
};

await act(async () => {
if (state) {
spyUseSelector = jest.spyOn(reactRedux, 'useSelector').mockImplementation(_ => _(state));
if (updatedOptions.state) {
spyUseSelector = jest.spyOn(reactRedux, 'useSelector').mockImplementation(_ => _(updatedOptions.state));
}
const { unmount: unmountRender } = await render(<Hook />);
unmountHook = unmountRender;

if (typeof callback === 'function') {
callback({ unmount, result });
}
});

if (state) {
if (updatedOptions.state) {
spyUseSelector.mockClear();
}

return { unmount, result };
const updatedResult = result;

if (result && updatedOptions.includeInstanceContext === true) {
Object.entries(result).forEach(([key, value]) => {
if (typeof value === 'function') {
updatedResult[key] = (...args) => {
let output;
act(() => {
output = value.call(result, ...args);
});
return output;
};
} else {
updatedResult[key] = value;
}
});
}

return { unmount, result: updatedResult };
};

/**
Expand All @@ -215,8 +249,9 @@ global.shallowComponent = async testComponent => {
const localRenderHook = async (component, updatedProps) => {
if (typeof component?.type === 'function') {
try {
const { unmount, result } = await global.renderHook(() =>
component.type({ ...component.type.defaultProps, ...component.props, ...updatedProps })
const { unmount, result } = await global.renderHook(
() => component.type({ ...component.type.defaultProps, ...component.props, ...updatedProps }),
{ includeInstanceContext: false }
);

if (!result || typeof result === 'string' || typeof result === 'number') {
Expand Down
19 changes: 6 additions & 13 deletions src/components/scans/__tests__/scansContext.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,14 @@ describe('ScansContext', () => {
}
};

let confirmCallbacks;

await renderHook(
() =>
useOnScanAction({
useDispatch: () => mockDispatch
}),
{
callback: ({ result }) => {
result.onStart(mockScan);
confirmCallbacks = result;
}
}
const { result: confirmCallbacks } = await renderHook(() =>
useOnScanAction({
useDispatch: () => mockDispatch
})
);

confirmCallbacks.onStart(mockScan);

expect(confirmCallbacks).toMatchSnapshot('callbacks');
expect(mockDispatch.mock.calls).toMatchSnapshot('dispatch onStart');

Expand Down

0 comments on commit 43d473b

Please sign in to comment.