For more details, see src/__tests__/exercise/*.md
files
- Use VanillaJS to prepare the DOM for your test.
- Assert the order of your elements by using Array destructuring, from that, you can get the corresponding methods of that DOM object (thanks to TypeScript, at line
17
). - Remember to type check
HTMLElement
in your test. - Use
dispatchEvent()
method to fire an event that doesn't have a dedicated method (like mouseover). - Clean up after each test to ensure their isolation:
beforeEach(() => {
document.body.innerHTML = ''
})
- Use
@testing-library/react
instead ofJest
(for abstractions like auto cleanups, auto DOM preparation,...).
- You can tell whether tests rely on implementation details if they're written in a way that would fail if the implementation changes. For example, what if we wrapped our counter component in another
div
or swapped ourchildren
from adiv
to aspan
orp
. - Avoid implementation details by querying for and interacting with the elements in a way that is implementation detail free (i.e. presented in isolation) and refactor friendly.
- Abstract away the implementation details of an event (e.g.
click
) by usinguserEvent
from the@testing-library/user-event
.
- Use
screen.debug()
with thetesting-playground
Chrome extension to build your test. - Use
jest.fn()
as a mock function (i.e. when you don't care what that function does or use its returned values) and assert it was called correctly rather than defining your own. - Generating test data by using
@jackfranklin/test-data-bot
.
- Use
msw
(at 01:30) as a request interceptor for testing (so that we don't have to worry about finding an available port for the server to listen to and making sure we're making requests to the right port). - Use
msw
as a offline module to write UI for APIs that aren't finished yet. - Use
toMatchInlineSnapshot()
rather than an explicit assertion on an error element to keep your tests up-to-date if the error message were to change in the future. - Colocating run-time server behavior tests (at 0:30) by using
server.use
. For such cases, remember to addserver.resetHandlers()
to preserve test isolation and restore the original handlers for other tests.
- Non-null assertion for a promise's return.
- Expand the
jsdom
's browser environment simulation in Node by mocking the browser's API, which allows us to continue to test with Jest (in Node) while not actually running in a browser. The main reason for that is because the tools we currently have for testing are WAY faster and WAY more capable when run in Node. - However, if you are testing something that really relies on browser APIs or layout (like drag-and-drop) then you may be better served by writing those tests in a real browser (using a tool like Cypress).
- Sometimes, the module is interacting with browser APIs that are just too hard to
mock (like
canvas
) or you're comfortable relying on the module's own test suite to give you confidence that as long as you use the module properly, everything should work. In that case, it makes sense to mock the module directly by usingjest.mock()
instead of mocking the browser's API.
- Use the
wrapper
option of therender()
fromtesting-library/react
to test a component that uses context. - Difference between a void function and a function that returns something (at 2:20).
- It's highly recommended to avoid implementation details by SoC into another module.
- The easiest and most straightforward way to test a custom hook is to create a component that uses it and then test that component instead.
- To do that, we'll make a test component that uses the hook in the typical way that our hook will be used and then test that component, therefore indirectly testing our hook.
- When it's difficult to create a test component that resembles the typical way that our hook will be used, we can isolate the hook by creating a
null
component that only uses what the hook returns. Remember to wrap anact()
around your state update (at 1:30). - Use the returned
{result}
ofrenderHook
(from@testing-library/react-hooks
) to test the returned values from your custom hooks (e.g. create a test for custom hooks that allows the hook's user to customize itsinitialProps
instead of using its default value).