diff --git a/README.md b/README.md index 75a3c86..d3b5675 100755 --- a/README.md +++ b/README.md @@ -123,6 +123,15 @@ npx ember-test-helpers-codemod acceptance tests/acceptance npx ember-test-helpers-codemod native-dom tests ``` +## Codeshift Options +`--wrapCreateModelWithRunLoop=true` + +This option will wrap `createRecord` calls with a runLoop. This was needed in older versions of Ember to avoid this error: "You have turned on testing mode, which disabled the run-loop's autorun." +``` +let model = this.subject({a:'a'}); //before +let model = Ember.run(() => this.owner.lookup('service:store').createRecord('rental', {a:'a'})); //after +``` + License ------------------------------------------------------------------------------ ember-mocha-codemods is licensed under the [MIT License](LICENSE). diff --git a/__testfixtures__/fourteen-testing-api/setup-model-test2.input.js b/__testfixtures__/fourteen-testing-api/setup-model-test2.input.js new file mode 100644 index 0000000..aac070d --- /dev/null +++ b/__testfixtures__/fourteen-testing-api/setup-model-test2.input.js @@ -0,0 +1,14 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { setupModelTest } from 'ember-mocha'; + +describe('Unit | Model | rental', function() { + setupModelTest('rental', { + needs: [] + }); + // Replace this with your real tests. + it('exists', function() { + let model = this.subject({num: 5, obj: {key: 'val'}, arr: [1,'two']}); + expect(model).to.be.ok; + }); +}); diff --git a/__testfixtures__/fourteen-testing-api/setup-model-test2.output.js b/__testfixtures__/fourteen-testing-api/setup-model-test2.output.js new file mode 100644 index 0000000..c8bf012 --- /dev/null +++ b/__testfixtures__/fourteen-testing-api/setup-model-test2.output.js @@ -0,0 +1,12 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { setupTest } from 'ember-mocha'; + +describe('Unit | Model | rental', function() { + setupTest(); + // Replace this with your real tests. + it('exists', function() { + let model = this.owner.lookup('service:store').createRecord('rental', {num: 5, obj: {key: 'val'}, arr: [1,'two']}); + expect(model).to.be.ok; + }); +}); diff --git a/__testfixtures__/fourteen-testing-api/setup-model-test3.output.js b/__testfixtures__/fourteen-testing-api/setup-model-test3.output.js new file mode 100644 index 0000000..cc848c7 --- /dev/null +++ b/__testfixtures__/fourteen-testing-api/setup-model-test3.output.js @@ -0,0 +1,14 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { setupTest } from 'ember-mocha'; + +describe('Unit | Model | rental', function() { + setupTest(); + // Replace this with your real tests. + it('exists', function() { + let model = Ember.run( + () => this.owner.lookup('service:store').createRecord('rental', {num: 5, obj: {key: 'val'}, arr: [1,'two']}) + ); + expect(model).to.be.ok; + }); +}); diff --git a/__testfixtures__/fourteen-testing-api/setup-model-test3.wrapCreateModelWithRunLoop=true.input.js b/__testfixtures__/fourteen-testing-api/setup-model-test3.wrapCreateModelWithRunLoop=true.input.js new file mode 100644 index 0000000..aac070d --- /dev/null +++ b/__testfixtures__/fourteen-testing-api/setup-model-test3.wrapCreateModelWithRunLoop=true.input.js @@ -0,0 +1,14 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { setupModelTest } from 'ember-mocha'; + +describe('Unit | Model | rental', function() { + setupModelTest('rental', { + needs: [] + }); + // Replace this with your real tests. + it('exists', function() { + let model = this.subject({num: 5, obj: {key: 'val'}, arr: [1,'two']}); + expect(model).to.be.ok; + }); +}); diff --git a/__tests__/fourteen-testing-api-test.js b/__tests__/fourteen-testing-api-test.js index b89f9da..d573e24 100755 --- a/__tests__/fourteen-testing-api-test.js +++ b/__tests__/fourteen-testing-api-test.js @@ -13,15 +13,19 @@ describe('fourteen-testing-api', function() { .readdirSync(fixtureFolder) .filter(filename => /\.input\.js$/.test(filename)) .forEach(filename => { - let testName = filename.replace('.input.js', ''); - let inputPath = path.join(fixtureFolder, `${testName}.input.js`); - let outputPath = path.join(fixtureFolder, `${testName}.output.js`); + // filename format - the-test-name.option1=foo.option2=bar.input.js + + let testNameWithOptions = filename.replace('.input.js', ''), // the-test-name.option1=foo.option2=bar + codeshiftOptions = testNameWithOptions.split('.').slice(1).reduce((p,c) => {p[c.split('=')[0]] = c.split('=')[1]; return p;}, {}), // {option1:foo, option2:bar} + testName = testNameWithOptions.split('.')[0], // the-test-name + inputPath = path.join(fixtureFolder, filename), + outputPath = path.join(fixtureFolder, `${testName}.output.js`); describe(testName, function() { it('transforms correctly', function() { runInlineTest( FourteenTestingAPITransform, - {}, + codeshiftOptions, { source: fs.readFileSync(inputPath, 'utf8') }, fs.readFileSync(outputPath, 'utf8') ); @@ -30,7 +34,7 @@ describe('fourteen-testing-api', function() { it('is idempotent', function() { runInlineTest( FourteenTestingAPITransform, - {}, + codeshiftOptions, { source: fs.readFileSync(outputPath, 'utf8') }, fs.readFileSync(outputPath, 'utf8') ); diff --git a/fourteen-testing-api.js b/fourteen-testing-api.js index a511cf3..e527d61 100755 --- a/fourteen-testing-api.js +++ b/fourteen-testing-api.js @@ -1,8 +1,9 @@ "use strict"; -module.exports = function(file, api) { +module.exports = function(file, api, options) { const j = api.jscodeshift; const root = j(file.source); + const codeShiftOptions = options; const SETUP_TYPE_METHODS = ["setupComponentTest", "setupModelTest"]; @@ -502,8 +503,12 @@ module.exports = function(file, api) { ) ); } else if (subjectType === 'model') { - p.replace( - j.callExpression( + // this.subject({props}) => this.owner.lookup('service:store').createRecord({props}); + + let createRecordArg = p.node.arguments[0] || j.objectExpression([]), /* the argument provided to this.subject() OR empty object expression*/ + { wrapCreateModelWithRunLoop } = codeShiftOptions, + createRecordExpression = (createRecordArg) => { + return j.callExpression( j.memberExpression( j.callExpression( j.memberExpression( @@ -514,11 +519,33 @@ module.exports = function(file, api) { ), j.identifier('createRecord') ), - // creating an empty object expression {} as the 2nd argument here - // because setupModelTests shouldn't need store dependencies - [j.literal(subjectName), j.objectExpression([])].filter(Boolean) + [j.literal(subjectName), createRecordArg].filter(Boolean) ) - ); + }, + runLoopExpression = (content) => { + return j.callExpression( + j.memberExpression( + j.identifier('Ember'), j.identifier('run') + ), [j.arrowFunctionExpression( + [], + content + )] + ) + }; + + if( wrapCreateModelWithRunLoop ){ + // If the user has opted into wrapping with run loop + p.replace( + runLoopExpression( + createRecordExpression(createRecordArg) + ) + ); + } else { + p.replace( + createRecordExpression(createRecordArg) + ); + } + } else { p.replace( j.callExpression(