我在努力
测试连接的TSX组件
.我以前测试过连接的组件,我完全知道如何实现它,但jest和typescript的交互方式似乎存在一些问题。
我试过什么?
-
出于测试目的,我已导出一个未连接的组件
-
我已经创建了一个模拟存储,并在测试文件中围绕一个提供者包装了组件
-
我修改了笑话。配置。正如错误所暗示的那样
我总是犯同样的错误!
Cannot find module 'react' from 'Provider.js'
However, Jest was able to find:
'components/Provider.js'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
However, Jest was able to find:
'./App.test.tsx'
'./App.tsx'
You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'].
See https://jestjs.io/docs/en/configuration#modulefileextensions-array-string
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:259:17)
at Object.<anonymous> (../node_modules/react-redux/lib/components/Provider.js:10:38)
我的组件如下所示(
应用程序。tsx
):
import React from "react";
import { connect } from "react-redux";
import { Album, Photo, fetchAlbums, fetchPhotos } from "../actions";
import { StoreState } from "../reducers";
// *Notice: in this file we have used React.UseEffect and React.UseState instead of importing
// hooks directly from React. That's for the reasons of testing and how Enzyme has not yet adopted
// very well with hooks.
// the type of your action creators has been intentionally set to "any", as typescript does not play well with redux-thunk
interface AppProps {
albums?: Album[];
photos?: Photo[];
fetchAlbums?(): any;
fetchPhotos?(id: number): any;
}
export const _App = ({
albums,
photos,
fetchAlbums,
fetchPhotos
}: AppProps) => {
// setting the initial state of the loader and thmbnail
const [fetching, setFetching] = React.useState(false);
const [image, setImage] = React.useState();
// setting the state back to false once our data updates
React.useEffect(() => {
setFetching(false);
}, [albums, photos]);
// click evnet handler
const ClickHandler = (): void => {
fetchAlbums();
setFetching(true);
};
// album entry event handler
const AlbumClickHandler = (id: number): void => {
fetchPhotos(id);
};
const display = (id: number): JSX.Element[] => {
const relevantThumbs = photos.filter(photo => photo.albumId === id);
return relevantThumbs.map((thumb, idx) => {
return (
<img
onClick={() => setImage(thumb.id)}
key={idx}
alt={thumb.title}
src={image === thumb.id ? thumb.url : thumb.thumbnailUrl}
></img>
);
});
};
// helper function to render jsx elements
const renderList = (): JSX.Element[] =>
albums.map(album => (
<div className="albums" key={album.id}>
<h2 onClick={() => AlbumClickHandler(album.id)}>{album.title}</h2>
{display(album.id).length !== 0 ? (
<div className="albums__thumbnails">{display(album.id)}</div>
) : null}
</div>
));
return (
<section className="container">
<button className="container__button" onClick={() => ClickHandler()}>
Fetch Albums
</button>
{/* conditionally rendering the loader */}
{fetching ? "loading" : null}
{renderList()}
</section>
);
};
const mapStateToProps = ({
albums,
photos
}: StoreState): { albums: Album[]; photos: Photo[] } => {
return { albums, photos };
};
export default connect(mapStateToProps, { fetchAlbums, fetchPhotos })(_App);
这是我的测试文件(
应用程序。测验tsx
):
import React from "react";
import Enzyme, { mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import { findByClass } from "../test/Utils";
import App from "./App";
Enzyme.configure({ adapter: new Adapter() });
// setting our initial mount, we use mount here bcause of the hooks
const setup = () => mount(<App />);
describe("app", () => {
it("renders succesfully", () => {
// Arrange
const wrapper = setup();
const component = findByClass(wrapper, "container");
// Assert & Act
expect(component.length).toBe(1);
});
});
我错过了什么?