Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError in superForm.js (v2.10.5): Cannot read properties of undefined (reading 'form') when testing with Vitest or Jest #394

Open
1 task done
LMarshallAfzal opened this issue Apr 3, 2024 · 1 comment

Comments

@LMarshallAfzal
Copy link

LMarshallAfzal commented Apr 3, 2024

  • Before posting an issue, read the FAQ and search the previous issues.

Description
I'm encountering a "TypeError: Cannot read properties of undefined (reading 'form')" error within the sveltekit-superforms library (superForm.js) during testing with Vitest unit tests. This error prevents form data from being processed successfully within tests.

Steps to Reproduce (in Testing)

  1. Create a SvelteKit form using the superForm and superValidate functions.
  2. Within a test (e.g., using Vitest), submit the form with valid data.
  3. The error occurs within the superForm.js file (approximately line 181), where the code attempts to access the form property of an object named postedForm, which is undefined.

Important Note
This issue does not appear when using the forms in a regular (non-test) environment.

Expected Behavior
Form data should be processed correctly by the superForm function, both during testing and in standard application usage.

Actual Behavior
The TypeError is thrown during testing, interrupting form processing within the test environment. Debugging indicates that the postedForm object is undefined when the problematic line executes.

Environment
Svelte version: 4.2.7
SvelteKit version: 2.0.0
sveltekit-superforms version: 2.10.5
joi validation library version: 17.12.2
Node.js version: 21.7.1
Testing framework: Vitest (I had the same issue with Jest)
Other relevant dependencies and versions (if applicable)

Error

TypeError: Cannot read properties of undefined (reading 'form')
 ❯ Module.superForm node_modules/sveltekit-superforms/dist/client/superForm.js:181:60
    180|                         form.message = clone(postedForm.message);
    181|                     }
    182|                     break;
       |                                      ^
    183|                 }
    184|             }
 ❯ instance src/routes/login/+page.svelte:8:37
 ❯ Module.init node_modules/svelte/src/runtime/internal/Component.js:130:5
 ❯ new Page src/routes/login/+page.svelte:887:25
 ❯ Module.render node_modules/@testing-library/svelte/src/pure.js:57:19
 ❯ src/lib/__tests__/login/LoginComponent.test.js:11:9

Test File

import { describe, test, expect, vi } from "vitest";
import { render, screen } from "@testing-library/svelte";
import LoginComponent from "../../../routes/login/+page.svelte";

vi.mock('form', () => ({
    resolve: vi.fn(),
}));

describe("Login", () => {
    test("renders login form", async () => {
        render(LoginComponent, {
            props: {
                data: { 
                    form: { 
                        email: 'johndoe@example.com',
                        password: 'Password123!'
                    }
                }
            }   
        });

        const emailInput = screen.getByLabelText("Email");
        const passwordInput = screen.getByLabelText("Password");
        const submitButton = screen.getByRole("button", { name: /sign in/i });

        expect(emailInput).toBeInTheDocument();
        expect(passwordInput).toBeInTheDocument();
        expect(submitButton).toBeInTheDocument();
    });
});

Component being tested

<script>
  import { superForm } from "sveltekit-superforms";

  export let data;

  let showAuthError = false;

  const { form, errors, enhance } = superForm(data.form);

  let selectedLoginMethod = "email"

</script>

  <main class="flex justify-center items-center h-screen">
    <div class="w-full max-w-md">
      <h1 class="text-center text-3xl font-bold mb-4">Login</h1>

      {#if selectedLoginMethod === "email"}
        <form method="POST" class="space-y-4" use:enhance>
        
          <input type="hidden" name="loginMethod" bind:value={selectedLoginMethod} />
          <input type="email" placeholder="johndoe@site.co.uk" name="email" aria-invalid={$errors.email ? 'true' : undefined} bind:value={$form.email} class="input input-bordered input-primary w-full max-w-xl" />
          <input type="password" placeholder="Pa$$word123!" name="password" aria-invalid={$errors.password ? 'true' : undefined} bind:value={$form.password} class="input input-bordered input-primary w-full max-w-xl" />
          <a class="block mb-2 text-secondary hover:text-primary" href="/signup">New to the platform? Join now</a>
          <a class="block mb-2 text-secondary hover:text-primary" href="/reset_password">Forgot password</a>
          <button type="submit" class="btn btn-primary grow">
            Sign in
          </button>
        </form>
      {:else if selectedLoginMethod === "emailCode"}
        <form method="POST" class="space-y-4" use:enhance>
          {#if $errors.email}
            <div role="alert" class="alert alert-error">
                <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
                <span>{$errors.email}</span>
            </div>
          {/if}
          <input type="hidden" name="loginMethod" bind:value={selectedLoginMethod} />
          <input type="email" placeholder="johndoe@site.co.uk" name="email" bind:value={$form.email} required class="input input-bordered input-primary w-full max-w-xl" />
          <button type="submit" class="btn btn-primary grow">
            {selectedLoginMethod === "magicLink" ? "Send link" : "Send code"}
          </button>
        </form>
    </div>
  </main>

  <style>
    .button-container {
      display: flex;
      gap: 1rem;
    }
  </style>
@LMarshallAfzal LMarshallAfzal added the bug Something isn't working label Apr 3, 2024
@ciscoheat
Copy link
Owner

You need to mock the SvelteKit environment to make it work with vitest. Check the superForm tests how to do it: https://github.com/ciscoheat/sveltekit-superforms/blob/main/src/tests/superForm.test.ts#L355

@ciscoheat ciscoheat removed the bug Something isn't working label Apr 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants