How do I get Jest to recognise JQuery in my Rails project?

35
October 22, 2019, at 5:10 PM

I'm working on an originally-Rails-4-now-upgraded-to-5.1.6.2 app.

We originally relied on Sprockets for our JS, but have now mostly migrated to Webpacker, and for which I want to start introducing Jest tests.

We still have a residual Sprockets presence in application.js:

//= require jquery
//= require jquery_ujs
//= require select2
//= require icheck.min
//= require jquery.Jcrop.min

And in our Gemfile we require gem "jquery-rails", "~> 4.3.3"

Having recently started integrating some Vue components to the project, I want to eventually be able to test Vue components, but since I don't feel like I understand them as well as I'd like, I started out trying to test the following 'simple' bit of JQuery dom manipulation:

// PledgeFormUpdates.js
export default function() {
  window.addEventListener("load", function() {
    if ( $('#pledge-form').length == 0 ) {
      return;
    }
    // Determine whether to show GDPR checkbox on country change
    $("#pledge_pledgor_home_country").change(function() {
      let gdpr_form_group = $("#js-gdpr-input");
      let checkbox = $('#pledge_receive_comms')
      const eu_countries = [
        "Austria",
        "Belgium",
        "Bulgaria",
        "Croatia",
        "Cyprus",
        "Czech Republic",
        "Denmark",
        "Estonia",
        "Finland",
        "France",
        "Germany",
        "Greece",
        "Hungary",
        "Ireland",
        "Italy",
        "Latvia",
        "Lithuania",
        "Luxembourg",
        "Malta",
        "Netherlands",
        "Poland",
        "Portugal",
        "Romania",
        "Slovakia",
        "Slovenia",
        "Spain",
        "Sweden",
        "United Kingdom of Great Britain and Northern Ireland"
      ]
      if ( eu_countries.includes(this.value) ) {
        checkbox.prop('disabled', false);
        gdpr_form_group.show();
      } else {
        checkbox.prop('disabled', true);
        gdpr_form_group.hide();
      };
    });
  });
}

The test file currently has this content:

'use strict';
import pledge_form_updates from '../../app/javascript/components/PledgeFormUpdates.js'
test('Displays GDPR checkbox on EU country selection', () => {
  // Set up our document body
  document.body.innerHTML =
    '<select id="pledge_pledgor_home_country">' +
    '  <option value="Brazil" selected>Brazil</option>'
    '  <option value="Germany">Germany</option>' +
    '  <button id="button" />' +
    '</select>';
});

Our package.json includes the following config:

{
  // ...
  "devDependencies": {
    "jest": "^24.9.0",
    "webpack-dev-server": "^3.4.1",
    "jquery": "^3.4.1"
  },
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "roots": [
      "spec/javascript"
    ],
    "setupFiles": ["./spec/javascript/setup-jest.js"]
  }
}

And lastly in the setup-jest.js file, we just attempt to import JQuery, based on suggestions I saw in posts like this:

import $ from 'jquery/src/jquery';
// Other failed attempts:
// import $ from 'jquery';
// import $ from 'jquery/jquery';
global.$ = global.jQuery = $;

But all variations of this fail with some variation of the error Cannot find module 'jquery/jquery' from 'setup-jest.js'

So how can I successfully import JQuery for use in this kind of test?

ETA: Based on the comment below, in case relevant here's also the (now-amended) contents of the environment.js file:

const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.plugins.append('Provide', new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }))
module.exports = environment
Answer 1

Ok, the answer was Cannon Moyer's comment plus one step:

From the terminal, I needed to run yarn add jquery

Then in environment.js, I needed to add his code:

environment.plugins.append('Provide', new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })) 

... and in setup-jest.js, to change import $ from 'jquery/src/jquery'; to import $ from 'jquery';

READ ALSO
Displaying image loading process as % on page load

Displaying image loading process as % on page load

I am trying to make loading screenSo i use jQuery for that

36
Check if URL has changed in javascript (cannot use hashChanged)

Check if URL has changed in javascript (cannot use hashChanged)

I've looked through a lot of questions and I can't find a solution that works well within my environmentThis is done within Shopify, I have a product with variants

25
jQuery hide Show More button when text is limited

jQuery hide Show More button when text is limited

I am trying to use a Show More/Show Less button for texts to expand and contract the long texts/paragraphsThe code seems to work fine in all aspect

49
Click event fired twice on touch device

Click event fired twice on touch device

I have a checkbox in a sortable div where the click or changed event is triggered twice on touch devices but not on desktop (nor simulating touch on Firefox dev tools) for some obscure reasonThe unwanted effect is the checkbox being toggled twice in a row leaving...

28