ember-cli-ajh
Version:
Command line tool for developing ambitious ember.js apps
358 lines (315 loc) • 13.9 kB
JavaScript
;
var path = require('path');
var fs = require('fs');
var crypto = require('crypto');
var expect = require('chai').expect;
var walkSync = require('walk-sync');
var appName = 'some-cool-app';
var EOL = require('os').EOL;
var runCommand = require('../helpers/run-command');
var acceptance = require('../helpers/acceptance');
var copyFixtureFiles = require('../helpers/copy-fixture-files');
var killCliProcess = require('../helpers/kill-cli-process');
var assertDirEmpty = require('../helpers/assert-dir-empty');
var ember = require('../helpers/ember');
var createTestTargets = acceptance.createTestTargets;
var teardownTestTargets = acceptance.teardownTestTargets;
var linkDependencies = acceptance.linkDependencies;
var cleanupRun = acceptance.cleanupRun;
describe('Acceptance: smoke-test', function() {
this.timeout(500000);
before(function() {
return createTestTargets(appName);
});
after(function() {
return teardownTestTargets();
});
beforeEach(function() {
return linkDependencies(appName);
});
afterEach(function() {
return cleanupRun().then(function() {
assertDirEmpty('tmp');
});
});
it('ember new foo, clean from scratch', function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test');
});
it('ember test exits with non-zero when tests fail', function() {
return copyFixtureFiles('smoke-tests/failing-test')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
.then(function() {
expect(false, 'should have rejected with a failing test');
})
.catch(function(result) {
expect(result.code).to.equal(1);
});
});
});
it('ember test exits with non-zero when build fails', function() {
return copyFixtureFiles('smoke-tests/test-with-syntax-error')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
.then(function() {
expect(false, 'should have rejected with a failing test');
})
.catch(function(result) {
expect(result.code).to.equal(1);
});
});
});
it('ember test exits with non-zero when no tests are run', function() {
return copyFixtureFiles('smoke-tests/no-testem-launchers')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
.then(function() {
expect(false, 'should have rejected with a failing test');
})
.catch(function(result) {
expect(result.code).to.equal(1);
});
});
});
it('ember test exits with zero when tests pass', function() {
return copyFixtureFiles('smoke-tests/passing-test')
.then(function() {
return ember(['test'])
.then(function(result) {
expect(result.code).to.equal(0);
})
.catch(function() {
expect(false, 'should have rejected with a failing test');
});
});
});
it('ember test still runs when only a JavaScript testem config exists', function() {
return copyFixtureFiles('smoke-tests/js-testem-config')
.then(function() {
return ember(['test']);
});
});
// there is a bug in here when running the entire suite on Travis
// when run in isolation, it passes
// here is the error:
// test-support-80f2fe63fae0c44478fe0f8af73200a7.js contains the fingerprint (2871106928f813936fdd64f4d16005ac): expected 'test-support-80f2fe63fae0c44478fe0f8af73200a7.js' to include '2871106928f813936fdd64f4d16005ac'
it.skip('ember new foo, build production and verify fingerprint', function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', '--environment=production')
.then(function() {
var dirPath = path.join('.', 'dist', 'assets');
var dir = fs.readdirSync(dirPath);
var files = [];
dir.forEach(function (filepath) {
if (filepath === '.gitkeep') {
return;
}
files.push(filepath);
var file = fs.readFileSync(path.join(dirPath, filepath), { encoding: null });
var md5 = crypto.createHash('md5');
md5.update(file);
var hex = md5.digest('hex');
expect(filepath).to.contain(hex, filepath + ' contains the fingerprint (' + hex + ')');
});
var indexHtml = fs.readFileSync(path.join('.', 'dist', 'index.html'), { encoding: 'utf8' });
files.forEach(function (filename) {
expect(indexHtml).to.contain(filename);
});
});
});
it('ember test --environment=production', function() {
return copyFixtureFiles('smoke-tests/passing-test')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test', '--environment=production');
})
.then(function(result) {
var exitCode = result.code;
var output = result.output.join(EOL);
expect(exitCode).to.equal(0, 'exit code should be 0 for passing tests');
expect(output).to.match(/JSHint/, 'JSHint should be run on production assets');
expect(output).to.match(/fail\s+0/, 'no failures');
expect(output).to.match(/pass\s+8/, '1 passing');
});
});
it('ember test --path with previous build', function() {
var originalWrite = process.stdout.write;
var output = [];
return copyFixtureFiles('smoke-tests/passing-test')
.then(function() {
// TODO: Change to using ember() helper once it properly saves build artifacts
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
})
.then(function() {
// TODO: Figure out how to get this to write into the MockUI
process.stdout.write = (function() {
return function() {
output.push(arguments[0]);
};
}(originalWrite));
return ember([ 'test', '--path=dist' ]);
})
.then(function(result) {
expect(result.exitCode).to.equal(0, 'exit code should be 0 for passing tests');
output = output.join(EOL);
expect(output).to.match(/JSHint/, 'JSHint should be run');
expect(output).to.match(/fail\s+0/, 'no failures');
expect(output).to.match(/pass\s+8/, '1 passing');
process.stdout.write = originalWrite;
});
});
it('ember new foo, build development, and verify generated files', function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build')
.then(function() {
var dirPath = path.join('.', 'dist');
var paths = walkSync(dirPath);
expect(paths).to.have.length.below(23, 'expected fewer than 23 files in dist, found ' + paths.length);
});
});
it('ember build exits with non-zero code when build fails', function () {
var appJsPath = path.join('.', 'app', 'app.js');
var ouputContainsBuildFailed = false;
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build')
.then(function (result) {
expect(result.code).to.equal(0, 'expected exit code to be zero, but got ' + result.code);
// add something broken to the project to make build fail
fs.appendFileSync(appJsPath, '{(syntaxError>$@}{');
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', {
onOutput: function(string) {
// discard output as there will be a lot of errors and a long stacktrace
// just mark that the output contains expected text
if (!ouputContainsBuildFailed && string.match(/Build failed/)) {
ouputContainsBuildFailed = true;
}
}
});
}).then(function () {
expect(false, 'should have rejected with a failing build');
}).catch(function (result) {
expect(ouputContainsBuildFailed, 'command output must contain "Build failed" text');
expect(result.code).to.not.equal(0, 'expected exit code to be non-zero, but got ' + result.code);
});
});
it('ember new foo, build --watch development, and verify rebuilt after change', function() {
var touched = false;
var appJsPath = path.join('.', 'app', 'app.js');
var builtJsPath = path.join('.', 'dist', 'assets', 'some-cool-app.js');
var text = 'anotuhaonteuhanothunaothanoteh';
var line = 'console.log("' + text + '");';
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', '--watch', {
onOutput: function(string, child) {
if (touched) {
if (string.match(/Build successful/)) {
// build after change to app.js
var contents = fs.readFileSync(builtJsPath).toString();
expect(contents).to.contain(text, 'must contain changed line after rebuild');
killCliProcess(child);
}
} else {
if (string.match(/Build successful/)) {
// first build
touched = true;
fs.appendFileSync(appJsPath, line);
}
}
}
})
.catch(function() {
// swallowing because of SIGINT
});
});
it('ember new foo, build --watch development, and verify rebuilt after multiple changes', function() {
var buildCount = 0;
var touched = false;
var appJsPath = path.join('.', 'app', 'app.js');
var builtJsPath = path.join('.', 'dist', 'assets', 'some-cool-app.js');
var firstText = 'anotuhaonteuhanothunaothanoteh';
var firstLine = 'console.log("' + firstText + '");';
var secondText = 'aahsldfjlwioruoiiononociwewqwr';
var secondLine = 'console.log("' + secondText + '");';
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', '--watch', {
onOutput: function(string, child) {
if (buildCount === 0) {
if (string.match(/Build successful/)) {
// first build
touched = true;
buildCount = 1;
fs.appendFileSync(appJsPath, firstLine);
}
} else if (buildCount === 1) {
if (string.match(/Build successful/)) {
// second build
touched = true;
buildCount = 2;
fs.appendFileSync(appJsPath, secondLine);
}
} else if (touched && buildCount === 2) {
if (string.match(/Build successful/)) {
// build after change to app.js
var contents = fs.readFileSync(builtJsPath).toString();
expect(contents.indexOf(secondText) > 1, 'must contain second changed line after rebuild');
killCliProcess(child);
}
}
}
})
.catch(function() {
// swallowing because of SIGINT
});
});
it('ember new foo, server, SIGINT clears tmp/', function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'server', '--port=54323','--live-reload=false', {
onOutput: function(string, child) {
if (string.match(/Build successful/)) {
killCliProcess(child);
}
}
})
.catch(function() {
// just eat the rejection as we are testing what happens
});
});
it('ember new foo, build production and verify css files are concatenated', function() {
return copyFixtureFiles('with-styles')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', '--environment=production')
.then(function() {
var dirPath = path.join('.', 'dist', 'assets');
var dir = fs.readdirSync(dirPath);
var cssNameRE = new RegExp(appName + '-([a-f0-9]+)\\.css','i');
dir.forEach(function (filepath) {
if(cssNameRE.test(filepath)) {
var appCss = fs.readFileSync(path.join('.', 'dist', 'assets', filepath), { encoding: 'utf8' });
expect(appCss).to.contain('.some-weird-selector');
expect(appCss).to.contain('.some-even-weirder-selector');
}
});
});
});
});
it('ember new foo, build production and verify single "use strict";', function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build', '--environment=production')
.then(function() {
var dirPath = path.join('.', 'dist', 'assets');
var dir = fs.readdirSync(dirPath);
var appNameRE = new RegExp(appName + '-([a-f0-9]+)\\.js','i');
dir.forEach(function(filepath) {
if (appNameRE.test(filepath)) {
var contents = fs.readFileSync(path.join('.', 'dist', 'assets', filepath), { encoding: 'utf8' });
var count = (contents.match(/(["'])use strict\1;/g) || []).length;
expect(count).to.equal(1);
}
});
});
});
it('ember can override and reuse the built-in blueprints', function() {
return copyFixtureFiles('addon/with-blueprint-override')
.then(function() {
return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'generate', 'component', 'foo-bar', '-p');
})
.then(function() {
// because we're overriding, the fileMapTokens is default, sans 'component'
var componentPath = path.join('app','foo-bar','component.js');
var contents = fs.readFileSync(componentPath, { encoding: 'utf8' });
expect(contents).to.contain('generated component successfully');
});
});
});