Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate acceptance tests to use destroy-app helper #84

Merged
merged 1 commit into from
Sep 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ Converts methods in file to ES6 method syntax.

Helps you locate all the places where your source may trigger the "Using the same function as getter and setter" deprecation.

#### `ember watson:use-destroy-app-helper <path>`

Convert (qunit or mocha flavored) acceptance tests to utilize the `destroyApp`
helper [introduced](https://github.com/ember-cli/ember-cli/pull/4772) in
Ember CLI 1.13.9.

### Specifying a file or path.

Expand Down
7 changes: 7 additions & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ program
watson.findOverloadedCPs(path).outputSummary(options.json ? 'json' : 'pretty');
});

program
.command('use-destroy-app-helper [path]')
.description('Use destroy-app helper after acceptance tests.')
.action(function(path) {
path = path || 'tests/acceptance';
watson.transformTestToUseDestroyApp(path);
});

module.exports = function init(args) {
program.parse(args);
Expand Down
3 changes: 2 additions & 1 deletion lib/commands/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ module.exports = {
'watson:convert-ember-data-async-false-relationships': require('./convert-ember-data-async-false-relationships'),
'watson:methodify': require('./methodify'),
'watson:convert-resource-router-mapping': require('./convert-resource-router-mapping'),
'watson:find-overloaded-cps': require('./find-overloaded-cps')
'watson:find-overloaded-cps': require('./find-overloaded-cps'),
'watson:use-destroy-app-helper': require('./use-destroy-app-helper')
};
17 changes: 17 additions & 0 deletions lib/commands/use-destroy-app-helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

var Watson = require('../../index');
var watson = new Watson();

module.exports = {
name: 'watson:use-destroy-app-helper',
description: 'Use destroy-app helper after acceptance tests.',
works: 'insideProject',
anonymousOptions: [
'<path>'
],
run: function(commandOptions, rawArgs) {
var path = rawArgs[0] || 'tests/acceptance';
watson.transformTestToUseDestroyApp(path);
}
};
77 changes: 77 additions & 0 deletions lib/formulas/destroy-app-transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
var isImportFor = require('./helpers/is-import-for');
var parseAst = require('../helpers/parse-ast');
var recast = require('recast');
var types = recast.types.namedTypes;
var builders = recast.types.builders;

var addDefaultImport = require('./helpers/add-default-import');

function isEmberCall(node) {
return types.MemberExpression.check(node.callee) &&
node.callee.object.name === 'Ember';
}

function isLegacyDestroy(node) {
return types.MemberExpression.check(node.callee) &&
node.callee.object.name === 'Ember' &&
node.callee.property.name === 'run' &&
node.arguments[1].value === 'destroy';
}

function isStartAppAssignment(node) {
return types.CallExpression.check(node.right) &&
node.right.callee.name === 'startApp';
}

module.exports = function transform(source) {
var ast = parseAst(source);
var appName = null;
var addDestroyAppImport = false;
var removeEmberImport = true;
var emberImport = null;

recast.visit(ast, {
visitCallExpression: function(path) {
var node = path.node;

if(isLegacyDestroy(node)) {
if (addDestroyAppImport !== true) {
addDestroyAppImport = true;
}

path.replace(builders.callExpression(
builders.identifier('destroyApp'),
[appName]
));
} else if (isEmberCall(node)) {
removeEmberImport = false;
}

this.traverse(path);
},
visitImportDeclaration: function(path) {
if (isImportFor('ember', path.node)) {
emberImport = path;
}

this.traverse(path);
},
visitAssignmentExpression: function(path) {
if (isStartAppAssignment(path.node)) {
appName = path.node.left;
}

this.traverse(path);
}
});

if (addDestroyAppImport) {
addDefaultImport(ast, '../helpers/destroy-app', 'destroyApp');
}

if (removeEmberImport && emberImport) {
emberImport.prune();
}

return recast.print(ast, { tabWidth: 2, quote: 'single' }).code;
};
29 changes: 27 additions & 2 deletions lib/watson.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var chalk = require('chalk');
var fs = require('fs');
var chalk = require('chalk');
var fs = require('fs');
var existsSync = require('exists-sync');
var EOL = require('os').EOL;

var findFiles = require('./helpers/find-files');

Expand All @@ -10,6 +12,7 @@ var transformEmberDataAsyncFalseRelationships = require('./formulas/ember-data-a
var transformResourceRouterMapping = require('./formulas/resource-router-mapping');
var transformMethodify = require('./formulas/methodify');
var FindOverloadedCPs = require('./formulas/find-overloaded-cps');
var transformDestroyApp = require('./formulas/destroy-app-transform');

module.exports = EmberWatson;

Expand Down Expand Up @@ -62,6 +65,28 @@ EmberWatson.prototype.transformResourceRouterMapping = function(routerPath) {
transform([routerPath], this._transformResourceRouterMapping);
};

EmberWatson.prototype._transformDestroyApp = transformDestroyApp;

EmberWatson.prototype.transformTestToUseDestroyApp = function(rootPath) {
if (!existsSync('tests/helpers/destroy-app.js')) {
console.log(
chalk.red('tests/helpers/destroy-app.js file is not present. ' +
'You must either manually place the file or upgrade to an ' +
'ember-cli version > 1.13.8.' + EOL +
'For more info, visit ' +
'https://gist.github.com/blimmer/35d3efbb64563029505a#create-your-own-destroy-app-helper'
)
);
return;
}

var tests = findFiles(rootPath, '.js').filter(function(file){
return file.indexOf('-test.js') > 0;
});

transform(tests, this._transformDestroyApp);
};

EmberWatson.prototype.findOverloadedCPs = function(rootPath) {
var searcher = new FindOverloadedCPs();
transform(findFiles(rootPath, '.js'), function(source, filename) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"babel-core": "^5.8.22",
"chalk": "^1.0.0",
"commander": "^2.6.0",
"exists-sync": "0.0.3",
"inflected": "^1.1.6",
"recast": "^0.10.29",
"walk-sync": "^0.1.3"
Expand Down
4 changes: 4 additions & 0 deletions tests/cli-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ var commands = {
'convert-resource-router-mapping': {
method: 'transformResourceRouterMapping',
path: 'app/router.js'
},
'use-destroy-app-helper': {
method: 'transformTestToUseDestroyApp',
path: 'tests/acceptance'
}
};

Expand Down
20 changes: 20 additions & 0 deletions tests/commands-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var transformPrototypeExtensionsCalledWith;
var transformQUnitTestCalledWith;
var transformResourceRouterMappingCalledWith;
var transformMethodifyCalledWith;
var transformTestToUseDestroyAppCalledWith;

proxyquire('../lib/commands/convert-ember-data-model-lookups', {
'../../index': Mock
Expand All @@ -34,6 +35,10 @@ proxyquire('../lib/commands/methodify', {
'../../index': Mock
});

proxyquire('../lib/commands/use-destroy-app-helper', {
'../../index': Mock
});

function Mock() {}

Mock.prototype.transformEmberDataModelLookups = function() {
Expand All @@ -60,6 +65,10 @@ Mock.prototype.transformMethodify = function () {
transformMethodifyCalledWith = Array.prototype.slice.apply(arguments);
};

Mock.prototype.transformTestToUseDestroyApp = function() {
transformTestToUseDestroyAppCalledWith = Array.prototype.slice.apply(arguments);
};

describe('Commands:', function () {

afterEach(function () {
Expand All @@ -69,6 +78,7 @@ describe('Commands:', function () {
transformQUnitTestCalledWith = null;
transformResourceRouterMappingCalledWith = null;
transformMethodifyCalledWith = null;
transformTestToUseDestroyAppCalledWith = null;
});

it('convert-ember-data-model-lookups calls the correct transform', function () {
Expand Down Expand Up @@ -136,4 +146,14 @@ describe('Commands:', function () {
Command.run({}, ['some-app']);
assert.deepEqual(transformMethodifyCalledWith, ['some-app']);
});

it('methodify calls the correct transform', function () {
var Command = require('../lib/commands/use-destroy-app-helper');

Command.run({}, []);
assert.deepEqual(transformTestToUseDestroyAppCalledWith, ['tests/acceptance']);

Command.run({}, ['tests/my-crazy-other-thing']);
assert.deepEqual(transformTestToUseDestroyAppCalledWith, ['tests/my-crazy-other-thing']);
});
});
54 changes: 54 additions & 0 deletions tests/destroy-app-transformation-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var Watson = require('../index.js');
var fs = require('fs');
var astEquality = require('./helpers/ast-equality');
var recast = require('recast');

describe('convert acceptance tests to use destroy-app helper', function() {
it('makes the correct transformations - qunit', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-default-qunit.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-default-qunit.js'));
});

it('makes the correct transformations - mocha', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-default-mocha.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-default-mocha.js'));
});

it('does not remove ember import if otherwise used in test - qunit', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-with-ember-usage-qunit.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-with-ember-usage-qunit.js'));
});

it('does not remove ember import if otherwise used in test - mocha', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-with-ember-usage-mocha.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-with-ember-usage-mocha.js'));
});

it('can handle a non-standard application name - qunit', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-crazy-app-name-qunit.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-crazy-app-name-qunit.js'));
});

it('can handle a non-standard application name - mocha', function() {
var source = fs.readFileSync('./tests/fixtures/destroy-app-transform/old-crazy-app-name-mocha.js');
var watson = new Watson();
var newSource = watson._transformDestroyApp(source);

astEquality(newSource, fs.readFileSync('./tests/fixtures/destroy-app-transform/new-crazy-app-name-mocha.js'));
});
});
30 changes: 30 additions & 0 deletions tests/fixtures/destroy-app-transform/new-crazy-app-name-mocha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import destroyApp from '../helpers/destroy-app';
/* jshint expr:true */
import {
describe,
it,
beforeEach,
afterEach
} from 'mocha';
import { expect } from 'chai';
import startApp from '../helpers/start-app';

describe('Acceptance: Index', function() {
var cahRayZeeName;

beforeEach(function() {
cahRayZeeName = startApp();
});

afterEach(function() {
destroyApp(cahRayZeeName);
});

it('can visit /index', function() {
visit('/index');

andThen(function() {
expect(currentPath()).to.equal('index');
});
});
});
21 changes: 21 additions & 0 deletions tests/fixtures/destroy-app-transform/new-crazy-app-name-qunit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import destroyApp from '../helpers/destroy-app';
import { module, test } from 'qunit';
import startApp from 'ember-cli-example-app-for-github/tests/helpers/start-app';

module('Acceptance | index', {
beforeEach: function() {
this.fooBarBazQux = startApp();
},

afterEach: function() {
destroyApp(this.fooBarBazQux);
}
});

test('visiting /index', function(assert) {
visit('/index');

andThen(function() {
assert.equal(currentURL(), '/index');
});
});
30 changes: 30 additions & 0 deletions tests/fixtures/destroy-app-transform/new-default-mocha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import destroyApp from '../helpers/destroy-app';
/* jshint expr:true */
import {
describe,
it,
beforeEach,
afterEach
} from 'mocha';
import { expect } from 'chai';
import startApp from '../helpers/start-app';

describe('Acceptance: Index', function() {
var application;

beforeEach(function() {
application = startApp();
});

afterEach(function() {
destroyApp(application);
});

it('can visit /index', function() {
visit('/index');

andThen(function() {
expect(currentPath()).to.equal('index');
});
});
});
Loading