代码之家  ›  专栏  ›  技术社区  ›  Pouya Ataei

测试Redux连接的Typescript文件

  •  0
  • Pouya Ataei  · 技术社区  · 6 年前

    我在努力 测试连接的TSX组件 .我以前测试过连接的组件,我完全知道如何实现它,但jest和typescript的交互方式似乎存在一些问题。

    我试过什么?

    1. 出于测试目的,我已导出一个未连接的组件
    2. 我已经创建了一个模拟存储,并在测试文件中围绕一个提供者包装了组件
    3. 我修改了笑话。配置。正如错误所暗示的那样

    我总是犯同样的错误!

    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);
      });
    });
    

    我错过了什么?

    0 回复  |  直到 6 年前