svelte-add-jest
svelte-add-jest copied to clipboard
Compatibility with import.meta
The primary discussion on Vite: https://github.com/vitejs/vite/issues/1955.
Based on https://github.com/vitejs/vite/issues/1955#issuecomment-862447863, the community seems to have settled around vite-jest
, available on NPM npmjs.com/package/vite-jest.
@rossyman - I'm thinking this might be the move, what do you think?
As an aside- it could be a good idea to submit a PR for a Svelte example if nobody has jumped on that yet.
I'll take a look into this and see what we can do
After looking into this further, vite-jest
is still in it's POC phase, meaning they're still in early development and most likely need to iron out some issues before adoption. Let's keep this issue open to track the progress of vite-jest
and when appropriate, look into it's utilisation.
On the point of creating a svelte example, this is something we can most likely do.
Thoughts? @FractalHQ
After even more investigation, here are a few points I've found:
- We use
svelte-jester
to transform our.svelte
components into Jest readable code. -
svelte-jester
requires^v26
of Jest, whereasvite-jest
requires^v27
, creating a blocking dependency for this task. This issue can be tracked here: https://github.com/mihar-22/svelte-jester/issues/55 - As-of-now,
vite-jest
, only seems to have explicit support for React and Vue, so a POC specifically for svelte seems to be in order, as we don't fully know how they play ball with each other. - We should investigate how
svelte-jester
andvite-jest
interact with each other oncesvelte-jester
is updated to support^v27
of Jest, or look into an alternative tosvelte-jester
as a means to allow developers to use Vite specific features.
Opened a related issue in vite-jest
to query how we could add svelte specific support in co-ordination with our current transformer setup with svelte-jester
:
- https://github.com/sodatea/vite-jest/issues/15
I got import.meta working by using esbuild-jest
"transform": {
"^.+\\.svelte$": "svelte-jester",
"^.+\\.(ts|tsx|js|jsx)$": ["esbuild-jest"]
},
There were a slew of other problems beyond that - such as mocking sveltekit's default context so things like $app/env
and the default stores that are stored in the __svelte__
wouldn't blow up.
Which were solved by mocks like these:
jest.mock('$app/env.js', () => ({
amp: false,
browser: true,
dev: true,
mode: 'test'
}))
jest.mock('$app/navigation.js', () => ({
goto: jest.fn()
}))
jest.mock('svelte', () => {
const { writable } = require('svelte/store')
const actualSvelte = jest.requireActual('svelte')
const fakeGetContext = jest.fn((name) => {
if (name === '__svelte__') {
return fakeSvelteKitContext
}
})
const fakeSvelteKitContext = {
page: writable({
path: '/'
}),
navigating: writable(false)
}
const mockedSvelteKit = {
...actualSvelte,
getContext: fakeGetContext,
}
return mockedSvelteKit
})
Mocking the sveltekit context was a bit tricky, so wanted to share for anyone else who comes down this path.
This is set up and working in this example repo here: https://github.com/CloudNativeEntrepreneur/sveltekit-eventsourced-funnel
Now using babel-jest
and babel-plugin-transform-vite-meta-env
for this and a TestHarness component instead of mocks:
https://github.com/CloudNativeEntrepreneur/sveltekit-eventsourced-funnel/blob/master/.babelrc https://github.com/CloudNativeEntrepreneur/sveltekit-eventsourced-funnel/blob/master/jest.json#L6-L9
babel-plugin-transform-vite-meta-env
works nicely -- This handles all of the vite specific import stuff. With regards to the test component harness, I'd be dubious as to whether including that in the adder (beyond documenting how to achieve a similar result) makes sense.
Raising a PR to implement the Vite specific transformations, beyond this will depend on the outcome of https://github.com/sveltejs/kit/issues/1485
For now, the solution to using sveltekit runtime modules appears to be a mixture of:
- Mocking the individual modules, as outlined in: https://github.com/sveltejs/kit/pull/2353
- Creating a test harness or mocking the default svelte context, as outlined in: https://github.com/rossyman/svelte-add-jest/issues/14#issuecomment-891387235 and https://github.com/sveltejs/kit/issues/1485#issuecomment-902965385
https://github.com/facebook/jest/issues/9430 makes several references to import.meta
. Is it still not available now that we're running with ESM? Or is the issue that the stuff Vite sticks there isn't being populated?
facebook/jest#9430 makes several references to
import.meta
. Is it still not available now that we're running with ESM? Or is the issue that the stuff Vite sticks there isn't being populated?
Tried using import.meta
directly and you're correct, it does appear that Jest v27 with ESM supports import.meta
natively now.
On the point of Vite specific variables not being populated, this is also correct. The only property that I'm observing within import.meta
at the moment is url
, which makes sense.
@benmccann
I believe the latter when in tests - looks like .env
of import.meta
specifically is undefined, and all properties of it - to test it, the repo I've been setting up as a demonstration is public:
I have jest.json as follows:
"transform": {
"^.+\\.svelte$": "svelte-jester",
"^.+\\.(ts|tsx|js|jsx)$": ["babel-jest"]
},
with the babel settings:
{
"plugins": ["babel-plugin-transform-vite-meta-env"]
}
Which works, and from what I understand it replaces import.meta.env.*
with process.env.*
- so I'm using ESM module but with a single babel plugin to deal with the undefined import.meta.env.*
s.
https://www.npmjs.com/package/babel-plugin-transform-vite-meta-env/v/1.0.1
When I remove babel from the equations, by deleting "^.+\\.(ts|tsx|js|jsx)$": ["babel-jest"]
from the jest config I get errors such as:
● Test suite failed to run
TypeError: Cannot read property 'SSR' of undefined
4 | * @type {import('$app/env').browser}
5 | */
> 6 | const browser = !import.meta.env.SSR;
| ^
7 | /**
8 | * @type {import('$app/env').dev}
9 | */
at .svelte-kit/build/runtime/app/env.js:6:34
repro: https://github.com/CloudNativeEntrepreneur/sveltekit-eventsourced-funnel/pull/42
maybe I'm missing something - such as a way to make sure those env vars are set in tests.
For now, the solution to using sveltekit runtime modules appears to be a mixture of:
Mocking the individual modules, as outlined in: [fix] refactor import.meta.env to be in one place for easier mocking sveltejs/kit#2353
I wasn't able to get those mocks to work in the same way with ESM modules (though it did fix the build that broke with sk updates in another project that hasn't been updated to ESM/jest@27/svelte-jester@2 yet - and thus uses this mocking strategy), but to be fair that was like 48 hours ago, or something, before new ESM mocking features landed in jest (https://github.com/facebook/jest/issues/10025#issuecomment-915138095), which I haven't tried yet.
Yeah, from what I can gather, import.meta.env
is populated purely on a contextual basis. Therefore, outside of Vite environments, those properties that svelte expects to exist, do not.
The problem we face is essentially setting up the environment around testing, i.e.: populating the vite specific variables based on some form of configuration when outside of Vite -- and also being able to mock sveltekit runtime modules without having to perform a build and subsequently point Jest to the output directory for module resolution.
Yeah, I think there's a couple ways to do test setup:
- @patrickleet's
TestHarness.svelte
along withbabel-plugin-transform-vite-meta-env
- Or Jest's brand new, experimental, and undocumented
unstable_mockModule
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. I'm glad you guys are paving the way on testing!
Yeah, I think there's a couple ways to do test setup:
- @patrickleet's
TestHarness.svelte
along withbabel-plugin-transform-vite-meta-env
- Or Jest's brand new, experimental, and undocumented
unstable_mockModule
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. I'm glad you guys are paving the way on testing!
I concur 😄 From a testing standpoint, being able to drive import.meta.env
off of process environment variables when outside of a Vite context feels like the most CI-orientated way to handle this (Similar to what is done in babel-plugin-transform-vite-meta-env
).
It'd be nice if Sveltekit had first-class support for testing, similar to vite-jest
, maybe something like sveltekit-jest
, that is capable of handling environment setup, populating import.meta.env
based on env variables and shimming runtime modules. In the same way that Angular has ng test
, maybe something along the lines of svelte-kit test
could be useful in the future.
Testing will definitely go a long way in increasing enterprise support and adoption. Having it as an integrated part of the sveltekit experience would be nice.
I'm just happy to be of some use, I'll keep my eyes peeled for developments in the Jest ESM world in the meantime.
@patrickleet's TestHarness.svelte along with babel-plugin-transform-vite-meta-env
To be clear, the TestHarness
was the result of the clever thinking of @wallw-bits https://github.com/sveltejs/kit/issues/1485#issuecomment-902965385
I had provided some of the example mocks, and plan on trying out the unstable_mockModule
at some point again soon-ish, but the "TestHarness" component actually felt a bit simpler, so I'll probably continue to use that, and I'm sure some mocks will help along the way in more testing situations to come.
A notion of a sveltekit testing adapter could be an interesting prospect, i.e.: a jest or jasmine adapter that is capable of transforming svelte projects into a format that jest or jasmine, respectively, can interpret and setup, all while hiding behind the facade of a command such as svelte-kit test