Reputation: 99
In my <App />
component I want to show a loading screen until I've fetched my data and after fetching my data all the images(whose source's I got from my data) are loaded.
I am having difficulty to test that.
I want in essence something like this
const { products } = await vi.hoisted(
async () => await import('./mock-products.js')
)
vi.mock('../../ShoppingCart-Core/api.js', () => {
return {
fetchData: vi.fn(
async () =>
new Promise((resolve) => {
resolve(products)
})
),
}
})
it('Loading Screen', () => {
const {queryAllByTitle} = render(<App />)
let products = queryAllByTitle(/category/i)
expect(products.length).toBe(0)
// do something that fetchs your mocked data and images are also loaded
products = queryAllByTitle(/category/i)
expect(products.length).toBe(0)
})
I know how to implement it but don't know how to test it.
I've tried to do this
vi.mock('../../ShoppingCart-Core/api.js', () => {
return {
fetchData: vi.fn(
async () =>
new Promise((resolve) => {
setTimeout(() => {
resolve(products)
}, 500)
})
),
}
it('Loading Screen', async () => {
vi.useFakeTimers()
render(<App />)
await waitFor(() => {
if (fetchData.mock.calls.length > 0) {
vi.advanceTimersByTime(800)
} else {
throw new Error('Fetch not called yet')
}
})
I am waiting for fetchData
to be called and then advance timer so that the promise is resolved but. it doesn't work. Advancing timers doesn't do anything and just says waitFor
timed out, and also the promise is not resolved.
My implementation in useEffect
const [products, setProducts] = useState([])
useEffect(() => {
const getProducts = async () => {
const products = await fetchData()
setProducts(products)
}
getProducts()
}, [])
Upvotes: 0
Views: 31
Reputation: 99
You can use fireEvent
to load images and then test if the loading state before and after load event.
it('Loading Screen', async () => {
const { getAllByAltText, findAllByTitle, getByTestId } = render(<App />)
const loadingScreen = getByTestId('loading-screen')
expect(loadingScreen).toBeInTheDocument()
await findAllByTitle(/category/i)
expect(loadingScreen).toBeInTheDocument()
const images = getAllByAltText('product image')
expect(loadingScreen).toBeInTheDocument()
images.forEach((image) => fireEvent.load(image))
expect(loadingScreen).not.toBeInTheDocument()
})
Upvotes: 0