如何测试具有更新背景的组件取决于状态变化
How to test a component with updates background depend on state changes
我有一个组件可以根据状态更改背景图像。我在下面添加了简化代码。
由于我在状态更改时从服务器获取图像,背景图像一直在闪烁。这就是我使用 preloadImage()
函数将它们加载到 DOM 的原因。这个函数解决了这个问题。
问题从测试开始。查看测试文件!
const BackgroundImage = styled`
...
background-image: ${(props) => props.bg && `url(${props.bg})`};
`
const preloadImage = (src, wrapperRef, callback) => {
const img = new Image();
img.src = src;
img.style.display = 'none';
img.dataset.testid = 'preloaded-image';
const el = wrapperRef.current;
el.innerHTML = '';
el.appendChild(img);
img.onload = () => typeof callback === 'function' && callback(src);
};
const Panel = (defaultBG) => {
const imageCacheRef = useRef();
const [bg, setBG] = useState(defaultBG);
useEffect(() => {
const fetchImage = async () => {
const imageSrc = await import(`https://fakeimageapi.com/${bg}.png`);
return preloadImage(imageSrc.default, imageCacheRef, setImage);
}
try {
await fetchImage()
} catch (error) {
console.log(error)
}
}, [])
return (
<div ref={imageCacheRef}>
<BackgroundImage bg={bg} data-testid="bg" />
<button onClick={ () => setBG('cat') }>Cat</button>
<button onClick={ () => setBG('dog') }>Cat</button>
<button onClick={ () => setBG('rabbit') }>Cat</button>
<button onClick={ () => setBG('parrot') }>Cat</button>
</div>
)
}
这是用测试库编写的测试套件。
import { render, waitFor, screen, act } from '@testing-library/react';
describe('Panel', () => {
test('Sets background-image correctly', async () => {
render(<Panel defaultBG="panda" />)
expect(screen.getByTestId('bg')).toHaveStyle(
'background-image: url(panda.png);',
);
})
})
不幸的是,这个测试失败了。图像加载到 useEffect
后我使用回调的问题(我猜)。我怎样才能以成功的结果结束这个测试?
问题已解决。我在 preloadImage() 中向图像添加了一个测试 ID,并使用 fireEvent 方法加载图像。就是这样!
import { render, waitFor, screen, fireEvent } from '@testing-library/react';
describe('Panel', () => {
test('Sets background-image correctly', async () => {
render(<Panel defaultBG="panda" />)
const image = await waitFor(() => screen.getByTestId('preloaded-image'));
fireEvent.load(image);
expect(screen.getByTestId('bg')).toHaveStyle(
'background-image: url(panda.png);',
);
})
})
此外,对 preloadImage()
函数进行了一些重构。
const preloadImage = (src, wrapperRef, callback) => {
const img = new Image();
img.src = src;
img.style.display = 'none';
img.dataset.testid = 'preloaded-image';
const el = wrapperRef.current;
el.innerHTML = '';
el.appendChild(img);
if (typeof callback === 'function') {
img.onload = () => callback(src);
}
};
我有一个组件可以根据状态更改背景图像。我在下面添加了简化代码。
由于我在状态更改时从服务器获取图像,背景图像一直在闪烁。这就是我使用 preloadImage()
函数将它们加载到 DOM 的原因。这个函数解决了这个问题。
问题从测试开始。查看测试文件!
const BackgroundImage = styled`
...
background-image: ${(props) => props.bg && `url(${props.bg})`};
`
const preloadImage = (src, wrapperRef, callback) => {
const img = new Image();
img.src = src;
img.style.display = 'none';
img.dataset.testid = 'preloaded-image';
const el = wrapperRef.current;
el.innerHTML = '';
el.appendChild(img);
img.onload = () => typeof callback === 'function' && callback(src);
};
const Panel = (defaultBG) => {
const imageCacheRef = useRef();
const [bg, setBG] = useState(defaultBG);
useEffect(() => {
const fetchImage = async () => {
const imageSrc = await import(`https://fakeimageapi.com/${bg}.png`);
return preloadImage(imageSrc.default, imageCacheRef, setImage);
}
try {
await fetchImage()
} catch (error) {
console.log(error)
}
}, [])
return (
<div ref={imageCacheRef}>
<BackgroundImage bg={bg} data-testid="bg" />
<button onClick={ () => setBG('cat') }>Cat</button>
<button onClick={ () => setBG('dog') }>Cat</button>
<button onClick={ () => setBG('rabbit') }>Cat</button>
<button onClick={ () => setBG('parrot') }>Cat</button>
</div>
)
}
这是用测试库编写的测试套件。
import { render, waitFor, screen, act } from '@testing-library/react';
describe('Panel', () => {
test('Sets background-image correctly', async () => {
render(<Panel defaultBG="panda" />)
expect(screen.getByTestId('bg')).toHaveStyle(
'background-image: url(panda.png);',
);
})
})
不幸的是,这个测试失败了。图像加载到 useEffect
后我使用回调的问题(我猜)。我怎样才能以成功的结果结束这个测试?
问题已解决。我在 preloadImage() 中向图像添加了一个测试 ID,并使用 fireEvent 方法加载图像。就是这样!
import { render, waitFor, screen, fireEvent } from '@testing-library/react';
describe('Panel', () => {
test('Sets background-image correctly', async () => {
render(<Panel defaultBG="panda" />)
const image = await waitFor(() => screen.getByTestId('preloaded-image'));
fireEvent.load(image);
expect(screen.getByTestId('bg')).toHaveStyle(
'background-image: url(panda.png);',
);
})
})
此外,对 preloadImage()
函数进行了一些重构。
const preloadImage = (src, wrapperRef, callback) => {
const img = new Image();
img.src = src;
img.style.display = 'none';
img.dataset.testid = 'preloaded-image';
const el = wrapperRef.current;
el.innerHTML = '';
el.appendChild(img);
if (typeof callback === 'function') {
img.onload = () => callback(src);
}
};