How to run tests in Angular & AngularJs hybrid app? - angularjs

As I want to migrate my AngularJs application to Angular 7, I created a hybrid app using ngUpgrade. The old AngularJs app is now embedded in the new Angular one.
When I run ng test it fires my Angular tests which is fine. But I also want to run the old tests written in AngularJs.
At the moment my Karma config looks like:
'use strict';
const webpackConfig = require('./karma.webpack.config');
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '#angular-devkit/build-angular', 'es6-shim'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('#angular-devkit/build-angular/plugins/karma'),
require('karma-es6-shim'),
require('karma-junit-reporter'),
require('karma-webpack'),
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'),
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
mime: {
'text/x-typescript': ['ts','tsx']
},
exclude: [
'**/*.html'
],
preprocessors: {
'./karma.entrypoint.ts': ['webpack']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
stats: 'errors-only'
},
junitReporter : {
// results will be saved as $outputDir/$browserName.xml
outputDir : 'build/test-results/test/'
},
reporters: ['progress', 'kjhtml', 'junit'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
});
};
The ./karma.webpack.config file is:
const config = require('./webpack.config.js')();
const webpack = require('webpack');
const path = require('path');
const nibStylusPlugin = require('nib');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = Object.assign({}, config, {
context: path.resolve(__dirname, '.'),
entry: {
test: './karma.entrypoint.ts'
},
mode: 'development',
devtool: 'cheap-module-inline-source-map',
optimization: {
splitChunks: false,
runtimeChunk: false
},
plugins: [
new ForkTsCheckerWebpackPlugin(),
new webpack.ProvidePlugin({
"window.jQuery": "jquery",
tv4: "tv4"
}),
new webpack.LoaderOptionsPlugin({
options: {
stylus: {
use: [nibStylusPlugin()],
import: ['~nib/lib/nib/index.styl'],
}
}
})
]
});
And last but not least the karma.entrypoint.ts:
import 'jquery';
import 'angular';
import 'angular-mocks';
import * as moment from 'moment';
import{appConfigMock} from './karma.app-mock.config';
window['__APP_CONFIG__'] = appConfigMock;
(<any>moment).suppressDeprecationWarnings = true;
const testsContext = (<any>require).context('./src/app/', true, /\.spec\.ts$/);
testsContext.keys().forEach(testsContext);
Before, when I had only the AngularJs app, I run the tests with a very similar structure by using karma command. It utilized my webpack config to create a new karma webpack config. Now, when I run it through the ng test command, I even cannot require the './karma.webpack.config' at the beginning on karma configuration (I get Invalid config file! TypeError: require(...) is not a function).
How should I approach this case to run all the tests?

I finally solved it by running the tests separately but with one npm command, npm run test:
"test-ng1": "cross-env APP_CONFIG=testing NODE_ENV=development karma start --single-run",
"test-ng2-apps": "ng test --watch=false --ts-config=./karma.tsconfig.json",
"test": "yarn test-ng2-apps && yarn test-ng1",

Related

CommonJS rollup plugin syntax error when importing 3rd party libraries, mostly related to 'process'

