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

[Feature Request]: SvelteKit mocks #20999

Closed
benmccann opened this issue Feb 7, 2023 · 9 comments · Fixed by #24795
Closed

[Feature Request]: SvelteKit mocks #20999

benmccann opened this issue Feb 7, 2023 · 9 comments · Fixed by #24795

Comments

@benmccann
Copy link
Contributor

benmccann commented Feb 7, 2023

Is your feature request related to a problem? Please describe

SvelteKit's $app/navigation and $app/forms don't work today because they rely on the SvelteKit client singleton, which isn't initialized since there's no application and just individual components. We wouldn't really want to make them work anyway because we don't want to actually do navigations and so we should mock these components.

Describe the solution you'd like

Implement a Vite plugin (probably in sveltekit/src/plugins) that overrides Kit's goto, and either calls the action() from addon-actions or sends an event over the channel.

If we wanted to get real fancy we'd let users map URLs to stories, and then use that map when intercepting goto and friends, to navigate stories instead. Like:

import * as OtherPageStories from './OtherPage.stories';
import ThisPage from '../pages/xyz';

export default {
  component: ThisPage,
  parameters: {
    goto: {
      ['/some/url/that/usually/displays/other-page']: OtherPageStories.DefaultPage
    }
  }
}

export const DefaultPage = {};

Describe alternatives you've considered

Intercept all navigations, ignores them, and logs them to the Actions panel similar to the NextJS integration

Are you able to assist to bring the feature to reality?

I can advise from the SvelteKit side, but not implement. PRs would be very welcome!

Additional context

No response

@JReinhold
Copy link
Contributor

@benmccann does SvelteKit's handling of <a> tags as described here use goto internally, or do they work differently?
https://kit.svelte.dev/docs/link-options

In other words, if we create mocks for goto would that automatically make <a> tags work too, or do we need something separate to handle that?

@benmccann
Copy link
Contributor Author

goto and clicking on <a> tags both call SvelteKit's internal navigate function:

https://github.com/sveltejs/kit/blob/b3c31a15eb245e58a7adf7187f39e9a21dc592ac/packages/kit/src/runtime/client/client.js#L1475

@eugenepentland
Copy link

I was able to come up with a workaround so I can test my forms that have use:enhance. With the storybook-addon-manual-mocks addon, you can make a wrapper for the enhance function to be able to mock it.

  1. Follow the getting started guide for the addon.
  2. Create a wrapper for your sveltekit function that uses $app/form (or potentially $app/navigate, haven't tested).

$lib/form.js

import { enhance } from "$app/forms";

export default enhance

Use the function as normal inside your svelte component and import the wrapper:

$lib/Component.svelte

<script>
	import enhance from "$lib/form";
</script>

<form use:enhance method="post">
...
</form>

Now create the mocked enhance function. The mocked folder needs to be in the same parent folder as the wrapper.
$lib/__ mocks __/form.js

export default function () {}

Directory:
Wrapper Function: $lib/form.js Mocked Function: $lib/__mocks__/form.js

It's a bit less than ideal needing to have a wrapper for the function, but at least I can run my tests without errors.

@JReinhold
Copy link
Contributor

Oh wow, that's great inspiration for how we could bake this in, in the future.

great job on the addon @gebeto!

@storybookjs storybookjs locked and limited conversation to collaborators Apr 27, 2023
@storybookjs storybookjs unlocked this conversation Apr 27, 2023
@jessielaf
Copy link

Is there any update on this issue? The proposed workaround by @eugenepentland only works when $app/forms is installed in the app itself. If you use a third party library that uses the forms module (for example, sveltekit-superforms) you cannot mock the function.

@HaydenBruin
Copy link

Sveltekit recently did an update which fixes the disable_scroll_handling issue in storybook. I was interested in mocks just so this error would quietly fail, this might help you as well.

sveltejs/kit#9808

@macmillen
Copy link

this feature is needed to use components with superforms because it uses beforeNavigate inside

import { superForm } from "sveltekit-superforms/client";

@DGollings
Copy link

hi, generally like SB but this issue is starting to make it impossible to actually use it for tests. Any goto anywhere breaks the entire test used to break pretty much all of Storybook, these days it only seems to break in CI mode

I've on occasion tried a variety of things over the past few months but can't get anything to ever work. Is there any way to currently test a component which calls or imports goto at any point of the lifetime of the component?

@macmillen
Copy link

If someone encounters this weird error when using superForms:

Uncaught (in promise) TypeError: Invalid value used as weak map key
    at WeakMap.set (<anonymous>)
    at superForm (sveltekit-superforms_client.js?v=49a9ffcb:2100:15)

you have to mock the page store inside your story to fix this:

export const Default: Story = {
  parameters: {
    sveltekit_experimental: {
      stores: {
        page: {},
      },
    },
  },
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants