inertiajs / inertia-laravel

The Laravel adapter for Inertia.js.
https://inertiajs.com
MIT License
2.04k stars 227 forks source link

Vitest + Inertia.js errors when running tests on Page/Components #459

Closed alisanie closed 1 year ago

alisanie commented 1 year ago

Hi I had a plan to use Vitest with Inertia js but there is a problem.After running below test

import { mount } from '@vue/test-utils'
import Register from '@/Pages/Auth/Register.vue';

it('Register Contains Register', () => {
    const wrapper = mount(Register);
    expect(wrapper.text()).toCaintain('Register');
})

I git this error:

TypeError: Cannot read properties of undefined (reading 'createProvider')

There is also a threat on laracast: https://laracasts.com/discuss/channels/inertia/vitest-inertiajs-errors-when-running-tests-on-pagecomponents

ryu022304 commented 1 year ago

Hi I had the same error following code.

// Welcome.test.js
// @vitest-environment happy-dom
import { mount } from '@vue/test-utils'
import { describe, expect, test } from 'vitest'
import Welcome from './Welcome.vue'

describe('Screen Display', () => {
  test('Display `Welcome` message', () => {
    const wrapper = mount(Welcome)
    expect(wrapper.text()).toContain('Welcome')
  })
})
// Welcome.vue
<script setup>
  import { onMounted } from "vue";
  import { Head } from "@inertiajs/inertia-vue3";
  onMounted(() => {
    console.log("Welcome Page mounted");
  });
</script>

<template>
  <Head>
    <title>Welcome</title>
  </Head>
  <h1>Welcome Inertia.js</h1>
</template>

in details of the error message, it seemed that the error was caused by Head from @inertiajs/inertia-vue3. So I split it into Layout.vue file and Welcome.vue file. Then Welcome.vue file test worked.

// Welcome.vue
<script setup>
  import { onMounted } from "vue";
  onMounted(() => {
    console.log("Welcome Page mounted");
  });
</script>

<script>
  import Layout from "./Layout.vue";
  export default {
    layout: Layout,
  }
</script>

<template>
  <h1>Welcome Inertia.js</h1>
</template>
// Layout.vue
<script>
  import { Head } from "@inertiajs/inertia-vue3";
  export default {
    components: {
      Head,
    }
  }
</script>

<template>
  <Head>
    <title>Welcome</title>
  </Head>
  <main>
    <slot />
  </main>
</template>
ryu022304 commented 1 year ago

@alisanie In my React & TypeScript case, I was able to test a component that included a Head component. I referenced this issue comment. https://github.com/vercel/next.js/discussions/11060#discussioncomment-33628

// Title.tsx
import React from 'react';
import { Head } from '@inertiajs/inertia-react';

type TitlePrpps = {
  title: string;
};

function Title(props: TitlePrpps) {
  const { title } = props;
  return (
    <Head>
      <title>{title ? `${title} - MyPage` : 'MyPage'}</title>
    </Head>
  );
}

export default Title;
// Title.test.tsx
// @vitest-environment happy-dom
import React from 'react';
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { describe, expect, test, vi } from 'vitest';
import Title from '@/Components/Layout/Title';

vi.mock('@inertiajs/inertia-react', () => ({
  Head: ({ children }: { children: Array<React.ReactElement> }) => (
    <>{children}</>
  )
}));

describe('Screen Display', () => {
  test('Display `title - MyPage` title', async () => {
    render(<Title title="test" />, {
      container: document.head
    });
    expect(document.head.querySelector('title')?.innerHTML).toEqual(
      'test - MyPage'
    );
  });
});

I hope this helps you.

reinink commented 1 year ago

Hey folks, this isn't really related to the Laravel adapter, so I'm going to close this one.

Probably best discussed on our Discord channel or GitHub Discussions.