(I couldn't think of a good title for this question, so feel free to edit it if you have a better idea)
My question
When I try to run tests for a specific component, I get this error:
Target container is not a DOM element.
I already found an answer to that in this SO question, but what I want to understand is:
- Why does this happens in Typescript but not in Javascript?
- Is this related to how Typescript imports modules?
My code
For this question purpose, I am removing unnecessary code.
index.tsx
import ReactDOM from 'react-dom'
import App from './app'
// This fooFunction needs to be declared here (project requirements)
export const fooFunction = (): string => 'foo'
ReactDOM.render(
<App />,
document.getElementById("root")
);
My component
import React from 'react'
import { fooFunction } from './index.js'
const MyComponent = () => {
const result = fooFunction()
return {
<p>{result}</p>
}
}
Now, when I write a test to my component, (I think) because my component is importing fooFunction
from index.ts, index.ts is compiled and since "root" does not exist in my test world (jsdom), the line document.getElementById("root")
fails and throws the error above.
However, I tried to reproduce the same thing in my Javascript project and it works fine. Any ideas why this is happening?
Update with additional files
Jest config (in package.json):
"moduleNameMapper": {
"\\.(css|less|scss)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(jpg|jpeg|png|svg)$": "<rootDir>/__mocks__/fileMock.js",
"^@App/(.*)$": "<rootDir>/src/$1",
"^lib/(.*)$": "<rootDir>/common/$1",
"^test/(.*)$": "<rootDir>/src/test/$1",
"^utils/(.*)$": "<rootDir>/src/utils/$1"
},
"transform": {
"^.+\\.(js|jsx|ts|tsx)?$": "babel-jest"
},
babel.config.js:
module.exports = function (api) {
api.cache(true)
const presets = [
'@babel/preset-env',
'@babel/preset-typescript',
'@babel/react',
[
'@babel/preset-react',
{
'runtime': 'automatic'
},
'preset-react-setting'
]]
const plugins = ['@babel/plugin-proposal-class-properties', '@babel/plugin-transform-runtime']
return {
presets,
plugins
}
}
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "src",
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": false,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"noImplicitAny": false,
"jsx": "react-jsx",
"sourceMap": true,
"declaration": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"incremental": true,
"noFallthroughCasesInSwitch": true,
"downlevelIteration": true
},
"include": [
"src/**/*",
"scripts"
],
"exclude": [
"node_modules",
"build",
"**/*.spec.ts"
]
}