Skip to content

Instantly share code, notes, and snippets.

@mrcleanandfresh
Last active April 13, 2020 18:08
Show Gist options
  • Save mrcleanandfresh/d90ddc9aadd0569a6d850b5530a0f3c1 to your computer and use it in GitHub Desktop.
Save mrcleanandfresh/d90ddc9aadd0569a6d850b5530a0f3c1 to your computer and use it in GitHub Desktop.
I am having a problem properly mocking this single function in a way where I can overwrite it for each test case.
import { mount } from 'enzyme';
import fetchMock from 'jest-fetch-mock'
import React from 'react';
import { act } from 'react-dom/test-utils';
import { getCountStatus } from '../../services/__mocks__/counts.service';
import CountingBanner from '../counting-banner';
jest.mock('../../services/api/counts.service', () => ({
getCountStatus() {
return jest.fn();
},
__esModule: true,
}));
describe( '<CountingBanner/>', () => {
let wrapper = {
// Mock Wrapper until it gets set
text() {new Error( 'Wrapper was not set!' )},
update() { this.text() }
};
beforeAll( () => {
jest.useFakeTimers();
} );
afterEach( () => {
jest.clearAllTimers();
fetchMock.resetMocks();
} );
afterAll( () => {
jest.useRealTimers();
} );
test( 'default state where it checks for count', () => {
// @ts-ignore
getCountStatus.mockReturnValue(Promise.resolve({status: 201}));
act( () => {
wrapper = mount( <CountingBanner/> );
} );
expect( wrapper.text() ).toBe( 'Checking for count...' )
} );
test( 'count is in progress', async () => {
// @ts-ignore
getCountStatus.mockResolvedValue({status: 201});
act( () => {
wrapper = mount( <CountingBanner/> );
} )
expect( wrapper.text() ).toBe( 'Checking for count...' );
await act( async () => {
jest.advanceTimersByTime( 1000 );
wrapper.update();
await Promise.resolve();
} );
expect( wrapper.text() ).toBe( 'Count in Progress...' );
} );
test( 'count is done', async () => {
// @ts-ignore
getCountStatus.mockResolvedValue({status: 200});
act( () => {
wrapper = mount( <CountingBanner/> );
} )
expect( wrapper.text() ).toBe( 'Checking for count...' );
await act( async () => {
jest.advanceTimersByTime( 1000 );
wrapper.update();
await Promise.resolve();
} );
expect( wrapper.text() ).toBe( 'Counting finished!' );
} );
// FIXME Write this test once the above issue is resolved.
test.skip( 'count had an error', async () => {
// @ts-ignore
getCountStatus.mockRejectedValue('any error');
act( () => {
wrapper = mount( <CountingBanner/> );
} )
expect( wrapper.text() ).toBe( 'Checking for count...' );
act( () => {
// FIXME cannot get status in counting-banner to equal what body is here. Am I missing something?
// https://github.com/jefflau/jest-fetch-mock#simple-mock-and-assert
fetchMock.mockReject( new Error( 'any error' ) );
jest.advanceTimersByTime( 1000 );
wrapper.update();
} );
await Promise.resolve();
expect( wrapper.text() ).toBe( 'Could not determine count doneness!' );
} )
} );
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Collapse } from 'react-bootstrap';
import { getCountStatus } from '../services/api/counts.service';
export enum CountStatus {
DONE = 'done', COUNTING = 'counting'
}
const CountingBanner = () => {
const [open, setOpen] = useState<boolean>(false);
const [message, setMessage] = useState<string>('Checking for count...');
const countCheckIntervalId = useRef<number>(-1);
const checkCountStatus = useCallback(() => {
if (process.env.NODE_ENV !== 'production') {
console.log("AJAX", "checking count");
}
getCountStatus.then(resp => {
const isDone = resp.status === 200;
const inProgressText = 'Count in Progress...';
if (isDone) {
if (process.env.NODE_ENV !== 'production') {
console.log("AJAX", "done counting");
}
setOpen(false);
setMessage('Counting finished!');
clearInterval(countCheckIntervalId.current);
} else {
if (process.env.NODE_ENV !== 'production') {
console.log("AJAX", "still counting...");
}
setOpen(isOpen => {
if (!isOpen) {
return true;
}
return isOpen;
});
setMessage(message => {
if (message !== inProgressText) {
return inProgressText;
}
return message;
});
}
}).catch(error => {
setMessage('Could not determine count doneness!');
console.error('Count Doneness: Stick a fork in it, to see if its done!', error);
const timeoutID = setTimeout(() => {
setOpen(false);
clearTimeout(timeoutID);
}, 2500)
});
}, [setOpen, setMessage]);
useEffect(() => {
checkCountStatus();
countCheckIntervalId.current = setInterval(
checkCountStatus,
1000 * 30 // every 30 seconds
)
}, []);
return (
<Collapse in={open}>
<div className="bg-primary px-1 py-2 text-center text-white">
<p className="mb-0">{message}</p>
</div>
</Collapse>
)
};
export default CountingBanner;
import { AppContext } from '../../index';
export const getCountStatus = fetch(
`${AppContext.WEB_APP_URL}/api/counts/status`, {
credentials: 'include',
headers: new Headers( { 'Content-Type': 'text/plain' } )
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment