html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress{vertical-align:baseline}[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}button,input,optgroup,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}html{font:87.5%/1.2 -apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;box-sizing:border-box;overflow-y:scroll;}*{box-sizing:inherit;}*:before{box-sizing:inherit;}*:after{box-sizing:inherit;}body{color:var(--app-foreground);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:normal;word-wrap:break-word;font-kerning:normal;-moz-font-feature-settings:"kern", "liga", "clig", "calt";-ms-font-feature-settings:"kern", "liga", "clig", "calt";-webkit-font-feature-settings:"kern", "liga", "clig", "calt";font-feature-settings:"kern", "liga", "clig", "calt";}img{max-width:100%;margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}h1{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:2rem;line-height:1.1;}h2{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1.51572rem;line-height:1.1;}h3{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1.31951rem;line-height:1.1;}h4{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:1rem;line-height:1.1;}h5{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:0.87055rem;line-height:1.1;}h6{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;color:var(--app-purple);font-family:-apple-system,'BlinkMacSystemFont','Segoe UI','Roboto','Oxygen-Sans','Ubuntu','Cantarell','Helvetica Neue',sans-serif;font-weight:bold;text-rendering:optimizeLegibility;font-size:0.81225rem;line-height:1.1;}hgroup{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}ul{margin-left:1.2rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;list-style-position:outside;list-style-image:none;}ol{margin-left:1.2rem;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;list-style-position:outside;list-style-image:none;}dl{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}dd{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}p{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}figure{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}pre{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;font-size:0.85rem;line-height:1.2rem;}table{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;font-size:1rem;line-height:1.8rem;border-collapse:collapse;width:100%;}fieldset{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}blockquote{margin-left:1.2rem;margin-right:1.2rem;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}form{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}noscript{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}iframe{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}hr{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:calc(1.2rem - 1px);background:hsla(0,0%,0%,0.2);border:none;height:1px;}address{margin-left:0;margin-right:0;margin-top:0;padding-bottom:0;padding-left:0;padding-right:0;padding-top:0;margin-bottom:1.2rem;}b{font-weight:bold;}strong{font-weight:bold;}dt{font-weight:bold;}th{font-weight:bold;}li{margin-bottom:calc(1.2rem / 2);}ol li{padding-left:0;}ul li{padding-left:0;}li > ol{margin-left:1.2rem;margin-bottom:calc(1.2rem / 2);margin-top:calc(1.2rem / 2);}li > ul{margin-left:1.2rem;margin-bottom:calc(1.2rem / 2);margin-top:calc(1.2rem / 2);}blockquote *:last-child{margin-bottom:0;}li *:last-child{margin-bottom:0;}p *:last-child{margin-bottom:0;}li > p{margin-bottom:calc(1.2rem / 2);}code{font-size:1em;line-height:1.4em;font-family:'Fira Code', monospace;}kbd{font-size:0.85rem;line-height:1.2rem;}samp{font-size:0.85rem;line-height:1.2rem;}abbr{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}acronym{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;}abbr[title]{border-bottom:1px dotted hsla(0,0%,0%,0.5);cursor:help;text-decoration:none;}thead{text-align:left;}td,th{text-align:left;border-bottom:1px solid hsla(0,0%,0%,0.12);font-feature-settings:"tnum";-moz-font-feature-settings:"tnum";-ms-font-feature-settings:"tnum";-webkit-font-feature-settings:"tnum";padding-left:0.8rem;padding-right:0.8rem;padding-top:0.6rem;padding-bottom:calc(0.6rem - 1px);}th:first-child,td:first-child{padding-left:0;}th:last-child,td:last-child{padding-right:0;}a{color:inherit;}a:focus{outline:2px solid var(--app-cyan);outline-offset:0;}a:visited{color:var(--app-cyan);}code.inline{line-height:1em;background:none;} .bOFKFr{fill:currentColor;height:2em;margin:0.25em;-webkit-transform:none;-ms-transform:none;transform:none;}/*!sc*/
.etECvA{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:none;-ms-transform:none;transform:none;}/*!sc*/
.crLEvQ{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);}/*!sc*/
.kpJAMR{fill:currentColor;height:1em;margin:0.25em;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);}/*!sc*/
data-styled.g3[id="icon__Icon-sc-1w03ldy-0"]{content:"bOFKFr,etECvA,crLEvQ,kpJAMR,"}/*!sc*/
.empDfs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:1em;border:1px solid var(--app-foreground);border-radius:var(--app-border-radius);-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/
data-styled.g4[id="example__Render-sc-1u0tgm1-0"]{content:"empDfs,"}/*!sc*/
.iXseCQ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-webkit-justify-content:flex-end;-ms-flex-pack:end;justify-content:flex-end;margin-top:0.25em;}/*!sc*/
data-styled.g5[id="example__FlexRight-sc-1u0tgm1-1"]{content:"iXseCQ,"}/*!sc*/
.eBWeFI{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/
data-styled.g6[id="example__CodeSandboxLink-sc-1u0tgm1-2"]{content:"eBWeFI,"}/*!sc*/
.iyGSwu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin:0;padding:0;color:var(--app-foreground);background:none;border:none;cursor:pointer;}/*!sc*/
.iyGSwu:focus,.iyGSwu:active{color:var(--app-cyan);outline:2px solid var(--app-cyan);}/*!sc*/
data-styled.g7[id="example__ResetButton-sc-1u0tgm1-3"]{content:"iyGSwu,"}/*!sc*/
.pTvQc{max-width:100%;overflow:auto;--grvsc-border-radius:var(--app-border-radius);--grvsc-padding-h:1em;--grvsc-padding-v:1em;}/*!sc*/
.dense .default-mdx-provider__pre-sc-15gdqwx-0{margin:0;}/*!sc*/
data-styled.g8[id="default-mdx-provider__pre-sc-15gdqwx-0"]{content:"pTvQc,"}/*!sc*/
.iojkbB{border-left:2px solid var(--app-pink);padding-left:0.5em;}/*!sc*/
data-styled.g9[id="default-mdx-provider__blockquote-sc-15gdqwx-1"]{content:"iojkbB,"}/*!sc*/
.hoMCCU.slug{font-size:0.75em;margin-left:0.5em;display:none;-webkit-text-decoration:none;text-decoration:none;}/*!sc*/
*:hover > .default-mdx-provider__a-sc-15gdqwx-2.slug{display:unset;}/*!sc*/
data-styled.g10[id="default-mdx-provider__a-sc-15gdqwx-2"]{content:"hoMCCU,"}/*!sc*/
.koMXVa{margin:3em 0 1em;text-align:center;}/*!sc*/
data-styled.g12[id="footer__Container-sc-1pf7cvd-0"]{content:"koMXVa,"}/*!sc*/
.dvvVYp{color:var(--app-comment);}/*!sc*/
data-styled.g13[id="footer__Text-sc-1pf7cvd-1"]{content:"dvvVYp,"}/*!sc*/
.kCIvmz{color:var(--app-comment);}/*!sc*/
.kCIvmz:visited{color:var(--app-comment);}/*!sc*/
data-styled.g14[id="footer__Link-sc-1pf7cvd-2"]{content:"kCIvmz,"}/*!sc*/
.eeUdUW{display:grid;grid-template-areas:'title expand' 'links links';grid-template-columns:1fr auto;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
@media (min-width:1200px){.eeUdUW{grid-template-areas:'title' 'links';grid-template-columns:unset;}}/*!sc*/
data-styled.g15[id="navigation__Container-sc-18boyty-0"]{content:"eeUdUW,"}/*!sc*/
.khCaEg{grid-area:title;margin:0;}/*!sc*/
@media (min-width:1200px){.khCaEg{margin-bottom:0.5em;}}/*!sc*/
data-styled.g16[id="navigation__Title-sc-18boyty-1"]{content:"khCaEg,"}/*!sc*/
.jyqapB{-webkit-text-decoration:none;text-decoration:none;color:var(--app-foreground);}/*!sc*/
.jyqapB:visited{color:var(--app-foreground);}/*!sc*/
data-styled.g17[id="navigation__TitleLink-sc-18boyty-2"]{content:"jyqapB,"}/*!sc*/
.iKXeho{grid-area:expand;color:var(--app-foreground);width:50px;height:50px;background:none;border:none;margin:0;padding:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
.iKXeho:focus,.iKXeho:active{color:var(--app-pink);outline:2px solid var(--app-pink);}/*!sc*/
@media (min-width:1200px){.iKXeho{display:none;}}/*!sc*/
data-styled.g18[id="navigation__Expand-sc-18boyty-3"]{content:"iKXeho,"}/*!sc*/
.ktoYoz{grid-area:links;display:none;}/*!sc*/
@media (min-width:1200px){.ktoYoz{display:unset;}}/*!sc*/
data-styled.g19[id="navigation__Links-sc-18boyty-4"]{content:"ktoYoz,"}/*!sc*/
.bwEVJA{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:1.2em;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/
data-styled.g20[id="prev-next__StyledLinkToSlug-sel85m-0"]{content:"bwEVJA,"}/*!sc*/
.fhnjmd{display:grid;grid-template-areas:'left-void nav right-void' 'left-void content right-void';grid-template-columns:1fr minmax(0,85ch) 1fr;padding:0 0.5rem;}/*!sc*/
@media (min-width:1200px){.fhnjmd{grid-template-areas:'nav content void';grid-template-columns:1fr 85ch 1fr;padding:1rem;max-width:150ch;margin:0 auto;}}/*!sc*/
data-styled.g21[id="default__Grid-cc4rlb-0"]{content:"fhnjmd,"}/*!sc*/
.giaaSE{grid-area:nav;}/*!sc*/
data-styled.g22[id="default__NavigationSlot-cc4rlb-1"]{content:"giaaSE,"}/*!sc*/
.hVUruk{grid-area:content;}/*!sc*/
data-styled.g23[id="default__Content-cc4rlb-2"]{content:"hVUruk,"}/*!sc*/
.iBPGgH{display:grid;grid-template-areas:'next' 'prev';}/*!sc*/
@media (min-width:576px){.iBPGgH{grid-template-areas:'prev void next';grid-template-columns:auto 1fr auto;}}/*!sc*/
data-styled.g24[id="default__Paging-cc4rlb-3"]{content:"iBPGgH,"}/*!sc*/
.bDSAqh{grid-area:prev;}/*!sc*/
data-styled.g25[id="default__StyledPrev-cc4rlb-4"]{content:"bDSAqh,"}/*!sc*/
.dmuBWa{grid-area:next;justify-self:flex-end;}/*!sc*/
data-styled.g26[id="default__StyledNext-cc4rlb-5"]{content:"dmuBWa,"}/*!sc*/
Testing# // pseudo tests using AAA, read it as prose
describe ( ' wrap everything in a describe ' , () => {
/* 1 */ beforeEach (() => {
// setup needed for every test
// ARRANGE
})
describe ( ' group main functionality in 1st level of describes ' , () => {
/* 2 */ beforeEach (() => {
// do something to change the state
// use a `beforeEach` even if there is only one `it`
// it will be easier to extend later
// ARRANGE & ACT
})
it ( ' should respond to the change ' , () => {
// test the outcome
// ASSERT
})
describe ( ' use nested describes to dive into branches ' , () => {
/* 3 */ beforeEach (() => {
// do something that changes the state further
// ARRANGE & ACT
})
it ( ' should respond to the change ' , () => {
// assertion given that 1, 2, 3 executed
// ASSERT
})
it ( ' should follow the structure of your code ' , () => {
// it should be easy to find where new tests need to go
// ASSERT
})
})
})
// #region events
describe ( ' example events ' , () => {
describe ( ' when the user types ' , () => {
beforeEach (() => {
// find input element
// ARRANGE
// fire change event so that it is invalid
// ACT
})
it ( ' should validate input ' , () => {
// find error
// match text in error
// ASSERT
})
describe ( ' when the input is valid ' , () => {
beforeEach (() => {
// fire a change event so that the input is valid
// ACT
})
it ( ' should validate input ' , () => {
// find error
// expect that there are none
// ASSERT
})
describe ( ' when the user submits ' , () => {
beforeEach (() => {
// find submit button
// click it
// ARRANGE & ACT
})
it ( ' should call api ' , () => {
// expect mock to have been called with form data
// ASSERT
})
})
})
})
})
// #endregion
// #region a11y
describe ( ' example a11y ' , () => {
describe ( ' when the accordion is closed ' , () => {
beforeEach (() => {
// find the toggle button
// ARRANGE
})
it ( ' should have aria-expanded=false ' , () => {
// expect the toggle button to have the attribute
// ASSERT
})
describe ( ' when the accordion is open ' , () => {
beforeEach (() => {
// click the toggle
// ACT
})
it ( ' should have aria-expanded=true ' , () => {
// expect the toggle button to have the attribute
// ASSERT
})
describe ( ' when the accordion is closed ' , () => {
beforeEach (() => {
// click the toggle
// ACT
})
it ( ' should have aria-expanded=false ' , () => {
// expect the toggle button to have the attribute
// ASSERT
})
})
})
})
})
// #endregion
// #region non-happy
describe ( ' example non-happy paths ' , () => {
describe ( ' when the api times out ' , () => {
beforeEach (() => {
// use mock timers
// set mock to return unresolved promise
// ARRANGE
// action that calls into api
// ACT
})
it ( ' should show spinner ' , () => {
// find spinner
// expect that it exists
// ASSERT
})
describe ( ' when request times out ' , () => {
beforeEach (() => {
// run timers
// ACT
})
it ( ' should show error ' , () => {
// find error
// match text
// ASSERT
})
})
})
describe ( ' when api errors ' , () => {
beforeEach (() => {
// set mock to return unresolved promise
// ARRANGE
// action that calls into api
// ACT
})
it ( ' should show error ' , () => {
// find error
// match text
// ASSERT
})
})
})
// #endregion
})
export const dummy = null GifFinder# let’s test a component that uses state & effects to find gifs import React, { FC, useEffect, useState } from ' react '
import classes from ' ./example.module.css '
import { TenorAPI } from ' ./tenor-api '
export interface GifFinderProps {
onFound ? ( url : string ) : void
}
export const GifFinder : FC < GifFinderProps > = ({ onFound }) => {
const [query, setQuery] = useState ( '' )
const [results, setResults] = useState < string [] | null >( null )
useEffect (() => {
let shouldUpdate = true
if (query) {
TenorAPI. search (query). then (( newResults ) => {
if (shouldUpdate) setResults (newResults)
})
}
return () => {
shouldUpdate = false
}
}, [query])
return (
< section >
< label >
find a gif
< input
placeholder = " query "
value = {query}
onChange = {( event ) => setQuery (event.target.value)}
/>
</ label >
{results && (
< div className = {classes.grid}>
{results. map (( result ) => (
< button
type = " button "
key = {result}
className = {classes.button}
onClick = {() => onFound && onFound (result)}
aria-label = " gif "
>
< img className = {classes.image} src = {result} alt = " gif " />
</ button >
))}
</ div >
)}
</ section >
)
}
export const Example : FC = () => {
const [gif, setGif] = useState < string | null >( null )
return gif ? (
< div >
< img src = {gif} alt = " gif " />
< p >found gif</ p >
< button type = " button " onClick = {() => setGif ( null )}>
find new gif
</ button >
</ div >
) : (
< GifFinder onFound = {setGif} />
)
}
export default < Example /> Testing GifFinder# The more your tests resemble the way your software is used,
the more confidence they can give you.
— @testing-library
import {
act,
cleanup,
fireEvent,
render,
RenderResult,
} from ' @testing-library/react '
import React from ' react '
import { GifFinder } from ' ./example '
import { TenorAPI } from ' ./tenor-api '
describe ( ' GifFinder ' , () => {
let component : RenderResult
let onFound : jest . Mock
beforeEach (() => {
onFound = jest. fn ()
component = render (< GifFinder onFound = {onFound} />)
})
afterEach (() => {
cleanup ()
})
it ( ' should snapshot ' , () => {
expect (component.container). toMatchSnapshot ()
})
describe ( ' when searching ' , () => {
let queryInput : HTMLElement
let searchSpy : jest . SpyInstance
beforeEach ( async () => {
const searchPromise = Promise . resolve ([ ' gif1 ' , ' gif2 ' , ' gif3 ' ])
searchSpy = jest. spyOn (TenorAPI, ' search ' ). mockReturnValue (searchPromise)
queryInput = component. getByLabelText ( ' find a gif ' )
fireEvent. input (queryInput, { target : { value : ' react ' } })
await act ( async () => {
await searchPromise
})
})
afterEach (() => {
searchSpy. mockRestore ()
})
it ( ' should start a search ' , () => {
expect (searchSpy). toHaveBeenCalledWith ( ' react ' )
expect (searchSpy). toHaveBeenCalledTimes ( 1 )
})
it ( ' should render the gifs ' , () => {
expect (component.container). toMatchSnapshot ()
})
describe ( ' when clicking a gif ' , () => {
beforeEach (() => {
const [, gif2] = component. getAllByLabelText ( ' gif ' )
fireEvent. click (gif2)
})
it ( ' should call onFound ' , () => {
expect (onFound). toHaveBeenCalledWith ( ' gif2 ' )
expect (onFound). toHaveBeenCalledTimes ( 1 )
})
})
})
})