我正在尝试配置应用程序(https://github.com/freeCodeCamp/meeting-for-good)进行测试。我在开玩笑。但是,运行测试时出现错误。看来我AboutDialog组件的路径无法传递。
zach@zach-VirtualBox:~/Documents/Code/fcc-for-good/meeting-for-good$ npm run test
> [email protected] test /home/zach/Documents/Code/fcc-for-good/meeting-for-good
> cross-env NODE_ENV=test jest
FAIL __tests__/test.js
● Test suite failed to run
/home/zach/Documents/Code/fcc-for-good/meeting-for-good/client/components/AboutDialog/about-dialog.css:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.AboutDialog {
^
SyntaxError: Unexpected token .
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/ScriptTransformer.js:289:17)
at Object.<anonymous> (client/components/AboutDialog/AboutDialog.js:7:20)
at Object.<anonymous> (__tests__/test.js:2:20)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 8.204s
Ran all test suites.
我正在尝试将AboutDialog组件导入到测试中。
import React from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import cssModules from 'react-css-modules';
import PropTypes from 'prop-types';
import styles from './about-dialog.css';
const inlineStyles = {
modal: { content: { width: '630px', maxWidth: '630px' }, bodyStyle: { paddingTop: 10, fontSize: '25px' } },
};
const AboutDialog = (props) => {
const { cbOpenModal, openModal } = props;
const actions = [
<FlatButton label="close" primary onTouchTap={() => cbOpenModal()} />,
];
return (
<Dialog
contentStyle={inlineStyles.modal.content}
bodyStyle={inlineStyles.modal.bodyStyle}
actions={actions}
modal
styleName="AboutDialog"
open={openModal}
>
<h1 styleName="titleStyle">Meeting for Good</h1>
<h6 styleName="versionStyle">Version {process.env.versionNumber}</h6>
<h4 styleName="descStyle">THE BEST MEETING COORDINATION APP</h4>
<h6>Created by campers from <a href="https://www.freecodecamp.com">FreeCodeCamp</a></h6>
<h6><a href="https://github.com/freeCodeCamp/meeting-for-good/"> License and GitHub Repository</a></h6>
</Dialog>
);
};
AboutDialog.propTypes = {
cbOpenModal: PropTypes.func.isRequired,
openModal: PropTypes.bool.isRequired,
};
export default cssModules(AboutDialog, styles);
我的测试。如果我从测试中删除AboutDialog导入,则测试套件将运行。
import React from 'react';
import AboutDialog from '../client/components/AboutDialog/AboutDialog';
import { shallow } from 'enzyme';
describe('Test', () => {
it('should test', () => {
});
});
我的.babelrc文件。
{
"presets": ["react", "es2015", "stage-1"],
"plugins": [
"transform-decorators-legacy",
"react-hot-loader/babel",
["transform-runtime", { "polyfill": false, "regenerator": true }]
],
"env": {
"development": {
"presets": [
"react-hmre"
]
}
}
}
我的package.json
{
"name": "meeting-for-good",
"version": "1.0.12",
"description": "Schedule events with ease!",
"homepage": "https://github.com/FreeCodeCamp/meeting-for-good/#readme",
"main": "index.js",
"scripts": {
"clean": "rimraf build",
"build:server": "babel -d ./build ./server -s",
"build:client": "cross-env NODE_ENV=production babel-node ./tools/build.js",
"build": "npm run clean && npm run copy && npm run build:server && npm run build:client",
"start": " node ./build/app.js",
"copy": "node tools/copy.js",
"serve": "npm run clean && npm run copy && npm run build:server && npm run dev",
"dev": "cross-env NODE_ENV=development node -r dotenv/config ./build/app.js",
"test": "cross-env NODE_ENV=test jest",
"heroku-postbuild": "npm run build",
"postinstall": "node tools/postInstall.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/FreeCodeCamp/meeting-for-good"
},
"author": "Jean Philip de Rogatis <[email protected]>",
"contributors": [
{
"name": "Aniruddh Agarwal",
"email": "[email protected]"
},
{
"name": "Bob Sutton",
"email": "[email protected]"
}
],
"license": "MIT",
"bugs": {
"url": "https://github.com/FreeCodeCamp/meeting-for-good/issues"
},
"engines": {
"node": "^8.0.0",
"npm": "^5.0.0"
},
"dependencies": {
"autobind-decorator": "^2.1.0",
"babel-cli": "^6.22.2",
"babel-core": "^6.22.1",
"babel-eslint": "^7.2.1",
"babel-loader": "^7.1.1",
"babel-plugin-react-transform": "^2.0.2",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.22.0",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-1": "^6.22.0",
"babel-runtime": "^6.25.0",
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"chai": "^4.1.0",
"chalk": "^2.0.1",
"chroma-js": "^1.3.3",
"chunk-manifest-webpack2-plugin": "^1.0.1",
"clipboard": "^1.6.1",
"compression": "^1.7.0",
"connect-flash": "^0.1.1",
"connect-mongo": "^1.3.2",
"cookie-parser": "^1.4.3",
"copy-webpack-plugin": "^4.0.1",
"cpy-cli": "^1.0.1",
"cross-env": "^5.0.1",
"css-loader": "^0.28.1",
"cssnano": "^3.10.0",
"dialog-polyfill": "^0.4.6",
"dotenv": "^4.0.0",
"ejs": "^2.5.5",
"email-templates": "^2.5.6",
"es6-promise": "^4.1.1",
"express": "^4.15.3",
"express-session": "^1.15.4",
"express-sessions": "^1.0.6",
"extract-text-webpack-plugin": "^2.1.0",
"fast-json-patch": "^2.0.4",
"favicons-webpack-plugin": "0.0.7",
"file-loader": "^0.11.1",
"google-calendar": "^1.3.2",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.29.0",
"image-webpack-loader": "^3.3.1",
"immutable": "^3.8.1",
"isomorphic-fetch": "^2.2.1",
"jstimezonedetect": "^1.0.6",
"lodash": "^4.17.2",
"material-ui": "^0.18.5",
"mocha": "^3.4.2",
"moment": "^2.18.1",
"moment-range": "^3.0.3",
"mongoose": "^4.11.3",
"morgan": "^1.8.2",
"nodemailer": "^4.0.1",
"nodemailer-ses-transport": "^1.5.0",
"nprogress": "^0.2.0",
"offline-plugin": "^4.8.3",
"opbeat": "^4.14.2",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"passport": "^0.3.2",
"passport-facebook": "^2.1.1",
"passport-google-oauth": "^1.0.0",
"passport-oauth2-refresh": "^1.0.0",
"pngquant-bin": "^3.1.1",
"prop-types": "^15.5.10",
"react": "^15.6.0",
"react-addons-update": "^15.5.2",
"react-css-modules": "^4.3.0",
"react-day-picker": "^5.5.1",
"react-dom": "^15.6.0",
"react-ga": "^2.2.0",
"react-hot-loader": "^3.0.0-beta.7",
"react-infinite": "^0.11.0",
"react-input-range": "^1.2.1",
"react-masonry-component": "^5.0.3",
"react-moment-proptypes": "^1.4.0",
"react-notification-system": "^0.2.14",
"react-router": "^3.0.2",
"react-tap-event-plugin": "^2.0.1",
"react-tooltip": "^3.3.0",
"react-transform-hmr": "^1.0.4",
"request": "^2.81.0",
"rimraf": "^2.6.1",
"shelljs": "^0.7.7",
"style-loader": "^0.18.1",
"url-loader": "^0.5.7",
"webpack": "^2.7.0",
"webpack-assets-manifest": "^0.7.0",
"webpack-bundle-analyzer": "^2.8.3",
"webpack-config": "^7.0.0",
"write-file-webpack-plugin": "^4.0.0",
"yargs": "^8.0.1"
},
"devDependencies": {
"babel-jest": "^20.0.3",
"babel-preset-jest": "^20.0.3",
"enzyme": "^2.9.1",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^15.0.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.8.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^5.1.0",
"eslint-plugin-react": "^7.0.1",
"jest": "^20.0.4",
"jest-css-modules": "^1.1.0",
"react-dom": "^15.6.1",
"react-test-renderer": "^15.6.1",
"regenerator-runtime": "^0.10.5",
"webpack-dev-middleware": "^1.11.0",
"webpack-dev-server": "^2.5.1",
"webpack-hot-middleware": "^2.18.2"
},
"jest": {
"transform": {
".*": "<rootDir>/node_modules/babel-jest"
}
}
}
我的webpack配置用于开发。
const webpack = require('webpack');
const WriteFilePlugin = require('write-file-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OptimizeCSS = require('optimize-css-assets-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const WebpackAssetsManifest = require('webpack-assets-manifest');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const cssNano = require('cssnano');
const packageJSON = require('./package.json');
const noVisualization = process.env.ANALYSE_PACK.toString() === 'false';
const lintCode = process.env.LINT_CODE.toString() === 'false';
const VENDOR_LIBS = [
'autobind-decorator',
'bluebird',
'clipboard',
'chroma-js',
'es6-promise',
'fast-json-patch',
'immutable',
'isomorphic-fetch',
'jstimezonedetect',
'lodash',
'material-ui',
'moment',
'moment-range',
'nprogress',
'react',
'react-addons-update',
'react-day-picker',
'react-tap-event-plugin',
'react-dom',
'react-css-modules',
'react-infinite',
'react-input-range',
'react-masonry-component',
'react-notification-system',
'react-router',
];
module.exports = {
context: __dirname,
entry: {
bundle: [
'react-hot-loader/patch',
'webpack-hot-middleware/client?reload=true',
'./client/main.js',
],
vendor: VENDOR_LIBS,
},
output: {
path: path.resolve('./build/client'),
publicPath: '/client/',
filename: '[name].[hash].js',
},
module: {
rules: [
(!lintCode ? {
test: /\.js$/,
enforce: 'pre',
loader: 'eslint-loader',
options: {
emitWarning: true,
},
} : {}),
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(ttf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
use: 'file-loader',
},
{
test: /\.(png|jp?g|gif|svg)$/,
use: [{
loader: 'url-loader',
options: {
limit: 1000,
},
},
{
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 4,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
},
],
},
{
test: /\.css$/,
exclude: [/node_modules/, /no-css-modules/],
use: [{
loader: 'style-loader?sourceMap',
},
{
loader: 'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
},
],
},
{
test: /\.css$/,
include: [/node_modules/, /no-css-modules/],
use: ExtractTextPlugin.extract({
fallback: 'style-loader?sourceMap',
use: 'css-loader',
}),
},
],
},
plugins: [
(!noVisualization ?
new BundleAnalyzerPlugin({
analyzerMode: 'static',
}) : null),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.GOOGLE_ANALYTICS_ID': JSON.stringify(process.env.GOOGLE_ANALYTICS_ID),
'process.env.GOOGLE_ANALYTICS_DEBUG': JSON.stringify(process.env.GOOGLE_ANALYTICS_DEBUG),
'process.env.versionNumber': JSON.stringify(packageJSON.version),
}),
new ExtractTextPlugin('vendor.css'),
new OptimizeCSS({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: cssNano,
cssProcessorOptions: {
discardComments: {
removeAll: true,
},
canPrint: true,
},
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[hash].js',
minChunks: 'Infinity',
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new WriteFilePlugin({
test: /\.(html|ejs)$/,
}),
new FaviconsWebpackPlugin({
logo: './client/assets/favicons/logo.png',
icons: {
appleStartup: false,
},
background: 'transparent',
persistentCache: true,
inject: true,
}),
new HtmlWebpackPlugin({
title: 'Meeting for Good',
template: 'html-loader!./client/index.html',
filename: '../index.html',
inject: 'body',
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new WebpackAssetsManifest({
writeToDisk: true,
merge: true,
done(manifest) {
console.log(`The manifest has been written to ${manifest.getOutputPath()}`);
},
apply(manifest) {
manifest.set('manifest_version', '2');
manifest.set('start_url', '/?homescreen=1');
manifest.set('version', '1');
manifest.set('default_locale', 'en');
manifest.set('description', 'THE BEST MEETING COORDINATION APP');
manifest.set('display', 'fullscreen');
manifest.set('short_name', 'MeetingFG');
manifest.set('name', 'Meeting For Good');
manifest.set('background_color', '#FBFFFB');
manifest.set('theme_color', '#FBFFFB');
},
}),
].filter(p => p),
resolve: {
extensions: ['.js', '.css'],
},
devtool: 'source-map',
};
最佳答案
我想到了。我只需要使用jest-css-modules(https://www.npmjs.com/package/jest-css-modules)。
所以我只需要添加即可制作package.json
"jest": {
"transform": {
".*": "<rootDir>/node_modules/jest-css-modules"
}
}