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

Allow setting HTTP response headers for browser tests #3743

Open
4 tasks done
DallasHoff opened this issue Jul 6, 2023 · 10 comments
Open
4 tasks done

Allow setting HTTP response headers for browser tests #3743

DallasHoff opened this issue Jul 6, 2023 · 10 comments
Labels
feat: browser Issues and PRs related to the browser runner p2-edge-case Bug, but has workaround or limited in scope (priority)

Comments

@DallasHoff
Copy link

DallasHoff commented Jul 6, 2023

Clear and concise description of the problem

Certain browser APIs like SharedArrayBuffer require cross-origin isolation. To enable this, the web page must be served with the below HTTP headers.

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

Vitest does not currently allow browser tests to set HTTP headers, so testing features that require cross-origin isolation is currently not possible.

Suggested solution

To enable this in the Vite development server, I use the following in the Vite config. Perhaps Vitest should read this same configuration to allow developers to modify the browser test's response headers.

plugins: [
  {
    name: 'configure-response-headers',
    configureServer: (server) => {
      server.middlewares.use((_req, res, next) => {
        res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
        res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
        next();
      });
    },
  },
],

Alternative

No response

Additional context

No response

Validations

@sheremet-va
Copy link
Member

Can't you do the same for browser tests? It uses the same config file.

@DallasHoff
Copy link
Author

DallasHoff commented Jul 7, 2023

Can't you do the same for browser tests? It uses the same config file.

As I said, that is the config that I am using, but the headers for browser tests are not affected.

@sheremet-va sheremet-va added bug feat: browser Issues and PRs related to the browser runner labels Jul 7, 2023
@hi-ogawa
Copy link
Contributor

hi-ogawa commented Dec 8, 2023

I think the issue might be due to vitest:browser plugin having enforce:pre, which steals html requests before your middleware:

{
enforce: 'pre',
name: 'vitest:browser',
async config(viteConfig) {
// Enables using ignore hint for coverage providers with @preserve keyword
if (viteConfig.esbuild !== false) {
viteConfig.esbuild ||= {}
viteConfig.esbuild.legalComments = 'inline'
}
},
async configureServer(server) {
server.middlewares.use(
base,
sirv(resolve(distRoot, 'client'), {
single: false,
dev: true,
}),
)
},
},

I think your can counter against this by setting enforce: "pre" on your plugin as well.
I tested locally and it seems to work:

it("repro", () => {
  expect(crossOriginIsolated).toBe(true);
  expect(SharedArrayBuffer).toBeDefined();
})

Side note: There seems to be a plan to run each test file in a separate iframe #3584, so if this landed, crossOriginIsolated related quirks might become more complicated?

@sheremet-va
Copy link
Member

I think the issue might be due to vitest:browser plugin having enforce:pre, which steals html requests before your middleware:

Maybe we can also add our middleware in the "after" hook like this? Will this fix the issue?

configureServer(server) {
  return () => {
    server.middlewares.use(...)
  }
}

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Dec 9, 2023

Maybe we can also add our middleware in the "after" hook like this? Will this fix the issue?

It seems "after" hook middleware doesn't work when vite config has appType: "spa" (which is the case by default).
The reason is that, unless appType: "custom", Vite server sets up htmlFallbackMiddleware to rewrite all unknown requests into req.url = "/index.html", so this will break vitest:browser plugin's sirv middleware, which is meant to serve its own assets (e.g. dist/client/index.html, __vitest__browser__/index....js, etc...).

I don't know about the consequence of forcing appType: "custom", so as an alternative, it might make more sense to remove enforce from vitest:browser plugin instead.

@userquin
Copy link
Member

userquin commented Dec 9, 2023

can you try using viteServer.middlewares.stack.push in your plugin?

@DallasHoff
Copy link
Author

I think your can counter against this by setting enforce: "pre" on your plugin as well.

Side note: There seems to be a plan to run each test file in a separate iframe #3584, so if this landed, crossOriginIsolated related quirks might become more complicated?

Adding enforce: "pre" does fix the issue for me for now.

If the tests are changed to run in separate iframes, there will need to be a way to directly customize the response headers of the frames. Hopefully that is accounted for.

@hi-ogawa hi-ogawa added the p2-edge-case Bug, but has workaround or limited in scope (priority) label Jan 19, 2024
@hi-ogawa
Copy link
Contributor

hi-ogawa commented Jan 19, 2024

As explained in the other issue #4888, Vitest browser mode now respects Vite's server.headers config, so the same thing can be achieved without custom plugin:

import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    headers: {
      "Cross-Origin-Embedder-Policy": "require-corp",
      "Cross-Origin-Opener-Policy": "same-origin"
    },
  },
});

@DallasHoff
Copy link
Author

As explained in the other issue #4888, Vitest browser mode now respects Vite's server.headers config, so the same thing can be achieved without custom plugin

I just tried this out with the latest versions of Vite and Vitest. It works when running the tests, but when running the app in the Vite dev server, the headers are not applied.

@hi-ogawa
Copy link
Contributor

hi-ogawa commented Jan 20, 2024

when running the app in the Vite dev server, the headers are not applied.

Thanks for testing. Hmm... that could be a Vite side bug since server.headers are intended to work especially for setting coop/coep headers at least vitejs/vite#8481 (comment)

This issue vitejs/vite#15641 is reported recently on Vite and it might be possible that you're seeing "304 Not modified" in devtools, but a browser should be aware of last response's header with coop/coep, so I didn't see any issue with 304 response (you may also try "disable cache" on devtools to see if it makes difference). If this also not the case, then it would be great if you can provide a reproduction and submit it as Vite issue.

(Actually Vite's 304 response might be quite annoying since this probably happens also when users are tweaking server.headers but it won't be reflected immediately until you disable cache. I'll dig into this later.)

@sheremet-va sheremet-va removed the bug label Feb 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: browser Issues and PRs related to the browser runner p2-edge-case Bug, but has workaround or limited in scope (priority)
Projects
None yet
4 participants