├── .gitignore ├── LICENSE ├── README.md └── examples ├── mocha-cli ├── .babelrc ├── README.md ├── package.json ├── src │ ├── index.js │ └── magnitude.js └── unit │ ├── magnitude.js │ └── vector.js ├── mocha-grunt ├── .babelrc ├── README.md ├── gruntfile.js ├── package.json ├── src │ ├── index.js │ └── magnitude.js └── unit │ ├── magnitude.js │ └── vector.js ├── mocha-gulp ├── .babelrc ├── README.md ├── gulpfile.babel.js ├── package.json ├── src │ ├── index.js │ └── magnitude.js └── unit │ ├── magnitude.js │ └── vector.js ├── mocha-istanbul-cli ├── .babelrc ├── README.md ├── package.json ├── src │ ├── index.js │ └── magnitude.js └── test │ ├── magnitude.js │ └── vector.js └── mocha-istanbul-gulp ├── .babelrc ├── README.md ├── gulpfile.babel.js ├── package.json ├── src ├── index.js └── magnitude.js └── unit ├── magnitude.js └── vector.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 James, please 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # testing-with-babel 2 | 3 | > This is an active work-in-progress project. I plan to add 1-3 new 4 | > configurations per day, so keep your eye on this project if you don't see 5 | > what you're looking for! 6 | 7 | Babel is a fantastic tool for transpiling JavaScript, but it can be difficult 8 | to get it working with other tools in the Node ecosystem. 9 | 10 | Perhaps the most important set of tools to get working with Babel are unit 11 | testing tools. I've spent a long time trying to figure out how to get Babel 12 | to work with these tools – scouring GitHub issues, reading blog posts, and 13 | experimenting on my own – and everything that I've learned will be posted 14 | here. 15 | 16 | Am I missing a testing test up that you'd like to see? 17 | [Make a request](https://github.com/jmeas/testing-with-babel), or better yet, 18 | submit a PR! 19 | 20 | #### How it works 21 | 22 | This repository is a collection of examples which all live in the `examples` 23 | directory. Every example has a README that explains how to get it 24 | set up locally, and then steps through how it works. 25 | 26 | To begin, you'll want to clone this repository. You can then either browse 27 | through the list of examples in the `examples` directory, or in the table 28 | of contents below. 29 | 30 | #### What presets of Babel are used? 31 | 32 | All of the examples in this project use only the 33 | [ES2015 preset](http://babeljs.io/docs/plugins/preset-es2015/). This is because 34 | this is the preset that the vast majority of people will care about: it's the 35 | one that lets you author things in ES2015. 36 | 37 | In the future, I plan to add some data around which set ups allow you to use 38 | additional presets, like, say, `stage-2`. In the meantime, you can test on your 39 | own the support for those presets. 40 | 41 | #### Node-only Examples 42 | 43 | These examples are suitable for libraries that you wish to test in Node only. 44 | 45 | **Without code coverage** 46 | 47 | - [Mocha + Chai, run on the CLI](examples/mocha-cli) 48 | - [Mocha + Chai + Gulp](examples/mocha-gulp) 49 | - [Mocha + Chai + Grunt](examples/mocha-grunt) 50 | 51 | **With code coverage** 52 | 53 | - [Mocha + Chai + Istanbul, run on the CLI](examples/mocha-istanbul-cli) 54 | - [Mocha + Chai + Istanbul + Gulp](examples/mocha-istanbul-gulp) 55 | 56 | #### Browser-only Examples 57 | 58 | These are good for tests that you only want to run in browser environments, 59 | and not Node. 60 | 61 | *Coming soon* 62 | 63 | #### Browser + Node environments 64 | 65 | This section are examples showing how to run the tests in a browser and in Node. 66 | 67 | *Coming soon* 68 | 69 | ### FAQ 70 | 71 | **Are there any limitations to using Istanbul with Babel?** 72 | 73 | Yes. The tool isparta is used to make Istanbul work with transpiled code, and 74 | by and large it works great. The coverage report will look like your original 75 | ES2015 code, and report accurately on the `lines` that are covered. 76 | 77 | However, every other property that Istanbul measures will *still* be based on 78 | the transpiled code. So the `statements`, `branches`, and `functions` 79 | measurements will be based off of the code that Babel computes. 80 | 81 | I haven't found this to be a problem on any of my projects, because I use 82 | code coverage as a tool to give me an idea of how complete my test coverage is. 83 | The approximation provided to me by using it with ES2015 is equally good for 84 | accomplishing that goal. 85 | 86 | However, if you're someone who requires that the coverage data be more precise, 87 | then you may want to shy away from Babel for now (or update isparta to be 88 | more accurate!) 89 | 90 | #### To-do 91 | 92 | ##### Node only 93 | 94 | - Mocha 95 | - [x] CLI 96 | - [x] Gulp 97 | - [x] Grunt 98 | - Mocha + Istanbul 99 | - [x] CLI 100 | - [x] Gulp 101 | - [ ] Grunt 102 | - Mocha + JSDom 103 | - [ ] CLI 104 | - [ ] Gulp 105 | - [ ] Grunt 106 | - Mocha + Istanbul + JSDom 107 | - [ ] CLI 108 | - [ ] Gulp 109 | - [ ] Grunt 110 | 111 | ##### Browser only 112 | 113 | - [ ] Mocha + Runner HTML file 114 | - [ ] Mocha + PhantomJS CLI 115 | - [ ] Mocha + PhantomJS + Runner HTML file 116 | - [ ] Mocha + Karma (no coverage) 117 | - [ ] Mocha + Karma (with coverage) 118 | - [ ] Mocha + Karma (without coverage) + Runner HTML File 119 | - [ ] Mocha + Karma (with coverage) + Runner HTML File 120 | 121 | ##### Node + Browser 122 | 123 | - Mocha/Chai + Karma 124 | - [ ] CLI 125 | - [ ] Gulp 126 | - [ ] Grunt 127 | -------------------------------------------------------------------------------- /examples/mocha-cli/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/mocha-cli/README.md: -------------------------------------------------------------------------------- 1 | ### Mocha + CLI 2 | 3 | This example shows how to use Babel in conjunction with Mocha. It doesn't use 4 | any task runner, like Grunt or Gulp; it's CLI-based. 5 | 6 | ### Installation 7 | 8 | 1. Clone this repository 9 | 2. Navigate to this directory via `cd examples/mocha-cli` 10 | 3. Install the `npm` dependencies via `npm install` 11 | 12 | ### Running the tests 13 | 14 | Run `npm test` 15 | 16 | ### How it works 17 | 18 | When `npm test` is run, the aliased `script` in our `package.json` is run. We 19 | can see in `package.json` that the associated command is: 20 | `mocha unit/*.js --compilers js:babel-register`. 21 | 22 | Let's break down that command piece-by-piece: 23 | 24 | ##### `mocha` 25 | 26 | This is just running [the Mocha CLI](https://mochajs.org/#usage). It doesn't 27 | need to be installed globally because we've specified `mocha` as a 28 | `devDependency` for our package. 29 | 30 | ##### `unit/*.js` 31 | 32 | These are where the unit tests are located. 33 | 34 | #### `--compilers js:babel-register` 35 | 36 | This is [an option exposed by Mocha's CLI](https://mochajs.org/#compilers). The 37 | value we've passed indicates that for all files ending in `js`, we wish to use 38 | the `babel-register` library to compile our code before running the tests. 39 | 40 | The `babel-register` library is a tool that transpiles anything that we 41 | `require` in. Because `mocha` is a Node tool, it ultimately `require`s in 42 | each of our unit tests. This is what allows us to write our tests in ES2015 43 | as well as our library itself. 44 | 45 | #### `.babelrc` 46 | 47 | There's one last important detail that makes all of this work: the `.babelrc` 48 | file. Our configuration in that file tells Babel that we want to transpile 49 | ES2015 code into ES5 code. This is necessary because Babel makes no assumptions 50 | about how you want to transform the code as of v6. 51 | 52 | #### A note on Chai 53 | 54 | These examples all use Chai as the assertion library for the tests. It should be 55 | relatively straightforward to swap it out for your assertion library of choice, 56 | which is why I haven't included other examples. If you're having trouble, 57 | [raise an issue](https://github.com/jmeas/testing-with-babel/issues) and I'll be 58 | glad to help out. 59 | -------------------------------------------------------------------------------- /examples/mocha-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha-cli", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "mocha unit/*.js --compilers js:babel-register" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-preset-es2015": "^6.3.13", 13 | "babel-register": "^6.3.13", 14 | "chai": "^3.4.1", 15 | "mocha": "^2.3.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mocha-cli/src/index.js: -------------------------------------------------------------------------------- 1 | import magnitude from './magnitude'; 2 | 3 | // This is the Class that we're testing. It's nothing serious; just a small 4 | // class representing a mathematical object called a vector. 5 | export default class Vector { 6 | constructor(x, y) { 7 | this._x = x; 8 | this._y = y; 9 | } 10 | 11 | get x() { 12 | return this._x; 13 | } 14 | 15 | get y() { 16 | return this._y; 17 | } 18 | 19 | set x(value) { 20 | if (typeof value !== 'number') { 21 | throw new Error('"x" must be a number.'); 22 | } 23 | 24 | this._x = value; 25 | } 26 | 27 | set y(value) { 28 | if (typeof value !== 'number') { 29 | throw new Error('"y" must be a number.'); 30 | } 31 | 32 | this._y = value; 33 | } 34 | 35 | // Returns the magnitude of the vector using the `magnitude` util method 36 | get magnitude() { 37 | return magnitude(this._x, this._y); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/mocha-cli/src/magnitude.js: -------------------------------------------------------------------------------- 1 | // A utility method that computes the magnitude of the vector (which is 2 | // just the Pythagorean theorem). 3 | // This is a separate file to make these examples slightly more complex than 4 | // having a single file. 5 | export default function(x, y) { 6 | // We can't use `x ** 2` because the exponentiation operator 7 | // is not included in the ES2015 preset as of Dec. 15, 2015 8 | return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 9 | } 10 | -------------------------------------------------------------------------------- /examples/mocha-cli/unit/magnitude.js: -------------------------------------------------------------------------------- 1 | import magnitude from '../src/magnitude'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('magnitude', () => { 9 | describe('when passed in (0, 0)', () => { 10 | it('should return 0', () => { 11 | expect(magnitude(0, 0)).to.equal(0); 12 | }); 13 | }); 14 | 15 | describe('when passed in (3, 4)', () => { 16 | it('should return 5', () => { 17 | expect(magnitude(3, 4)).to.equal(5); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-cli/unit/vector.js: -------------------------------------------------------------------------------- 1 | import Vector from '../src/index'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('Vector', () => { 9 | it('should be a function', () => { 10 | expect(Vector).to.be.a('function'); 11 | }); 12 | 13 | describe('creating a vector, then querying for its values', () => { 14 | it('should return the values that you passed in', () => { 15 | var vector = new Vector(2, 3); 16 | expect(vector.x).to.equal(2); 17 | expect(vector.y).to.equal(3); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-grunt/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/mocha-grunt/README.md: -------------------------------------------------------------------------------- 1 | ### Mocha + Grunt 2 | 3 | This example shows how to use Babel in conjunction with Mocha and Grunt. 4 | 5 | ### Installation 6 | 7 | 1. Clone this repository 8 | 2. Navigate to this directory via `cd examples/mocha-grunt` 9 | 3. Install the `npm` dependencies via `npm install` 10 | 11 | ### Running the tests 12 | 13 | Run `npm test` 14 | 15 | ### How it works 16 | 17 | When `npm test` is run, the aliased `script` in our `package.json` is run. That 18 | alias is simply `grunt`, which runs the default `grunt` task. 19 | 20 | This task is defined in `gruntfile.js`. Let's look at that task. 21 | 22 | #### `grunt-mocha-test` 23 | 24 | Because these are Node-only tests, we're using the 25 | [grunt-mocha-test](https://github.com/pghalliday/grunt-mocha-test) package. The 26 | more idiomatically-named `grunt-mocha` is for running tests in PhantomJS, but 27 | that's a use case for another example. 28 | 29 | #### `babel-register` 30 | 31 | The key to this example is specifying `babel-register` in the `require` option 32 | for `mochaTest`. This use case is described in 33 | [the documentation](https://github.com/pghalliday/grunt-mocha-test#specifying-compilers) 34 | for that Grunt task. 35 | 36 | #### `.babelrc` 37 | 38 | There's one last important detail that makes all of this work: the `.babelrc` 39 | file. Our configuration in that file tells Babel that we want to transpile 40 | ES2015 code into ES5 code. This is necessary because Babel makes no assumptions 41 | about how you want to transform the code as of v6. 42 | 43 | #### A note on Chai 44 | 45 | These examples all use Chai as the assertion library for the tests. It should be 46 | relatively straightforward to swap it out for your assertion library of choice, 47 | which is why I haven't included other examples. If you're having trouble, 48 | [raise an issue](https://github.com/jmeas/testing-with-babel/issues) and I'll be 49 | glad to help out. 50 | -------------------------------------------------------------------------------- /examples/mocha-grunt/gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.loadNpmTasks('grunt-mocha-test'); 3 | 4 | grunt.initConfig({ 5 | mochaTest: { 6 | test: { 7 | options: { 8 | require: 'babel-register' 9 | }, 10 | src: ['unit/*.js'] 11 | } 12 | } 13 | }); 14 | 15 | grunt.registerTask('default', ['mochaTest']); 16 | }; 17 | -------------------------------------------------------------------------------- /examples/mocha-grunt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha-grunt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "grunt" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-preset-es2015": "^6.3.13", 13 | "babel-register": "^6.3.13", 14 | "chai": "^3.4.1", 15 | "grunt": "^0.4.5", 16 | "grunt-cli": "^0.1.13", 17 | "grunt-mocha-test": "^0.12.7" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/mocha-grunt/src/index.js: -------------------------------------------------------------------------------- 1 | import magnitude from './magnitude'; 2 | 3 | // This is the Class that we're testing. It's nothing serious; just a small 4 | // class representing a mathematical object called a vector. 5 | export default class Vector { 6 | constructor(x, y) { 7 | this._x = x; 8 | this._y = y; 9 | } 10 | 11 | get x() { 12 | return this._x; 13 | } 14 | 15 | get y() { 16 | return this._y; 17 | } 18 | 19 | set x(value) { 20 | if (typeof value !== 'number') { 21 | throw new Error('"x" must be a number.'); 22 | } 23 | 24 | this._x = value; 25 | } 26 | 27 | set y(value) { 28 | if (typeof value !== 'number') { 29 | throw new Error('"y" must be a number.'); 30 | } 31 | 32 | this._y = value; 33 | } 34 | 35 | // Returns the magnitude of the vector using the `magnitude` util method 36 | get magnitude() { 37 | return magnitude(this._x, this._y); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/mocha-grunt/src/magnitude.js: -------------------------------------------------------------------------------- 1 | // A utility method that computes the magnitude of the vector (which is 2 | // just the Pythagorean theorem). 3 | // This is a separate file to make these examples slightly more complex than 4 | // having a single file. 5 | export default function(x, y) { 6 | // We can't use `x ** 2` because the exponentiation operator 7 | // is not included in the ES2015 preset as of Dec. 15, 2015 8 | return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 9 | } 10 | -------------------------------------------------------------------------------- /examples/mocha-grunt/unit/magnitude.js: -------------------------------------------------------------------------------- 1 | import magnitude from '../src/magnitude'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('magnitude', () => { 9 | describe('when passed in (0, 0)', () => { 10 | it('should return 0', () => { 11 | expect(magnitude(0, 0)).to.equal(0); 12 | }); 13 | }); 14 | 15 | describe('when passed in (3, 4)', () => { 16 | it('should return 5', () => { 17 | expect(magnitude(3, 4)).to.equal(5); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-grunt/unit/vector.js: -------------------------------------------------------------------------------- 1 | import Vector from '../src/index'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('Vector', () => { 9 | it('should be a function', () => { 10 | expect(Vector).to.be.a('function'); 11 | }); 12 | 13 | describe('creating a vector, then querying for its values', () => { 14 | it('should return the values that you passed in', () => { 15 | var vector = new Vector(2, 3); 16 | expect(vector.x).to.equal(2); 17 | expect(vector.y).to.equal(3); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-gulp/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/mocha-gulp/README.md: -------------------------------------------------------------------------------- 1 | ### Mocha + Gulp 2 | 3 | This example shows how to use Babel in conjunction with Mocha and Gulp. 4 | 5 | ### Installation 6 | 7 | 1. Clone this repository 8 | 2. Navigate to this directory via `cd examples/mocha-gulp` 9 | 3. Install the `npm` dependencies via `npm install` 10 | 11 | ### Running the tests 12 | 13 | Run `npm test` 14 | 15 | ### How it works 16 | 17 | When `npm test` is run, the aliased `script` in our `package.json` is run. That 18 | alias is simply `gulp`, which runs the default `gulp` task. 19 | 20 | This task is defined in `gulpfile.babel.js`. Let's look at that file. 21 | 22 | #### `gulpfile.babel.js` 23 | 24 | You may be surprised to see that this file is exactly the same file as if we 25 | weren't using Babel. You might be wondering how that works. 26 | 27 | The trick is that we've implicitly told Babel to transpile all of our files. 28 | That is, in fact, the way that `gulpfile.babel.js` works. When you run any 29 | `gulp` command within a Babel'd `gulpfile`, you will notice on the command line 30 | that the first thing that is output is: 31 | `Requiring external module babel-core/register`. 32 | 33 | That's the code that transpiles everything that follows. 34 | 35 | If we **weren't** using `gulpfile.babel.js`, we would need to manually require 36 | in the module `babel-register`. Do keep that in mind if you decide not to use 37 | ES2015 in your `gulpfile`. 38 | 39 | #### `.babelrc` 40 | 41 | There's one last important detail that makes all of this work: the `.babelrc` 42 | file. Our configuration in that file tells Babel that we want to transpile 43 | ES2015 code into ES5 code. This is necessary because Babel makes no assumptions 44 | about how you want to transform the code as of v6. 45 | 46 | #### `gulpfile.babel.js` 47 | 48 | By installing the `babel-core` module, we're able to write ES2015 in our 49 | Gulpfile by naming the file `gulpfile.babel.js`. Keep in mind that the only 50 | reason we need `babel-core` is to enable this feature. If you don't wish to 51 | use ES2015 in your Gulpfile, then you do not need to specify that dependency. 52 | 53 | #### A note on Chai 54 | 55 | These examples all use Chai as the assertion library for the tests. It should be 56 | relatively straightforward to swap it out for your assertion library of choice, 57 | which is why I haven't included other examples. If you're having trouble, 58 | [raise an issue](https://github.com/jmeas/testing-with-babel/issues) and I'll be 59 | glad to help out. 60 | -------------------------------------------------------------------------------- /examples/mocha-gulp/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import mocha from 'gulp-mocha'; 3 | 4 | function test() { 5 | return gulp.src('unit/*.js') 6 | .pipe(mocha()); 7 | } 8 | 9 | // Run our tests as the default task 10 | gulp.task('default', test); 11 | -------------------------------------------------------------------------------- /examples/mocha-gulp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha-gulp", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "gulp" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-core": "^6.3.26", 13 | "babel-preset-es2015": "^6.3.13", 14 | "chai": "^3.4.1", 15 | "gulp": "^3.9.0", 16 | "gulp-mocha": "^2.2.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mocha-gulp/src/index.js: -------------------------------------------------------------------------------- 1 | import magnitude from './magnitude'; 2 | 3 | // This is the Class that we're testing. It's nothing serious; just a small 4 | // class representing a mathematical object called a vector. 5 | export default class Vector { 6 | constructor(x, y) { 7 | this._x = x; 8 | this._y = y; 9 | } 10 | 11 | get x() { 12 | return this._x; 13 | } 14 | 15 | get y() { 16 | return this._y; 17 | } 18 | 19 | set x(value) { 20 | if (typeof value !== 'number') { 21 | throw new Error('"x" must be a number.'); 22 | } 23 | 24 | this._x = value; 25 | } 26 | 27 | set y(value) { 28 | if (typeof value !== 'number') { 29 | throw new Error('"y" must be a number.'); 30 | } 31 | 32 | this._y = value; 33 | } 34 | 35 | // Returns the magnitude of the vector using the `magnitude` util method 36 | get magnitude() { 37 | return magnitude(this._x, this._y); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/mocha-gulp/src/magnitude.js: -------------------------------------------------------------------------------- 1 | // A utility method that computes the magnitude of the vector (which is 2 | // just the Pythagorean theorem). 3 | // This is a separate file to make these examples slightly more complex than 4 | // having a single file. 5 | export default function(x, y) { 6 | // We can't use `x ** 2` because the exponentiation operator 7 | // is not included in the ES2015 preset as of Dec. 15, 2015 8 | return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 9 | } 10 | -------------------------------------------------------------------------------- /examples/mocha-gulp/unit/magnitude.js: -------------------------------------------------------------------------------- 1 | import magnitude from '../src/magnitude'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('magnitude', () => { 9 | describe('when passed in (0, 0)', () => { 10 | it('should return 0', () => { 11 | expect(magnitude(0, 0)).to.equal(0); 12 | }); 13 | }); 14 | 15 | describe('when passed in (3, 4)', () => { 16 | it('should return 5', () => { 17 | expect(magnitude(3, 4)).to.equal(5); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-gulp/unit/vector.js: -------------------------------------------------------------------------------- 1 | import Vector from '../src/index'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('Vector', () => { 9 | it('should be a function', () => { 10 | expect(Vector).to.be.a('function'); 11 | }); 12 | 13 | describe('creating a vector, then querying for its values', () => { 14 | it('should return the values that you passed in', () => { 15 | var vector = new Vector(2, 3); 16 | expect(vector.x).to.equal(2); 17 | expect(vector.y).to.equal(3); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/README.md: -------------------------------------------------------------------------------- 1 | ### Mocha + Istanbul + CLI 2 | 3 | This example shows how to use Babel in conjunction with Mocha and Istanbul. It 4 | allows you to run the tests by themselves, but also to run them with code 5 | coverage. 6 | 7 | ### Installation 8 | 9 | 1. Clone this repository 10 | 2. Navigate to this directory via `cd examples/mocha-istanbul-cli` 11 | 3. Install the `npm` dependencies via `npm install` 12 | 13 | ### Running the scripts 14 | 15 | To run the tests, run `npm test`. For code coverage, run `npm run coverage`. 16 | 17 | ### How it works 18 | 19 | For a description of the `npm test` command, refer to the 20 | [`mocha-cli` example](../mocha-cli#how-it-works). The script here is identical 21 | to the one in that example. 22 | 23 | What's new to this example is the `npm run coverage` script. I'd love to 24 | walk through it step-by-step with you, but I'd be lying if I said I understood 25 | *exactly* how it works. I'll do my best and explain what I do know, though. 26 | 27 | The first thing you might be wondering is...where's Instanbul? This example 28 | *does* use Istanbul, just indirectly. 29 | [isparta](https://github.com/douglasduteil/isparta) is a wrapper for Istanbul 30 | that allows us to write ES2015 code. 31 | 32 | Back to the command. It starts off with `babel-node`, which is 33 | [a tool](http://babeljs.io/docs/usage/cli/#babel-node) provided by Babel. What 34 | it does is automatically transpile any subsequent scripts run in Node. 35 | 36 | The script that we execute is `node_modules/.bin/isparta`. The directory 37 | `node_modules/.bin` is provided to us by `npm`: it's a collection of all of the 38 | executables in [the locally-installed node_modules](https://docs.npmjs.com/files/folders#executables). 39 | 40 | This tells `babel-node` to execute `isparta`'s executable. 41 | 42 | Next up is `cover`. This seems to be an API that `isparta` inherited from 43 | `istanbul`. 44 | 45 | The last piece is `_mocha`, which users of `istanbul` will know differs from 46 | the standard `istanbul` CLI. What this is is a reference to the `_mocha` 47 | executable from the `mocha` npm package. Did you know that such a thing 48 | existed? As a consumer of mocha, and not a maintainer, I did not before 49 | using isparta. 50 | 51 | We can see from [the repository](https://github.com/mochajs/mocha/tree/d811eb9614e5b459dabb4f2496e69f961decec90/bin) 52 | that mocha's main , `mocha`, is a small wrapper around the `_mocha` executable, 53 | which does most of the heavy lifting. 54 | 55 | `isparta` only works with `_mocha`, and not `mocha`. Why? I'm not sure. That's 56 | what I meant about not fully understanding this command. I learned how to do 57 | this from 58 | [the `isparta` documentation](https://github.com/douglasduteil/isparta#usage), 59 | but the docs do go into much depth as to why it must work this way. 60 | 61 | I'd love to elaborate further on how this command works. Got any ideas? Please 62 | let me know 63 | [by opening an issue](https://github.com/jmeas/testing-with-babel/issues/new)! 64 | 65 | #### `.babelrc` 66 | 67 | There's one last important detail that makes all of this work: the `.babelrc` 68 | file. Our configuration in that file tells Babel that we want to transpile 69 | ES2015 code into ES5 code. This is necessary because Babel makes no assumptions 70 | about how you want to transform the code as of v6. 71 | 72 | #### A note on Chai 73 | 74 | These examples all use Chai as the assertion library for the tests. It should be 75 | relatively straightforward to swap it out for your assertion library of choice, 76 | which is why I haven't included other examples. If you're having trouble, 77 | [raise an issue](https://github.com/jmeas/testing-with-babel/issues) and I'll be 78 | glad to help out. 79 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha-istanbul-cli", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "mocha unit/*.js --compilers js:babel-register", 8 | "coverage": "babel-node node_modules/.bin/isparta cover _mocha" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-core": "^6.3.26", 14 | "babel-preset-es2015": "^6.3.13", 15 | "babel-register": "^6.3.13", 16 | "chai": "^3.4.1", 17 | "isparta": "^4.0.0", 18 | "mocha": "^2.3.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/src/index.js: -------------------------------------------------------------------------------- 1 | import magnitude from './magnitude'; 2 | 3 | // This is the Class that we're testing. It's nothing serious; just a small 4 | // class representing a mathematical object called a vector. 5 | export default class Vector { 6 | constructor(x, y) { 7 | this._x = x; 8 | this._y = y; 9 | } 10 | 11 | get x() { 12 | return this._x; 13 | } 14 | 15 | get y() { 16 | return this._y; 17 | } 18 | 19 | set x(value) { 20 | if (typeof value !== 'number') { 21 | throw new Error('"x" must be a number.'); 22 | } 23 | 24 | this._x = value; 25 | } 26 | 27 | set y(value) { 28 | if (typeof value !== 'number') { 29 | throw new Error('"y" must be a number.'); 30 | } 31 | 32 | this._y = value; 33 | } 34 | 35 | // Returns the magnitude of the vector using the `magnitude` util method 36 | get magnitude() { 37 | return magnitude(this._x, this._y); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/src/magnitude.js: -------------------------------------------------------------------------------- 1 | // A utility method that computes the magnitude of the vector (which is 2 | // just the Pythagorean theorem). 3 | // This is a separate file to make these examples slightly more complex than 4 | // having a single file. 5 | export default function(x, y) { 6 | // We can't use `x ** 2` because the exponentiation operator 7 | // is not included in the ES2015 preset as of Dec. 15, 2015 8 | return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 9 | } 10 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/test/magnitude.js: -------------------------------------------------------------------------------- 1 | import magnitude from '../src/magnitude'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('magnitude', () => { 9 | describe('when passed in (0, 0)', () => { 10 | it('should return 0', () => { 11 | expect(magnitude(0, 0)).to.equal(0); 12 | }); 13 | }); 14 | 15 | describe('when passed in (3, 4)', () => { 16 | it('should return 5', () => { 17 | expect(magnitude(3, 4)).to.equal(5); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-cli/test/vector.js: -------------------------------------------------------------------------------- 1 | import Vector from '../src/index'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('Vector', () => { 9 | it('should be a function', () => { 10 | expect(Vector).to.be.a('function'); 11 | }); 12 | 13 | describe('creating a vector, then querying for its values', () => { 14 | it('should return the values that you passed in', () => { 15 | var vector = new Vector(2, 3); 16 | expect(vector.x).to.equal(2); 17 | expect(vector.y).to.equal(3); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/README.md: -------------------------------------------------------------------------------- 1 | ### Mocha + Istanbul + Gulp 2 | 3 | This example shows how to use Babel in conjunction with Mocha, Istanbul, and 4 | Gulp. 5 | 6 | ### Installation 7 | 8 | 1. Clone this repository 9 | 2. Navigate to this directory via `cd examples/mocha-gulp` 10 | 3. Install the `npm` dependencies via `npm install` 11 | 12 | ### Running the tests 13 | 14 | To only run the unit tests, run `npm test`. For coverage reports, run 15 | `npm coverage`. 16 | 17 | ### How it works 18 | 19 | The `npm test` command is explained in 20 | [the `mocha-gulp` example](../mocha-gulp#how-it-works); it's identical to the 21 | one here. 22 | 23 | The `npm run coverage` command is new, though. It's basically a minor 24 | refactor of the example given in the `gulp-istanbul` 25 | [documentation](https://github.com/SBoudrias/gulp-istanbul#nodejs-testing); 26 | whereas they recommend using two gulp tasks, it can be made into one by using 27 | stream events. 28 | 29 | In addition, the [`instrumenter` property](https://github.com/SBoudrias/gulp-istanbul#instrumenter) 30 | is utilized, which is the recommended way to use isparta with `gulp-istanbul`. 31 | 32 | #### `.babelrc` 33 | 34 | There's one last important detail that makes all of this work: the `.babelrc` 35 | file. Our configuration in that file tells Babel that we want to transpile 36 | ES2015 code into ES5 code. This is necessary because Babel makes no assumptions 37 | about how you want to transform the code as of v6. 38 | 39 | #### `gulpfile.babel.js` 40 | 41 | By installing the `babel-core` module, we're able to write ES2015 in our 42 | Gulpfile by naming the file `gulpfile.babel.js`. Keep in mind that the only 43 | reason we need `babel-core` is to enable this feature. If you don't wish to 44 | use ES2015 in your Gulpfile, then you do not need to specify that dependency. 45 | 46 | #### A note on Chai 47 | 48 | These examples all use Chai as the assertion library for the tests. It should be 49 | relatively straightforward to swap it out for your assertion library of choice, 50 | which is why I haven't included other examples. If you're having trouble, 51 | [raise an issue](https://github.com/jmeas/testing-with-babel/issues) and I'll be 52 | glad to help out. 53 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import mocha from 'gulp-mocha'; 3 | import istanbul from 'gulp-istanbul'; 4 | import { Instrumenter } from 'isparta'; 5 | 6 | function test() { 7 | return gulp.src('unit/*.js') 8 | .pipe(mocha()); 9 | } 10 | 11 | function coverage(done) { 12 | gulp.src(['src/*.js']) 13 | .pipe(istanbul({ instrumenter: Instrumenter })) 14 | .pipe(istanbul.hookRequire()) 15 | .on('finish', function() { 16 | return test() 17 | .pipe(istanbul.writeReports()) 18 | .on('end', done); 19 | }); 20 | } 21 | 22 | // Run our tests as the default task 23 | gulp.task('default', test); 24 | gulp.task('coverage', coverage); 25 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha-istanbul-gulp", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "gulp", 8 | "coverage": "gulp coverage" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-core": "^6.3.26", 14 | "babel-preset-es2015": "^6.3.13", 15 | "chai": "^3.4.1", 16 | "gulp": "^3.9.0", 17 | "gulp-istanbul": "^0.10.3", 18 | "gulp-mocha": "^2.2.0", 19 | "isparta": "^4.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/src/index.js: -------------------------------------------------------------------------------- 1 | import magnitude from './magnitude'; 2 | 3 | // This is the Class that we're testing. It's nothing serious; just a small 4 | // class representing a mathematical object called a vector. 5 | export default class Vector { 6 | constructor(x, y) { 7 | this._x = x; 8 | this._y = y; 9 | } 10 | 11 | get x() { 12 | return this._x; 13 | } 14 | 15 | get y() { 16 | return this._y; 17 | } 18 | 19 | set x(value) { 20 | if (typeof value !== 'number') { 21 | throw new Error('"x" must be a number.'); 22 | } 23 | 24 | this._x = value; 25 | } 26 | 27 | set y(value) { 28 | if (typeof value !== 'number') { 29 | throw new Error('"y" must be a number.'); 30 | } 31 | 32 | this._y = value; 33 | } 34 | 35 | // Returns the magnitude of the vector using the `magnitude` util method 36 | get magnitude() { 37 | return magnitude(this._x, this._y); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/src/magnitude.js: -------------------------------------------------------------------------------- 1 | // A utility method that computes the magnitude of the vector (which is 2 | // just the Pythagorean theorem). 3 | // This is a separate file to make these examples slightly more complex than 4 | // having a single file. 5 | export default function(x, y) { 6 | // We can't use `x ** 2` because the exponentiation operator 7 | // is not included in the ES2015 preset as of Dec. 15, 2015 8 | return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 9 | } 10 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/unit/magnitude.js: -------------------------------------------------------------------------------- 1 | import magnitude from '../src/magnitude'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('magnitude', () => { 9 | describe('when passed in (0, 0)', () => { 10 | it('should return 0', () => { 11 | expect(magnitude(0, 0)).to.equal(0); 12 | }); 13 | }); 14 | 15 | describe('when passed in (3, 4)', () => { 16 | it('should return 5', () => { 17 | expect(magnitude(3, 4)).to.equal(5); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/mocha-istanbul-gulp/unit/vector.js: -------------------------------------------------------------------------------- 1 | import Vector from '../src/index'; 2 | import chai from 'chai'; 3 | 4 | // A common pattern for large webapps is to set this as a global in a `setup` 5 | // file, but I'm not doing anything fancy to keep the example simple. 6 | const expect = chai.expect; 7 | 8 | describe('Vector', () => { 9 | it('should be a function', () => { 10 | expect(Vector).to.be.a('function'); 11 | }); 12 | 13 | describe('creating a vector, then querying for its values', () => { 14 | it('should return the values that you passed in', () => { 15 | var vector = new Vector(2, 3); 16 | expect(vector.x).to.equal(2); 17 | expect(vector.y).to.equal(3); 18 | }); 19 | }); 20 | }); 21 | --------------------------------------------------------------------------------