fetch-mock Response Does Not Have JSON Method - javascript

I'm trying to get fetch-mock to work in my testing setup, but the response object looks different than expected.
Specifically, it does not have a json method.
Here's the class I'm calling with the actual call to fetch:
import 'whatwg-fetch';
export class Store {
load() {
return fetch("/api", {
method: "get",
headers: {'Content-Type': 'application/json'}
});
}
}
Here is a snippet from the test code:
import fetchMock from 'fetch-mock';
fetchMock.get("*", {code: "1", name: "cde", image: 'hello.jpeg'})
this.store = new Store;
this.store.load().then(response => console.log(response._bodyInit()));
console.log('hello', this.brandStore.brands[0]);
fetchMock.restore();
The console will print:
Response{
type: 'default',
status: 200,
ok: true,
statusText: 'OK',
headers: Headers{map: Object{content-type: ...}},
url: '/api',
_bodyInit: '{"code":"1","name":"cde","image":"hello.jpeg"}',
_bodyText: '{"code":"1","name":"cde","image":"hello.jpeg"}'
}
This error also gets output:
'Unhandled promise rejection', TypeError{line: 4005, sourceURL: 'http://localhost:9876/base/test/stores/BrandStore.spec.js?572679e0c28b63839a5f5829ef1a60b8d62f8b84', stack: 'http://localhost:9876/base/test/stores/BrandStore.spec.js?572679e0c28b63839a5f5829ef1a60b8d62f8b84:4005:168
run#http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:3911:29
http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:3924:31
flush#http://localhost:9876/base/node_modules/babel-polyfill/dist/polyfill.js?00cf5c53ec5ebd52d0521aed551c593eef05a0d6:1209:11'}
My Karma (with Webpack config) looks like:
const webpack = require('webpack');
var argv = require('yargs').argv;
var path = require('path');
let srcPath = path.join(__dirname, '/../src/');
const webpackConfig = {
devtool: 'inline-source-map',
resolve: {
// allow us to import components in tests like:
// import Example from 'components/Example';
root: path.resolve(__dirname, './src'),
// allow us to avoid including extension name
extensions: ['', '.js', '.jsx', '.css', '.scss', '.json'],
// required for enzyme to work properly
alias: {
'sinon': 'sinon/pkg/sinon',
}
},
module: {
// don't run babel-loader through the sinon module
noParse: [
/node_modules\/sinon\//
],
isparta: {
embedSource: true,
noAutoWrap: true,
// these babel options will be passed only to isparta and not to babel-loader
babel: {
presets: ['es2015', 'stage-0', 'react']
}
},
// run babel loader for our tests
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
plugins: ['transform-decorators-legacy'],
presets: ['es2015', 'airbnb', 'stage-1', 'react']
}
},
{
test: /\.json$/, loader: 'json'
},
{
test: /\.scss$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[local]',
'postcss',
'sass'
]
},
{
test: /\.css$/,
exclude: /[\/\\](node_modules|bower_components|public)[\/\\]/,
loaders: [
'style?sourceMap',
'css?modules&importLoaders=1&localIdentName=[local]'
]
}
],
preLoaders: [ { //delays coverage til after tests are run, fixing transpiled source coverage error
test: /\.(jsx|js)$/,
include: path.resolve('src/'),
loader: 'isparta',
} ]
},
plugins: [
new webpack.IgnorePlugin(/node-fetch/)
],
// required for enzyme to work properly
externals: {
'jsdom': 'window',
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': 'window',
'react/addons': true
},
};
module.exports = function(config) {
config.set({
browsers: ['PhantomJS'],
singleRun: !argv.watch,
frameworks: ['mocha', 'chai'],
reporters: ['spec', 'coverage'],
// include some polyfills for babel and phantomjs
files: [
'node_modules/whatwg-fetch/fetch.js',
'node_modules/babel-polyfill/dist/polyfill.js',
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
'test/**/*.js'
],
preprocessors: {
// add webpack as preprocessor
'src/**/*.js': ['webpack', 'sourcemap'],
'test/**/*.js': ['webpack', 'sourcemap']
},
// A lot of people will reuse the same webpack config that they use
// in development for karma but remove any production plugins like UglifyJS etc.
// I chose to just re-write the config so readers can see what it needs to have
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: 'coverage/',
reporters: [
{ type: 'html' },
{ type: 'text' }
]
},
// tell karma all the plugins we're going to be using to prevent warnings
plugins: [
'karma-mocha',
'karma-chai',
'karma-webpack',
'karma-phantomjs-launcher',
'karma-spec-reporter',
'karma-sourcemap-loader',
'karma-coverage'
]
});
};

Related

Getting Unexexpted token caused error due to loader when using Stripe checkout

I am trying to integrate Stripe checkout into a VueJS application, but get the following error when the app compiles;
ERROR in ./node_modules/stripe/lib/utils.js
Module parse failed: Unexpected token (152:24)
You may need an appropriate loader to handle this file type.
| opts.auth = args.pop();
| } else if (utils.isOptionsHash(arg)) {
| const params = {...args.pop()};
|
| const extraKeys = Object.keys(params).filter(
# ./node_modules/stripe/lib/stripe.js 44:14-32
# ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/app/CMS/eCommerce/Checkout.vue
# ./src/app/CMS/eCommerce/Checkout.vue
# ./src/routes.js
# ./src/main.js
# multi (webpack)-dev-server/client?http://localhost:8082 webpack/hot/dev-server ./src/main.js
I happens when i add the following variable to mt Checkout.vue file;
import Stripe from 'stripe';
const stripe = Stripe('MYAPI');
Here is we webpack file
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
filename: 'build.js',
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'style-loader',
'css-loader'
],
},
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]',
outputPath: 'assets/images/'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true,
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
Any advice would be great. Thank you
It seems to me like something went wrong in the file ./src/app/CMS/eCommerce/Checkout.vue.
First: Do both variables arg and args really exist?
Second: In order for the syntax params = {...args.pop()} to work argsmuss be an array of objects
Third: Do you have a babel config file? Because I think you need the babel preset "#babel/preset-env" or some babel plugins like "#babel/plugin-proposal-object-rest-spread" and "#babel/plugin-transform-spread" for babel to transpile the code for the browser...
A minimal babel.config.js can look like this:
module.exports = api => {
api.cache(true);
const presets = [];
const plugins = [];
/*
// If you want to transpile just some syntaxes manually - micromanagement
plugins.push(
[ "#babel/plugin-transform-block-scoping" ],
[ "#babel/plugin-proposal-object-rest-spread" ],
[ "#babel/plugin-transform-classes" ],
[ "#babel/plugin-transform-spread" ],
[ "#babel/plugin-transform-destructuring" ],
[ "#babel/plugin-transform-for-of" ],
[ "#babel/plugin-transform-template-literals" ],
[ "#babel/plugin-transform-arrow-functions", { spec: false } ],
);
*/
// Or let babel transpile everthing
presets.push(
[ "#babel/preset-env" ]
)
return {
presets,
plugins
}
}

Using Imports with .Net, React.Js, and Url.Content

I am using a .Net MVC framework, and trying to render a jsx (React) file that has imports. I am including this file in the razor page (cshtml) through the standard Url.Content injection as follows:
<script src="#Url.Content("~/js/queue/QueueIndex.js")"></script>
<script>
ReactDOM.render(React.createElement(QueueIndex), document.getElementById("queue-index"));
jQuery(window).on("load scroll", function () {
'use strict'; // Start of use strict
// Loader
$("#dvLoading").fadeOut("fast");
});
</script>
If I do not have an import at the top of my React file (QueueIndex.jsx) the page loads just fine. However, I would like to import the react-table package, but if include any imports in my QueueIndex.jsx file, the page breaks.
The error I'm getting is require is not defined.
I think the solution is somewhere in the use of webpack, here is my config:
const webpack = require("webpack");
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
nhqueue: './wwwroot/js/queue/QueueIndex.jsx'
},
output: {
path: __dirname + '/wwwroot/js/',
publicPath: '/wwwroot/js/',
filename: '[name].bundle.js'
},
module: {
preLoaders: [
],
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{ test: /\.tsx?$/, loaders: ['babel', 'ts'] },
{ test: /\.json$ /, loader: "json-loader" },
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: "babel",
query:
{
presets: ['react']
}
}
],
externals: {
"moment": "moment",
},
},
devtool: 'source-map',
target: 'web',
plugins: [
new CleanWebpackPlugin(['./wwwroot/js/*.js'], {
root: __dirname,
verbose: true,
dry: false
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin()
],
resolve: {
extensions: ['', '.jsx', '.js', '.tsx', '.ts']
},
node: {
fs: "empty",
child_process: "empty"
}
}
Unfortunately, I have had no luck there. Please let me know if you have any ideas of how to resolve this issue. Thanks!
Also, Here is the Babel configuration:
{"presets" : ["es2015", "react"]}

Coverage reports with karma and a mix of javascript and typescript src files

I have a project where I use webpack for development/testing and karma as my test runner. This project has source files written half in js and half in ts/tsx. The test suite is written completely in js. I currently use karma-coverage, which shows coverage reports for all my js source files, but it does not support typescript files. All my tests run, there is no problem there, I just would like coverage reports for all my test files. Can anyone point me in the right direction?
Here is my karma.conf.js if this helps.
'use strict';
const webpackCfg = require('./webpack.config')('test');
module.exports = function karmaConfig(config) {
config.set({
browsers: ['Chrome'],
files: [
'test/loadtests.js'
],
port: 8080,
captureTimeout: 60000,
frameworks: [
'mocha',
'chai',
'sinon'
],
client: {
mocha: {}
},
singleRun: true,
reporters: ['mocha', 'coverage', 'junit'],
mochaReporter: {
output: 'autowatch'
},
preprocessors: {
'test/loadtests.js': ['webpack', 'sourcemap']
},
webpack: webpackCfg,
webpackServer: {
noInfo: true
},
junitReporter: {
outputDir: 'coverage',
outputFile: 'junit-result.xml',
useBrowserName: false
},
coverageReporter: {
dir: 'coverage/',
watermarks: {
statements: [70, 80],
functions: [70, 80],
branches: [70, 80],
lines: [70, 80]
},
reporters: [
{ type: 'text' },
{
type: 'html',
subdir: 'html'
},
{
type: 'cobertura',
subdir: 'cobertura'
},
{
type: 'lcovonly',
subdir: 'lcov'
}
]
}
});
};
And the relevant part of my webpack test config
{
devtool: 'inline-source-map',
externals: {
cheerio: 'window',
'react/lib/ExecutionEnvironment': true,
'react/addons': true,
'react/lib/ReactContext': true,
},
module: {
preLoaders: [
{
test: /\.(js|jsx)$/,
loader: 'isparta-loader',
include: [
this.srcPathAbsolute
]
}
],
loaders: [
{
test: /\.cssmodule\.css$/,
loaders: [
'style',
'css?modules&importLoaders=1&localIdentName=[name]-[local]-[hash:base64:5]'
]
},
{
test: /^.((?!cssmodule).)*\.css$/,
loader: 'null-loader'
},
{
test: /\.(sass|scss|less|styl|png|jpg|gif|mp4|ogg|svg|woff|woff2)$/,
loader: 'null-loader'
},
{
test: /\.json$/,
loader: 'json'
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
loader: ['babel', 'ts-loader']
},
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
query: {
presets: ['airbnb']
},
include: [].concat(
this.includedPackages,
[
this.srcPathAbsolute,
this.testPathAbsolute
]
)
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"test"'
})
]
}
After a couple days of soul and google searching amongst hundreds of browser tabs, I have found a working solution. This is using TypeScript 2.x and Webpack 2.x. test.js is my entry point. It could just as easily be test.ts (and it will be eventually). In that entry point, I load my *.spec.js and *.spec.ts files. And then those files import whichever source they need to test from. I have put all the webpack config in the karma.conf.js so it's easier to see:
let myArgs = require('yargs').argv;
let path = require('path');
let webpack = require('webpack');
module.exports = function(config) {
const REPORTS_PATH = myArgs.reportsPath ? myArgs.reportsPath :path.join(__dirname, 'build');
config.set({
basePath: '',
frameworks: ['jasmine', 'es6-shim'],
files: [
'./test.js'
],
exclude: [],
reporters: ['progress', 'spec', 'coverage', 'junit', 'coverage-istanbul'],
preprocessors: {
'./test.js': ['webpack', 'sourcemap']
},
webpackServer: {
noInfo: true // prevent console spamming when running in Karma!
},
webpack: {
devtool: 'inline-source-map',
resolve: {
modules: [
path.resolve('./node_modules'),
path.resolve('./')
],
extensions: ['.js', '.ts', '.css', '.scss']
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
],
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
use: 'source-map-loader',
exclude: [/node_modules/]
},
{
test: /\.ts$/,
use: [{
loader: 'awesome-typescript-loader',
options: {
module: 'commonjs'
},
}]
},
{
test: /\.js$/,
use: [{
loader: 'awesome-typescript-loader',
options: {
entryFileIsJs: true,
transpileOnly: true
}
}],
exclude: [/node_modules/],
},
{
enforce: 'post',
test: /\.(js|ts)$/,
use: [{
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true
}
}],
exclude: [/node_modules/, /\.spec\.(js|ts)$/, /test/]
},
{ test: /\.html/, use: 'raw-loader' },
{ test: /\.(s)?css$/, use: 'null-loader' },
{ test: /\.(png|jpg|jpeg|gif|svg|pdf)$/, use: 'null-loader' },
{ test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'null-loader' },
{ test: /\.(ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: 'null-loader' },
{ test: /\.json$/, use: 'null-loader' }
]
}
},
coverageReporter: {
type: 'in-memory'
},
coverageIstanbulReporter: {
//TODO: Figure out why the 'html' reporter blows up with istanbul-reports (something with absolute path copying files)
reports: ['text-summary', 'cobertura'],
// base output directory
dir: REPORTS_PATH,
fixWebpackSourcePaths: true,
'report-config': {
cobertura: {
file: 'coverage.xml'
},
'text-summary': {
file: null
}
}
},
junitReporter: {
outputDir: `${REPORTS_PATH}/junit/`,
outputFile: 'jasmine-results.xml'
},
// Hide webpack build information from output
webpackMiddleware: {
stats: {
chunkModules: false,
colors: true
},
noInfo: 'errors-only'
},
colors: true,
logLevel: config.LOG_ERROR,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
autoWatchBatchDelay: 400
});
};
So, the key pieces here are awesome-typescript-loader, karma-coverage-istanbul-reporter, source-map-loader, and in the tsconfig.json, you want to set these in compilerOptions:
"inlineSourceMap": true,
"sourceMap": false,
I indicated a TODO about the html report. It DOES work but I couldn't get it to output to a custom directory (subdir) with TypeScript files as a part of it. JavaScript only worked fine. Could be a windows-specific problem with istanbul-reports. If you add html to the reports array under coverageIstanbulReporter, you should see it in your project dir but may have problems putting it in REPORTS_PATH.
It's also worth noting that I had a lot of luck using karma-remap-coverage instead of karma-coverage-istanbul-reporter but the former would not correctly generate cobertura reports for coverage which is what I needed for Jenkins.

Why doesn't my karma support for...of statement?

I have setup karma as my unit test framework. But it doesn't compile below code:
let {btnData} = this.props
let buttons = []
for (let btn of btnData) {
btn = {...btnCategories[btn.type], ...btn}
buttons.push(btn)
}
I got below error on the line of for loop. Why doesn't it recognise for...of statement?
Can't find variable: Symbol
Below is my karma config file. My project includes webpack, reactjs and use karma, mocha, chai, enzyme as test libraries.
var path = require('path')
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'chai'],
files: [
'../test/**/*.js'
],
preprocessors: {
// add webpack as preprocessor
'../src/**/*.js': ['webpack', 'sourcemap'],
'../test/**/*.js': ['webpack', 'sourcemap'],
'../src/**/*.less': ['webpack', 'sourcemap']
},
webpack: { //kind of a copy of your webpack config
devtool: 'inline-source-map', //just do inline source maps instead of the default
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['airbnb']
}
},
{
test: /\.json$/,
loader: 'json',
},{
test: /\.less$/,
loader: "style!css!less",
},
]
},
externals: {
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true,
'react/addons': true
},
resolve: {
alias: {
app: path.join(__dirname, '../src/js')
}
}
},
webpackServer: {
noInfo: true //please don't spam the console when running in karma!
},
plugins: [
'karma-webpack',
'karma-jasmine',
'karma-sourcemap-loader',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-mocha',
'karma-chai',
'karma-mocha-reporter'
],
babelPreprocessor: {
options: {
presets: ['airbnb']
}
},
reporters: ['mocha'],
// reporter options
mochaReporter: {
colors: {
success: 'blue',
info: 'bgGreen',
warning: 'cyan',
error: 'red'
},
symbols: {
success: '+',
info: '#',
warning: '!',
error: 'x'
}
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
})
};

How Can I Exclude Spec Files from Code Coverage with Karma using Webpack and Babel?

Problem
I'm working on a small react-redux project configured with webpack, babel, and karma. I added code coverage to karma, but I couldn't find a way to exclude the test files from coverage. So my code coverage has spec files.
How can I exclude these spec files from coverage?
I tried to use a regex expression to exclude the spec files, but since it was being loaded by webpack, it didn't work.
tests.webpack.js
const context = require.context('./src', true, /.+\Spec\.js$/);
context.keys().forEach(context);
module.exports = context;
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
path: __dirname,
filename: 'dist/bundle.js'
},
devtool: 'source-map',
resolve: {
extensions: ['', '.js', '.scss'],
modulesDirectories: [
'node_modules',
'src'
]
},
module: {
preLoaders: [
{
test: /\.js$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
],
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
],
},
};
karma.config.js
var path = require('path');
module.exports = function (config) {
config.set({
browsers: ['PhantomJS'],
singleRun: true,
frameworks: ['mocha', 'sinon-chai'],
files: [
'tests.webpack.js'
],
preprocessors: {
'tests.webpack.js': ['webpack', 'sourcemap']
},
reporters: ['mocha', 'osx', 'coverage'],
webpack: {
module: {
preLoaders: [
{
test: /\.js$/,
exclude: [
path.resolve('src/'),
path.resolve('node_modules/')
],
loader: 'babel'
},
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'isparta'
}
]
}
},
webpackServer: {
noInfo: true
},
coverageReporter: {
type: 'html',
dir: 'coverage/'
}
});
};
This is how I do it on my project, where I have all my tests in __test__ folders included with each component. You should be able to change this to a regex something like this /\.spec.js$/.
karmaConfig.webpack.module.preLoaders = [{
test : /\.(js|jsx)$/,
include : new RegExp(config.dir_client),
loader : 'isparta',
exclude : [
/node_modules/,
/__test__/,
],
}];
In your case you need to add exclude to this bit of your config.
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'isparta'
}
I solved this by filtering out the results I didn't want by placing a .filter() before the .forEach(context).
const includes = require('lodash/includes');
const context = require.context('./src', true, /\.test\.js$/);
context.keys()
.filter(file => includes(file, './api/') === false)
.forEach(context);
You could also write it directly into the .forEach().
const includes = require('lodash/includes');
const context = require.context('./src', true, /\.test\.js$/);
context.keys()
.forEach(file => {
if (includes(file, './api/') === false) {
context(file);
}
});
If you don't use Lodash, you can use:
file.indexOf('./api/') === -1

Categories

Resources