如何测试使用 React.createportal 渲染的组件?

问题描述 投票:0回答:2

我正在使用 jest 和 React 测试库。当我尝试渲染组件时,我无法测试它。你们能告诉我正确的方法吗?

it("Render PopUp Properly", () => {
      const props = {
        setIsOpen: jest.fn(),
        children: <div>Test</div>,
      };
      const {getByTestId}= render(<Popup isOpen={true} {...props} />);
      expect(screen.getByTestId("popup-component")).toBeInTheDocument();
    });

出现以下错误:

PopUp › Render PopUp Properly                            
                                                             
    Target container is not a DOM element.

      13 |   }
      14 |
    > 15 |   return createPortal(
         |                      ^
      16 |     <motion.div
      17 |       data-testid="blur-bg"
      18 |       initial={{

我原本希望我的组件能够正确渲染,但结果却出现了错误。

reactjs next.js jestjs react-testing-library
2个回答
1
投票
  it("Render PopUp Properly", () => {
      const props = {
        setIsOpen: jest.fn(),
        children: <div>Test</div>,
      };
      const container = document.createElement("div");
      document.body.appendChild(container);
      ReactDOM.createPortal(<Popup isOpen={true} {...props} />, container);
      expect(container.innerHTML).toMatchSnapshot();
      expect(container).toBeInTheDocument();
    });

这对我有用。


0
投票

我正在将 React 与 vitest 和 jest 一起使用。 我需要测试一个使用 headlessui Dialog 的组件https://headlessui.com/react/dialog

经过长时间的搜索,我想到了 Expect(document.body).toMatchSnapshot() 并为我工作

import { MockedProvider } from '@apollo/client/testing'
import AccountAndPartitionModal from '@src/modules/Devices/AccountAndPartitionModal'
import { UPDATE_GROUP_MUTATION } from '@src/tests/queries_mock'
import { render } from '@src/tests/testUtils'

const mocks = [
  {
    request: {
      query: UPDATE_GROUP_MUTATION,
      variables: { group: { account: 'account', partition: 'partition', id: '1' } },
    },
    result: {
      data: {
        updateGroup: {
          messages: [
            {
              message: 'message',
              code: 'code',
              field: 'field',
            },
          ],
          successful: true,
          result: {
            id: 'id',
            companyId: '123',
            account: 'account',
            name: 'name',
          },
        },
      },
    },
  },
]

describe('AccountAndPartitionModal', () => {
  test('should render', () => {
    const refetch = jest.fn()
    const setOpenModal = jest.fn()

    const { container, getByTestId } = render(
      <MockedProvider mocks={mocks}>
        <AccountAndPartitionModal
          groupId='1'
          account='account'
          partition='partition'
          setOpenModal={setOpenModal}
          refetch={refetch}
        />
      </MockedProvider>,
    )

    expect(container).toBeInTheDocument()
    expect(document.body).toMatchSnapshot()
    expect(getByTestId('AccountAndPartitionModal')).toBeInTheDocument()
    expect(getByTestId('form')).toBeInTheDocument()
    expect(getByTestId('cancelButton')).toBeInTheDocument()
    expect(getByTestId('confirmButton')).toBeInTheDocument()
  })
})

快照

// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`AccountAndPartitionModal > should render 1`] = `
<body>
  <div
    aria-hidden="true"
  >
    <div
      style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px; display: none;"
    />
  </div>
  <div
    id="headlessui-portal-root"
  >
    <div
      data-headlessui-portal=""
    >
      <button
        aria-hidden="true"
        data-headlessui-focus-guard="true"
        style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px;"
        type="button"
      />
      <div>
        <div
          aria-modal="true"
          class="relative z-10"
          data-headlessui-state="open"
          data-testid="modal-component"
          id="headlessui-dialog-:r0:"
          role="dialog"
        >
          <div
            class="fixed inset-0 bg-black bg-opacity-40 ease-out duration-300 opacity-0"
          />
          <div
            class="fixed inset-0 overflow-y-auto"
          >
            <div
              class="flex min-h-full items-center justify-center p-4 text-center mx-auto"
            >
              <div
                class="transform overflow-hidden rounded bg-white p-6 text-left align-middle shadow-xl transition-all w-[575px] h-[374px] ease-out duration-300 opacity-0 scale-95"
                data-headlessui-state="open"
                data-testid="AccountAndPartitionModal"
                id="headlessui-dialog-panel-:r1:"
              >
                <form
                  class="h-full flex flex-col gap-[24px]"
                  data-testid="form"
                >
                  <div>
                    <div
                      class="w-full"
                    >
                      <label
                        class="text-secondary-darkest text-sm leading-5 font-medium"
                        for="Conta"
                      >
                        Conta
                      </label>
                      <div
                        class="relative mt-1"
                      >
                        <input
                          class="h-[42px] min-h-[42px] text-secondary-darkest py-2 px-3 w-full bg-white rounded-md border border-solid border-secondary-light text-sm leading-5 font-normal focus:outline-none focus:border-main-600 focus:ring-main-600"
                          data-testid="Input"
                          id="Conta"
                          name="account"
                          placeholder="account"
                          type="text"
                        />
                      </div>
                    </div>
                    <span
                      class="text-error-darkest text-sm"
                    />
                  </div>
                  <div>
                    <div
                      class="w-full"
                    >
                      <label
                        class="text-secondary-darkest text-sm leading-5 font-medium"
                        for="Partição"
                      >
                        Partição
                      </label>
                      <div
                        class="relative mt-1"
                      >
                        <input
                          class="h-[42px] min-h-[42px] text-secondary-darkest py-2 px-3 w-full bg-white rounded-md border border-solid border-secondary-light text-sm leading-5 font-normal focus:outline-none focus:border-main-600 focus:ring-main-600"
                          data-testid="Input"
                          id="Partição"
                          name="partition"
                          placeholder="partition"
                          type="text"
                        />
                      </div>
                    </div>
                    <span
                      class="text-error-darkest text-sm"
                    />
                  </div>
                  <div
                    class="flex justify-between mt-auto"
                  >
                    <button
                      class="button-white button-type-none button-base w-[257px] outline-none"
                      data-testid="cancelButton"
                    >
                      Cancelar
                    </button>
                    <button
                      class="button-primary button-type-none button-base w-[257px] outline-none"
                      data-testid="confirmButton"
                      type="submit"
                    >
                      Confirmar e adicionar
                    </button>
                  </div>
                </form>
              </div>
            </div>
          </div>
        </div>
      </div>
      <button
        aria-hidden="true"
        data-headlessui-focus-guard="true"
        style="position: fixed; top: 1px; left: 1px; width: 1px; height: 0px; padding: 0px; margin: -1px; overflow: hidden; clip: rect(0px, 0px, 0px, 0px); white-space: nowrap; border-width: 0px;"
        type="button"
      />
    </div>
  </div>
</body>
`;
© www.soinside.com 2019 - 2024. All rights reserved.