【问题标题】:How to use TypeScript in a Custom Test Environment file in Jest?如何在 Jest 的自定义测试环境文件中使用 TypeScript?
【发布时间】:2020-01-29 11:19:39
【问题描述】:

我需要为我的测试启用一些全局变量,因此我设置了一个自定义环境以在我的jest.config.json 中的testEnvironment 选项中使用以实现此目的。

对于我们的项目,我们有一个用于setupFilesAfterEnv 选项的 TypeScript 文件,它工作得很好,但是testEnvironment 似乎只支持 ES5。有没有办法在这样的选项中使用 TypeScript?

我使用 ES5 语法成功创建了自定义 Jest 环境,但是由于我们要注入全局变量,因此我需要 TypeScript 来声明全局命名空间,请参阅:https://stackoverflow.com/a/42304473/4655076

{
  ///...
  setupFilesAfterEnv: ['<rootDir>/test/setup.ts'], // This works with ts
  testEnvironment: '<rootDir>/test/customJestEnvironment.ts', // This doesn't work with ts
}

【问题讨论】:

    标签: node.js typescript jestjs


    【解决方案1】:

    您可以在项目的根目录下创建一个global.d.ts 文件。

    然后您可以定义全局变量,如下所示。在我的例子中,它是一个 NestJS 应用程序,但你可以定义任何东西。

    declare global {
      namespace NodeJS {
        interface Global {
          app: INestApplication;
        }
      }
    }
    
    

    这是客户端项目的另一个例子,我们定义了像innerWidth这样的窗口属性;

    declare namespace NodeJS {
        interface Global {
            innerWidth: number;
            dispatchEvent: Function;
        }
    }
    

    【讨论】:

    • 需要能够设置这些变量,而不仅仅是声明类型。问题 id 基本上是如何为 Jest 提供 environment.ts。
    【解决方案2】:

    在您的 .d.ts 定义文件中:

    type MyGlobalFunctionType = (name: string) => void
    

    将成员添加到浏览器的窗口上下文中:

    interface Window {
      myGlobalFunction: MyGlobalFunctionType
    }
    

    NodeJS 也一样:

    declare module NodeJS {
      interface Global {
        myGlobalFunction: MyGlobalFunctionType
      }
    }
    

    现在你声明根变量

    declare const myGlobalFunction: MyGlobalFunctionType;
    

    然后在一个常规的 .ts 文件中,但作为副作用导入,你实际实现它:

    global/* or window */.myGlobalFunction = function (name: string) {
      console.log("Hey !", name);
    };
    

    最后在别处使用它:

    global/* or window */.myGlobalFunction("Ayush");
    
    myGlobalFunction("Ayush");
    

    【讨论】:

    • 感谢您提供实现跨测试功能共享的 hacky 解决方案。问题是关于如何使用 TypeScript 编写环境。 IE。 setupFile 但全局。
    【解决方案3】:

    您可能会觉得这很有帮助:Configure Jest global tests setup with .ts file (TypeScript)

    但基本上你只能将编译好的 JS 文件作为环境传入。

    你可以按照那篇文章的建议去做。但这对我来说并没有开箱即用。所以我手动编译我的环境。

    在 package.json 中

    "test": "tsc --lib es6 --target es6 --skipLibCheck -m commonjs --esModuleInterop true path/to/env.ts && 
    jest --config=jest.config.js",
    

    在 jest.config.js 中

    {
      testEnvironment: '<rootDir>/path/to/env.js', // Note JS extension.
    }
    

    【讨论】:

      【解决方案4】:

      您可能知道,typescript 文件只是 javascript 的超集,以提供强大的类型检查。然而,Jest 的引擎/运行时需要您的文件为 CommonJS 格式的 javascript 文件。

      您可以为这个env.ts 设置一个单独的tsconfig.env.json。在运行 jest 测试之前编译它并在你的jest.config.js 中使用编译的env.js

      tsc -p tsconfig.env.json && jest
      

      我也从未见过有人在 TS 中编写配置文件。

      为什么是 CommonJS ?因为 jest 本质上是在节点之上运行的。 node 支持 CommonJS 格式的 Javascript 文件。 Node 最近也开始支持 es 模块!这是一件大事!

      【讨论】:

        【解决方案5】:

        我通过使用ts-node 和以下命令解决了这个问题:

        node -r ts-node/register ./node_modules/jest/bin/jest.js

        这实质上是即时编译打字稿,因此 jest 接收发出的 javascript,而无需实际将打字稿源编译为 js。

        您需要启用esModuleInterop TS 编译器选项才能正常工作。

        TestEnvironment.ts

        
        import NodeEnvironment from 'jest-environment-node';
        import type {Config} from '@jest/types';
        
        class TestEnvironment extends NodeEnvironment {
            
            constructor(config: Config.ProjectConfig) {
                super(config);
                // this.testPath = context.testPath;
                // this.docblockPragmas = context.docblockPragmas;
            }
        
            public async setup(): Promise<void> {
                await super.setup();
        
                console.log('SETTING UP...');
                // await someSetupTasks(this.testPath);
                // this.global.someGlobalObject = createGlobalObject();
            
                // // Will trigger if docblock contains @my-custom-pragma my-pragma-value
                // if (this.docblockPragmas['my-custom-pragma'] === 'my-pragma-value') {
                //   // ...
                // }
            }
        
            public async teardown(): Promise<void> {
                await super.teardown();
                console.log('TEARING DOWN!');
                // this.global.someGlobalObject = destroyGlobalObject();
                // await someTeardownTasks();
                
            }
        }
        
        export default TestEnvironment;
        
        

        但是,此解决方案将破坏 globalSetup -- 如果您使用 jest-ts

        【讨论】:

          猜你喜欢
          • 2023-02-19
          • 2020-09-10
          • 1970-01-01
          • 2018-08-26
          • 2021-04-28
          • 2020-04-03
          • 1970-01-01
          • 1970-01-01
          • 2020-01-15
          相关资源
          最近更新 更多