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

[BUG] Rollup failed to resolve import "$env/static/public" #18825

Open
vhscom opened this issue Nov 15, 2022 · 6 comments
Open

[BUG] Rollup failed to resolve import "$env/static/public" #18825

vhscom opened this issue Nov 15, 2022 · 6 comments

Comments

@vhscom
Copy link

vhscom commented Nov 15, 2022

This is a continuation of #18465. Maintainer asked to re-open when SvelteKit was stable. SvelteKit is on 1.0 track and is considered stable by its maintainers as noted in the docs Introduction and in the FAQ.

Context:

  • Playwright Version: "@playwright/experimental-ct-svelte": "^1.27.1"
  • Operating System: macOS
  • Node.js version: 18
  • Browser: Chromium
  • Extra:
## System:
 - OS: macOS 12.6
 - Memory: 81.05 MB / 16.00 GB
## Binaries:
 - Node: 18.6.0 - ~/Library/Caches/fnm_multishells/77742_1666972699539/bin/node
 - Yarn: 1.22.19 - /opt/homebrew/bin/yarn
 - npm: 8.13.2 - ~/Library/Caches/fnm_multishells/77742_1666972699539/bin/npm
## Languages:
 - Bash: 5.1.16 - /opt/homebrew/bin/bash

Reduced Test Case
https://github.com/vhscom/playwright-ct-env-reduced-test

Important bits from reduced test case called out below:

tests/component/test.ts

import { test, expect } from '@playwright/experimental-ct-svelte';
import Foo from '$lib/Foo.svelte';

test('should work', async ({ mount }) => {
  const component = await mount(Foo);
  await expect(component).toContainText('Vite + Svelte');
});

src/variable.ts

import { VITE_APP_NAME } from '$env/static/public';

// the old way still works
// const variables = {
//   appName: import.meta.env.VITE_APP_NAME
// };

// the new way does not work
const variables = {
  appName: VITE_APP_NAME
};

export default variables;

Describe the bug

Above fails in supplied reduced test case, which is the Svelte boilerplate generated today with a single Environment variable added by following SvelteKit. Open src/variable.ts to the difference in the failing scenario and a working scenario. Use of functionality is security-related in SvelteKit and, as such, should enjoy first-class support in Playwright.

More background

This is likely related to sveltejs/kit#1485

@benmccann
Copy link
Contributor

Hi, SvelteKit maintainer here. I think the issue is the usage of ctViteConfig here: https://github.com/vhscom/playwright-ct-env-reduced-test/blob/1d674b4b1bd5d3e20e757fc0943414c540863bfe/playwright-ct.config.ts#L7

I wouldn't recommend it be implemented that way because you're going to be missing all of our Vite plugins, will be missing the user's Vite config, will need to redeclare a bunch of stuff (as can be seen in that example where $lib and $environment are being redeclared instead of provided by the SvelteKit plugins), etc. This should probably be handled similarly to how Storybook does it which uses the user's Vite config minus vite-plugin-sveltekit-compile.

@brandonp-ais
Copy link

@benmccann would you mind fleshing out how this could be achieved using the techniques Storybook use?

This thread is still the canonical thread on this problem, and I've still not been able to piece together how to get this working. You commented in this storybook issue about vite config that seems related, but I could not get anything working using hints from there.

Thanks!

@frederikhors
Copy link

Any news on this? I'm blocked too with Cannot find package '$lib' imported from....

@jacob-8
Copy link

jacob-8 commented Sep 12, 2023

From Storybook's implementation, (1 of 2) and (2 of 2), I worked out the following. It successfully runs normal Svelte components, but still throws errors when trying to use an import like $app/stores.

import { defineConfig } from '@playwright/experimental-ct-svelte'
import viteConfig from './vite.config'
import type { UserConfig, PluginOption } from 'vite'

export default defineConfig({
  use: {
    ctViteConfig: removeSvelteKitCompilePlugin(viteConfig),
  },
})

async function removeSvelteKitCompilePlugin(config: UserConfig) {
  const pluginsToRemove = [
    'vite-plugin-sveltekit-compile',
    'vite-plugin-sveltekit-guard', // ensures client-side code can't accidentally import server-side code (useless in this context)
  ]
  const plugins = await withoutVitePlugins(config.plugins || [], pluginsToRemove)
  return { ...config, plugins }
}

async function withoutVitePlugins(
  plugins: PluginOption[],
  namesToRemove: string[],
): Promise<PluginOption[]> {
  const result: PluginOption[] = []
  const resolvedPlugins = await Promise.all(plugins)

  for (const plugin of resolvedPlugins) {
    if (Array.isArray(plugin))
      result.push(await withoutVitePlugins(plugin, namesToRemove))

    if (plugin && 'name' in plugin && !namesToRemove.includes(plugin.name))
      result.push(plugin)
  }
  return result
}

It may have to do with an additional plugin needing awaited as discussed in histoire-dev/histoire#393

But even after modeling my function after Histoire's implementation as seen in https://github.com/histoire-dev/histoire/pull/402/files#diff-b139a32e00b9080e8307447aa2708eefe0cb582d2c22dbd612b778c4490ee9ac and written below I had no luck.

async function withoutVitePlugins2(
  plugins: PluginOption[],
  namesToRemove: string[],
): Promise<PluginOption[]> {
  let flatPlugins: PluginOption[] = []

  for (const pluginOption of plugins) {
    const resolvedPluginOption = await pluginOption

    if (Array.isArray(resolvedPluginOption))
      flatPlugins.push(...await Promise.all(resolvedPluginOption))
    else
      flatPlugins.push(resolvedPluginOption)
  }
  flatPlugins = flatPlugins.filter(Boolean)
  flatPlugins = flatPlugins.filter(plugin => !namesToRemove.includes(plugin?.name))
  return flatPlugins
}

And for reference, the vite-plugin-sveltekit-compile plugin source code

I'm going a little different direction now with my component testing, but perhaps this can be a starting point for others.

@benmccann
Copy link
Contributor

@jacob-8 is your implementation an overall improvement from what's in Playwright now? E.g. does it fix $env and is $app/stores broken either way? If so, it'd be great to see a PR for it. That'd provide a base that others could work off of and maybe I could debug it then.

@flo-at
Copy link

flo-at commented Jan 13, 2024

Same problem here. If I replace the import path with a relative one to avoid the resolve alias altogether, it fails with an unexpected token on a : in a type definition (as in #19970).
It looks like playwright doesn't transpile the typescript in a .svelte file.
It's kind of hard to debug but it seems like whatever is set in ctViteConfig is ignored.

// playwright-ct.config.ts
import { defineConfig } from "@playwright/experimental-ct-svelte";
import { sveltekit } from "@sveltejs/kit/vite";

export default defineConfig({
    use: {
        ctViteConfig: {
            plugins: [sveltekit()], // this does not seem to work (`Unexpected token, expected "}"`) on a `:`)
            resolve: {
              alias: {
                $lib: resolve('src/lib') // this doesn't work either
              }

        },
    },
});

I'm using the Svelte 5 preview and haven't tried the same with a stable release. So maybe that's part of the problem, I don't know.

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

No branches or pull requests

8 participants