3
votes

I have a .ts file I want to test.

frontend/game/index.ts

import App from '@/views/app';
let app = new App({
  el: "#app",
});
export default app;

The file I'd like to import in index.ts is frontend/game/views/app.vue . Webpack-dev-server, eslint, and (I assume) ts-loader are all capable of resolving the module import with the @ alias, as there are no errors in my build or develop steps.

However, when I run jest, I get the following error:

   TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    frontend/game/index.ts:1:17 - error TS2307: Cannot find module '@/views/app'.

    1 import App from '@/views/app';
                      ~~~~~~~~~~~~~

It refers to the first line of my file.spec.js file:

frontend/tests/game/models/file.spec.js

import App from '@/views/app';

I have followed the recommendations of the typescript module resolution documentation, as well as articles specifically about setting up webpack/typescript/jest projects.

Their recommendations generally revolve around setting up the alias in 3 places:

  1. webpack config, under resolve.alias. Mine:

webpack.config.js

module.exports = {
  entry: './frontend/game/index.ts',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'staticfiles')
  },
  resolve: {
    extensions: [ '.ts', '.js', '.vue', '.scss', '.sass'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.resolve(__dirname, 'frontend/game/')
    }
  },
  1. Jest Config, under moduleNameMapper. Mine:

package.json (where my jest config is located)

 "jest": {
    "verbose": true,
    "moduleFileExtensions": [
      "js",
      "json",
      "vue",
      "ts"
    ],
    "moduleDirectories": [
      "node_modules",
      "<rootDir>/frontend/game"
    ],
    "transform": {
      ".*\\.(vue)$": "vue-jest",
      "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.ts$": "<rootDir>/node_modules/ts-jest"
    },
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/frontend/game/$1",
      "\\.(css|less|sass|scss)$": "<rootDir>/frontend/tests/styleMock.js",
      "\\.(gif|ttf|eot|svg)$": "<rootDir>/frontend/tests/fileMock.js"
    },
    "transformIgnorePatterns": [
      "/node_modules/(?!local-echo).+\\.js$"
    ]
  },
  1. Typescript config, leveraging baseUrl combined with paths. Mine:

tsconfig.json

{
  "compilerOptions": {
    "outDir": "./built/",
    "sourceMap": true,
    "strict": false,
    "noImplicitReturns": true,
    "module": "es2015",
    "moduleResolution": "node",
    "target": "es5",
    "esModuleInterop": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["frontend/game/*"]
    }
  },
  "include": [
    "./frontend/**/*"
  ]
}

As far as I can tell, I have followed instructions exactly as indicated. After snooping around on github and stackoverflow, I've failed to discover what I am doing wrong, or whether there is some bug right now. I have experimented with adding .vue extension to the import, trying various combinations of path experiments (i.e. removing "frontend" from the paths object, placing and replacing pre- and post-path slashes, etc), and toggled settings such as esModuleInterop, to no avail.

How can I get Jest to recognize my module aliases?

EDIT: Fascinatingly, adding //@ts-ignore immediately before the import statement, causes this error to "go away," and jest then successfully imports the file.

EDIT2: The tsignore step made me suspicious of jest's ability to import a .vue file at all, so I explored that in this issue on github as well as the typescript recommendations on .vue files. However, I already have a vue-shims.d.ts file identical to their recommendations. Just to experiment, I copied it all over the app, but no matter where I put it, there was no effect.

1

1 Answers

-1
votes

You need to add a jest.config.js with modulesNameMapper configuration matching your Webpack's. Have a look at this easily digestible article: https://alexjover.com/blog/enhance-jest-configuration-with-module-aliases/