Using react-hot-loader with custom babel preset - babeljs

My app doesn't support older browsers, and I like to trim down the set of Babel transforms to make the code easier to debug (so that the code in the debugger looks like more the original source).
However, when I migrate to react-hot-loader 3, this no longer works. That is, I can get RHL 3 to work with the standard es2015 preset, but not with my custom set of transforms. What happens is that the react components are rendered but never mounted, and won't respond to any events.
The set of transforms I am trying to use is:
var babel_plugins = [
'transform-runtime',
'transform-object-rest-spread',
// Transforms needed for modern browsers only
'babel-plugin-check-es2015-constants',
'babel-plugin-transform-es2015-block-scoping',
'babel-plugin-transform-es2015-function-name',
'babel-plugin-transform-es2015-parameters',
'babel-plugin-transform-es2015-destructuring',
// No longer needed with Webpack 2
// 'babel-plugin-transform-es2015-modules-commonjs',
'react-hot-loader/babel',
];
In response to the comments, here's more information:
Here's how I'm using the AppContainer:
export default (
<AppContainer>
<Router history={browserHistory}>
(My routes here...)
</Router>
</AppContainer>
);
And here's my dev server setup:
// Adjust the config for hot reloading.
config.entry = {
main: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://127.0.0.1:8000', // WebpackDevServer host and port
'webpack/hot/only-dev-server', // "only" prevents reload on syntax errors
'./src/main.js', // Your appʼs entry point
],
frame: './src/frame_main.js', // Entry point for popup tab
};
config.plugins.push(new webpack.HotModuleReplacementPlugin());
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
contentBase: path.resolve(__dirname, '../builds/'),
historyApiFallback: true,
stats: 'errors-only',
hot: true,
});
server.listen(8000, '127.0.0.1', () => {});
Here's the relevant portion of my webpack config:
test: /\.jsx?$/,
include: __dirname + '/src',
exclude: __dirname + '/src/libs',
use: [
{
loader: 'babel-loader',
options: {
plugins: babel_plugins,
presets: babel_presets
},
},
{
loader: 'eslint-loader',
},
]

Related

Why is my Workbox GenerateSW showing my offline page while connected?