I've been working on a custom rollup config which takes a React project, and inlines the js and css in index.html.
When I've imported some third party react libraries (like material-ui-color) I run into a problem with CommonJS where it says there's a syntax error. Of the libraries I've tried to install so far, the word 'process' is most commonly the word it breaks on. Here is the log from the material-ui-color issue:
[!] (plugin commonjs) SyntaxError: Unexpected token (205:28) in /Users/meyerm/Documents/GitHub/button-generator-figma-plugin/node_modules/jss/dist/jss.esm.js
node_modules/jss/dist/jss.esm.js (205:28)
203: var newValue = value;
204:
205: if (!options || options.process !== false) {
^
I've included the rollup-plugin-replace to fix any occurrences of process.env.NODE_ENV but this seems to be a different issue.
Here is my rollup config:
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import babel from '#rollup/plugin-babel';
import livereload from 'rollup-plugin-livereload';
import replace from '#rollup/plugin-replace';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import html from 'rollup-plugin-bundle-html-plus';
import typescript from 'rollup-plugin-typescript';
import svgr from '#svgr/rollup';
const production = !process.env.ROLLUP_WATCH;
export default [
/*
Transpiling React code and injecting into index.html for Figma
*/
{
input: 'src/app/index.tsx',
output: {
name: 'ui',
file: 'dist/bundle.js',
format: 'umd',
},
plugins: [
// What extensions is rollup looking for
resolve({
extensions: ['.jsx', '.js', '.json', '.ts', '.tsx'],
}),
// Manage process.env
replace({
preventAssignment: true,
process: JSON.stringify({
env: {
isProd: production,
},
}),
'process.env.NODE_ENV': JSON.stringify(production),
}),
typescript({ sourceMap: !production }),
// Babel config to support React
babel({
presets: ['#babel/preset-react', '#babel/preset-env'],
babelHelpers: 'runtime',
plugins: ['#babel/plugin-transform-runtime'],
extensions: ['.js', '.ts', 'tsx', 'jsx'],
compact: true,
exclude: 'node_modules/**',
}),
commonjs({
include: 'node_modules/**',
}),
svgr(),
// Config to allow sass and css modules
postcss({
extensions: ['.css, .scss, .sass'],
modules: true,
use: ['sass'],
}),
// Injecting UI code into ui.html
html({
template: 'src/app/index.html',
dest: 'dist',
filename: 'index.html',
inline: true,
inject: 'body',
ignore: /code.js/,
}),
// If dev mode, serve and livereload
!production && serve(),
!production && livereload('dist'),
// If prod mode, minify
production && terser(),
],
watch: {
clearScreen: true,
},
},
/*
Main Figma plugin code
*/
{
input: 'src/plugin/controller.ts',
output: {
file: 'dist/code.js',
format: 'iife',
name: 'code',
},
plugins: [resolve(), typescript(), commonjs({ transformMixedEsModules: true }), production && terser()],
},
];
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
// Start localhost dev server on port 5000 to work on the UI in the browser
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true,
});
}
},
};
}
Any ideas how I can overcome this and import 3rd party libraries into the project easily?
I recommend rewriting the config in the following way:
replace({
"process.env.isProd": production,
}),

Slow Karma Unit Tests

I wrote unit tests for a small reach application using Jasmine and Karma.And Karma is running slow for these tests.
This is my karma config:
var unitTestReportOutputDir = 'unit-test-report';
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
reporters: ['dots'],
port: 9876,
colors: false,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
autoWatchBatchDelay: 300,
exclude: ['./test/data/*.js'],
files: [
'tests.webpack.js'],
preprocessors: {
'tests.webpack.js': ['webpack']
},
webpack: require('./webpack.config.js'),
webpackMiddleware: {
noInfo: true
},
htmlReporter: {
outputDir: unitTestReportOutputDir, // where to put the reports
focusOnFailures: true, // reports show failures on start
namedFiles: true, // name files instead of creating sub-directories
pageTitle: 'Unit Test Report', // page title for reports; browser info by default
urlFriendlyName: false, // simply replaces spaces with _ for files/dirs
reportName: 'test-summary', // report summary filename; browser info by default
// experimental
preserveDescribeNesting: false, // folded suites stay folded
foldAll: false, // reports start folded (only with preserveDescribeNesting)
}
});
}
This is my webpack.config.js:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
var UglifyJsPlugin = require('uglify-js-plugin');
const path = require('path');
module.exports = {
devtool: 'inline-source-map',
entry: ['./src/index.js'],
output: {path: path.resolve(__dirname, "builds"), filename: 'bundle.js'},
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader'
}
]
},
{
test: /\.sass$/,
exclude: '/node_modules/',
use: ExtractTextPlugin.extract({
fallback: "style-loader",
loader: "css-loader!sass-loader"
})
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.sass']
},
plugins: [
new ExtractTextPlugin({
filename: "stylesheets/style.css",
disable: false,
allChunks: true
}),
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery": "jquery",
"window.jQuery": "jquery"
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
})
]
};
What do you guys usually do to speed up Karma in running unit tests ?
I put the code at: https://github.com/zainulfranciscus/karma-test
karma took 1 min 15 sec to start and 33 seconds to ran the tests, whenever I updated a test. There are 35 unit tests
Thank you.
Check out the karma-parallel plugin here:
https://www.npmjs.com/package/karma-parallel
More popular and karma-webpack compatible compared to the karma-sharding plugin.
Have you looked at karma-sharding? This plugin addresses some memory usage problems with some browsers, and numerous or memory intensive specs.
It will not run your tests all in parallel, but as of version 4.0.0, it supports parallel browser execution(i.e. will shard tests across browsers listed in your karma.conf.js)

