Ember CLI Blueprint Testing
@trabus
@jakebixby


Jake Bixby
Senior Engineer @

father
ember-cli core team member
corgi food balancing enthusiast

I may have a problem

He doesn't mind, I promise.

Why?
What is the point of testing blueprints?
Testing your blueprints will save you a lot of pain if you're an addon developer.
It will alert you to ember-cli changes that may inadvertently break your blueprints.
It's a great way to test all permutations of your complicated blueprints.
How the heck do I test a blueprint in my addon?
- generate the blueprint
- ???
- what even is happening
What are we actually testing here?
- Can the blueprint be generated?
- Can the blueprint be destroyed?
- Are the generated contents correct?
- Does it do any other expected work?
- Test in node, since that's ember-cli's domain.
- Only concerned with the blueprint, not generated content's functionality.
The 3 A's
- Arrange
- Act
- Assert
x2!
Arrange
1. Generate a clean ember-cli project or addon
2. Step into the project or addon
3. Symlink your addon so the blueprint can be found
Act
1. Generate your blueprint with options
2. Optionally generate additional related blueprints
Assert
1. Assert blueprint ran successfully or threw an error (if expected)
2. Assert the content of the generated files, ui output, and changed files
Arrange
1. Already did that in the generate step!
2. No reason to leave a perfectly setup project laying around
Act
1. Destroy blueprint, generally using the same options as when it was generated
Assert
1. Assert files are gone and that destroy blueprint ran successfully or threw an error (if expected)
2. Assert the generated files, ui output, and changed files
Done.
(cleanup for the next test)
Some Background
it was all for the addons
The addonification of ember and ember-data prompted the extraction of blueprints, which included their tests.
We needed a way to quickly setup a temp project or addon, then generate and destroy from its context
(what's this all about then?)
ember-cli has had a form of blueprint test helpers from the beginning, but they weren't usable outside ember-cli.
Extraction happened
Many thanks to Tobias Bieniek (@turbo87), who helped bring this project to completion!
We've developed a simple set of promise based test helpers to allow you to setup, generate, destroy, and assert in many flexible permutations.
To support testing the extracted blueprints, we also extracted much of the test helpers and setup utilities.
We pass the testings on to you!
ember-cli-blueprint-test-helpers
https://github.com/ember-cli/ember-cli-blueprint-test-helpers
A library of test
helpers to:
-
Generate a clean test ember app/addon
-
Generate/Destroy blueprints in that test app/addon
-
Assert file contents with chai helpers
-
Assert cli output and errors
- Manipulate your test's package.json
Fine Print
-
Addons only. Doesn't work for blueprints contained inside projects (but may work in the future)
-
Doesn't support generating inside engines (yet)
-
Generates tests with ES6 syntax, so Node 5.x or higher is recommended, or use babel
How to use them
ember install ember-cli-blueprint-test-helpers
ember g blueprint-test my-blueprint
This will generate a blueprint-test inside your addon's node-tests folder. From there you can fill in your tests.
If you need babel
ember g ember-cli-blueprint-test-helpers --babel
This will install babel testing dependencies in your addon, including a .babelrc, and add an npm script which will run your tests with babel-register
Using the helpers
describe('Acceptance: ember generate and destroy my-blueprint', function() {
// create and destroy temporary working directories
setupTestHooks(this);
it('my-blueprint foo', function() {
var args = ['my-blueprint', 'foo'];
// create a new Ember.js app in the working directory
return emberNew()
// then generate and destroy the `my-blueprint` blueprint called `foo`
.then(() => emberGenerateDestroy(args, (file) => {
// and run some assertions in between
expect(file('path/to/file.js'))
.to.contain('file contents to match')
.to.contain('more file contents\n');
}));
// magically done for you:
// assert that the generated files are destroyed again
});
});Finer control use
describe('Acceptance: ember generate and destroy my-blueprint', function() {
// create and destroy temporary working directories
setupTestHooks(this);
it('my-blueprint foo', function() {
var args = ['my-blueprint', 'foo'];
// create a new Ember.js app in the working directory
return emberNew()
// then generate the `my-blueprint` blueprint called `foo`
.then(() => emberGenerate(args))
// then assert that the files were generated correctly
.then(() => expect(file('path/to/file.js'))
.to.contain('file contents to match')
.to.contain('more file contents\n'))
// then destroy the `my-blueprint` blueprint called `foo`
.then(() => emberDestroy(args))
// then assert that the files were destroyed correctly
.then(() => expect(file('path/to/file.js')).to.not.exist);
});
});Asserting throws
describe('Acceptance: ember generate and destroy my-blueprint', function() {
// create and destroy temporary working directories
setupTestHooks(this);
it('my-blueprint foo', function() {
var args = ['my-blueprint', 'foo'];
// create a new Ember.js app in the working directory
return emberNew()
// we only need to generate, since we're expecting an error
.then(() => expect(emberGenerate(args))
// use chai-as-promised rejectedWith helper
.to.be.rejectedWith(SilentError, /Foo is overused/));
});
});Asserting output
describe('Acceptance: ember generate and destroy my-blueprint', function() {
// create and destroy temporary working directories
setupTestHooks(this);
it('my-blueprint foo', function() {
var args = ['my-blueprint', 'foo'];
// create a new Ember.js app in the working directory
return emberNew()
// then generate the `my-blueprint` blueprint called `foo`
.then(() => emberGenerate(args))
// then assert that the files were generated correctly
.then((result) => => {
let output = result.outputStream.join('');
// test ui output because we can't test for actual npm install modifying package.json
expect(output).to.contain('npm-package')
});
});
});Running the tests
mocha node-tests --recursive
If you installed the babel dependencies, your npm node-test script has been updated to:
mocha node-tests --recursive --require babel-register
Then you can run your tests through an npm script!
npm run nodetest
Recap
-
Use ember-cli-blueprint-test-helpers to test your generated blueprint output
-
Catch issues caused by upstream changes to ember-cli and prepare for future blueprints changes
-
Addon authors: the tools are available now, please test your addon's blueprints!
Thanks!

@trabus
@jakebixby


Ember CLI Blueprint Testing
By Jacob Bixby
Ember CLI Blueprint Testing
Introducing `ember-cli-blueprint-test-helpers`, blueprint testing for the masses.
- 915