I'm trying to setup my offline page using Workbox GenerateSW() and running into an issue where on the first load after I clear site data and hard refresh displays my homepage, but on subsequent loads I am getting the offline page I set up even though I'm online. I have a multi page PHP app that has the assets served up by a CDN. I run the GenerateSW() task in a JS file called by an npm node script.
Here is my GenerateSW() code...
// Pull in .env file values...
const dotEnv = require('dotenv').config({ path: '/var/www/my-project/sites/www/.env' });
if (dotEnv.error) {
throw dotEnv.error
}
const {generateSW} = require('workbox-build');
// Used to break cache on generate of new SW where file is composed of multiple pieces that can't be watched.
const genRanHex = (size = 24) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');
const mode = 'development';
generateSW({
swDest: './sites/www/public/service-worker.js',
skipWaiting: true,
clientsClaim: true,
cleanupOutdatedCaches: true,
cacheId: genRanHex(),
mode: mode,
navigateFallback: '/offline',
offlineGoogleAnalytics: mode === 'production',
globDirectory: './sites/assets/public',
globPatterns: [
'img/shell/**/*.{svg,png}',
'dist/**/*.{js,css}',
'manifest.json'
],
modifyURLPrefix: {
'dist/': `${dotEnv.parsed.APPLICATION_ASSETS_CDN}/dist/`,
'img/shell/': `${dotEnv.parsed.APPLICATION_ASSETS_CDN}/img/shell/`,
},
ignoreURLParametersMatching: [/v/],
additionalManifestEntries: [
{
"url": "/offline",
"revision": genRanHex()
}
],
runtimeCaching: []
}).then(({count, size}) => {
console.log(`Generated service worker, which will precache ${count} files, totaling ${size} bytes.`);
}).catch(console.error);
navigateFallback is not actually offline page. From workbox docs:
If specified, all navigation requests for URLs that aren't precached will be fulfilled with the HTML at the URL provided. You must pass in the URL of an HTML document that is listed in your precache manifest. This is meant to be used in a Single Page App scenario, in which you want all navigations to use common App Shell HTML.
For offline page, this question might help.
So the accepted answer was correct in my misuse of navigateFallback which I was trying to use as an offline fallback for non cached routes. After some digging and tinkering, I found the correct way to go about it. The important part that I missed or was not documented well enough on Workbox is that the offline fallback happens at the runtimeCache level...
// Pull in .env file values...
const dotEnv = require('dotenv').config({ path: '/var/www/my-project/sites/www/.env' });
if (dotEnv.error) {
throw dotEnv.error
}
const {generateSW} = require('workbox-build');
// Used to break cache on generate of new SW where file is composed of multiple pieces that can't be watched.
const genRanHex = (size = 24) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');
const mode = 'development';
generateSW({
swDest: './sites/www/public/service-worker.js',
skipWaiting: true,
clientsClaim: true,
cleanupOutdatedCaches: true,
cacheId: genRanHex(),
mode: mode,
offlineGoogleAnalytics: mode === 'production',
globDirectory: './sites/assets/public',
globPatterns: [
'img/shell/**/*.{svg,png}',
'dist/**/*.{js,css}',
'manifest.json'
],
modifyURLPrefix: {
'dist/': `${dotEnv.parsed.APPLICATION_ASSETS_CDN}/dist/`,
'img/shell/': `${dotEnv.parsed.APPLICATION_ASSETS_CDN}/img/shell/`,
},
ignoreURLParametersMatching: [/v/],
additionalManifestEntries: [
{
"url": "/offline",
"revision": genRanHex()
}
],
runtimeCaching: [
{
urlPattern: /^https:\/\/([\w+\.\-]+www\.mysite\.tv)(|\/.*)$/,
handler: 'StaleWhileRevalidate',
options: {
cacheName: 'core',
precacheFallback: {
fallbackURL: '/offline' // THIS IS THE KEY
}
}
}
]
}).then(({count, size}) => {
console.log(`Generated service worker, which will precache ${count} files, totaling ${size} bytes.`);
}).catch(console.error);

Swagger Tools Production Build Node js

We implemented the swagger in our nodeJs application. As of now we are created production build using webpack and remove the controller and services file.
bin/www.js
const YAML = require('yamljs');
const swaggerTools = require('swagger-tools');
const swaggerDoc = YAML.safeLoad('./swagger.yaml');
// swaggerRouter configuration
const swaggerOptions = {
controllers: path.join(__dirname, '../public/javascripts/controllers'),
useStubs: true, // Conditionally turn on stubs (mock mode)
};
// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, (middleware) => {
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());
// validate the security using JWT token
app.use(middleware.swaggerSecurity({
Bearer: auth.verifyToken
}));
// Validate Swagger requests
app.use(middleware.swaggerValidator({
validateResponse: true
}));
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(swaggerOptions));
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi());
});
If we did the same in production build and the swagger middleware expecting the same path to resolve. after build we delete the public folder.
Webpack code
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: {
server: './bin/www',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'server.build.js',
},
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
},
externals: [nodeExternals()],
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};
Pleas help us to create a build using swagger middleware
Thanks in advance
Swagger tools is not a package bundler like webpack. So you will still need to provide it the controller files. Since you are deleting /public from prod then there is no way for swagger tools middleware to get the files it needs. Webpack in this case is basically building a dist from your code which is why it's ok to delete the controller and services.

Using Karma + Jasmine, what is the best way to run only one test at a time?

