title: Testing with Jest, Babel, Webpack, and React. Support for the experimental syntax 'classProperties' isn't currently enabled
body: <p>Okey I have a huge problem trying to enable Jest on my React-native app. And every single answer from this topic gives me a different configuration for my webpack or my package.json. I hope to find an answer here. </p>
  
  <p>For this simple test: </p>
  
  <pre><code>import 'react-native';
  import React from 'react';
  import Index from '../index.ios.js';
  
  // Note: test renderer must be required after react-native.
  import renderer from 'react-test-renderer';
  
  it('renders correctly', () =&gt; {
    const tree = renderer.create(
      &lt;Index /&gt;
    );
  });
  </code></pre>
  
  <p>I run: <code>npm test</code> and get:</p>
  
  <blockquote>
    <p>SyntaxError:
    D:\workspaces\web\react\site\node_modules\react-native\jest\mockComponent.js:
    Support for the experimental syntax 'classProperties' isn't currently
    enabled (20:24):</p>
  </blockquote>
  
  <p>With a lovely solution: </p>
  
  <blockquote>
    <p>Add @babel/plugin-proposal-class-properties (<a href="https://git.io/vb4SL" rel="nofollow noreferrer">https://git.io/vb4SL</a>) to
    the 'plugins' section of your Babel config to enable transformation.</p>
  </blockquote>
  
  <p>But I dont know how to do it. </p>
  
  <p>This is my package.json configuration: </p>
  
  <pre><code>{
    "name": "site",
    "version": "0.0.1",
    "private": true,
    "scripts": {
      "start": "node node_modules/react-native/local-cli/cli.js start",
      "build-sitedev-home-css": "NODE_ENV=sitedev node_modules/webpack/bin/webpack.js --config ./modules/Home/assets/css/src/webpack.config.js",
      "build-sitedev-home-js": "NODE_ENV=sitedev node_modules/bundle-js/bin/bundle-js.js ./modules/Home/assets/js/src/entryfile.js --disable-beautify -p &gt; ./modules/Home/assets/js/build/bundle.js",
      "startweb": "cross-env NODE_ENV=webdevelopment node_modules/webpack/bin/webpack.js --watch",
      "buildweb": "cross-env NODE_ENV=webproduction node_modules/webpack/bin/webpack.js -p",
      "test": "jest",
      "android": "react-native run-android",
      "ios": "react-native run-ios",
      "android:expo": "react-native-scripts android",
      "react-devtools": "react-devtools"
    },
    "dependencies": {
      "abortcontroller-polyfill": "1.3.0",
      "adb": "0.2.0",
      "ag-grid": "18.1.1",
      "ag-grid-react": "18.1.0",
      "blueimp-file-upload": "9.32.0",
      "bundle-js": "1.0.3",
      "chart.js": "2.8.0",
      "elastic-apm-js-base": "3.0.0",
      "jquery": "3.4.1",
      "lodash.get": "4.4.2",
      "lodash.isequal": "4.5.0",
      "material-ui": "0.20.2",
      "meow": "5.0.0",
      "moment": "2.24.0",
      "moment-timezone": "0.5.26",
      "qrcode.react": "0.9.3",
      "react": "16.4.2",
      "react-art": "16.8.6",
      "react-chartjs": "1.2.0",
      "react-dom": "16.8.6",
      "react-dom-factories": "1.0.2",
      "react-infinite-scroller": "1.2.4",
      "react-native": "^0.60.5",
      "react-native-calendars": "1.21.0",
      "react-native-drawer": "2.5.1",
      "react-native-floating-label-text-input": "0.1.5",
      "react-native-progress-circle": "2.0.1",
      "react-native-snap-carousel": "3.8.0",
      "react-native-vector-icons": "4.6.0",
      "react-native-video": "4.4.4",
      "react-native-web": "0.11.5",
      "react-native-web-linear-gradient": "1.0.5",
      "react-tooltip": "3.10.0",
      "video.js": "7.6.0",
      "xdate": "0.8.2"
    },
    "devDependencies": {
      "@babel/core": "7.4.3",
      "@babel/plugin-proposal-class-properties": "7.5.5",
      "@babel/preset-env": "7.4.3",
      "@babel/preset-es2016": "7.0.0-beta.53",
      "@babel/preset-react": "7.0.0",
      "@babel/runtime": "7.4.3",
      "@types/prop-types": "15.7.1",
      "babel-cli": "6.26.0",
      "babel-core": "6.22.1",
      "babel-eslint": "10.0.1",
      "babel-jest": "24.1.0",
      "babel-loader": "6.2.10",
      "babel-plugin-transform-async-to-generator": "6.24.1",
      "babel-plugin-transform-runtime": "6.23.0",
      "babel-preset-env": "1.7.0",
      "babel-preset-es2016": "6.24.1",
      "babel-preset-react": "6.24.1",
      "babel-preset-react-native": "3.0.2",
      "babel-preset-stage-0": "6.24.1",
      "babel-register": "6.26.0",
      "cross-env": "5.2.0",
      "css-loader": "3.1.0",
      "eslint": "5.16.0",
      "eslint-plugin-react": "7.12.4",
      "expo": "33.0.7",
      "extract-text-webpack-plugin": "3.0.2",
      "file-loader": "4.1.0",
      "jest": "24.8.0",
      "jest-react-native": "18.0.0",
      "metro-react-native-babel-preset": "0.55.0",
      "react-devtools": "3.4.3",
      "react-native-scripts": "2.0.1",
      "react-test-renderer": "16.4.2",
      "style-loader": "0.23.1",
      "webpack": "3.10.0",
      "webpack-dev-server": "3.2.1"
    },
    "jest": {
      "preset": "react-native"
    },
    "rnpm": {
      "assets": [
        "./assets/fonts/"
      ]
    }
  }
  </code></pre>
  
  <p>And this is my webpack configuration: </p>
  
  <pre><code>var debug = process.env.NODE_ENV !== "webproduction";
  var webpack = require('webpack');
  var path = require('path');
  var fs = require('fs');
  
  var buildPath = __dirname + "/../../siteweb/site/www/themes/tmpux/assets/js/uxbuild";
  var wpk_local_configuration = {};
  if (fs.existsSync('./local.webpack.config.js')) {
    let local_webpack_config = require('./local.webpack.config');
    buildPath = local_webpack_config.buildPath;
    wpk_local_configuration = local_webpack_config.wpk_local_configuration;
  }
  
  console.log('buildPath = ' + buildPath);
  console.log('wpk_local_configuration = ' + JSON.stringify(wpk_local_configuration));
  
  if (!fs.existsSync(buildPath)) {
    fs.mkdirSync(buildPath);
  }
  
  fs.createReadStream(__dirname + "/components/parts/PDFViewer/configPDFViewer.js")
    .pipe(fs.createWriteStream(buildPath + "/configPDFViewer.js"));
  
  var _version = new Date().getTime();
  console.log('version = ' + _version);
  
  var wpk_configuration = {
    entry: {
      main: './index.web.js',
    },
    output: {
      path: buildPath,
      filename: "bundle.main.js",
      publicPath: "./assets/js/uxbuild/",
      chunkFilename: "bundle.[name].js"
    },
    module: {
      loaders: [
        {
          test: /\.js?$/,
          exclude: function (modulePath) {
            return (
              /node_modules/.test(modulePath) &amp;&amp;
              !/node_modules(\\|\/)react-native-datepicker/.test(modulePath) &amp;&amp;
              !/node_modules(\\|\/)react-native-progress-circle/.test(modulePath) &amp;&amp;
              !/node_modules(\\|\/)react-native-snap-carousel/.test(modulePath)
            );
          },
          loader: 'babel-loader',
          query: {
            presets: ['es2016', 'react-native'],
            plugins: ['transform-runtime']
          },
        },
        {
          test: /\.(png|jpg|gif|mp4)$/,
          loader: 'file-loader?context=' + __dirname + "/themes/tmpux/assets/js/components/" + '&amp;emitFile=true&amp;name=[path][hash].[ext]',
          options: {
            publicPath: "./assets/js/uxbuild/"
          }
        },
        {
          test: /\.css$/,
          loader: 'style-loader!css-loader'
        },
        {
          test: /\.ttf$/,
          loader: 'file-loader',
          include: path.resolve(__dirname, "node_modules/react-native-vector-icons"),
        }
      ],
    },
    resolve: {
      alias: {
        'react-native': 'react-native-web',
        'jquery-ui/ui/widget': 'blueimp-file-upload/js/vendor/jquery.ui.widget.js',
      },
      extensions: [ '.web.js', '.js' ]
    },
    plugins: debug ? [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'node-static',
                path: buildPath,
                filename: 'node-static.js',
                minChunks(module, count) {
                    var context = module.context;
                    return context &amp;&amp; context.indexOf('node_modules') &gt;= 0;
                }
            }),
            new webpack.DefinePlugin({
              'process.env': {
                NODE_ENV: JSON.stringify('development')
              }
            }),
          ] : [
            new webpack.optimize.CommonsChunkPlugin({
                  name: 'node-static',
                  path: buildPath,
                  filename: 'node-static.js',
                  minChunks(module, count) {
                      var context = module.context;
                      return context &amp;&amp; context.indexOf('node_modules') &gt;= 0;
                  }
            }),
            new webpack.DefinePlugin({
              'process.env': {
               NODE_ENV: JSON.stringify('production')
              }
            }),
            new webpack.optimize.DedupePlugin(),
            new webpack.optimize.OccurrenceOrderPlugin(),
            new webpack.optimize.UglifyJsPlugin({ mangle: false, sourceMap: true }),
          ]
  };
  
  module.exports = Object.assign(wpk_configuration, wpk_local_configuration);
  </code></pre>
  
  <p>And my local babel config: local.webpack.config</p>
  
  <pre><code>module.exports = {
      buildPath: __dirname + "/../../siteweb/site/www/themes/tmpux/assets/js/uxbuild",
      wpk_local_configuration: {
          devtool: 'eval-source-map',
      },
      presets: ["module:metro-react-native-babel-preset"], 
      plugins: ["@babel/plugin-proposal-class-properties"]
  };
  </code></pre>