Botframework-webchat causing Jest tests to fail in Create React App
I have a question
Hello,
TL;DR How do I write a Jest test for a component that contains ReactWebChat?
I am trying to write a test file for my website and the ReactWebChat component consistently causes the test to fail with the same error message every time, always indicating that the issue lies somewhere in the botframework-webchat package.
My real implementation has a lot more going on in it - auth flows, handling data, styles, etc - so I stripped all of that away to the essence of the problem detailed in the steps below. I receive the same failure message regardless of if I use a real directLine with a real token or if I use the directLine with a fake token, like below.
I am using Create-React-App (CRA) and its subsequent dependencies (i.e. Jest) in addition with botframework-webchat. That's it.
Steps to recreate:
npx create-react-app webchat-test
cd webchat-test
npm install botframework-webchat
code package.json
Observe the addition of "type": "module", - everything else is OOTB from CRA and installing the botframework-webchat pkg
{
"name": "webchat-test",
"version": "0.1.0",
"private": true,
"type": "module",
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"botframework-webchat": "^4.18.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Save
cd src
code index.js
Observe the adjustment on the import App statement, now including the file extension .js - everything else is CRA OOTB
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.js";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Save
code App.js
Observe the removal of most OOTB pieces here, substituted with the WebChat component we will be making shortly
// App.js
import WebChat from "./WebChat/WebChat.jsx";
const App = () => (
<div className="App">
<WebChat />
</div>
);
export default App;
Save
mkdir WebChat
cd WebChat
touch WebChat.jsx
code WebChat.jsx
// WebChat.jsx
import React from "react";
import ReactWebChat, { createDirectLine } from "botframework-webchat";
const WebChat = () => {
const dl = createDirectLine({ token: "TOKEN" });
return <ReactWebChat directLine={dl} />;
};
export default WebChat;
Save
mkdir __test__
cd __test__
touch WebChat.test.jsx
// WebChat.test.jsx
import { render } from "@testing-library/react";
import WebChat from "../WebChat";
describe("WebChat component", () => {
it("should render", () => render(<WebChat />));
});
Save
At this point, feel free to remove the css files, the App.test.js file, and any other unused files
npm run build
npm run test
Observe the test fails:
FAIL src/WebChat/__test__/WebChat.test.jsx
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/Users/donnese/Codebase/webchat-test/node_modules/botframework-webchat-core/node_modules/mime/dist/src/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import otherTypes from '../types/other.js';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (node_modules/botframework-webchat-core/lib/sagas/core:/src/sagas/sendFilesToPostActivitySaga.js:2:1)
at Object.<anonymous> (node_modules/botframework-webchat-core/lib/core:/src/createSagas.ts:14:1)
at Object.<anonymous> (node_modules/botframework-webchat-core/lib/core:/src/createStore.ts:6:1)
at Object.<anonymous> (node_modules/botframework-webchat-core/lib/core:/src/index.ts:28:1)
at Object.<anonymous> (node_modules/botframework-webchat-api/lib/decorator/private/component:/src/decorator/private/templateMiddleware.ts:1:1)
at Object.<anonymous> (node_modules/botframework-webchat-api/lib/decorator/private/component:/src/decorator/private/ActivityBorderDecoratorMiddleware.ts:4:1)
at Object.<anonymous> (node_modules/botframework-webchat-api/lib/decorator/private/component:/src/decorator/private/createDecoratorComposer.tsx:2:1)
at Object.<anonymous> (node_modules/botframework-webchat-api/lib/decorator/private/component:/src/decorator/private/DecoratorComposer.tsx:2:1)
at Object.<anonymous> (node_modules/botframework-webchat-api/lib/decorator/component:/src/decorator/index.ts:1:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 0.31 s
Ran all test suites.
I'm at a loss of what I should do next, I have been entirely unsuccessful in overcoming this error message. I have tried ejecting CRA, I have tried the suggestions as they are explained in the error message, I have tried without including "type": "module" in the package.json file, I have tried using Typescript and using different jest presets like ts-jest, I have tried to include the file causing the issue /node_modules/mime/dist/src/index.js as part of the transformignorepatterns in jest, several other small tweaks and attempts have been made over the past few days and I cannot get this error message to budge.
Does anyone know what I am doing wrong?
Thank you, Sean
Anyone experiencing something similar? Does anyone need any more information to replicate this error?