Is the best way to do that, simply to use the .only flag?
However, if I used describe.only(, I get
Uncaught TypeError: describe.only is not a function
So how can I run/debug only one test at a time?
Here is my karma.conf.js file:
const path = require('path');
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: [
'./node_modules/angular/angular.js',
'./node_modules/angular-ui-router/release/angular-ui-router.js',
'./node_modules/angular-mocks/angular-mocks.js',
// './public/pages/admin/specs/abc.js'
'./public/dist/app-production.js',
// './public/**/*.spec.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: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['spec', 'junit', /*progress*/],
junitReporter: {
outputDir: 'karma-results',
outputFile: 'karma-results.xml'
},
// 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_WARN'],
// 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: [/*Chrome*/ 'PhantomJS'],
// process.env.USER === dftjenkins
plugins: [
'karma-phantomjs-launcher',
'karma-chrome-launcher',
'karma-jasmine',
'karma-junit-reporter',
'karma-spec-reporter'
],
// 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: 5
})
};
The solution I have for the moment works quite well, all I do is change one line of our karma.conf.js file, like so:
before:
files: [
'./node_modules/angular/angular.js',
'./node_modules/angular-ui-router/release/angular-ui-router.js',
'./node_modules/angular-mocks/angular-mocks.js',
'./public/dist/app-production.js',
'./public/**/*.spec.js'
],
after:
files: [
'./node_modules/angular/angular.js',
'./node_modules/angular-ui-router/release/angular-ui-router.js',
'./node_modules/angular-mocks/angular-mocks.js',
'./public/dist/app-production.js',
process.env.KARMA_TEST_PATH || './public/**/*.spec.js'
],
now your just run karma like so:
KARMA_TEST_PATH=public/pages/x/specs/foo.spec.js karma start
and it will run that single test instead of all your specs.

SystemJS and KarmaJS: TypeError: System.import is not a function

