Lucas Amos
Lucas Amos

Reputation: 1195

TypeError: Select is not a constructor when using Svelte and jest

When writing a Jest test for a Svelte component I am getting a TypeError: Select is not a constructor error when the component imports a library using the es6 import syntax.

TestSelect.js:

<script>
  import Select from 'svelte-select';

  let items = [
    {value: 'chocolate', label: 'Chocolate'},
    {value: 'pizza', label: 'Pizza'},
    {value: 'cake', label: 'Cake'},
    {value: 'chips', label: 'Chips'},
    {value: 'ice-cream', label: 'Ice Cream'},
  ];
  
  let selectedValue = undefined;
</script>

<Select {items} bind:selectedValue></Select>


TestSelect.spec.js:

import '@testing-library/jest-dom/extend-expect';
import { render } from '@testing-library/svelte';

import TestSelect from './TestSelect.svelte';


describe('Component', () => {
  test('Should render', () => {
    const { container } = render(TestSelect, {});
    expect(true);
  });
});



Jest config

 "jest": {
    "collectCoverage": true,
    "testResultsProcessor": "jest-sonar-reporter",
    "coveragePathIgnorePatterns": [
      "/node_modules/"
    ],
    "transform": {
      "^.+\\.js$": "babel-jest",
      "^.+\\.svelte$": "svelte-jester"
    },
    "moduleFileExtensions": [
      "js",
      "svelte"
    ],
    "setupFilesAfterEnv": [
      "@testing-library/jest-dom/extend-expect"
    ],
    "verbose": true
  }

I'm wondering if there is a jest config option that I have missed. Thanks in advance

Upvotes: 4

Views: 4048

Answers (3)

Xiao Wang
Xiao Wang

Reputation: 56

I fixed this issue. I am using Typescript for my svelte APP.

// TestSelect.js:
import Select from 'svelte-select/Select';

Jest config file


  "jest": {
    "resetMocks": false,
    "transform": {
      "^.+\\.svelte$": [
        "svelte-jester",
        {
          "preprocess": true
        }
      ],
      "^.+\\.ts$": "ts-jest",
      "^.+\\.js$": "babel-jest"
    },
    "moduleFileExtensions": [
      "js",
      "ts",
      "svelte"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(svelte-select))"
    ],
    "testPathIgnorePatterns": [
      "cypress"
    ],
    "moduleNameMapper": {
      ".css": "<rootDir>/empty-module.js",
      "intl-tel-input": "<rootDir>/user-intl-module.js"
    }
  }

Upvotes: 1

johannchopin
johannchopin

Reputation: 14873

So the main problem with Jest, is that by default it ignore all files in the node_folder. So when Jest see imported Svelte libraries in your code it doesn't compile them before running the test which cause errors.

An solution would be to tell jest to not ignore the svelte-select library by adding this in the jest config:

  transformIgnorePatterns: [
    'node_modules/(?!(svelte-select)/)' /* ignore node_module but not node_modules/svelte-select/* */
  ],

Another issue with the library itself, is that the default exported element is not a Svelte component but a precompiled simple .js file as you see here. This file is not understand by jest and cause your error:

TypeError: Select is not a constructor

The library export the Svelte component in the Select.js file. This one is valid to be understand by your application and jest.

So to fix your issue, you should import this component using:

import Select from 'svelte-select/Select';

Like that, jest will understand that it imports a .svelte file and should compile it using the svelte-jester transformer.

Ideally you can ask the author of the library to export by default the Svelte component using in package.json:

 "main": "Select.js",

I've created a repo to show you the working configuration: https://github.com/johannchopin/test-svelte-component-in-node_module.

Upvotes: 4

leiropi
leiropi

Reputation: 474

I was able to work around this problem by using rollup to bundle my tests first and then run jest on the bundled output. A similar way is described in this blog post.

Upvotes: 2

Related Questions