modernweb-dev / web

Guides, tools and libraries for modern web development.
https://modern-web.dev
MIT License
2.22k stars 288 forks source link

[test-runner] Content-Type header always application/javascript via test-framework virtual path #1523

Open rhashimoto opened 3 years ago

rhashimoto commented 3 years ago

Summary

It looks like files served via the virtual path /__web-test-runner__/test-framework always have the response header Content-Type: application/javascript; charset=utf-8, which frustrates fetching resources of a different type.

Background

I'm trying to write my own test framework that uses Jasmine. I want my framework script to load Jasmine standalone assets from a location relative to the framework script, so I'm doing that via import.meta.url. Because the framework script is loaded with a special virtual path, so are the Jasmine assets. The problem is that all these assets are assigned a Content-Type of application/javascript but not all of them are scripts.

Test Case

To reproduce the issue:

Expected

The custom framework dynamically adds HTML elements to the document, two link elements and two script elements at the bottom of the document head.

The Network tab should show the four files successfully loaded by the framework:

Actual

The PNG file doesn't load at all, with the server returning a 500 status, but if you look at the server response headers it contains Content-Type: application/javascript; charset=utf-8, which isn't correct either for an image or an error message.

The CSS file is returned but it also has the wrong Content-Type, which apparently prevents it from being used in Chrome and Firefox (Safari doesn't seem to care).

Screen Shot 2021-06-14 at 1 51 54 PM

Other Notes

If I change the framework code not to use import.meta.url like this:

--- a/custom-framework.js
+++ b/custom-framework.js
@@ -4,7 +4,7 @@ import {
   sessionFailed,
 } from '@web/test-runner-core/browser/session.js';

-const STANDALONE_PATH = new URL('./jasmine-standalone/lib/jasmine-3.7.1', import.meta.url).href;
+const STANDALONE_PATH = './jasmine-standalone/lib/jasmine-3.7.1';

This works so both the PNG and CSS are loaded properly without the virtual path, but this makes it harder to put the custom framework in its own module to share across projects.

rhashimoto commented 3 years ago

If you have your framework file that uses import.meta.url in a separate module, then there is a simple workaround. Just import the module in a local framework file, e.g.:

// This is the framework file referenced by testFramework.path in the config file.
// In this file import the actual framework:
import 'my-framework-module/framework.js';

The file above will be loaded using the virtual path that looks like http://localhost:8002/__web-test-runner__/test-framework/home/dev/wtr-test/framework.js but the module it imports will be loaded with a real path and assets loaded relative to import.meta.url in the imported file will have the proper Content-Type.

Originally I was wanting to set the path in the config file directly to the module file by doing something like this (this won't work because of Content-Type issues):

// This is web-test-runner.config.cjs
module.exports = {
  files: [...],
  nodeResolve: true,
  testFramework: { path: require.resolve('my-framework-module/framework.js') }
}

(edit: I think the above might need a path.relative() call if it could be used but it gets the idea across)

LarsDenBakker commented 3 years ago

This is a bug indeed, we need look into fixing this.

Out of curiousity, why do you want to use jasmine over mocha?

rhashimoto commented 3 years ago

I was able to get the workaround above to live inside the framework module, so while the issue does seem like something that should be fixed the impact on my use case is now small. Here's my web-test-runner-jasmine framework.

I want to use Jasmine not because I necessarily prefer it to Mocha; it's that I prefer it to Chai. Chai.just.seems.a.lot.wordier.in.comparison.which.is.minor.but.is.not.my.preference. 😀 The less subjective reason is that I also have existing karma-jasmine tests I want to migrate to @web/test-runner.

Thanks for this project, it's essential for buildless web development!