Use of reserved word 'class' with karma and webpack

I'm building a project with angularJS in ES6.
I'm trying to config karma test runner and coverage with istanbul.
When I try to lauch unit test with Karma, I've following error :
Use of reserved word 'class'
This is my karma config file :
var path = require('path');
module.exports = function (config) {
config.set({
basePath: '',
plugins: [
'karma-coverage',
'karma-jasmine',
'karma-phantomjs-launcher',
'karma-webpack',
'karma-coverage-istanbul-reporter'
],
frameworks: ['jasmine'],
files: [
'tests/index.js'
],
preprocessors: {
'tests/index.js': 'webpack'
},
webpack: {
module: {
rules: [{
test : /\.js$/,
use : {
loader: 'istanbul-instrumenter-loader',
query : {
esModules: true
}
},
include: path.resolve('src/')
}, {
test: /\.html$/, loaders: ["html-loader"]
}, {
test: /\.less$/,
use : [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader"
}]
}, {
test : /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
loader: 'url-loader'
}]
}
},
reporters: ['progress', 'coverage-istanbul'],
coverageIstanbulReporter: {
reports : ['text-summary'],
fixWebpackSourcePaths: true
},
port : 9876,
colors : true,
logLevel : config.LOG_INFO,
autoWatch : true,
browsers : ['PhantomJS'],
singleRun : true,
concurrency: Infinity,
})
};
And this is my tests/index.js file
// requires all tests in `project/test/src/components/**/index.js`
const tests = require.context('./specs/', true, /index\.js$/);
tests.keys().forEach(tests);
// requires all components in `project/src/components/**/index.js`
const components = require.context('../src/', true, /\.js$/);
components.keys().forEach(components);
Did I miss something ?
Thanks.
PhantomJS currently doesn't support es2015+.
So you either need a transpiler loader like babel-loader,
or you need to install PhantomJS beta which supports new syntax.

Can't find nodes with enzyme and css-modules when using karma-webpack

I've been using css-modules with mocha, enzyme and css-modules-require-hook without any problems.
Foo.js
import React from 'react';
import styles from './Foo.css';
const Foo = () => <div className={ styles.foo }>Foo component</div>;
export default Foo;
Foo.css
.foo {
color: rebeccapurple;
}
Foo.test.js
import Foo from './Foo';
describe('<Foo />', () => {
it('should render proper markup', () => {
const wrapper = shallow(<Foo />);
expect(wrapper.find('.foo')).to.have.length(1);
});
});
I started using Karma with karma-webpack-with-fast-source-maps and now the test fails because the styles in Foo.js is an array and it's not using keys to keep original class name.
[[376, '.Foo__foo___3QT3e {
color: rebeccapurple;
}
', '']]
I've tried importing the css-modules-require-hook in test-bundler.js for karma-webpack but that throws a bunch of errors.
WARNING in ./~/css-modules-require-hook/preset.js
Critical dependencies:
13:7-22 the request of a dependency is an expression
# ./~/css-modules-require-hook/preset.js 13:7-22
// many more warnings
ERROR in ./~/css-modules-require-hook/lib/index.js
Module not found: Error: Cannot resolve module 'fs' in /Users/qmmr/code/streetlife/composer/code/site/node_modules/css-modules-require-hook/lib
# ./~/css-modules-require-hook/lib/index.js 14:19-32
// more errors
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
SyntaxError: Unexpected token ')'
webpack.config.test.js
/* eslint-disable */
var path = require('path');
const CSS_MODULES_LOADER = [
'modules',
'importLoaders=1',
'localIdentName=[name]__[local]___[hash:base64:5]'
].join('&');
module.exports = {
resolve: {
extensions: [ '', '.js' ],
},
devtool: 'inline-source-map',
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
cacheDirectory: true,
plugins: [ 'transform-runtime', 'transform-class-properties', 'transform-export-extensions' ],
presets: [ 'es2015', 'react', 'stage-2' ],
}
},
{
test: /\.css$/,
loader: `css?${ CSS_MODULES_LOADER }`,
include: path.join(__dirname, '/css/modules'),
},
{ test: /\.json$/, loader: 'json' },
],
},
externals: {
'cheerio': 'window',
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
},
};
karma.conf.js
// Karma configuration
var webpackConfig = require('./webpack.config.test');
module.exports = function(config) {
config.set({
basePath: '',
frameworks: [ 'mocha' ],
plugins: [
'karma-mocha',
'karma-phantomjs-launcher',
'karma-webpack-with-fast-source-maps'
],
files: [
{
pattern: './testBundler.js',
watched: false,
served: true,
included: true,
},
],
exclude: [],
preprocessors: {
[ './test-bundler.js' ]: [ 'webpack' ]
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
stats: 'errors-only',
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: [ 'PhantomJS' ],
singleRun: true,
concurrency: Infinity,
})
}
test-bundler.js
// ---------------------------------------
// Test Environment Setup
// ---------------------------------------
import React from 'react';
import chai from 'chai';
import sinon from 'sinon';
import { shallow, mount } from 'enzyme';
// require('css-modules-require-hook/preset'); // Fix css-modules not rendering in tests
global.React = React;
global.expect = chai.expect;
global.sinon = sinon;
global.shallow = shallow;
global.mount = mount;
// ---------------------------------------
// Require Tests
// ---------------------------------------
// for use with karma-webpack-with-fast-source-maps
const __karmaWebpackManifest__ = new Array(); // eslint-disable-line
const inManifest = (path) => ~__karmaWebpackManifest__.indexOf(path);
const testsContext = require.context('../react', true, /\.test\.js$/);
// only run tests that have changed after the first pass.
const testsToRun = testsContext.keys().filter(inManifest);
(testsToRun.length ? testsToRun : testsContext.keys()).forEach(testsContext);
How can I use css-modules-require-hook in my setup (karma + webpack)?
EDIT: I've created a repository https://github.com/qmmr/yab to show the issue. When running npm run test:mocha the test passes. When running npm run test it fails (this is the karma-webpack integration).

Webpack error while loading module DomUtils after import enzyme

I have a project with TypeScript and React 0.14.
And I set-up test enviroment with karma/mocha/chai. And its work. But when I import and use function from enzyme I got error in browser (Human-readable error from Chrome):
Uncaught TypeError: ext[key].bind is not a function
As I understood modules 227...232 (internal DomUtils files) not loaded before using.
Maybe I forgot something? Or does anyone know workaround?
Sorry for huge configs:
Webpack config:
var webpack = require("webpack"),
path = require("path"),
ExtractTextPlugin = require("extract-text-webpack-plugin"),
precss = require('precss'),
autoprefixer = require('autoprefixer');
module.exports = {
entry: [
path.resolve(__dirname, "app/app.tsx")
],
output: {
filename: "bundle.js",
publicPath: "/build/",
path: path.resolve(__dirname, "build")
},
module: {
loaders: [
{test: /\.json$/, loader: 'json'},
{test: /\.tsx$/, exclude: /node_modules/, loader: 'es3ify!ts'},
{test: /\.s?css$/, loader: ExtractTextPlugin.extract('style', 'css!postcss')},
{test: /\.svg|eot|ttf|woff|woff2|ico|png|gif|jpg($|\?)/, loader: 'file'}
]
},
postcss: function () {
return [precss, autoprefixer];
},
resolve: {
root: path.resolve(__dirname, "app"),
extensions: ["", ".js", ".ts", ".tsx", ".json"]
},
plugins: [
new ExtractTextPlugin("bundle.css")
]
};
Karma config:
var webpack = require('webpack');
var webpackConfig = require('./webpack.config');
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'chai', 'sinon'],
files: [
'app/**/*-test.tsx'
],
exclude: [],
preprocessors: {
'app/**/*.tsx': ['webpack']
},
webpack: {
resolve: webpackConfig.resolve,
module: webpackConfig.module,
externals: {
'cheereo': 'window',
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}
},
reporters: ['progress', 'spec'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true,
concurrency: Infinity
})
}
Test file:
import * as React from 'react';
import { shallow } from 'enzyme';
describe('Dashboard', () => {
it('should be OK', () => {
const instance = shallow(<div />);
expect(true).to.equal(true, 'true === true');
});
});
Webpack import chain: enzyme -> ... -> cheerio -> ... -> DomUtils
StackOverflow my last chance to solve the problem, Google don't know answer.
I've faced with same issue, for me it helps to put domutils as extrenal in webpack configuration. Based on your config try this:
webpack: {
resolve: webpackConfig.resolve,
module: webpackConfig.module,
externals: {
'domutils': 'true',
'cheereo': 'window',
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
}
}

Resources