Jasmine: Fixing common errors during initialization

Updated . Posted . Visible to the public.

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.

Profile picture of Henning Koch
Henning Koch
Last edit
Arne Hartherz
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2022-02-23 10:36)