I am trying to get my project working with Karma and SystemJS. I am using the karma-systemjs plugin with karma.
I keep getting the error below about System.import.
I believe it is because SystemJS is not being loaded by the time the karma-systemjs plugin runs. Please tell me what I am doing wrong.
Project structure
SystemJS configuration (system.conf.js)
System.config({
baseUrl: '',
defaultJSExtensions: true,
map: {
'jquery': 'vendor/kendo/js/jquery.min.js',
'angular': 'vendor/kendo/js/angular.js',
'kendo': 'vendor/kendo/js/kendo.all.min.js',
'angular-mocks': 'vendor/bower_components/angular-mocks/angular-mocks.js',
'angular-ui-router': 'vendor/bower_components/angular-ui-router/release/angular-ui-router.min.js',
'angular-toastr': 'vendor/bower_components/angular-toastr/dist/angular-toastr.tpls.min.js',
'angular-local-storage': 'vendor/bower_components/angular-local-storage/dist/angular-local-storage.min.js'
},
paths: {
'systemjs': 'vendor/bower_components/system.js/dist/system.js',
'system-polyfills': 'vendor/bower_components/system.js/dist/system-polyfills.js'
},
meta: {
'vendor/kendo/js/jquery.min.js': {
format: 'global',
exports: '$'
},
'vendor/kendo/js/angular.js': {
format: 'global',
deps: [
'vendor/kendo/js/jquery.min.js'
],
exports: 'angular'
},
'vendor/kendo/js/kendo.all.min.js': {
format: 'global',
deps: [
'vendor/kendo/js/angular.js'
],
exports: 'kendo'
},
'vendor/bower_components/angular-ui-router/release/angular-ui-router.min.js': {
format: 'global',
deps: [
'vendor/kendo/js/angular.js'
]
},
'vendor/bower_components/angular-mocks/angular-mocks.js': {
format: 'global',
deps: [
'vendor/kendo/js/angular.js'
],
exports: 'angular.mock'
},
'vendor/bower_components/angular-toastr/dist/angular-toastr.tpls.min.js': {
format: 'global',
deps: [
'vendor/kendo/js/angular.js'
]
},
'vendor/bower_components/angular-local-storage/dist/angular-local-storage.min': {
format: 'global',
deps: [
'vendor/kendo/js/angular.js'
]
}
}
});
Promise.all([
System.import('kendo'),
System.import('angular-mocks'),
System.import('angular-ui-router'),
System.import('angular-toastr'),
System.import('angular-local-storage')
]).then(function () {
System.import('angular')
.then(function (angular) {
System.import('ng/app/app.module')
.then(function (app) {
angular.bootstrap(document, ['s9.app']);
}, function (err) {
console.log(err);
});
}, function (err) {
console.log(err);
});
});
//# sourceMappingURL=system.conf.js.map
karma.conf.js
// Karma configuration
var configure = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '.',
transpiler: null,
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['systemjs', 'jasmine'],
systemjs: {
// Path to your SystemJS configuration file
configFile: 'system.conf.js',
// Patterns for files that you want Karma to make available, but not loaded until a module
// requests them. eg. Third-party libraries.
serveFiles: [
'vendor/kendo/js/**/*.js',
'vendor/bower_components/**/*.js',
'ng/**/*.js',
'test/**/*Spec.js'
],
config: {
paths: {
'systemjs': 'vendor/bower_components/system.js/dist/system.js',
'system-polyfills': 'vendor/bower_components/system.js/dist/system-polyfills.js'
}
}
},
// list of files / patterns to load in the browser
files: [
{pattern: 'vendor/kendo/js/**/*.js', included: false},
{pattern: 'vendor/bower_components/**/*.js', included: false},
{pattern: 'ng/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false}
],
// 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: {},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// 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_DEBUG,
// 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: ['PhantomJS'],
// 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: Infinity
});
};
module.exports = configure;
//# sourceMappingURL=karma.conf.js.map
Error
I fixed this by moving the bootstrap code out of the config code. Apparently when using the karma-systemjs plugin System.import is not available yet when this is called (although it is at normal runtime).
What I did: I moved the bootstrap code (i.e. Promise.all([....) into into a separate file called bootstrap.js (name is not important) and then in my index.html I added them in this order:
Also from this link (the karma system js plugin author says): https://github.com/rolaveric/karma-systemjs/issues/71
I see the problem. It's because you've got your bootstrapping code
(eg. System.import() calls) inside your SystemJS config file -
system.conf.js karma-systemjs expects just a simple System.config()
call that it can then intercept to find out where your transpiler and
polyfills are. It does this by evaluating your config file with a fake
System object which simply records whatever is passed to
System.config(). This fake object has no System.import() method, which
causes your error.
I'd recommend moving your bootstrapping code into a separate file (I
personally put it in a script tag with my HTML). Otherwise you'll run
into similar problems if you try to use systemjs-builder, and you
probably don't want angular.bootstrap() to be called at the start of
your unit tests.

browserify/karma/angular.js "TypeError: Cannot read property '$injector' of null" when second test uses "angular.mock.inject", "currentSpec" is null

I have an Angular.js app and am experimenting with using it with Browserify. The app works, but I want to run tests too, I have two jasmine tests that I run with karma. I user browserify to give me access to angular.js and angular-mocks.js and other test fixtures within the tests.
Versions are:-
"angular": "^1.4.0",
"angular-mocks": "^1.4.0",
"browserify": "^10.2.3",
"karma": "^0.12.32",
"karma-browserify": "^4.2.1",
"karma-chrome-launcher": "^0.1.12",
"karma-coffee-preprocessor": "^0.2.1",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4",
If I run the tests individually (by commenting one or the other from the karma.conf file) they both work OK. (yey!)
But if I run them both I get this error
TypeError: Cannot read property '$injector' of null
at Object.workFn (/tmp/3efdb16f2047e981872d82fd8db9c0a8.browserify:2272:22 <- node_modules/angular-mocks/angular-mocks.js:2271:0)
looking at line 2271 of the angular.mocks.js It reads
if (currentSpec.$injector) {
So clearly currentSpec is somehow now null.
I have isolated the problem to when I call "angular.mock.inject" in the second test.
beforeEach(angular.mock.inject(function (_GridUtilService_) {
gridUtilService = _GridUtilService_;
}));
If I comment this out it works, but obviously I can't then run a test n my gridUtilService.
Does anyone know how to run two (or more :-) angular-mock jasmine tests with karma and browserify?
below are my tests, karma.conf file. the Angular services work when deployed but for this purpose they can simply be dumb services that do nothing.
karma.conf:-
// Karma configuration
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: ['browserify', 'jasmine'],
// list of files / patterns to load in the browser
files: [
'src/main/assets/js/**/*.js',
// 'src/test/**/*.js'
'src/test/services/SettingUtil*.js',
'src/test/services/GridUtil*.js'
],
// list of files to exclude
exclude: [
'src/main/assets/js/**/app-config.js'
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/main/assets/js/**/*.js': ['browserify'],
'src/test/**/*.js': ['browserify']
},
browserify: {
debug: true,
extensions: ['.js', '.coffee', '.hbs']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// 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_DEBUG,
// 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: ['PhantomJS', 'Chrome'],
// browsers: ['PhantomJS'],
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
src/test/services/SettingUtilServiceTest.js:
'use strict';
describe("SettingUtilServiceTest.", function() {
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
require('angular');
require('angular-mocks');
// can't do below see error at https://github.com/xdissent/karma-browserify/issues/10
//beforeEach(module('dpServices'));
//so need todo this
beforeEach(angular.mock.module('dpServices'));
var fixtures = require('./serviceFixtures.js');
var sus = fixtures.settingUtilServiceTestFixtures;
var ts1 = sus.tablesetting1;
var ts2 = sus.tablesetting2;
var settingUtilService;
beforeEach(angular.mock.inject(function (_settingUtilService_) {
settingUtilService = _settingUtilService_;
}));
it('should return an object containing mins and maxs from function minMaxes()', function() {
expect(ts1).toBeDefined();
expect(ts2).toBeDefined();
var minMaxs = settingUtilService.minMaxs(ts1);
var mins = minMaxs.mins;
expect(mins).toBeDefined();
var maxs = minMaxs.maxs;
expect(maxs).toBeDefined();
});
});
src/test/services/GridUtilServiceTest.js:
'use strict';
describe("GridUtilServiceTest.", function() {
it("is a set of tests to test GridUtilService.", function() {
expect(true).toBe(true);
});
require('angular');
require('angular-mocks');
// can't do below see error at https://github.com/xdissent/karma-browserify/issues/10
// beforeEach(module('dpServices'));
//so need todo this
beforeEach(angular.mock.module('dpServices'));
var fixtures = require('./gridFixtures.js');
var gridFix = fixtures.gridUtilServiceTestFixtures;
var ts1 = gridFix.tablesetting1;
var ts2 = gridFix.tablesetting2;
var ts3 = gridFix.tablesetting3;
var gridUtilService;
beforeEach(angular.mock.inject(function (_GridUtilService_) {
gridUtilService = _GridUtilService_;
}));
it('should return an object containing mins and maxs from function minMaxes()', function() {
expect(ts1).toBeDefined();
expect(ts2).toBeDefined();
expect(ts3).toBeDefined();
});
});
If you need access to the angular setup I can provide it (split into multiple files using browserify's require() function and built with gulp... but as I say the app runs ok and the tests only fail when there are two tests, so I think the issue is with karma-jasmine and angular-mocks or overwriting the currentSpec variable.
If anyone knows how to split my angular tests into multiple tests (I don't want a monolithic angular test) without the error message all help is appreciated. thanks.
I had the same issue, the issue for me was because I was requiring angular and angular-mocks exactly as you were inside each describe block. I moved the two lines
require('angular');
require('angular-mocks');
above the describe blocks and made sure to only call them once.