0
votes

I've seen that this question has been asked plenty of times already but in this case I think it's more related to my karma/webpack configuration that on what I'm doing in Vue. That because I only get the warning when running the tests with Karma (using the latest of Chrome headless) but I don't get it when using the webpack-dev-server straight away.

Here's my conf starting from the app/webpack.base.config.js file:

module.exports = {
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {}
                    // other vue-loader options go here
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader?limit=10000&mimetype=application/font-woff'
            },
            {
                test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader?limit=10000&mimetype=application/font-woff'
            },
            {
                test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader?limit=10000&mimetype=application/octet-stream'
            },
            {
                test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'file-loader'
            }, {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader?limit=10000&mimetype=image/svg+xml'
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'file-loader',
                options: {
                    name: '[name].[ext]?[hash]'
                }
            }
        ]
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    }
};

app/webpack.config.js

const path = require('path');
const webpack = require('webpack');
const mergeConfig = require('webpack-merge');
const baseConfig = require('./webpack.base.config');

module.exports = mergeConfig(baseConfig, {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
    },
    devServer: {
        historyApiFallback: true,
        noInfo: true,
        hot: true
    },
    performance: {
        hints: false
    },
    devtool: '#eval-source-map',
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
});

app/test/karma.conf.js (which only uses the webpack.base.config.js file here, not the whole thing)

// Karma configuration
const webpackConfig = require('../webpack.base.config');

process.env.CHROME_BIN = require('puppeteer').executablePath();

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

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '.',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: [
            './index.js'
        ],

        // list of files to exclude
        exclude: [],

        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
            './index.js': ['webpack']
        },

        // karma watches the test entry points
        // (you don't need to specify the entry option)
        // webpack watches dependencies
        webpack: webpackConfig,

        webpackMiddleware: {
            noInfo: true
        },

        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['spec'],

        // web server port
        port: 8080,

        // enable / disable colors in the output (reporters and logs)
        colors: true,

        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,

        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,

        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadlessNoSandbox'],

        customLaunchers: {
            ChromeHeadlessNoSandbox: {
                base: 'ChromeHeadless',
                flags: ['--no-sandbox']
            }
        },

        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: 1
    });
};

app/test/index.js

import Vue from 'vue';

Vue.config.productionTip = false;

// require all test files (files that ends with .js)
const testsContext = require.context('./specs', true, /\.js/);
testsContext.keys().forEach(testsContext);

And then I get the warning when mounting the component in my specs like this:

import Vue from 'vue';
import Extractor from './../../../src/components/Extractor.vue';

describe('Extractor component', () => {
    it('sets the correct default data', () => {
        const component = new Vue(Extractor).$mount();

        expect(component.url).toBe('');
        expect(component.responseCode).toBe(null);
        expect(component.body).toBe(null);
        expect(component.errorMessage).toBe(null);
    });
});

WARNING: this happens ONLY if:

  1. I use the vue-class-component library
  2. My component inherits from another
  3. When running the code through Karma/Chrome headless

The error I get in the logs is:

[Vue warn]: Property or method "valid" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

The "valid" property it is complaining about is inside the ApiComponent class (the parent one basically).

Here's one of the component that gives me the warning:

import http from './../modules/http';
import ApiComponent from './sub/ApiComponent';
import Component from 'vue-class-component';

// @see https://github.com/vuejs/vue-class-component
// @see https://github.com/wycats/javascript-decorators/blob/master/README.md
@Component()

export default class Extractor extends ApiComponent {
    url = '';

    sendRequest() {
        return new Promise((resolve, reject) => {
            // some AJAX call here
        });
    }
}

If rather than making the Extractor extend from the ApiComponent I make it extend the Vue class and copy and paste all the ApiComponent code inside the Extractor class then the warning goes away. The point is though... How come I get the warning only when running the code through Karma?

1

1 Answers

0
votes

The warning goes away by decorating also the super class (ApiComponent).

import Vue from 'vue';
import Component from 'vue-class-component';

@Component
export default class ApiComponent extends Vue {
    // ...
}