-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Shim SvelteKit runtime import aliases / Importing $app/*
fails
#1485
Comments
This sounds loosely related to allowing SvelteKit to build components as suggested in #518 |
Yep that would solve the second use case (distributing components/actions that rely on sveltekit), but I don’t think it would address the first? Testing etc components of a sveltekit app outside the main sveltekit dev/build runtime? Storybook being a very common use case |
TBH I am hitting this issue trying to just do basic testing with |
Are we able to use something like https://github.com/eirslett/storybook-builder-vite to help with this - or is this a problem outside of Vite? |
@madeleineostoja for Storybook, in the .storybook/main.js/cjs, can you try using const path = require('path');
const sveltePreprocess = require('svelte-preprocess');
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx|svelte)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-svelte-csf'],
svelteOptions: {
preprocess: [
sveltePreprocess({
replace: [['~', path.resolve('./src')]],
}),
],
},
}; |
Ah, I see the challenge - the modules like |
Yeah this isn't to do with your own custom aliases, but the runtime modules of sveltekit. There needs to be a way to consume or shim them in non-sveltekit contexts like testing. Updated issue title to be clearer on the issue |
I'd like to voice my support for a feature that would allow libraries to neatly get access to the As the creator and maintainer of SvelteKitAuth we're trying to provide a way for users to augment the SvelteKit session with authentication data using the signIn().then(goto); Letting libraries handle these things internally means less boilerplate for our users, so getting access to the SvelteKit router in a global module, instead of a scoped one would be useful. This is how other frameworks and libraries such as the Vue Router and React Router handle this, as they make use of the global React instance SvelteKit might have to work around the fact that Svelte doesn't provide such a thing, but create its own global context or a singleton. |
I've fixed this in storybook by using their new vite-builder and adding manual aliases to sveltekit's async viteFinal(config) {
config.resolve.alias = {
$app: path.resolve('./.svelte-kit/dev/runtime/app')
}
return config;
} With the caveat being that you have to have run |
Here's an example of someone having to mock this stuff out for testing: rossyman/svelte-add-jest#14 (comment) |
Author of comment of the said person who had to mock this stuff. I don't mind mocking - fine as a workaround for unit testing anyway. It wasn't exactly simple to figure out the correct mocks though. |
It looks like |
Here's the test mock we've been using to handle <script>
import {setContext} from 'svelte';
import {writable} from 'svelte/store';
export let Component;
export let stores = {
page: writable('/'),
navigating: writable(null),
session: writable(null),
};
setContext('__svelte__', stores);
</script>
<svelte:component this={Component} {...$$restProps} /> So you just pass it the actual component to be tested and (optionally) the stores you want to use for EDIT: Added spreading of other props onto the component to be tested. |
I think there's a couple ways to do test setup thus far:
I'm not sure what the tradeoffs are and which is the better approach. Also, if there's anything SvelteKit can do to make testing easier I'd be happy to support changes there. Related, there's a request to mock |
As the one who made that request to mock
So without the ability to mock |
In at least pre-esm jest@26 and svelte-jester@1, you can mock Theoretically this should now also be possible in ESM jest@27 and svelte-jester@2, via the new
In my tests directory, I find it simplest to have two test files Here's an image of a coverage report showing lines of the load function being hit: Maybe I'm missing something about mocking fetch, but you should be able to just mock fetch in the same way. In the same code this is pulled from, my load function is loading graphql over HTTP, however I am using a graphql library for that, not fetch directly, and thus, just mock the graphql library to return the responses I would get in good, bad, and other important cases. Similarly, if you were using axios instead of fetch, you could mock the response of the .get or whatever. You don't want to rely on networks in unit tests as that is outside of the scope of the unit. Things like that are best left for integration tests. |
Other sveltekit mocking tips:
|
@patrickleet wrote:
What's the setup you're using for those tests? I've looked at https://github.com/CloudNativeEntrepreneur/sveltekit-eventsourced-funnel, but there you're using |
This is from a different repo for a client, so it's private, unfortunately - it's still on jest@26 / svelte-jester@1, and the "funnel" example was more of an example of event sourcing with svelte than a unit test demonstration - just happened to be public and relevant to some of the recent testing changes. That said - let me see about pulling out relevant pieces... Ok - looked ... Looks like I just exported/imported
|
If you don't mind using experimental features of the latest Node.js, along with esmodules/ Rough beginner example link follows. One could mock the module into a no-op, or rewrite it to I've built a loader for This allows me to simply test my
These loader hooks do not chain well yet, so it's far from a perfect solution, in general. EDIT: Big update in my next comment below! |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
The introduction of |
per sveltejs/kit#1485, packaged components cannot reference SvelteKit runtime import aliases.
Most aliases are now supported out-of-the-box with the latest Storybook 7. You can see a summary of what is supported and not supported here: https://github.com/storybookjs/storybook/tree/next/code/frameworks/sveltekit There are a few that are not yet supported and make more sense to support as mocks. I've created a new issue to track that: storybookjs/storybook#20999. PRs for it would be very welcome! |
So good! I originally opened this for the storybook use-case, and that seems like it's met now (or could be closed out in favour of the new issue you opened). I guess the only thing left for this issue is shimming them in other context, like test suites etc. |
Hey all! I have been searching for the correct issue, but all other issues about importing Currently, I am getting the error Does anybody know how to enable |
Now that we're post v1.0 do we have a better testing story for sveltekit modules? Looks like the It's kinda crazy that component unit testing doesn't work OOTB yet with a v1 framework |
@benjaminpreiss and anyone using ssr: {
noExternal: ['your_package_name'],
} |
Any update on this? I really would love to be able to use Playwright component testing with Sveltekit, but this issue is sadly preventing it and keeping us from being able to adopt Svelte(Kit) on a larger scale... |
I would also like to use Playwright component testing with SvelteKit. Does anyone know if there is a work-around that works for the case of using Playwright component testing? |
For anyone else that gets the error
I believe that is related to this issue. I had a minimal repro set up for a new issue before realizing it's probably the same as this issue. Run
to reproduce. On commit |
We found some solution to work around not being able to mock those modules. In case it can help someone in the same situation, and in order to gather some feedback about what we found, I write below the whole story: our context and our solution. Some contextJust to explain how this “shimming” this is crucial to us, and how we really tried to avoid is… in vain :-( For our project, we are using TDD, SvelteKit and Superforms. So, be able to test is crucial for us. That being said, we ran into this “mocking” problem before with We spent a lot of time on the Internet, browsing issues, testing solutions. But as there seem to be no way to correctly shim the
Our workaround solutionAs no solution was valid, we tried to change a bit our way of doing things. Currently, we do component testing with Playwright experimental component testing feature. But in the end, component testing is just end-to-end testing with a specific page containing only one component. This seems to be indeed how SvelteKit seems to be tested: small “apps” exposing only a specific feature to be tested. So we implemented this:
Reading test results in the Playwright testTo be able to make this work, we also had to find a way to retrieve some result value from the tested component. For example, how to test that a button component correctly calls a callback when it is submitted? In e2e testing, this can be tricky because we only browse as a user do, we do not have access to the code. For this purpose, we created a utility component and method to help displaying and retrieving data: // test-result.svelte
<script lang="ts">
export let id = 'test-result'
export let value: unknown
</script>
<span data-testid={id} class="hidden">{JSON.stringify(value)}</span>
// test-result.util.ts
import type { Page } from 'playwright-core'
export const getTestResult = async <T>(page: Page, id: string = 'test-result'): Promise<T> => {
const resultText = await page.getByTestId(id).innerText()
return JSON.parse(resultText) as T
} We then use it like this: // src/routes/tests/lib/components/form-input/_has-initial-value/+page.svelte
<script lang="ts">
import FormInput from '$lib/components/form-input/form-input.svelte'
import TestResult from '$routes/tests/test-result.svelte'
import { generateRandomUsername } from '$tests/unit/utils/string-generator.util'
const initialUsername = generateRandomUsername()
</script>
<FormInput value={initialUsername} />
<TestResult value={initialUsername} />
// $lib/components/form-input/form-input.spec.ts
test('has the passed value by default', async ({ page, pom: { username } }) => {
await expect(username).toHaveValue(await getTestResult(page))
}) What’s coolWe are just begining to use this, so maybe I’ll come back in a few days/weeks and tell it’s totally lame to do that 😅 But what we see in this solution are the following perks:
What’s not so greatThere are some downsides to this technique:
What I would love from SvelteKitI hope this will help someone, but I would love to have some things from SK out-of-the-box:
Please feel free to tell me what you think about this solution, and if I missed something. We will continue on this path and I will come back here and edit if we found something interesting, especially if everything turned out to be garbage in the end 😅 (but I hope not 😉) |
Hi! As promised, here's some feedback after using this technique for 2 weeks. It's working rather well regarding the initial problem of not having a way to mock
@benmccann I know you're all very busy and that there's a lot of work to be done on this framework that we all love. Nevertheless, in the absence of any feedback from the team on this subject, I can't help but wonder how this work is being prioritized. In any case, that's the conclusion we've reached. Today, we'd like to have some feedback on the implementation of a solution to this problem, as well as a possible delivery target. I'm well aware that the notion of a deadline on such a project is a very complicated one, but we need to know whether we can expect to wait a few weeks, or whether we're talking months or years, in which case we'll have to turn to another framework. I'm not sure I'll be able to help more directly by contributing code, but if possible please feel free to give some general lines on what needs to be done, in case I or someone passing by can lend a hand on the subject 😉 Thanks again for your work, really, and I hope this topic can move forward! 🙏 |
Storybook now has built-in mocks for SvelteKit: storybookjs/storybook#24795 |
Hi! I also received the notification for this, but it does not help for using Playwright Component Testing 😩 |
Describe the bug
As far as I can tell there's no way to use sveltekit runtime imports (eg:
$app/navigation
) outside of sveltekit dev/build. Which makes testing virtually impossible. If there is a way to shim these imports outside of the main sveltekit context I haven't found it, so perhaps documentation is needed.My particular use-case is with Storybook, where UI components that rely on any sveltekit modules break the whole setup. I tried aliasing them with webpack (pointing to
.svelte-kit/dev/...
) but that didn't work either.Another use-case is publishing components for sveltekit that would need to rely on those imports.
To Reproduce
$app/env
)cannot resolve module $app/env
)Severity
Not blocking, but makes building a component library with Storybook or other development/testing frameworks impossible. So, severe annoyance?
The text was updated successfully, but these errors were encountered: