Writing tests with karma/jasmine - javascript

I have been building normal js apps using frameworks like ember/angular. They already have everything built in for compilation and testing.
I started building an app in vanilla js. I wrote code in es6.
I started with tests using karma/jasmine. I got stuck with the configuration. I went through couple of articles and got a little success but again got stuck in relative error from browserify in karma. ERROR [framework.browserify]: Error: Cannot find module
How can I write tests with karma/jasmine. What to use? webpack/browserify?
My app structure is:
app/js/**/*.js app/tests/**/*.js app/css/**.css app/index.html app/Gruntfile.js app/karma.conf.js app/package.json app/server.js
This is my gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
browserify: {
development: {
src: [
"./js/application.js",
],
dest: './js/common.js',
options: {
browserifyOptions: {
debug: true
},
transform: [
["babelify", {
"presets": ["es2015"]
}]
]
}
}
},
watch: {
scripts: {
files: ["./js/**/*.js"],
tasks: ["browserify"]
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
};
This is karma.conf.js
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['browserify', 'jasmine'],
browsers: ['Chrome'],
files: [
'js/**/*.js',
'tests/**/*.js'
],
exclude: [],
preprocessors: {
'js/**/*.js': ['browserify'],
'tests/**/*.js': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
},
reporters: ['progress', 'html'],
// the default configuration
htmlReporter: {
outputDir: 'karma_html', // where to put the reports
templatePath: null, // set if you moved jasmine_template.html
focusOnFailures: true, // reports show failures on start
namedFiles: false, // name files instead of creating sub-directories
pageTitle: null, // page title for reports; browser info by default
urlFriendlyName: false, // simply replaces spaces with _ for files/dirs
reportName: 'report-summary-filename', // 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 package.json
{
"author": "Yomn",
"name": "myapp",
"version": "0.0.0",
"scripts": {
"start": "node server.js",
"tests": "karma start"
},
"devDependencies": {
"babel-core": "^5.0.0",
"babel-loader": "^5.0.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babelify": "^7.3.0",
"browserify": "^14.4.0",
"grunt": "^1.0.1",
"grunt-browserify": "^5.1.0",
"grunt-contrib-watch": "^1.0.0",
"jasmine": "^2.2.1",
"jasmine-core": "^2.2.0",
"karma": "^0.13.2",
"karma-browserify": "~3.0.2",
"karma-chrome-launcher": "^2.2.0",
"karma-html-reporter": "^0.2.7",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^1.0.4",
"karma-webpack": "^1.6.0",
"phantomjs-prebuilt": "^2.1.15",
"webpack": "^1.8.4"
}
}

I tried to run project with your configuration, but since you did not provide examples of the files, I sketched out my example that works. I hope it will be useful.
js\Circle.js:
class Circle {
constructor(x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
}
exports.Circle = Circle;
tests\Circle.js:
var Circle = require('../js/Circle');
describe('Circle', () => {
describe(`constructor`, () => {
it(`should initialize properties correctly`, () => {
const circle = new Circle.Circle(1, 2, 3);
expect(circle.x).toBe(1);
});
});
});
Karma start command: "node_modules\.bin\karma" start --no-single-run

Related

webpack nodejs - Calling an external js file in script tag api call

I am new to nodejs, webpacks and javascripts, looking for assistance.
I have the below project structure using webpack with nodejs:
-dist
-node_modules
-public
--test.png
-routes
--web
---usage.html
--api
---testapi.js
-src
--app.js
-index.html
-package-lock.json
-package.json
-webpack.config.js
webpack.config.js has this structure:
webpack.config.js:
module.exports = {
mode: 'development',
target: "node",
entry: {
main: './src/app.js',
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: [".js", ".jsx", ".json", ".css"]
},
module: {
rules: [
{
test: /\.(js|jsx)?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.html$/i,
loader: "html-loader",
},
//other rules
]
},
devServer: {
client: {
overlay: true
},
hot: true,
watchFiles: ['src/*', 'index.html'],
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
},
plugins: [
new CopyWebpackPlugin({
patterns: ['index.html']
}),
new HtmlWebpackPlugin({
filename: 'usage.html',
template: 'routes/web/usage.html',
}),
//other plugins
]
};
In testapi.js I have a api call using axios :
testapi.js:
const axios = require('axios');
var temp;
const config = {
//some_config
};
axios.get(some_url, config)
.then(async result => {
temp = result.data;
console.log("Results: " + JSON.stringify(temp))
})
.catch(error => {
console.log(error)
});
In usage.html I am calling the testapi.js script (also to cors issue as testapi.js is from a external api) and doing some actions as follows:
usage.html :
//other scripts
<script>
$(document).ready(function () {
$.getScript("testapi.js", async function (result) {
//some logic goes here
});
</script>
//body follows
package.json :
{
"name": //some_app_name,
"version": "1.0.0",
"description": //some_desc,
"dependencies": {
"#babel/core": "^7.18.13",
"async": "^3.2.4",
"aws-amplify": "latest",
"axios": "^0.27.2",
"express": "^4.18.1",
"html-webpack-plugin": "^5.5.0",
"node-fetch": "^2.6.7"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^8.2.5",
"babel-preset-env": "^1.7.0",
"babel-preset-es2016": "^6.24.1",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^6.4.1",
"extract-loader": "^5.1.0",
"file-loader": "^6.2.0",
"html-loader": "^4.1.0",
"html-webpack-partials-plugin": "^0.8.0",
"url-loader": "^4.1.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
},
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack",
"prestart": "npm run build",
"start": "webpack && webpack-dev-server --mode development"
}
}
I have tried the below things and nothing seems to be working:
Adding the js file as entry // The api gets called in console but with cors issue and not sure how i can use it in usage.html.
Added plugin in webpack config with :
new CopyWebpackPlugin({
patterns: ['routes/api/testapi.js']
}),
When I do this, I can see the raw code instead of the api response output in Network tab when I load that usage.html page.
Used $get instead of $getScript in usage.html.
Tried moving testapi to src as well and making necessary changes.
Kindly assist me with this

Cannot Read Property 'start' of undefined using gulp.js

So, I have 1 error in my GULP when I use the following:
node ./node_modules/gulp/bin/gulp.js test
Here's the error I'm getting when I run: node ./node_modules/gulp/bin/gulp.js test
PS C:\Users\myuser\repos\wwwroot\acqustn-aem-global-comps\ui.apps> node
./node_modules/gulp/bin/gulp.js test
[09:41:14] Using gulpfile ~\repos\wwwroot\global-comps\ui.apps\gulpfile.js
[09:41:14] Starting 'test'...
[09:41:14] 'test' errored after 4.45 ms
[09:41:14] TypeError: Cannot read property 'start' of undefined
at C:\Users\myuser\repos\wwwroot\global-comps\ui.apps\gulpfile.js:12:11
at test (C:\Users\myuser\repos\wwwroot\global-comps\ui.apps\node_modules\undertaker\lib\set-task.js:13:15)
at bound (domain.js:426:14)
at runBound (domain.js:439:12)
at asyncRunner (C:\Users\myuser\repos\wwwroot\global-comps\ui.apps\node_modules\async-done\index.js:55:18)
at processTicksAndRejections (internal/process/task_queues.js:79:11)
Here is my karma.conf.js file that's formatted in the following manner. I'm adding more text here because I have to as I cannot post unless I describe more information
module.exports = function (config) {
const process = require('process');
process.env.CHROME_BIN = require('puppeteer').executablePath();
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-jquery', 'jasmine'],
plugins: [
require('jquery'),
require('karma-junit-reporter'),
require('karma-coverage'),
require('karma-jasmine-jquery-2'),
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-phantomjs-launcher'),
require('karma-coverage-istanbul-reporter'),
require('#angular-devkit/build-angular/plugins/karma'),
require('karma-sonarqube-unit-reporter')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/global-comps'),
reports: ['lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
// list of files / patterns to load in the browser
files: [
'./src/main/content/jcr_root/etc/designs/global-components/footer/**/*.js',
'./src/main/content/jcr_root/etc/designs/global-components/header/**/*.js',
'./src/main/content/jcr_root/etc/designs/global-components/action/**/*.js'
],
// list of files / patterns to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'./test/navigationClientLibs/js/header.spec.js': ['coverage']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['junit', 'progress', 'kjhtml', 'coverage-istanbul', 'sonarqubeUnit', 'coverage'],
sonarQubeUnitReporter: {
sonarQubeVersion: 'LATEST',
outputFile: 'reports/ut_report.xml',
overrideTestDescription: true,
testPaths: ['./test/navigationClientLibs/'],
testFilePattern: '.js',
useBrowserName: false
},
// web server port
port: 9876,
// 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: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
junitReporter: {
outputFile: 'reports/junit/TESTS-xunit.xml'
},
coverageReporter: {
type: 'lcov',
dir: 'reports',
subdir: 'coverage'
}
})
}
Now my GULP FILE which is failing with karma.start() whenever I run the following node ./node_modules/gulp/bin/gulp.js test at the command prompt in VS Code Terminal
var gulp = require('gulp');
var karma = require('karma').server;
var replace = require('gulp-replace');
var postprocessLCOV = function() {
return gulp.src('reports/coverage/lcov.info')
.pipe(replace('SF:.', 'SF:frontend-project'))
.pipe(gulp.dest('reports/coverage'));
};
gulp.task('test', function () {
karma.start({
configFile: __dirname + '/src/test/js/karma.conf.ci.js'
}, postprocessLCOV);
});
Of Note: My karma.conf.js and .ci.js are exactly the same so I don't have to post both files here.
Finally, my package.json which shows everything I'm using. Whenever I added an new library, I have to delete the package.lock.json, after the new library is installed then re-run npm install.
{
"name": "global-comps",
"version": "1.0.0",
"description": "This is for the Navigator",
"main": "qunit.js",
"scripts": {
"lint": "eslint '**/*.js'",
"test": "qunit",
"compodoc": "npx compodoc -p tsconfig.doc.json",
"ng": "ng",
"clean": "rm -rf node*",
"ng-cli": "npm install --no-optional #angular/cli",
"start": "ng serve --proxy-config proxy.config.json",
"build": "ng build",
"prod": "node --max_old_space_size=8192 node_modules/#angular/cli/bin/ng build --prod --output-hashing none && npm run test && npm run clean",
"e2e": "ng e2e",
"sonar": "sonar-scanner"
},
"repository": {
"type": "git",
"url": "somerepo.git"
},
"author": "Some Author",
"license": "MIT",
"dependencies": {
"#angular/common": "~9.0.2",
"#angular/compiler": "~9.0.2",
"#angular/core": "~9.0.2",
"#angular/platform-browser": "~9.0.2",
"#angular/platform-browser-dynamic": "~9.0.2",
"#angular/router": "~9.0.2",
"#types/mocha": "^9.0.0",
"JSONPath": "^0.11.2",
"browserify": "^17.0.0",
"common-js": "^0.3.8",
"eslint-plugin-qunit": "^6.1.1",
"jquery": "^3.4.1",
"jquery-browserify": "^1.8.1",
"jsdom": "^16.5.3",
"junit": "^1.4.9",
"karma-junit-reporter": "^2.0.1",
"ng-mocks": "^11.10.1",
"node": "^15.12.0",
"npm-check-updates": "^11.5.13",
"phantomjs": "^2.1.7",
"qunit-reporter-junit": "^1.1.1",
"qunit-reporter-lcov": "^1.0.2",
"require": "^2.4.20",
"rxjs": "~6.5.4",
"tslib": "^1.10.0"
},
"devDependencies": {
"#angular-devkit/build-angular": "^12.1.3",
"#angular-devkit/build-webpack": "^0.1201.3",
"#angular/compiler-cli": "~9.0.2",
"#types/jasmine": "~3.5.0",
"#types/jasminewd2": "~2.0.3",
"#types/jsdom": "^16.2.13",
"#types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"grunt": "^1.3.0",
"grunt-contrib-connect": "^3.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-qunit": "^4.0.0",
"grunt-git-authors": "^3.2.0",
"grunt-search": "^0.1.8",
"gulp": "^4.0.2",
"gulp-replace": "^1.1.3",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "^6.3.2",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-jasmine": "^4.0.1",
"karma-jasmine-html-reporter": "^1.7.0",
"karma-jasmine-jquery-2": "^0.1.1",
"karma-mocha-reporter": "^2.2.5",
"karma-phantomjs-launcher": "^1.0.4",
"karma-qunit": "^4.1.2",
"karma-sonarqube-unit-reporter": "0.0.23",
"karma-webpack": "^5.0.0",
"protractor": "~5.4.3",
"puppeteer": "^1.20.0",
"sonar-scanner": "^3.1.0",
"sonarqube-scanner": "~2.7.0",
"ts-node": "~8.3.0",
"typescript": "~3.7.5"
},
"global": "window"
}
So, that's where I'm at.
UPDATE!
So, I've abandoned GULP and got Karma to work.
But in SONARQUBE, what I'm getting is 0% coverage because Karma is NOT creating the lcov.info file even though it's creating the coverage directory and subsequent files.
OF NOTE: I can run my tests in the browser in QUNIT and see them succeed or fail in either case.
BUT I need KARMA to create the lcov.info file with the tests I've created in my .js file. Since this is not Angular but just pure JavaScript, that's where I'm stuck.
Here's a screen shot of my SONARQUBE Coverage to show you what I'm getting.
I'd really like some help here.
Again, here are the Two SIMPLE test files that I'm running using QUNIT that work but are NOT when I run them in KARMA.
Thank you everyone for your continued support.
describe('A Suite for a simple test', () => {
var a;
it('and so it is a spec', () => {
a = true;
expect(a).toBe(true);
});
it('2 plus 2 should be 4', () => {
const result = add(2, 2);
expect(result).toBe(4);
});
});
describe('Test case 1', () => {
var zipcodevalue = '';
const test1 = sendToTest1;
console.log('Test 1 is: ', test1);
beforeEach(function () {
zipToTestCase.call(this, {
assert: assert,
zipcodevalue: '98237',
expected: "Success"
});
});
function zipToTestCase() {
if (isNaN(zipcodevalue === false)) {
expect(zipcodevalue, '98237', 'string value and hard code value are NOT equal', function (callback) {
callback(zipcodevalue);
});
} else {
expect(zipcodevalue, '98237', 'string value and hard code value are equal', function (callback) {
callback(zipcodevalue);
});
}
}
it('test for Valid ZipCode', () => {
expect(zipcodevalue).toBeTruthy();
})
it('test for INValid ZipCode', () => {
expect(zipcodevalue).toBeFalsy();
})
});
I found the answer here with this article!
https://sourcedcode.com/blog/aem/how-to-write-javascript-unit-tests-for-aem-client-libraries-with-jest
This is EXACTLY what I needed and the results are PERFECT!

Error ReferenceError: regeneratorRuntime is not defined (Chrome Console Error - not during gulp / babel build)

I have a bit of a strange issue that I'm hoping I can get some help with.
I've got a WordPress theme that I've been developing using a dev setup including gulp & babel. I have a hosting provider with a development environment, and production environment. Up until now, I have had no issues building the theme, uploading it to the dev environment and testing it - it's all been pretty smooth.
Now I'm trying to upload the same theme (I'm talking exactly the same), to the production site, instead of the development site, and I get the following error in the console:
Error retrieving XXX: ReferenceError: regeneratorRuntime is not defined
at bundle.js?ver=1.0.0:726
at S (bundle.js?ver=1.0.0:726)
at window.initMap (bundle.js?ver=1.0.0:726)
.....
Everything that I've searched for has indicated that people have been getting this issue when trying to build or run their development environments, and it has something to do with their gulp or babel setup, or the packages they're using. So, I'll add my config below... Although I'm stumped as to why the theme builds and runs in one environment error-free, and falls over with this error in another.
gulpfile.babel.js
// Gulp.js configuration
'use strict';
import "regenerator-runtime/runtime.js";
import "core-js/stable";
const
// Gulp and plugins
{ src,
dest,
watch,
series,
parallel
} = require('gulp'),
imagemin = require('gulp-imagemin'),
autoprefixer = require('autoprefixer'),
cssnano = require('cssnano'),
sass = require('gulp-sass'),
sourcemaps = require('gulp-sourcemaps'),
postcss = require('gulp-postcss'),
gulpif = require('gulp-if'),
cleanCss = require('gulp-clean-css'),
yargs = require('yargs'),
del = require('del'),
webpack = require('webpack-stream')
[...]
// Task to build js file as bundle.js
export const scripts = () => {
return src([
js.src + 'map.js',
js.src + 'bundle.js'
])
.pipe(webpack({
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
}
}
}
]
},
optimization:{
namedChunks: true,
minimize: true,
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'async'
},
}
}
},
mode: PRODUCTION ? 'production' : 'development',
devtool: !PRODUCTION ? 'inline-source-map' : false,
output: {
filename: js.filename
},
}))
.pipe(dest(js.build))
}
[...]
.babelrc
{
"presets": [
[
"#babel/preset-env",
{
"targets": "> 0.25%, not dead",
"useBuiltIns": "usage",
"corejs": 3
}
]
],
"plugins": ["#babel/plugin-transform-runtime"]
}
I tried updating the package.json to use #babel/runtime as a dependancy, along with regenerator-runtime, which I didn't think would do anything - and it didn't.
package.json
"browserslist": [
"last 3 and_chr versions",
"last 3 chrome versions",
"last 3 opera versions",
"last 3 ios_saf versions",
"last 3 safari versions"
],
"devDependencies": {
"#babel/core": "^7.10.5",
"#babel/plugin-transform-runtime": "^7.10.5",
"#babel/preset-env": "^7.10.4",
"#babel/register": "^7.10.5",
"autoprefixer": "^9.8.5",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"browser-sync": "^2.26.7",
"core-js": "^3.6.5",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.8.0",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^7.0.1",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-notify": "^3.2.0",
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.1.0",
"gulp-sourcemaps": "^2.6.5",
"scss": "^0.2.4",
"vinyl-named": "^1.1.0",
"webpack-stream": "^5.2.1",
"yargs": "^15.4.1"
},
"dependencies": {
"#babel/runtime": "^7.10.5",
"moment": "^2.27.0",
"regenerator-runtime": "^0.13.5",
"snazzy-info-window": "^1.1.1"
}
The particular piece of code which is throwing the error is in my map.js (pulls custom posts from the wp-rest api, and populates them on the google map), and is below:
import 'regenerator-runtime/runtime'; // top of file
[...]
const getXXX = () => {
try{
async function fetchXXX() {
const res = await fetch(url);
if(!res.ok){
console.log('Error retrieving XXX:', res.status);
throw new Error(res.status);
}
const data = await res.json();
return data;
}
fetchXXX()
.then(data => {
xxx = data;
renderXXX();
})
.catch(error => {
console.log('Error retriving XXX: ', error);
});
} catch (err) {
console.log('Error retrieving XXX: ', err);
}
}
If anyone has any pointers, it would be hugely appreciated.
For anyone who stumbles across this issue in the future (probably unlikely).
It turns out the culprit was the CDN being used in our production environment. I figured out that the bundle.js file I was uploading wasn't the same as was being served up in the site, and turned the CDN off which seemed to fix the issue. :/

Webpack creating separate JS files for few imports

I am trying to build a custom webpack configuration for a complex project. While building I have observed that webpack is generating separate JS file when I import babel-runtime/core-js/json/stringify. Can someone help me understand what's happening here and why webpack is generating a separate JS file.
package.json
{
"name": "react-boilerplate",
"version": "1.0.0",
"description": "A boilerplate for large scale react apps",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "sh -ac 'webpack --mode production ${DEPLOY_TARGET:+--env.target $DEPLOY_TARGET}'",
"build:production": "DEPLOY_TARGET='production' yarn build",
"build:staging": "DEPLOY_TARGET='staging' yarn build"
},
"devDependencies": {
"#babel/core": "^7.6.4",
"#babel/plugin-proposal-class-properties": "^7.5.5",
"#babel/preset-env": "^7.6.3",
"#babel/preset-react": "^7.6.3",
"#typescript-eslint/eslint-plugin": "2.x",
"#typescript-eslint/parser": "2.x",
"babel-eslint": "10.x",
"babel-loader": "^8.0.6",
"babel-preset-react-app": "^9.0.2",
"clean-webpack-plugin": "^3.0.0",
"compression-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.4",
"dotenv": "^8.2.0",
"eslint": "6.x",
"eslint-config-react-app": "^5.0.2",
"eslint-loader": "^3.0.2",
"eslint-plugin-flowtype": "3.x",
"eslint-plugin-import": "2.x",
"eslint-plugin-jsx-a11y": "6.x",
"eslint-plugin-react": "7.x",
"eslint-plugin-react-hooks": "1.x",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"react-hot-loader": "^4.12.15",
"stylelint": "^11.1.1",
"stylelint-config-standard": "^19.0.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-custom-processor-loader": "^0.6.0",
"stylelint-processor-styled-components": "^1.8.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2",
"webpack-merge": "^4.2.2",
"workbox-webpack-plugin": "^4.3.1"
},
"dependencies": {
"lodash": "^4.17.15",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"react-router-dom": "^5.1.2",
},
"peerDependencies": {
"stylelint": "^11.1.1"
}
}
webpack.config.js
const { DefinePlugin } = require('webpack');
const path = require('path');
// Webpack plugins
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWepackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { rootDir } = require('./utils');
const {
entryPath,
getEnvJson,
htmlTemplatePath,
outputDir,
publicDir,
sourceDir,
} = require('./utils');
module.exports = env => ({
// Configure's our app entry points
entry: {
main: entryPath,
},
// Configure's loaders to let webpact know how different extension should be
// loaded when bundling
module: {
rules: [
// Configure's babel loader for transpiling javascript, eslint loader
// for linting javascript, stylelint loader for css linting
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
'babel-loader',
{
loader: 'stylelint-custom-processor-loader',
options: {
configPath: path.resolve(rootDir, '.stylelintrc.js'),
},
},
'eslint-loader',
]
},
// Configure's loaders for images
{
test: /.(png|jpg|jpeg|svg|gif)/,
use: 'file-loader'
},
]
},
// Configure's destination for the bundled code
output: {
path: outputDir,
},
// Configure's additions plugins to be used by webpack
// Order of plugins is important
plugins: [
// Removes all the contents of output folder(but not the folder itself)
// before every webpack build
new CleanWebpackPlugin(),
// Copies all contents of public folder as it is excluding index.html file
new CopyWepackPlugin([
{
from: publicDir,
to: outputDir,
ignore: ['index.html']
}
]),
// Injects target specific enviroment variables
new DefinePlugin({
'process.env': getEnvJson(env.target)
}),
// Uses `public/index.html` and creates a `index.html` file for the app
// by injecting the generated bundles javascript files
new HtmlWebpackPlugin({
template: htmlTemplatePath
}),
],
// Configure's custom behavior for how modules are resolved by webpack
resolve: {
modules: [sourceDir, 'node_modules']
}
});
.babelrc
{
"presets": ["react-app"]
}
That is because of your entryPath.
module.exports = {
entry: {
bundle1: '.src/fileForBundle1.js',
bundle2: '.src/fileForBundle2.js'
},
This would generate two bundles.
Make sure entryPath is not an object of multiple values.
Issue was with the file-loader regex which was incorrectly configured and which resulted in matching babel-runtime/core-js/json/stringify. So file-loader was being used to load it.

Can't specify a custom reporter in mocha options/mocharc/etc

I am trying to develop a custom reporter for mocha output that will be used with protractor. I have developed a good deal of the reporter and if I use the "--reporter" command line argument it works fine. However if I try to specify it in mocharc, or more importantly reporterOptions within the protractor configuration file it can't seem to find the package. Is the command line reporter flag the only way to specify a local/custom reporter? If not, how are you supposed to specify it outside of the command line?
.babelrc:
require:
- '#babel/polyfill'
- '#babel/register'
reporter: './mocha-reporter'
spec: '_src/js/tests/unit/**/*.spec.js'
package.json:
{
"name": "box",
"version": "1.0.0",
"description": "boom!",
"main": "index.js",
"scripts": {
"mocha": "mocha",
"mocha-custom": "mocha -O outputDir=_src/js/tests/reports,testDir=_src/js/tests/unit --reporter mocha-reporter",
"mochawesonme": "mocha --reporter mochawesome --reporter-options reportDir=_src/js/tests/reports,reportFilename=PCMS_unit_test_results",
"check-types": "tsc",
"clean-selenium": "webdriver-manager clean",
"update-selenium": "webdriver-manager update --standalone --versions.standalone=3.8.0",
"start-selenium": "webdriver-manager start --versions.standalone=3.8.0",
"integration-tests": "protractor protractor.conf.js"
},
"devDependencies": {
"#babel/cli": "~7.4.3",
"#babel/core": "~7.4.3",
"#babel/plugin-proposal-class-properties": "7.4.0",
"#babel/plugin-proposal-object-rest-spread": "~7.4.3",
"#babel/plugin-transform-destructuring": "~7.4.3",
"#babel/polyfill": "~7.4.3",
"#babel/preset-env": "~7.4.3",
"#babel/preset-typescript": "~7.3.3",
"#babel/register": "~7.4.0",
"#fortawesome/fontawesome-free": "5.8.1",
"#types/bluebird": "3.5.26",
"#types/jquery": "3.3.29",
"#types/knockout": "~3.4.65",
"#typescript-eslint/eslint-plugin": "~1.7.0",
"#typescript-eslint/parser": "~1.7.0",
"appcache-webpack-plugin": "~1.4.0",
"autoprefixer": "~9.5.1",
"babel-loader": "~8.0.5",
"chai": "~4.2.0",
"chai-as-promised": "7.1.1",
"copy-webpack-plugin": "~5.0.3",
"css-loader": "~2.1.1",
"eslint": "~5.16.0",
"eslint-config-airbnb-base": "~13.1.0",
"eslint-config-airbnb-typescript": "~3.0.0",
"eslint-plugin-import": "~2.17.2",
"file-loader": "~3.0.1",
"html-loader": "~0.5.5",
"html-webpack-plugin": "3.2.0",
"js-yaml": "~3.13.1",
"json-loader": "~0.5.7",
"jszip": "~3.2.1",
"karma": "~4.1.0",
"karma-chai": "~0.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-firefox-launcher": "~1.1.0",
"karma-mocha": "~1.3.0",
"karma-sinon": "~1.0.5",
"karma-webpack": "~3.0.5",
"mini-css-extract-plugin": "~0.6.0",
"mocha": "~6.1.4",
"mocha-reporter": "file:mocha-reporter",
"mochawesome": "~3.1.2",
"mochawesome-report-generator": "3.1.5",
"mochawesome-screenshots": "1.6.0",
"node-sass": "^4.12.0",
"popper.js": "~1.15.0",
"postcss-loader": "~3.0.0",
"protractor": "5.4.2",
"protractor-image-comparison": "3.1.0",
"sass-loader": "~7.1.0",
"sinon": "~7.3.2",
"style-loader": "~0.23.1",
"typescript": "~3.4.5",
"url-loader": "~1.1.2",
"webpack": "~4.30.0",
"webpack-cli": "~3.3.1",
"webpack-dev-server": "~3.3.1"
},
"dependencies": {
"bluebird": "~3.5.4",
"bootstrap": "3.3.7",
"d3": "~5.9.2",
"isomorphic-fetch": "2.2.1",
"jquery": "^3.4.0",
"jquery-ui": "~1.12.1",
"knockout": "~3.5.0",
"knockout-mapping": "~2.6.0",
"lodash": "~4.17.11",
"numeral": "~2.0.6",
"page": "~1.11.4"
}
}
index.js:
import mochaBaseReporter from 'mocha/lib/reporters/base';
import { takeScreenShot } from './javascript/screenShots';
import { populateTestResults } from './javascript/testTree';
import {
getFileContents,
writeToOutputFile,
} from './javascript/fileSystemAccess';
import {
getTemplate,
parseTestsIntoOutput,
addValuesToTemplate,
} from './javascript/templating';
import {
SUCCESS,
FAILURE,
FINISHED,
} from './constants';
const addStyle = template => getFileContents('styles.css')
.then(styles => addValuesToTemplate(template, { styles }))
.catch(error => console.log('file read of styles.css failed', error));
const createReport = (outputDirectory, fileName, data) => getTemplate('report')
.then(template => addValuesToTemplate(template, { 'test-suites': data }))
.then(template => writeToOutputFile(outputDirectory, `${fileName}.html`, template))
.catch(error => console.log('file read of template.html failed', error));
function mochaReporter(runner, environment) {
const tests = {};
const fileName = 'testfile';
const { outputDir, testDir, takeScreenShotOnFailure } = environment.reporterOptions || {};
const outputDirectory = outputDir && `${process.cwd()}/${outputDir}`;
const accumulateTestResults = (test, image) => populateTestResults(test, testDir, tests, image);
mochaBaseReporter.call(this, runner);
runner.on(SUCCESS, accumulateTestResults);
runner.on(FAILURE, test => (
takeScreenShotOnFailure && window
? takeScreenShot()
: Promise.resolve()
).then(image => accumulateTestResults(test, image)));
runner.on(FINISHED, () => {
parseTestsIntoOutput(tests)
.then(addStyle)
.then(template => addValuesToTemplate(template, runner.stats))
.then(html => createReport(outputDirectory, fileName, html))
.then(() => writeToOutputFile(
`${outputDirectory}/history`,
`test-run-${Date.now()}.json`,
JSON.stringify(tests),
));
});
return runner;
}
module.exports = mochaReporter;
protractor.conf:
/* eslint-disable global-require */
/* eslint-disable #typescript-eslint/no-var-requires */
const protractor = require('protractor');
const { join } = require('path');
const testDirectory = '_src/js/tests';
const baseDirectory = `${testDirectory}/integration/`;
// specifies whether tests will be run in parralel or not
const shardTestFiles = true;
// specifies how many browsers/drivers may be run in parralel
const maxInstances = 4;
function onPrepare() {
// register typescript file extensions with the babel compiler
require('#babel/register')({ extensions: ['.js', '.ts'] });
require('#babel/polyfill');
// don't wait for angular (since our app is currently not angular)
protractor.browser.waitForAngularEnabled(false);
// hot fix for protractor strange map behavior
// found here: https://github.com/angular/protractor/issues/2227#issuecomment-337249891
protractor.ElementArrayFinder.prototype.map = function mapHotFix(mapFn) {
return this.reduce((arr, el) => arr.concat(mapFn(el, arr.length)), []);
};
}
exports.config = {
// mocha configuration
framework: 'mocha',
mochaOpts: {
reporter: './mocha-reporter',
reporterOptions: {
outputDir: `${testDirectory}/reports`,
testDir: `${baseDirectory}/endToEnd`,
takeScreenShotOnFailure: true,
},
timeout: 600000,
slow: 3000,
},
seleniumAddress: 'http://localhost:4444/wd/hub',
// turn off promise management in favor of async/await
SELENIUM_PROMISE_MANAGER: false,
// spec config
specs: [`${baseDirectory}/endToEnd/**/*.spec.js`],
// browser configuration
timeout: 100000,
multiCapabilities: [
{
browserName: 'chrome',
shardTestFiles,
maxInstances,
chromeOptions: {
args: [
// 'show-fps-counter=true',
'--headless',
// '--disable-gpu',
'--window-size=1300,1000',
],
},
},
{
browserName: 'firefox',
shardTestFiles,
maxInstances,
'moz:firefoxOptions': {
args: [
'--headless',
],
},
},
],
onPrepare,
plugins: [
{
package: 'protractor-image-comparison',
options: {
baselineFolder: join(process.cwd(), `${baseDirectory}/screenshots/baseline/`),
screenshotPath: join(process.cwd(), `${baseDirectory}/screenshots/tmp/`),
formatImageName: '{tag}-{logName}-{width}x{height}',
savePerInstance: true,
autoSaveBaseline: true,
},
},
],
};
I could not find a way to load the local file directly, however I gave it a package.json and installed it directly to node_modules with npm. To be specific I ran
npm install ./mocha-reporter --save-dev
on my project directory after creating a package.json within the project folder. After some debugging I was able to solve my issue since the package was now a part of node's named packages.

Categories

Resources