Jest catches TypeError ... is not a function
stevenpollack opened this issue · 0 comments
stevenpollack commented
I'm building a Next.JS app with typescript and testing with Jest and testing-library/react
, and I'm noticing that Jest is failing to find getBackendOptions
as a module export. It catches the following error:
TypeError: (0 , _reactdndtreeview.getBackendOptions) is not a function
16 | return (
17 | <div className="app">
> 18 | <DndProvider backend={MultiBackend} options={getBackendOptions()}>
| ^
19 | <Tree
20 | tree={treeData}
21 | rootId={0}
at NavTree (src/views/khub/nav-tree.test.tsx:18:69)
To Reproduce
Using the minimal configuration example from storybook:
// nav-tree.test.tsx
import React, { useState } from 'react';
import { DndProvider } from 'react-dnd';
import {
Tree,
NodeModel,
MultiBackend,
getBackendOptions,
} from '@minoru/react-dnd-treeview';
import SampleData from './sample_data.json';
import { render } from '@testing-library/react';
function NavTree() {
const [treeData, setTreeData] = useState<NodeModel[]>(SampleData);
const handleDrop = (newTree: NodeModel[]) => setTreeData(newTree);
return (
<div className="app">
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
<Tree
tree={treeData}
rootId={0}
render={(node, { depth, isOpen, onToggle }) => (
<div style={{ marginInlineStart: depth * 10 }}>
{node.droppable && (
<span onClick={onToggle}>{isOpen ? '[-]' : '[+]'}</span>
)}
{node.text}
</div>
)}
dragPreviewRender={(monitorProps) => (
<div>{monitorProps.item.text}</div>
)}
onDrop={handleDrop}
/>
</DndProvider>
</div>
);
}
describe('NavTree', () => {
it('should render', () => {
const { getAllByText } = render(<NavTree />);
expect(getAllByText('Folder 1')).toBeInTheDocument();
});
});
I also had to install a couple cjs
packages and modify my Jest config:
// jest.config.mjs
import nextJest from "next/jest.js";
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: "./",
});
// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config = {
// Add more setup options before each test is run
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
testEnvironment: "jest-environment-jsdom",
moduleNameMapper: {
"^.+\\.(svg)$": "<rootDir>/src/mocks/svg.jsx",
"react-markdown":
"<rootDir>/node_modules/react-markdown/react-markdown.min.js",
"react-dnd": "react-dnd-cjs",
"react-dnd-html5-backend": "react-dnd-html5-backend-cjs",
"react-dnd-touch-backend": "react-dnd-touch-backend-cjs",
},
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "!src/**/*.d.ts"],
coverageReporters: ["text", "html", "cobertura"],
coverageThreshold: {
global: {
statements: 77,
branches: 67,
functions: 65,
lines: 77,
},
},
snapshotSerializers: ["@emotion/jest/serializer"],
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config);
Expected behavior
I expect the module exports to be in sync with what I see in dist/index.js
but when I put the following in the test
jest.mock('@minoru/react-dnd-treeview', () => {
const originalModule = jest.requireActual('@minoru/react-dnd-treeview');
console.log('original::', originalModule);
return originalModule;
});
I see:
original:: {
DndContext: <ref *1> {
'$$typeof': Symbol(react.context),
_currentValue: { dragDropManager: undefined },
_currentValue2: { dragDropManager: undefined },
_threadCount: 0,
Provider: { '$$typeof': Symbol(react.provider), _context: [Circular *1] },
Consumer: { '$$typeof': Symbol(react.context), _context: [Circular *1] },
_defaultValue: null,
_globalName: null,
_currentRenderer: null,
_currentRenderer2: null
},
createDndContext: [Function: createDndContext],
DndProvider: {
'$$typeof': Symbol(react.memo),
type: [Function (anonymous)] { displayName: 'DndProvider' },
compare: null
},
DragPreviewImage: {
'$$typeof': Symbol(react.memo),
type: [Function (anonymous)] { displayName: 'DragPreviewImage' },
compare: null
},
useDrag: [Function: useDrag],
useDrop: [Function: useDrop],
useDragLayer: [Function: useDragLayer],
DragSource: [Function: DragSource],
DropTarget: [Function: DropTarget],
DragLayer: [Function: DragLayer]
}
Desktop (please complete the following information):
- OS: macOS Ventura 13.4.1 (M1 Max)
- Browser: N/A
Additional context
Here's my package.json:
{
"name": "accelerate-fe",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "TZ=UTC jest --all --watchAll=false --testResultsProcessor=jest-junit --coverage",
"test-watch": "TZ=UTC jest --watchAll --testResultsProcessor=jest-junit --coverage --colors",
"format": "prettier --check --ignore-path .gitignore .",
"format:fix": "prettier --write . --ignore-path .gitignore",
"lint": "eslint --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore src",
"lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore --fix src",
"eject": "react-scripts eject",
"prepare": "husky install",
"pre-commit": "npm run build && npm test -- -o"
},
"dependencies": {
"@apollo/client": "3.7.14",
"@axe-core/react": "4.4.3",
"@azure/msal-browser": "2.28.1",
"@azure/msal-react": "1.4.5",
"@bphxd/ds-core-react": "3.8.0-beta",
"@emotion/react": "11.10.8",
"@emotion/styled": "11.10.8",
"@hookform/resolvers": "2.9.11",
"@minoru/react-dnd-treeview": "3.4.4",
"@opentelemetry/api": "1.2.0",
"@opentelemetry/auto-instrumentations-web": "0.30.0",
"@opentelemetry/context-zone": "1.7.0",
"@opentelemetry/core": "1.7.0",
"@opentelemetry/exporter-jaeger": "1.7.0",
"@opentelemetry/exporter-trace-otlp-http": "0.33.0",
"@opentelemetry/instrumentation": "0.33.0",
"@opentelemetry/resources": "1.7.0",
"@opentelemetry/sdk-trace-base": "1.7.0",
"@opentelemetry/sdk-trace-web": "1.7.0",
"@opentelemetry/semantic-conventions": "1.7.0",
"@svgr/webpack": "7.0.0",
"@types/luxon": "3.3.0",
"@types/mixpanel-browser": "2.47.0",
"@types/node": "20.1.4",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"@types/react-helmet": "6.1.6",
"@types/react-router-dom": "5.3.3",
"@types/url-join": "4.0.1",
"@types/uuid": "9.0.1",
"@typescript-eslint/eslint-plugin": "5.59.6",
"@typescript-eslint/parser": "5.59.6",
"apollo-upload-client": "17.0.0",
"buffer": "6.0.3",
"crypto-js": "4.1.1",
"dotenv": "10.0.0",
"eslint": "8.39.0",
"eslint-config-next": "13.4.2",
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-prettier": "3.4.1",
"graphql": "16.6.0",
"history": "4.10.1",
"jest": "29.5.0",
"jest-environment-jsdom": "29.5.0",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"luxon": "3.3.0",
"mixpanel-browser": "2.47.0",
"msw": "0.35.0",
"next": "13.4.2",
"prettier": "2.8.8",
"react": "18.2.0",
"react-burger-menu": "3.0.8",
"react-content-loader": "6.2.1",
"react-dnd": "16.0.1",
"react-dnd-html5-backend": "16.0.1",
"react-dnd-touch-backend": "16.0.1",
"react-dom": "18.2.0",
"react-error-boundary": "3.1.4",
"react-feather": "2.0.10",
"react-helmet": "6.1.0",
"react-hook-form": "7.43.9",
"react-icons": "4.8.0",
"react-markdown": "8.0.7",
"react-markdown-editor-lite": "1.3.4",
"react-query": "3.39.3",
"react-router-dom": "5.3.4",
"react-select": "5.7.3",
"react-syntax-highlighter": "15.5.0",
"react-table": "7.8.0",
"reactstrap": "9.1.4",
"rehype-raw": "6.1.1",
"rehype-sanitize": "5.0.1",
"remark-gfm": "3.0.1",
"sass": "1.62.1",
"sharp": "0.32.1",
"socket.io-client": "4.6.1",
"tsc-files": "1.1.3",
"typescript": "5.0.4",
"url-join": "4.0.1",
"utf8": "3.0.0",
"uuid": "9.0.0",
"whatwg-fetch": "3.6.2",
"yup": "0.32.11"
},
"devDependencies": {
"@emotion/jest": "11.10.8",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "14.0.0",
"@testing-library/user-event": "14.4.3",
"husky": "7.0.4",
"jest-junit": "16.0.0",
"lint-staged": "13.0.3",
"mocha-junit-reporter": "2.2.0",
"npmlog": "6.0.1",
"react-dnd-cjs": "9.5.1",
"react-dnd-html5-backend-cjs": "9.5.1",
"react-dnd-test-utils": "16.0.1",
"react-dnd-touch-backend-cjs": "9.5.1",
"react-select-event": "5.5.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"volta": {
"node": "20.0.0",
"npm": "9.6.4"
}
}