close
  • 简体中文
  • extends

    • 类型: ExtendConfig | ExtendConfigFn | (ExtendConfig | ExtendConfigFn)[]
    • 默认值: undefined

    extends 选项允许你从外部来源扩展 Rstest 配置,例如使用适配器将其他构建工具的配置转换为 Rstest 兼容格式。

    这样可以实现以下功能:

    • 适配器集成:通过 @rstest/adapter-rslib 等适配器从其他构建工具配置中扩展 Rstest 配置
    • 异步配置:从外部源异步加载配置
    • 配置合并:自动将扩展配置与本地 Rstest 配置合并
    • 可组合预设:通过 extends 数组组合多个共享配置

    基本用法(对象)

    type ExtendConfig = Omit<RstestConfig, 'projects'>;

    ExtendConfigRstestConfig 子集,不包含 projects 字段。

    你可以用它从外部源扩展 Rstest 配置。Rstest 会按合并规则将扩展配置与本地配置合并。

    import { defineConfig } from '@rstest/core';
    import { sharedConfig } from './shared.config';
    
    export default defineConfig({
      extends: sharedConfig,
      // 本地配置
      testTimeout: 10000,
      retry: 2,
    });

    函数用法

    type ExtendConfigFn = (
      userConfig: Readonly<RstestConfig>,
    ) => ExtendConfig | Promise<ExtendConfig>;

    ExtendConfigFn 是一个接收用户配置(只读)并返回扩展配置的函数。

    它适用于加载外部配置文件、获取远程配置或基于用户设置进行动态配置。

    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      extends: async (user) => {
        const useJsdom = user.testEnvironment === 'jsdom';
        return {
          setupFiles: useJsdom ? ['<rootDir>/setupDomTests.ts'] : undefined,
          source: {
            define: {
              BUILD_TARGET: '"test" ',
            },
          },
        };
      },
      testTimeout: 10_000,
    });

    多个 extends

    当你需要组合多个预设时,可以给 extends 传入数组。

    Rstest 会按从左到右的顺序依次解析数组。后面的条目会覆盖前面的冲突字段,而本地配置仍然拥有最高优先级。

    当数组项为函数时,每个 ExtendConfigFn 都会基于原始的用户配置独立解析。数组顺序只影响最终合并优先级,不会影响传给每个函数的输入。

    import { defineConfig } from '@rstest/core';
    import { withRslibConfig } from '@rstest/adapter-rslib';
    import { sharedConfig } from './shared.config';
    
    export default defineConfig({
      extends: [
        sharedConfig,
        withRslibConfig({}),
        (userConfig) => ({
          globals: userConfig.retry !== undefined,
        }),
      ],
      testTimeout: 10_000,
    });

    配置合并

    Rstest 对对象配置执行深度合并,对基本类型配置执行简单覆盖。本地配置优先于扩展配置。

    extends 为数组时,优先级顺序如下:

    extends[0] < extends[1] < ... < extends[n] < local config

    主要合并规则如下:

    • testTimeoutretryglobals 这类基本类型字段由后者直接覆盖前者。
    • setupFilesglobalSetupplugins 会拼接,方便多个预设共同追加配置。
    • includereporterscoverage.reporters 会被后者整体替换。
    • sourceresolveoutputtoolsenvcoverage 等对象字段会执行深度合并。
    • browser 会执行浅合并,后者的同名属性覆盖前者。
    • 每个扩展配置中的 projects 都会被忽略。
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      extends: [
        {
          testEnvironment: 'jsdom',
          setupFiles: ['./setup-a.ts'],
          testTimeout: 5000,
          source: {
            define: {
              BASE_URL: '"https://example.com"',
            },
          },
        },
        {
          globals: true,
          setupFiles: ['./setup-b.ts'],
          source: {
            define: {
              API_URL: '"https://api.example.com"',
            },
          },
        },
      ],
      // 本地配置
      testTimeout: 10000,
      retry: 2,
    });
    
    // 结果:
    // {
    //   testEnvironment: 'jsdom',
    //   globals: true,
    //   testTimeout: 10000,
    //   retry: 2,
    //   setupFiles: ['./setup-a.ts', './setup-b.ts'],
    //   source: {
    //     define: {
    //       BASE_URL: '"https://example.com"',
    //       API_URL: '"https://api.example.com"',
    //     },
    //   },
    // }

    使用适配器

    示例:从 Rslib 配置扩展

    使用 @rstest/adapter-rslib 适配器可从现有 Rslib 配置文件扩展 Rstest 配置。该适配器会自动映射兼容选项,如 source.definesource.includesource.excludesource.transformImport 等。

    import { defineConfig } from '@rstest/core';
    import { withRslibConfig } from '@rstest/adapter-rslib';
    
    export default defineConfig({
      extends: withRslibConfig({}),
      // 额外的 Rstest 特定配置
      coverage: {
        enabled: true,
        reporters: ['text', 'html'],
      },
    });

    限制

    extends 配置不支持 projects 字段。要定义多个项目,请单独扩展每个项目:

    export default defineConfig({
      projects: [
        {
          extends: withRslibConfig({ libId: 'node' }),
          include: ['tests/node/**/*.{test,spec}.?(c|m)[jt]s'],
        },
        {
          extends: withRslibConfig({ libId: 'react' }),
          include: ['tests/react/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
        },
      ],
    });