TDD Browserify and ReactJS - mocha.js

I'm trying to find a good, clean, way to test React components. I'm liking the idea of mochify as it looks like it abstracts a lot of the hassle of test runners, works with webdriver/saucelabs, etc.
The trouble is that I'm using Browserify with various transforms for jsx, coffee, less, etc from the command line. And can't find how get mochify to run those transforms.
How do I do this?
Or is there a better option out there... Karma maybe?
Thanks

Browserify transforms can also be specified in package.json, for example:
...
"devDependencies": {
"browserify": "*",
"coffeeify": "^0.6.0",
"mocha": "*",
"mochify": "*",
"reactify": "^0.13.1"
},
"browserify": {
"transform": [
"coffeeify",
"reactify"
]
},
...
In your test files, just requires the actual component file using relative path, and write tests as you normally do with mocha:
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var MyComponent = require('../src/app/MyComponent');
...

Edit: Mochify now supports additional transforms and plugins with --transform and --plugin.
This problem will be addressed in a future release of Mochify.
Make sure to watch the issue on GitHub.

Related

NG-ANTD nz-tslint-rules migration not working

I was trying to update our production project which holds 500+ modules and we certainly need this tool to make it work because manually doing so would be a nightmare. I've been the whole afternoon trying to make it work even copying and pasting your import example and haven't manage to do so.
Our imports are like following in the whole project:
import {
NzTableModule,
NzCheckboxModule,
NzInputModule,
NzFormModule,
NzSelectModule,
NzDrawerModule,
NzDividerModule,
NzToolTipModule,
NzDatePickerModule,
} from 'ng-zorro-antd';
I'm using the following config:
{
"rulesDirectory": [
"nz-tslint-rules"
],
"rules": {
"nz-secondary-entry-imports": true
}
}
package.json:
"ng-zorro-antd": "^9.3.0",
"typescript": "~3.8.3",
"nz-tslint-rules": "^0.901.2",
"#angular/core": "~9.1.12",
I'm executing the following command from the app root:
"tslint --project ."
I've managed to be sure about the script execution with a console log in the nzSecondaryEntryImportsRule.js file
Also I've notice that:
tsutils.isImportDeclaration(node)
Always returns false therefore it continues to the next iteration in the for loop
I'd appreciate any help on this.
I guess because the global version is too low.
here are three solutions:
upgrade your global tslint
npm install tslint -g
add the command to the scripts in package.json, and then use npm run lint:fix
{
"scripts": {
"lint:fix": "tslint --project tsconfig.json --fix"
}
}
run from node_modules/.bin/tslint
node_modules/.bin/tslint --project tsconfig.json --fix

Internationalization (i18n) in Angular 8

