●测试套件无法运行
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• 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/en/configuration.html
Details:
SyntaxError: C:\Projects\myProject\src\__tests__\Event.test.js: Unexpected token (354:4)
352 |
353 | it('renders without errors', (done) => {
> 354 | const { getByTestId } = render(
| ^
355 | <Router history={history}>
356 | <Home />
357 | </Router>
at Object._raise (node_modules/@babel/parser/src/parser/location.js:241:45)
at Object.raiseWithData (node_modules/@babel/parser/src/parser/location.js:236:17)
at Object.raise (node_modules/@babel/parser/src/parser/location.js:220:17)
at Object.unexpected (node_modules/@babel/parser/src/parser/util.js:149:16)
at Object.parseExprAtom (node_modules/@babel/parser/src/parser/expression.js:1144:20)
at Object.parseExprAtom (node_modules/@babel/parser/src/plugins/jsx/index.js:532:22)
at Object.parseExprSubscripts (node_modules/@babel/parser/src/parser/expression.js:539:23)
at Object.parseMaybeUnary (node_modules/@babel/parser/src/parser/expression.js:519:21)
at Object.parseExprOps (node_modules/@babel/parser/src/parser/expression.js:311:23)
at Object.parseMaybeConditional (node_modules/@babel/parser/src/parser/expression.js:263:23)
这是我的配置文件: package.json
{
"name": "ant4",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^4.2.0",
"aws-amplify": "^2.3.0",
"axios": "^0.19.2",
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/register": "^7.0.0",
"lodash": "^4.17.15",
"moment": "^2.25.3",
"moment-timezone": "^0.5.27",
"node-jsencrypt": "^1.0.0",
"react": "^16.13.1",
"react-copy-to-clipboard": "^5.0.2",
"react-dnd": "^10.0.2",
"react-dom": "^16.13.1",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@testing-library/dom": "^7.5.1",
"axios-mock-adapter": "^1.18.1",
"babel-preset-jest": "^24.3.0",
"babel-preset-env": "^1.7.0",
"jest": "^24.5.0"
},
"babel": {
"babelrc": false,
"presets": [
"es2015"
],
"plugins": [
"transform-class-properties"
]
}
}
jest.config.js
module.exports = {
modulePaths: ["/shared/vendor/modules"],
collectCoverageFrom: ["src/**/*.{js,jsx,mjs}"],
testMatch: ["<rootDir>/src/**/__tests__/**/*.{js,jsx,mjs}", "<rootDir>/src/**/?(*.)(spec|test).{js,jsx,mjs}"],
transform: {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"
},
transformIgnorePatterns: ["[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs)$"],
moduleDirectories: ["node_modules", "bower_components", "shared"],
moduleFileExtensions: ["js", "jsx", "json"],
verbose: true,
moduleNameMapper
};
webpack.config.js
module.exports = {
module: {
loaders: [
{exclude: ['node_modules'], loader: 'babel', test: /\.jsx?$/},
{loader: 'style-loader!css-loader', test: /\.css$/},
{loader: 'url-loader', test: /\.gif$/},
{loader: 'file-loader', test: /\.(ttf|eot|svg)$/},
],
},
resolve: {
alias: {
config$: './configs/app-config.js',
react: './vendor/react-master',
},
extensions: ['', 'js', 'jsx'],
modules: [
'node_modules',
'bower_components',
'shared',
'/shared/vendor/modules',
],
},
};
我曾经有一个babel.config.js,但是它什么也没做,所以我删除了它。
fileTransformer.js
const path = require('path');
module.exports = {
process(src, filename, config, options) {
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
},
};
我想念什么?需要更改什么?我尝试了尽可能地遵循这些开玩笑的文档:https://jestjs.io/docs/en/webpack
任何帮助,非常感谢。
Events.test.js
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
import ReactDOM from "react-dom";
import axios from 'axios';
import Events from "../Components/Events/index";
import Home from "../Components/Home";
import { Router, BrowserRouter, MemoryRouter } from "react-router-dom";
import moment from 'moment-timezone';
import { createMemoryHistory } from "history";
import { Auth } from "aws-amplify";
describe('Event', () => {
jest.mock("../apis");
const path = "/events";
const route = "/events";
const history = createMemoryHistory({ initialEntries: [route] });
let props = {
match: {
path: path,
url: route,
isExact: true,
params: {
...
}
},
location: {
pathname: route
}
};
beforeEach(() => {
Auth.currentSession = jest.fn().mockImplementation(
() => {
return new Promise((resolve) => resolve({...})
);
});
});
afterEach(cleanup);
it('should take a snapshot and match it', (done) => {
let mockUseEffect = jest.spyOn(React, 'useEffect');
const { asFragment } = render(
<Router history={history}>
<Home />
</Router>
);
expect(asFragment(<Router history={history}>
<Home />
done();
});
it('renders without errors', (done) => {
const { getByTestId } = render(
<Router history={history}>
<Home />
</Router>
);
expect(getByTestId('event-index-title')).toHaveTextContent('All Events');
done();
});
});
index.js
import React, { useState, useEffect } from "react";
import {
Layout,
Row,
Table,
Button,
Modal,
Select,
Steps,
message,
} from "antd";
import { withRouter } from "react-router-dom";
import EventForm from "./EventForm";
import { getAllEvents, getAggregatedEvents } from "../../apis";
import spinner from "../helpers/spinner";
import * as moment from "moment";
const { Sider } = Layout;
const { Option } = Select;
const { Step } = Steps;
const Events = (props) => {
const [expId] = useState("abc_123");
const [events, setEvents] = useState([]);
const [aggregatedEvents, setAggregatedEvents] = useState([]);
const [selectedEvent, setSelectedEvent] = useState({ venue: {} });
const [currentStep, setCurrentStep] = useState(0);
const [isFetching, setIsFetching] = useState(true);
const [showAddModal, setShowAddModal] = useState(false);
useEffect(() => {
(async function fetchData() {
await getAllEvents(expId)
.then((events) => setEvents(events))
.catch((err) => message.error("Error retrieving Events"))
.finally(() => setIsFetching(false));
await getAggregatedEvents(expId)
.then((events) =>
setAggregatedEvents(events.sort((a, b) => a.weekId - b.weekId))
)
.catch((err) => message.error("Error retrieving aggregated Events"));
})();
}, [expId]);
const handleCancel = (e) => {
setShowAddModal(false);
};
const sider = (
<Sider
width={210}
style={{
background: "#fff",
padding: "1em",
}}
>
<Button
type="primary"
data-testid="add-btn"
onClick={() => {
setSelectedEvent({ venue: {} });
setShowAddModal(true);
}}
>
+ Add Event
</Button>
</Sider>
);
const columns = [
{
title: "Event Category",
dataIndex: "eventCategory",
key: "event.eventCategory",
sorter: (a, b) => a.eventCategory.localeCompare(b.eventCategory),
},
{
title: "Event Title",
dataIndex: "eventTitle",
key: "event.eventTitle",
sorter: (a, b) => a.eventTitle.localeCompare(b.eventTitle),
},
{
title: "Event Start Date",
dataIndex: "eventStartDateUTC",
key: "event.eventStartDateUTC",
render: (text) =>
text && text.length > 0 ? moment(text).format("MM/DD/YYYY") : "",
defaultSortOrder: "descend",
sorter: (a, b) =>
moment(a.eventStartDateUTC) - moment(b.eventStartDateUTC),
sortDirections: ["descend", "ascend"],
},
{
title: "Description",
dataIndex: "eventCaption",
key: "event.eventCaption",
},
];
const steps = [
{
title: "Select Event",
content: (
<div>
<Row>
<Select
data-testid="select-event"
showSearch
style={{ width: 800 }}
placeholder="Select an event"
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
size="large"
onChange={(val) => {
setSelectedEvent(
aggregatedEvents.filter((evt) => evt.id === val)[0]
);
setCurrentStep(1);
}}
>
{aggregatedEvents.map((evt) => (
<Option
key={`${evt.id}`}
value={`${evt.id}`}
>{`Week ${evt.weekId} - ${evt.homeTeam.fullName} vs ${evt.awayTeam.fullName}`}</Option>
))}
</Select>
</Row>
</div>
),
},
{
title: "Save Event",
content: (
<EventForm
data={selectedEvent}
isAddingEvent={true}
closeModal={handleCancel}
/>
),
},
];
return (
<div>
<Layout.Content
style={{
background: "#fff",
minHeight: 280,
borderRadius: 7,
color: "black",
}}
>
<h2
data-testid="event-index-title"
style={{
width: "100%",
backgroundColor: "#F7F7F7",
color: "#334D66",
height: "50px",
lineHeight: "50px",
paddingLeft: "30px",
}}
>
All Events
</h2>
<Layout>
{sider}
<Layout>
<Table
dataSource={events}
columns={columns}
rowKey="id"
loading={{ spinning: isFetching, indicator: spinner }}
onRow={(record) => ({
onClick: (evt) => {
const currentUrl = props.location.pathname;
props.history.push({
pathname: `${currentUrl}/${record.id}`,
});
},
})}
/>
</Layout>
</Layout>
</Layout.Content>
<Modal
title="Add an Event"
visible={showAddModal}
onCancel={handleCancel}
width={880}
footer={[]}
>
<Steps current={currentStep}>
{steps.map((item) => (
<Step key={item.title} title={item.title} />
))}
</Steps>
<br />
{steps[currentStep].content}
</Modal>
</div>
);
};
export default withRouter(Events);
答案 0 :(得分:0)
呈现组件和分解RTL函数的语法可以是:
describe('<MyComponent />', () => {
let rtl: RenderResult;
beforeEach(() => {
rtl = render(<MyComponent />);
}
test('something', () => {
// here you can access all RTL functions on rtl object
expect(rtl.getByText('...')).toBeTruthy();
// ...
})
})
如果您希望坚持使用语法:
({ getByText, getAllByTestId, ... } = render(
<MyComponent />
));
// then in test
expect(getByext('...')).toBeTruthy();