typescript 使用JEST编写React功能组件的单元测试用例

of1yzvn4  于 2023-03-09  发布在  TypeScript
关注(0)|答案(1)|浏览(246)

我是单元测试用例的新手,我的项目使用的是带有React的typescript。我希望在为我的组件之一编写以下代码的测试用例时得到一些帮助。我一直在尝试编写一个测试用例来满足这里的getLogo和setupRegistry两个函数。无法找出正确的方法来完成这一操作-

import {
    getMediaToken,
    isManifestRegistryItem,
    MediaRegistryHelper,
    RegistryItem,
    SupportedRegistryMedia,
    SvgUtils,
  } from 'common';
  import React, {
    FunctionComponent,
    useEffect,
    useState,
    useContext,
  } from 'react';
  import { Observable, of } from 'rxjs';
  import { filter, map } from 'rxjs/operators';
  import { downloadMedia, loadMediaRegistry } from '../media-registry';
  import { LogoAssetContext } from '../media-context';
  
  export interface RBCLogoProperties {
    token: string;
    srLabel: string;
  }
  
  type RBCLogoType = RBCLogoProperties & React.HTMLAttributes<HTMLLabelElement>;
  export const RCLogo: FunctionComponent<RBCLogoType> = (props: RBCLogoType) => {
    const { token, srLabel } = props;
    const LOGOASSETREGISTRY = useContext(LogoAssetContext);
  
    useEffect(() => {
      setupRegistry(
        LOGOASSETREGISTRY as Array<RegistryItem<SupportedRegistryMedia>>,
      );
    });
  
    // Media Helper Instance to access the methods defined in media helper
  
    const mediaHelperInstance = new MediaRegistryHelper();
  
    // State to set the svg to html to show the logo
  
    const [svg, setSVG] = useState<string>();
  
    //Set up the registry for logo assets
  
    const setupRegistry = (
      registryConfig: Array<RegistryItem<SupportedRegistryMedia>>,
    ) => {
      let config: Array<RegistryItem<SupportedRegistryMedia>> = [];
      if (registryConfig && registryConfig.length > 0) {
        const items = registryConfig;
        config = [...config, ...items];
      }
      loadMediaRegistry?.('logo', config).subscribe(() => getLogo());
    };
  
    const getLogo = () => {
      if (token) {
        const logo = getMediaToken(token);
        const registryItem = mediaHelperInstance?.getRegistryMediaItem(
          'logo',
          logo.scope || 'default',
        );
        let item$: Observable<RegistryItem<SupportedRegistryMedia> | undefined> =
          of(registryItem);
  
        if (isManifestRegistryItem(registryItem)) {
          item$ = registryItem.data.pipe(
            filter((v) => !!v),
            map(() => registryItem),
          );
        }
        const downLoadMediaResponse = downloadMedia('logo', logo);
        downLoadMediaResponse
          ? downLoadMediaResponse.subscribe((data: any) => {
              const svg = data as SVGElement;
              setSVG(svg.outerHTML);
              SvgUtils.setSvgAttributes(svg);
              SvgUtils.addA11ytoSVG(
                svg,
                token,
                srLabel ? srLabel : ' ',
                document,
              );
            })
          : console.log('Download Media Response is undefined for', token);
      }
    };
  
    return (
      <div
        aria-label={srLabel}
        dangerouslySetInnerHTML={{ __html: svg || '' }}
      ></div>
    );
  };
  
  export default RCLogo;
5f0d552i

5f0d552i1#

关于React组件的单元测试,您通常根据组件测试整个单元,而不能测试getLogosetupRegistry(我假设这就是您所说的setSubscription?如果不是,您需要为该函数添加一个代码段)。
你不能测试那些特定的函数,因为它们被封装在你的组件中,测试运行者不能访问它们。更重要的是,测试运行者不应该访问它们,因为这会暴露组件的实现细节,测试应该是不可知的。
但是,测试组件内函数的方法有限,但前提是函数在其他地方声明并导入到组件中。然后,您可以使用spy来观察被监视的方法是否被调用过,调用的次数是多少。同样,您只能在特定情况下使用它(假设您需要测试组件中的分析事件是否只被分派过一次,即使组件重新呈现等。)
因此,如果我为这个组件编写一个单元测试,我将有以下测试用例:
1.组件是否返回预期的svg徽标元素?
1.艾瑞亚的标签正确吗?
我不会测试getLogo或任何其他封装的函数,因为您关心的是最终的SVG输出。
因此,在测试此组件之前,您需要从所提供的代码示例中获得三件东西。
1.用预期的数据模拟API响应(可以使用Jest nock
1.将组件 Package 到LogoAssetContext提供程序中,以便组件可以访问它。
1.为部件提供正确的支撑。
还有一个关于how much value the unit test brings的争论,即表示性组件(如徽标)除了显示image/svg之外不做任何事情。
另外,我会尽量避免使用危险的set HTML来呈现SVG。因为它是作为字符串返回的,而且也是从API调用返回的,所以我不相信从其他地方返回的信息会被用来设置内部HTML。如果svg不是真正的svg,它会使您面临XSS攻击。
我会在你的div中使用类似下面的东西。

<img src={`data:image/svg+xml;utf8,${svg}`} />

相关问题