I am working on the requirement on Angular 8.
I need a feature that translates the UI on the local languages based on the locality So I am going through the Internationalization (i18n) feature in Angular 8.
I have understood the functionality and I am having one doubt.
to translate the page do I need to add i18 tags in all components?
can anyone give me some guidance on this?
Thanks in Advance.
Recently created an article on that topic ...
Internationalization
Introduction
The Introduction of ngx-i18nsupport sums up the problem pretty well
Angular has a specific way of dealing with internationalization (i18n). It is described in the official documentation Angular Cookbook Internationalization (i18n).
Said in one sentence,
markup your strings to translate in your templates with an attribute i18n
run the Angular extraction tool (ng-xi18n) to extract the strings in an XML Format called [XLIFF-1.2]
copy and then translate the extracted file for every language you plan to support
run the ng compiler to generate a special version of your app for the different languages
But there are some maior gaps in the workflow. That´s where this tool comes into play.
First, you have to create a complete translation, otherwise, the ng compiler will not generate a version. It is not possible to run with partial translation.
Second, whenever you change something in your app, you have to regenerate the xliff, but there is no documented way how to merge this with the already existing translated files. There are new translation unit, that you have to merge in, and there are translation units, that do not exist any more.
We're going to use the ngx-i18nsupport-package to solve this issue.
Prepare Angular-App for i18n
Install Package #angular/localize using the angular-cli
ng add #angular/localize
Add the i18n-section to your angular.json in your project-section. Add the languages you need and change the source of your translations (the language you use as default in code/html) if required NOT RECOMMENDED STICK WITH EN IF EVER POSSIBLE.
Also make sure to set localize to true for your production-configuration.
{
...
"projects": {
"yourprojectname": {
"i18n": {
"sourceLocale": "en",
"locales": {
"de": "src/locale/messages.de.xlf",
"fr": "src/locale/messages.fr.xlf",
"it": "src/locale/messages.it.xlf"
}
},
...
"architect": {
"build": {
...
"configurations": {
"production": {
"localize": true,
...
Install ngx-i18nsupport
Run the following command to install ngx-i18nsupport
npm install -g ngx-i18nsupport
Configure xlf-merge
Add the following block the root-section of package.json and change it for your needs.
"xliffmergeOptions": {
"srcDir": "src/locale",
"languages": [
"de",
"fr",
"it"
],
"preserveOrder": true,
"beautifyOutput": true
}
languages
languages your app needs to support. Make sure it matches the i18n-definition your angular.json!
srcDir
output-dir for translation-files. Make sure it matches the i18n-definition your angular.json!
preserveOrder
Ensures the order of you translation isn't changed (not ordered to abc or whatever). This makes it easier to compare different version of the translation files.
beatifyOutput
formats xml nicely
Add some translations to your code
Make sure you have actual translations in your app like
<p i18n>Some random pagagraph that needs translation</p>
or
alert($localize `User ${username} doesn't exist!`);
Generate Translation Files
Run the following command to generate translation files. If you changed the --output-path make sure to change it accordingly.
ng extract-i18n --output-path src/locale
Call xliffmerge now to fix the issues mentioned in the introduction
xliffmerge
Recommendation Add this Command to the scrips section in your
package.json
"scripts": {
"translate": "ng extract-i18n --output-path src/locale && xliffmerge",
"xliffmerge": "xliffmerge",
...
You can run npm run translate any time you want to upate translations.
Test your app in a different language
You may want to test how your app looks translated for a specific language.
Add a build-configurations and serve-options to set the localize-language for each language used in your app.
HINT Don't forget to replace yourprojectname
angular.json
{
...
"projects": {
"yourprojectname": {
...
"architect": {
"build": {
...
"configurations": {
"de": {
"localize": ["de"]
},
"fr": {
"localize": ["fr"]
},
"it": {
"localize": ["it"]
}
...
}
},
"serve": {
...
"configurations": {
...
"development-de": {
"browserTarget": "yourprojectname:build:development,de"
},
"development-fr": {
"browserTarget": "yourprojectname:build:development,fr"
},
"development-it": {
"browserTarget": "yourprojectname:build:development,it"
}
Run your app in the desired language
ng serve -o --configuration=development-de
Recommendation Add a script starting your app in your apps supported langauges simultanialy each language on a different port
package.json
"scripts": {
"start": "ng serve -o",
"start-de": "ng serve -o --configuration=development-de --port=4201",
"start-fr": "ng serve -o --configuration=development-fr --port=4202",
"start-it": "ng serve -o --configuration=development-it --port=4203",
...
Now you can run your app simultaneously in any language you like
npm run start-de.
Have Fun!
😄

How to prevent Webpack from running several times from Makefile recipes

This is, presumably, more a make than a webpack question.
I'm using good ol' make to manage dependencies and builds, and webpack for building JS components. Example:
Makefile:
foo.js: src/foo.js
webpack -p
bar.js: src/bar.js
webpack -p
webpack.config.js:
var webpack = require('webpack');
module.exports = {
entry: {
'foo': './src/foo.js',
'bar': './src/bar.js',
},
output: {
path: './',
filename: '[name].js',
}
};
Quite obviously, every time when any of src/{foo,bar}.js changes, Webpack runs and builds both files. This might not be fixable, as I've read that this is on purpose (to cater for possible interactions between the modules).
However, when both change, Webpack will run twice, because the recipes don't know of each other. This is unnecessary and gets out of hand quickly.
Is there any possibility to "collect" the files and make Webpack only run once, independently of how many source files changed?
You could specify the entry point from the command line:
foo.js: src/foo.js package.json
webpack -p --entry src/foo.js
bar.js: src/bar.js package.json
webpack -p --entry src/bar.js
This answer set me on the right track. GNU Make runs recipes of so-called pattern rules only once. So changing my Makefile to this does the trick of running Webpack exactly once:
foo.j% bar.j%:
webpack -p
foo.js: src/foo.js
bar.js: src/bar.js

How to run mocha tests with webpack when you don't have a single entry point to tests?

I'm trying to convert a project from browserify+mochify to webpack.
The webpack docs demonstrate how to use mocha-loader to run the tests with webpack-dev-server, but assumes a single entry point into the tests.
All the existing tests were designed with mochify in mind which does not require a single entry point as it recursively bundles ./test/*.js.
The setup below sort of works for me. It still uses mochify to run the tests (because it has all the phantomjs interfacing), but doesn't rely on anything from browserify. If you run webpack --watch, it reruns all tests when a file changes.
webpack.config.js:
var path = require("path");
var child_process = require('child_process');
module.exports = {
entry: {
tests: "./tests.js"
},
output: {
filename: "tests.js", // Should be a unique name
path: "/tmp"
},
plugins: [
// Automatically run all tests when webpack is done
function () {
this.plugin("done", function (stats) {
child_process.execSync('mochify /tmp/tests.js', { stdio: 'inherit'});
});
}
],
};
tests.js:
// List all test dirs here if you have multiple
var contexts = [
require.context('./dir1/test', true, /\.js$/),
require.context('./dir2/test', true, /\.js$/)
];
contexts.forEach(function (context) {
context.keys().forEach(context);
});
Another approach is described here: https://stackoverflow.com/a/32386750/675011
This is not exactly an answer, but it solved the problem for me. The reason I wanted to combine mochify and webpack was that I wanted to use the browser console to debug my mocha tests. Since my mocha tests themselves don't rely on a browser, it was enough for me to finally realize I could use a node debugger and it would bring up the Chrome console, (almost) solving my problem. node-inspector is the node debugger, but I'm using babel, so I needed babel-node-debug, but that doesn't yet work with babel6, but there's an unmerged pull request that fixes it: https://github.com/CrabDude/babel-node-debug/pull/12.

Yeoman angular-fullstack ckeditor production

I'm using yeoman's angular-fullstack generator with default parameters.
I would like to use ckeditor with https://github.com/lemonde/angular-ckeditor , so I extended my bower.json with the following lines:
"ckeditor": "#full/4.4.7",
"angular-ckeditor": "~0.4.2"
It works well in development mode ( grunt serve ), but it fails in production ( grunt serve:dist ). It tries to load /config.js and /skins/moono/editor_gecko.css and the language file dynamically, but it fails.
Have anybody idea how to solve it?
Had similar issue with ACE editor. What I did is I added override in bower.json
for ace looks like this
"overrides": {
"ace-builds": {
"main": [
"src-noconflict/ace.js",
"src-noconflict/theme-monokai.js",
"src-noconflict/worker-javascript.js",
"src-noconflict/mode-javascript.js"
]
},
for you ckeditor config you can specify it in a similar way in the overrides
i.e.
"overrides": {
"ckeditor": {
"main": [
"path/to/your/ckeditor.js",
"path/to/your/ckeditor/config.js"
]
}
}
for the CSS, not sure but if you check your gruntfile you might come up with a simple solution (i.e. add one more folder to the CSS sources).
If you find a nice CSS solution please post it as it could be helpful to more people ;)

Resources