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

Compatibility with import.meta #14

Open
braebo opened this issue Jul 25, 2021 · 17 comments
Open

Compatibility with import.meta #14

braebo opened this issue Jul 25, 2021 · 17 comments
Assignees
Labels
enhancement New feature or request question Further information is requested

Comments

@braebo
Copy link
Collaborator

braebo commented Jul 25, 2021

The primary discussion on Vite: vitejs/vite#1955.

Based on vitejs/vite#1955 (comment), 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.

@braebo braebo added the bug Something isn't working label Jul 25, 2021
@rossyman
Copy link
Owner

I'll take a look into this and see what we can do

@rossyman rossyman added enhancement New feature or request question Further information is requested and removed bug Something isn't working labels Jul 28, 2021
@rossyman
Copy link
Owner

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

@rossyman
Copy link
Owner

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, whereas vite-jest requires ^v27, creating a blocking dependency for this task. This issue can be tracked here: Are there plans to support jest ^27? svelteness/svelte-jester#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 and vite-jest interact with each other once svelte-jester is updated to support ^v27 of Jest, or look into an alternative to svelte-jester as a means to allow developers to use Vite specific features.

@rossyman
Copy link
Owner

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:

@patrickleet
Copy link

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

@patrickleet
Copy link

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

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

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.

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

Raising a PR to implement the Vite specific transformations, beyond this will depend on the outcome of sveltejs/kit#1485

For now, the solution to using sveltekit runtime modules appears to be a mixture of:

@rossyman rossyman changed the title compatibility with import.meta Compatibility with import.meta Sep 9, 2021
rossyman added a commit that referenced this issue Sep 9, 2021
@benmccann
Copy link
Contributor

jestjs/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?

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

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.

@patrickleet
Copy link

@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: CloudNativeEntrepreneur/sveltekit-eventsourced-funnel#42

maybe I'm missing something - such as a way to make sure those env vars are set in tests.

@patrickleet
Copy link

patrickleet commented Sep 9, 2021

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 (jestjs/jest#10025 (comment)), which I haven't tried yet.

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

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.

@benmccann
Copy link
Contributor

Yeah, I think there's a couple ways to do test setup:

  • @patrickleet's TestHarness.svelte along with babel-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!

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

Yeah, I think there's a couple ways to do test setup:

  • @patrickleet's TestHarness.svelte along with babel-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
Copy link

@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 sveltejs/kit#1485 (comment)

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.

@rossyman
Copy link
Owner

rossyman commented Sep 9, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants