tusbar/babel-plugin-dotenv-import

Cannot resolve module @env when running jest

Clumsy-Coder opened this issue · 7 comments

Following the guide from link

Jest can't seem to find the dotenv module.

babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    [
      'dotenv-import',
      {
        moduleName: '@env',
        path: '.env',
      },
    ],
    [
      'module-resolver',
      {
        root: ['.'],
        extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
        alias: {
          'tests/*': './__tests__',
          src: './src',
          '@redux': './src/redux/',
          '@components': './src/components/',
          '@containers': './src/containers/',
          '@routes': './src/routes/',
          '@screens': './src/screens/',
          '@share': './src/share/',
          '@configs': './src/configs/',
        },
      },
    ],
  ],
};

jest config

module.exports = {
  preset: 'react-native',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  verbose: false,
  collectCoverage: false,
  collectCoverageFrom: [
    '**/*.{js,jsx, ts, tsx}',
    './src/**',
    '!**/node_modules/**',
    '!**/android/**',
    '!**/ios/**',
    '!**/.vscode/**',
    '!**/.circleci/**',
    '!metro.config.js',
    '!babel.config.js',
    '!jest.config.js',
    '!./test-results/**',
    '!./src/configs/**',
    '!./src/**/**/tests/**/*.test.ts.snap',
    '!./src/**/**/tests/**/*.test.ts?.snap',
    '!./coverage/**',
  ],
  // coverageDirectory: './test-results/coverage/',
  coverageReporters: ['text', 'text-summary', 'lcov', 'clover', 'json'],
  reporters: [
    'default',
    [
      'jest-html-reporters',
      {
        publicPath: './test-results/',
        filename: 'test-report.html',
        expand: true,
      },
    ],
    [
      'jest-junit',
      {
        outputDirectory: './test-results/junit',
      },
    ],
  ],
  transform: {
    '^.+\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js',
    '\\.(ts|tsx)$': 'ts-jest',
  },
  globals: {
    'ts-jest': {
      tsConfig: 'tsconfig.jest.json',
      babelConfig: 'babel.config.js',
    },
  },
  setupFiles: ['./jest.setup.js', './node_modules/react-native-gesture-handler/jestSetup.js'],
  transformIgnorePatterns: [
    // eslint-disable-next-line max-len
    'node_modules/(?!(jest-)?react-native|@?react-navigation|native-base|native-base-[a-z, -]*|victory-*|react-native-vector-icons)',
  ],
  snapshotSerializers: ['enzyme-to-json/serializer'],
  setupFilesAfterEnv: ['@testing-library/react-native/cleanup-after-each'],
};

tsconfig.json

{
  "compilerOptions": {
    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "ESNext",                       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "lib": ["ES6"],                           /* Specify library files to be included in the compilation. */
    "allowJs": true,                          /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    "jsx": "react",                           /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    "removeComments": true,                   /* Do not emit comments to output. */
    "noEmit": true,                           /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    "isolatedModules": true,                  /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    "moduleResolution": "node",               /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    "baseUrl": ".",                           /* Base directory to resolve non-absolute module names. */
    "paths": {                                /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
      "src": ["src/*"],
      "@redux/*": ["src/redux/*"],
      "@components/*": ["src/components/*"],
      "@containers/*": ["src/containers/*"],
      "@routes/*": ["src/routes/*"],
      "@screens/*": ["src/screens/*"],
      "@share/*": ["src/share/*"],
      "@configs/*": ["src/configs/*"],
      "tests": ["__tests__/*"],
    },
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
    "resolveJsonModule": true                 /* Include modules imported with .json extension. */
  },
  "exclude": [
    "node_modules",
    "test-results/",
  ]
}

tsconfig.jest.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "jsx": "react",
    "module": "commonjs"
  }
}

Also eslint complains the module doesn't exist

Same to me, I did a workaround on the eslint error disabling eslint on that import line, but i couldn't figure out the problem with jest

Would some of these suggestions help? goatandsheep/react-native-dotenv#52

jest.mock("@env", () => {
    return {
        ...
        URL_API: "http://someURL.com"
        ...
    };
});

Code above not working unfortunately :/
Any update on this issue or someone has a temporary fix?

I solved using this:

jest.config.js

   ...
   setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect', './setupJestMock.js'],
   moduleNameMapper: {
    ...,
    "^@env(.*)$": "<rootDir>/.env.test$1"
   },

setupJestMock.js

jest.mock("@env", () => ({
  YOUR_BEATFUL_VAR: "YOUR_BEATFUL_VAR",
}));

babel.config.js

     plugins: [
       ...
       [
          "dotenv-import",
          {
            "moduleName": "@env",
            "path": ".env",
            "blacklist": null,
            "whitelist": null,
            "safe": false,
            "allowUndefined": true
          }
        ],
       ...

And also create the types at types/env.d.ts

declare module '@env' {
  export const YOUR_BEATFUL_VAR: string;
}

This is it :)

@oliveirasWell that makes it resolve but you can't use it in a mock. All the values are undefined.

I hate that this is the solution but it's the only thing that worked 😭😂