ReferenceError: customElements is not defined

ReferenceError: customElements is not defined

我在一个项目中使用 @angular@9.0.7@ngneat/spectator@5.3.1 (with Jest), Inputmask@5.0.3,当我 运行 ng serve 甚至 ng build,但是当我尝试 运行 一个使用 Inputmask:

@Pipe 的测试套件时它失败了

@Pipe:

import { Pipe, PipeTransform } from '@angular/core';

import Inputmask from 'inputmask';

@Pipe({
  name: 'appSomePipe',
})
export class SomePipe implements PipeTransform {
  transform(value: string): string {
    return Inputmask.format(value, {
      jitMasking: true,
      mask: '1111-1',
    });
  }
}

@Spec:

import { createPipeFactory, SpectatorPipe } from '@ngneat/spectator/jest';

import { SomePipe } from './some.pipe';

describe('SomePipe', () => {
  let spectator: SpectatorPipe<SomePipe>;
  const createPipe = createPipeFactory(SomePipe);

  it('test', () => {
    spectator = createPipe(`{{ '11111' | appSome }}`);
    expect(spectator.element).toHaveText('1111-1');
  });
});

当我运行ng test时,显示:

ReferenceError: customElements is not defined

  2 | 
> 3 | import Inputmask from 'inputmask';

PS: 这个错误是Angular9才出现的,在Angular8所有的测试都成功通过了。

我记得偶然发现了你的问题,我偶然发现了与 ngx-bootstrap 相关的其他问题,即 importAngular 9 中不起作用。

https://valor-software.com/ngx-bootstrap/#/datepicker

查看用法部分及其关于 Angular 9 的警告。

尝试 import InputMask from 'inputmask/somethingMoreSpecificHere'; 或 `import { somethingSpecificHere } from 'inputmask';

A quick search into inputmask repository shows that it uses customElements 这是现代浏览器实现的一项功能,用于创建本机 Web 组件(没有框架)。

看的时候Jest documentation we can see that the default testEnvironment is jsdom, which is an implementation of the DOM that runs without a browser. This library implements custom elements since version 16.2.0 and this version is pretty recent, and is not yet used by jest (the last version of jest uses jsdom v15.1.1).

所以你只需要等待 jest 更新 jsdom 依赖项,然后更新你的项目以使用最新版本的 jest。

另一种选择:您可以使用 jest-browser,它在基于 puppeteer 的无头浏览器中运行 Jest。

更新 05-2020:

升级到(至少)使用 jsdom 16.2.0 的 Jest 26.0.0 (Source)

问题是您没有将 Inputmask 依赖项注入到您的测试中。

这是因为您正在使用 javascript 导入。有 Angular 个库可以执行此操作 (ngx-mask)。

在 Angular 中,我们使用 Dependency Injection with IOC,因此对于此示例,我将使用 InputMaskService 来创建 angular 依赖项。

管道

import { Pipe, PipeTransform } from '@angular/core';

import { InputMaskService } from './inputmask.service';

@Pipe({
  name: 'appSomePipe',
})
export class SomePipe implements PipeTransform {

  constructor(private inputMaskService: InputMaskService){}

  transform(value: string): string {
    return this.inputMaskService.format(value, {
      jitMasking: true,
      mask: '1111-1',
    });
  }
}

请注意,我在构造函数中注入服务并在 transform 方法中使用该实例。

测试

您可以创建一个传递服务引用的管道实例

beforeEach(() => {
  const inputMaskService = new InputMaskService();
  const pipe = new SomePipe(inputMaskService);
});

正如 Guerric P 所写,jsdom 在 v16.2.0 之前不支持自定义元素。

要开玩笑 运行 jsdom v 16,您需要执行以下操作

yarn add jest-environment-jsdom-sixteen

然后在你jest.config.js添加这个

module.exports = {
  testEnvironment: 'jest-environment-jsdom-sixteen',
  ...
}

这将强制 jest 使用更新的实现。 这应该可以解决您的问题。