SyntaxError:意外的令牌

时间:2017-08-16 18:54:38

标签: javascript reactjs testing jestjs

我正在尝试配置我的应用程序(https://github.com/freeCodeCamp/meeting-for-good)进行测试。我正在使用开玩笑。但是,当我运行测试时出现错误。看起来我的AboutDialog组件的路径无法转换。

   zach@zach-VirtualBox:~/Documents/Code/fcc-for-good/meeting-for-good$ npm run test

> meeting-for-good@1.0.12 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 <jrogatis@rogatis.eti.br>",
  "contributors": [
    {
      "name": "Aniruddh Agarwal",
      "email": "aaniruddh99@gmail.com"
    },
    {
      "name": "Bob Sutton",
      "email": "anischyros@gmail.com"
    }
  ],
  "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',
};

1 个答案:

答案 0 :(得分:1)

我明白了。我只需要使用jest-css-modules(https://www.npmjs.com/package/jest-css-modules)。

所以我只需要添加make package.json

"jest": {
    "transform": {
      ".*": "<rootDir>/node_modules/jest-css-modules"
    }
  }