Due to the way we setup Jasmine tests in our projects, you may run into various errors when Jasmine boots.
Setting jasmineRequire on undefined
Jasmine 4 may fail with an error like this:
Uncaught TypeError: Cannot set properties of undefined (setting 'jasmineRequire')
This is due to issues in Jasmine's environment detection Show archive.org snapshot . It must be fixed by patching the Jasmine sources.
Fix for Webpacker
Add the package string-replace-loader to your package.json. If you're on Webpacker 5 (Webpack 4) the latest version you can use is 2.x.
Now add the following loader to your config/webpack/environment.js:
environment.loaders.prepend('fix-jasmine4-global-detection', {
test: /jasmine-core\/lib\/jasmine-core\/jasmine\.js$/,
use: [{
loader: 'string-replace-loader',
options: {
search: 'window.toString() === \'[object GjsGlobal]\'',
replace: 'window.toString() === \'[object Window]\''
}
}]
})
Fix for ESBuild / jsbundling-rails
Add the package esbuild-plugin-text-replace to your package.json.
Now add the following plugin to your esbuild.config.js:
const textReplace = require('esbuild-plugin-text-replace')
const esbuild = require('esbuild')
esbuild.build({
...
plugins: [
textReplace({
include: /jasmine-core\/lib\/jasmine-core\/jasmine\.js$/,
pattern: [
['let jasmineRequire;', 'let jasmineRequire; const global = window;'], // Make Jasmine available at window.jasmine
['const loadedAsBrowserEsm =', 'const loadedAsBrowserEsm = false &&'], // Disable module detection in Jasmine 6.0
],
}),
],
})
Jasmine 6
Starting with version 6, Jasmine tries to detect if it's running in a module context as this is officially unsupported. It then renders a deprecation warning message:
DEPRECATION: jasmine-core isn't an ES module but it was loaded as one. This is not a supported configuration.
Note: This message will be shown only once. Set the verboseDeprecations config property to true to see every occurrence.
The detection is a flawed when your <script> tag has a type="module" -- which is needed for code splitting in esbuild.
Note how we patch Jasmine's code to assume global = window which makes Jasmine be placed on window.jasmine.
Doing that actually doesn't run Jasmine in a module. But its detection looks at document.currentScript which is unavailable for type="module" script tags.
Because of this (and only when also placing it on window), we also need to switch off its detection with a simple false &&.
Jasmine < 4.3
If you are on Jasmine < 4.3.0, use var instead of let in the code above.
Missing getJasmineRequireObj()
If you get this error:
Uncaught ReferenceError: getJasmineRequireObj is not defined
then you need a manually expose getJasmineRequireObj() to your specs.
Fix for Webpack
Add a file
// app/webpack/spec/support/jasmine_provider.js
import jasmineRequire from 'jasmine-core/lib/jasmine-core/jasmine.js'
export default function getJasmineRequireObj() {
return jasmineRequire;
}
Then expose the provider in your config/webpack/environment.js:
const webpack = require('webpack')
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
getJasmineRequireObj: ['spec/support/jasmine_provider.js', 'default'],
}))
Fix for ESBuild / jsbundling-rails
TODO.