Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit testing a component with Jest that imports a @smui component results in SyntaxError #120

Closed
snowman-repos opened this issue Apr 2, 2020 · 1 comment

Comments

@snowman-repos
Copy link

snowman-repos commented Apr 2, 2020

I'm trying to unit test my Svelte components using Jest. When those components import @smui components, running Jest throws an error:

SyntaxError: Cannot use import statement outside a module

Importing other node modules or other Svelte components runs fine. Running node v13.12.0. Have node-sass installed in node_modules.

The error seems to be caused by the first line import './_index.scss'; in node_modules/@smui/button/index.js.

Any ideas?

rollup.config.js

import resolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import commonjs from '@rollup/plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import postcss from 'rollup-plugin-postcss';
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup.js';
import pkg from './package.json';

const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;

const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning);
const postcssOptions = () => ({
  extensions: ['.scss', '.sass'],
  extract: false,
  minimize: true,
  use: [
    ['sass', {
      includePaths: [
        './src/theme',
        './node_modules',
      ]
    }]
  ]
});

export default {
	client: {
		input: config.client.input(),
		output: config.client.output(),
		plugins: [
			replace({
				'process.browser': true,
				'process.env.NODE_ENV': JSON.stringify(mode)
			}),
			svelte({
				dev,
				hydratable: true,
				emitCss: true
			}),
			resolve({
				browser: true,
				dedupe: ['svelte']
			}),
			commonjs(),

      postcss(postcssOptions()),

			legacy && babel({
				extensions: ['.js', '.mjs', '.html', '.svelte'],
				runtimeHelpers: true,
				exclude: ['node_modules/@babel/**'],
				presets: [
					['@babel/preset-env', {
						targets: '> 0.25%, not dead'
					}]
				],
				plugins: [
					'@babel/plugin-syntax-dynamic-import',
					['@babel/plugin-transform-runtime', {
						useESModules: true
					}]
				]
			}),

			!dev && terser({
				module: true
			})
		],

		onwarn,
	},

	server: {
		input: config.server.input(),
		output: config.server.output(),
		plugins: [
			replace({
				'process.browser': false,
				'process.env.NODE_ENV': JSON.stringify(mode)
			}),
			svelte({
				generate: 'ssr',
				dev
			}),
			resolve({
				dedupe: ['svelte']
			}),
			commonjs(),

      postcss(postcssOptions())
		],
		external: Object.keys(pkg.dependencies).concat(
			require('module').builtinModules || Object.keys(process.binding('natives'))
		),

		onwarn,
	},

	serviceworker: {
		input: config.serviceworker.input(),
		output: config.serviceworker.output(),
		plugins: [
			resolve(),
			replace({
				'process.browser': true,
				'process.env.NODE_ENV': JSON.stringify(mode)
			}),
			commonjs(),
			!dev && terser()
		],

		onwarn,
	}
};

jest.config.js

module.exports = {
  transform: {
    "^.+\\.svelte$": "jest-transform-svelte",
    "^.+\\.js$": "babel-jest",
  },
  moduleFileExtensions: ["js", "svelte"],
  testPathIgnorePatterns: ["node_modules"],
  bail: false,
  verbose: true,
  transformIgnorePatterns: ["node_modules"],
  setupFilesAfterEnv: ["@testing-library/jest-dom/extend-expect"],
};

babel.config.js

module.exports = {
  presets: [
    [
      "@babel/preset-env",
      {
        targets: {
          node: "current",
        },
      },
    ],
  ],
};

./src/components/Button.svelte (component to be tested)

<script>
  import Button from "@smui/button";
  export let text;
</script>

<button>{text}</button>

./tests/button.spec.js

import { render, cleanup } from "@testing-library/svelte";
import Button from "../src/components/Button.svelte";

describe("button component", () => {
  afterEach(() => {
    cleanup();
  }); // Default on import: runs it after each test.

  test("should render component correctly", () => {
    const test = "testing";

    const { container } = render(Button, {
      props: {
        text: test,
      },
    });

    expect(container).toContainHTML(`<button>${test}</button>`);
  });
});

Error when running jest tests

 ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import './_index.scss';
                                                                                             ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      1 | <script type="module">
    > 2 |   import Button from "@smui/button";
        |                ^
      3 |   export let text;
      4 | </script>
      5 | 

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1085:14)
      at Object.<anonymous> (src/components/Button.svelte:2:16)

Repo: https://github.com/darryl-snow/sapper-test

@snowman-repos
Copy link
Author

In case anyone else faces the same issue, adding this to jest.config.js fixed it!

"moduleNameMapper": {
  "^.+\\.(css|less|scss)$": "babel-jest"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant