web-dev-qa-db-fra.com

SyntaxError: Jeton inattendu 'const' (avec Vue, Karma, Webpack, PhantomJS)

J'ai une application plus ou moins vanille Laravel + Vue.js et j'essaie de faire quelques tests JS avec Karma et Jasmine . Si j'essaie d'utiliser des fonctions de style () => {} ou des mots clés tels que const dans mes tests, ils échouent avec Jeton inattendu erreurs. Cependant, je n'ai pas de problème à utiliser le mot clé import et je peux transpiler et travailler avec .vue fichiers sans problème.

Une affirmation triviale comme

expect(true).toBe(true);

Semble fonctionner correctement (voir dernière ligne)

$ ./node_modules/karma/bin/karma start
22 11 2016 11:09:23.250:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:09:23.254:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:09:23.263:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:09:24.025:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#U1dCZ7i3UtsC-M3_AAAA with id 84458811
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 1 of 1 SUCCESS (0.004 secs / 0.002 secs)

Then , si j'ajoute une déclaration triviale const à ma fonction de test

const myVar = 1
expect(true).toBe(true);

Je reçois une erreur:

$ ./node_modules/karma/bin/karma start
22 11 2016 11:10:00.741:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:10:00.745:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:10:00.752:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:10:01.659:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#Gwh8ywcLStrKf-ljAAAA with id 78654911
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  SyntaxError: Unexpected token 'const'
  at tests/unit/Example.spec.js:165

Au lieu de cela , si j'essaie de provoquer une erreur de syntaxe

const  = 1   // syntax error
expect(true).toBe(true);

puis Babel se plaint (sur la première ligne, avant que Karma ou PhantomJS ne démarre)

22 11 2016 11:07:00.079:ERROR [preprocessor.babel]: /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js: Unexpected token (8:15)
 at /Users/crcarter/Software/CropPlanning/cps-php/resources/assets/js/tests/unit/Example.spec.js
22 11 2016 11:07:00.090:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
22 11 2016 11:07:00.091:INFO [launcher]: Launching browser PhantomJS with unlimited concurrency
22 11 2016 11:07:00.101:INFO [launcher]: Starting browser PhantomJS
22 11 2016 11:07:00.986:INFO [PhantomJS 2.1.1 (Mac OS X 0.0.0)]: Connected on socket /#9Y6QLVxtJ57qRrgDAAAA with id 56249014
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
  You need to include some adapter that implements __karma__.start method!

Cela semble impliquer que le fichier Example.spec.js a été analysé/transpilé par Babel, mais que la version transpilée n’est pas livrée correctement au navigateur, même si le fichier Example.vue semble avoir été livré correctement.

Que puis-je faire pour que des éléments tels que const et () => {} soient utilisés dans mes tests? Merci.

Voici les fichiers pertinents:

resources/assets/js/components/Example.vue
resources/assets/js/tests/unit/Example.spec.js
karma.conf.js                             
package.json

// Example.vue
<template>
    <div class="container">
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component ready.')
        },
        data() {
            return { input: '# Hello!' }
        }
    }
</script>

// Example.spec.js
import Example from '../../components/Example.vue';

describe('Example', function () {
    it('should set correct default data', function () {

        const myVar = 1

        // trivial assertions
        expect(true).toBe(true);
    });
});

// karma.conf.js
var path = require('path')
var basePath = './resources/assets/js/';

module.exports = function(config) {
    config.set({

        frameworks: ['jasmine'],
        port: 9876,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['PhantomJS'],
        singleRun: true,
        basePath: basePath,

        webpack: {
            resolve: {
                extensions: ['', '.js', '.vue'],
                fallback: [path.join(__dirname, 'node_modules')],
            },
            resolveLoader: {
                fallback: [path.join(__dirname, 'node_modules')]
            },
            module: {
                loaders: [
                  { test: /\.vue$/, loader: 'vue' },
                  { test: /\.js$/,  loader: 'babel',
                    include: basePath,
                  }
                ]
            }
        },

        webpackMiddleware: {
            noInfo: true,
            stats: 'errors-only'
        },

        files: [
            { pattern: 'tests/**/*.spec.js', watched: false },
        ],

        exclude: [],

        preprocessors: {
            'app.js': ['webpack', 'babel'],
            'tests/**/*.spec.js': [ 'babel', 'webpack' ]
        },

    })
}

Et package.json

{
  "private": true,
  "scripts": {
    "prod": "gulp --production",
    "dev": "gulp watch"
  },
  "devDependencies": {
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.0",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.2",
    "lodash": "^4.16.2",
    "vue": "^2.0.1",
    "vue-resource": "^1.0.3"
  },
  "dependencies": {
    "jasmine-core": "^2.5.2",
    "karma": "^1.3.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chrome-launcher": "^2.0.0",
    "karma-firefox-launcher": "^1.0.0",
    "karma-jasmine": "^1.0.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-webpack": "^1.8.0"
  }
}
6
Clayton

Les commentaires de @craig_h et @PanJunjie m'ont mis sur la piste de regarder la configuration pour karma-babel-preprocessor, ce qui m'a conduit à la configuration pour karma-webpack. Je ne suis toujours pas sûr de la cause du problème initial, mais il semble que la configuration de mon Webpack pour Karma était incorrecte ou incomplète et qu'elle échouait en silence. J'ai ajouté les packages babel-loader et babel-preset-es2015 via

yarn add babel-loader babel-preset-es2015

Et puis j'ai refait et nettoyé mon karma.conf.js en tant que tel:

module.exports = function(config) {

    config.set({

        singleRun: false, // false => watch for changes and rerun tests
        autoWatch: true, // enable / disable watching files & then run tests

        frameworks: ['jasmine'],
        browsers: ['PhantomJS'],

        // Options: LOG_DISABLE, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG
        logLevel: config.LOG_INFO,

        basePath: './resources/assets/js/',

        files: [
            { pattern: 'tests/**/*.spec.js', watched: false },
        ],

        // how to process files before serving them to the browser for testing
        preprocessors: {
            'app.js': ['webpack'],
            'tests/**/*.spec.js': ['webpack'],
        },

        webpack: {
            module: {
                loaders: [
                    { test: /\.vue$/, loader: 'vue' },
                    { test: /\.js$/,
                      loader: 'babel-loader',
                      exclude: /node_modules/,
                      query: { presets: ['es2015'] }
                    }
                ]
            },
            // make sure to use the stand-alone version of Vue
            resolve: {
                alias: {vue: 'vue/dist/vue.js'}
            }
        },

        webpackMiddleware: {
          noInfo: true,
          stats: 'errors-only'
        }
    });
};

Mon package.json ressemble maintenant à ceci:

{
  "private": true,
  "scripts": {
    "prod": "gulp --production",
    "dev": "gulp watch"
  },
  "devDependencies": {
    "bootstrap-sass": "^3.3.7",
    "gulp": "^3.9.1",
    "jquery": "^3.1.0",
    "laravel-elixir": "^6.0.0-11",
    "laravel-elixir-vue-2": "^0.2.0",
    "laravel-elixir-webpack-official": "^1.0.2",
    "lodash": "^4.16.2",
    "vue": "^2.0.1",
    "vue-resource": "^1.0.3"
  },
  "dependencies": {
    "babel-loader": "^6.2.8",
    "babel-preset-es2015": "^6.18.0",
    "jasmine-core": "^2.5.2",
    "karma": "^1.3.0",
    "karma-babel-preprocessor": "^6.0.1",
    "karma-chrome-launcher": "^2.0.0",
    "karma-firefox-launcher": "^1.0.0",
    "karma-jasmine": "^1.0.2",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-webpack": "^1.8.0"
  }
}

Avec tout cela, je peux maintenant utiliser toute la qualité ES2015 comme const et () => {}. Désolé de répondre à ma propre question, mais j'espère que cela aidera quelqu'un d'autre qui rencontre un problème similaire.

4
Clayton

En plus du commentaire de RyanQuey: il a raison. La configuration par défaut de la CLI Vue + Webpack inclut uniquement certains contextes à gérer par le chargeur babel. Examinez build/webpack.base.conf.js, puis la règle de module pour les fichiers JS. Vous pouvez voir que seuls les chemins src, test et node_modules/webpack-dev-server/client sont inclus (au moment de l'écriture).

1
nicoes

J'ai eu un problème similaire (mais pas identique; votre configuration est assez spécifique). J'utilisais également Vue, Karma, Webpack et Phantomjs (comme configuré dans le modèle Vue-Webpack). 

Cependant, mon problème est que je définissais const dans un fichier d'aide importé dans mon application. Lorsque j'ai remplacé const par var dans ce fichier, les tests ont pu être exécutés (peu importe que const soit ou non utilisé dans d'autres fichiers déjà présents dans le répertoire src

Ce problème a été résolu lorsque j'ai déplacé ce fichier d'assistance dans mon dossier src ou l'un de ses sous-répertoires. Je suis trop novice pour savoir pourquoi cela résout le problème, mais j'imagine que babel n'était pas configuré pour fonctionner dans le dossier racine et n'était dirigé que vers le dossier src.

Espérons que cela soit utile pour les autres également. 

1
RyanQuey