如何使用 React 测试库模拟 Stencil Web 组件?

How to mock stencil web components by using react testing library?

我使用 Stencljs 创建了一个单独的 Web 组件库并将其用于 React 应用程序,在编写测试用例时意识到事件没有按预期工作。我试图模拟该组件,但无法找出正确的方法。绝对需要一些帮助..!

模板网络组件:

import { Component, ComponentInterface, Element, Event, EventEmitter, h, Host, Prop } from '@stencil/core';
import { ButtonAppearance, ButtonSize, ButtonType } from '../types';
import classnames from 'classnames';
import { generateUniqueId } from '../../utils/utils';
@Component({
  tag: 'stencil-button',
  styleUrl: 'stencil-button.scss',
  shadow: true,
})
export class StencilButton implements ComponentInterface {
  @Element() el!: HTMLElement;

  @Prop({ attribute: 'autofocus' }) autoFocus?: boolean;

  @Prop({ mutable: true }) value: string;

  @Prop() disabled?: boolean;

  @Prop() name?: string;

  @Prop() form?: string;

  @Prop() stencilHidden?: boolean;

  @Prop() type?: ButtonType = 'button';

  @Prop() class: string;

  @Prop() appearance: ButtonAppearance;

  @Prop() size: ButtonSize;

  @Prop() bold: boolean;

  @Prop() stencilId: any;

  @Prop() inLine: boolean;

  private handleClick = (e: Event) => {
    if (this.disabled) {
      e.preventDefault();
      e.stopPropagation();
    }
    const form = this.el.closest('form');
    if (form) {
      e.preventDefault();
      const dummyButton = document.createElement('button');
      dummyButton.type = this.type;
      dummyButton.style.display = 'none';
      dummyButton.name = 'dummy-button';
      form.appendChild(dummyButton);
      dummyButton.click();
      dummyButton.remove();
    }
  };
  @Event() stencilClick!: EventEmitter<void>;
  private onHandle = e => {
    this.stencilClick.emit(e);
  };
  private buttonId = `gt-button-${generateUniqueId()}`;

  render () {
    const isWrapper = this.appearance === 'wrapper';
    const classList = classnames({
      btn: true && !isWrapper,
      [this.appearance]: this.appearance && !isWrapper,
      [this.size]: this.size && !isWrapper,
      [this.class]: this.class && !isWrapper,
      bold: this.bold && !isWrapper,
      wrapper: isWrapper,
      stencilInline: this.inLine,
    });
    const hostStyles = classnames({
      stencilInline: this.inLine
    })
    return (
      <Host onClick={this.handleClick} class={hostStyles}>
        <button
          class={classList}
          id={this.stencilId ? this.stencilId : this.buttonId}
          onClick={this.onHandle}
          autoFocus={this.autoFocus}
          hidden={this.stencilHidden}
          disabled={this.disabled}
          name={this.name}
          type={this.type}
          form={this.form}
        >
          <slot></slot>
        </button>
      </Host>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

目前,我正在尝试在我的 React 应用程序中模拟 Stencil 按钮:

const App = () => {


const [btnvalue, setbtnvalue] = useState(0);

  const increment = () => {
    setbtnvalue(btnvalue + 1);
  };

  return (
    <div>
      <StencilButton onStencilClick={increment} data-testid='click-btn'>
        {btnvalue}
      </StencilButton >
    </div>
  );
};

下面是我的测试用例:

describe('counter test cases', () => {
  it('updated counter on click', () => {  
    const clickBtn = getByTestId('click-btn');
    fireEvent.click(clickBtn);
    console.log(clickBtn.textContent);
    expect(clickBtn.textContent).toBe('1'); 
  });
});

我最近遇到了类似的问题。发现这个堆栈溢出希望得到帮助。不确定您在技术上是否遇到了与我相同的问题,但是由于在 Stencil slack 帐户上的帮助,我被解锁了。

在我的例子中,我需要像在索引中一样在我的测试文件中注册组件。

示例:

defineCustomElements(window);

然后我就等待组件水化 class:

await waitFor(() => {
      expect(filter).toHaveClass('hydrated');
});

终于找到了解决办法。

import StencilButton from 'stencil-components';

jest.mock('stencil-components', () => ({
  StencilButton: (props) => {
    return (
      <button
        {...props}
      />
    );
  },
}));