0

我正在使用基于模型的测试使用@xstate/testand来测试状态机@testing-library/react

基本上,我正在测试这台机器:

const itemDamagedMachine = createMachine({
  initial: 'newModal',
  context: {
    productScan: '',
    binScan: '',
  },
  states: {
    newModal: {
      initial: 'scanDamagedItem',
      states: {
        scanDamagedItem: {},
        scanDamagedBin: {},
        declareItemDamaged: {},
      },
    },
    closed: {},
  },
  on: {
    UPDATE_PRODUCT_SCAN: {
      actions: assign({
        productScan: 123456,
      }),
    },
    VALIDATE: {
      target: 'newModal.scanDamagedBin',
    },
    UNREADABLE: {
      target: 'newModal.scanDamagedBin',
    },
    CANCEL: {
      target: 'closed',
    },
    UPDATE_DAMAGED_BIN_SCAN: {
      actions: assign({
        binScan: 'PB_DAMAGED',
      }),
    },
  },
});

然后我正在配置模型,并使用const testPlans = itemDamagedModel.getSimplePathPlans();.

通过大约 200 个通过测试,一切似乎都运行顺利,但我遇到了一些问题:

  • 对于我的每个测试和每个事件,我都会收到警告Missing config for event "VALIDATE"。我不明白它应该是什么意思。
  • 即使我在模型活动中故意打错字,我的所有测试都会得到验证。有时测试的数量会减少,但我希望在模型找不到特定输入或按钮时看到一些警告。
  • 测试都通过了,即使我将一个空的 div 作为我的 xstate/test 渲染组件传递。
4

1 回答 1

0

我不明白,但我已经测试了一个组件,如下所示:

首先我有我的机器:

import { createMachine, sendParent } from 'xstate';

export const machineDefinition = {
  id: 'checkbox',
  initial: 'unchecked',
  states: {
    unchecked: {
      on: {
        TOGGLE: [
          {
            actions: [ 'sendParent' ],
            target: 'checked',
          },
        ],
      },
    },
    checked: {
      on: {
        TOGGLE: [
          {
            actions: [ 'sendParent' ],
            target: 'unchecked',
          },
        ],
      },
    },
  },
};

const machineOptions = {
  actions: {
    sendParent: sendParent((context, event) => event.data),
  },
};

export default createMachine(machineDefinition, machineOptions);

二、我扩展了render方法testing-library

import React from 'react'
import HelmetProvider from 'react-navi-helmet-async'
import SpinnerProvider from '@atoms/GlobalSpinner'
import AlertProvider from '@molecules/GlobalAlert'
import InternationalizationProvider from '@internationalization/InternationalizationProvider'
import { render as originalRender } from '@testing-library/react'

const render = (ui, { locale = 'es', ...renderOptions } = {}) => {
  
  const Wrapper = ({ children }) => {
    return (
      <InternationalizationProvider>
          <AlertProvider>
            <SpinnerProvider>
              <HelmetProvider>
                {children}
              </HelmetProvider>
            </SpinnerProvider>
          </AlertProvider>
      </InternationalizationProvider>
    )
  }

  return originalRender(ui, { wrapper: Wrapper, ...renderOptions })
}

export * from '@testing-library/react'

export { render }

最后,我创建了测试

import React from 'react';
import { produce } from 'immer';
import { machineDefinition } from '@stateMachines/atoms/checkbox';
import { createMachine } from 'xstate';
import { createModel } from '@xstate/test';
import { render, cleanup, fireEvent } from '@root/jest.utils';
import Checkbox from '@atoms/Checkbox';

const getMachineDefinitionWithTests = () => produce(machineDefinition, (draft) => {
  draft.states.unchecked.meta = {
    test: ({ getByTestId }) => {
      expect(getByTestId('checkbox-child-3')).toHaveClass('w-8 h-4 rounded-md duration-500 bg-dark-300 dark:bg-accent-100');
    },
  };
  draft.states.checked.meta = {
    test: ({ getByTestId }) => {
      expect(getByTestId('checkbox-child-3')).toHaveClass('w-8 h-4 rounded-md duration-500 bg-dark-300 dark:bg-accent-100');
      expect(getByTestId('checkbox-child-3.1')).toHaveClass('bg-light-100 w-4 h-4 rounded-full duration-500 dark:transform dark:translate-x-full');
    },
  };
});

const getEvents = () => ({
  TOGGLE: {
    exec: ({ getByTestId }) => {
      fireEvent.click(getByTestId('checkbox-container'));
    },
    cases: [ {} ],
  },
});

describe('checkbox', () => {
  const machine = createMachine(getMachineDefinitionWithTests(), {
    actions: {
      sendParent: () => {},
    },
  });
  const machineModel = createModel(machine)
    .withEvents(getEvents());
  const testPlans = machineModel.getSimplePathPlans();

  testPlans.forEach((plan) => {
    describe(plan.description, () => {
      afterEach(cleanup);

      plan.paths.forEach((path) => {
        it(path.description, () => {
          const rendered = render(
            <Checkbox
              test
              label='main.txt1'
              data={{}}
              machine={machine}
            />,
            { locale: 'en' },
          );

          return path.test(rendered);
        });
      });
    });
  });

  describe('coverage', () => {
    it('should have full coverage', () => {
      machineModel.testCoverage();
    });
  });
});

我创建了一个包含 XState的反应样板,在那里你可以找到以前的测试

于 2021-12-09T17:52:48.773 回答