Skip to content
This repository was archived by the owner on Dec 31, 2022. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 3 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
58 changes: 52 additions & 6 deletions blueprints/component-test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

const path = require('path');
const stringUtil = require('ember-cli-string-utils');
const isPackageMissing = require('ember-cli-is-package-missing');
const getPathOption = require('ember-cli-get-component-path-option');
const semver = require('semver');

const useTestFrameworkDetector = require('../test-framework-detector');

function invocationFor(options) {
let parts = options.entity.name.split('/');
return parts.map((p) => stringUtil.classify(p)).join('::');
}

module.exports = useTestFrameworkDetector({
description: 'Generates a component integration or unit test.',

Expand All @@ -23,7 +30,7 @@ module.exports = useTestFrameworkDetector({
},
],

fileMapTokens: function() {
fileMapTokens: function () {
return {
__root__() {
return 'tests';
Expand All @@ -40,7 +47,7 @@ module.exports = useTestFrameworkDetector({
};
},

locals: function(options) {
locals: function (options) {
let dasherizedModuleName = stringUtil.dasherize(options.entity.name);
let componentPathName = dasherizedModuleName;
let testType = options.testType || 'integration';
Expand All @@ -55,11 +62,50 @@ module.exports = useTestFrameworkDetector({
componentPathName = [options.path, dasherizedModuleName].filter(Boolean).join('/');
}

let hbsImportStatement = this._useNamedHbsImport()
? "import { hbs } from 'ember-cli-htmlbars';"
: "import hbs from 'htmlbars-inline-precompile';";

let templateInvocation = invocationFor(options);
let componentName = templateInvocation;
let openComponent = (descriptor) => `<${descriptor}>`;
let closeComponent = (descriptor) => `</${descriptor}>`;
let selfCloseComponent = (descriptor) => `<${descriptor} />`;

return {
path: getPathOption(options),
testType: testType,
componentPathName: componentPathName,
friendlyTestDescription: friendlyTestDescription,
componentName,
componentPathName,
templateInvocation,
openComponent,
closeComponent,
selfCloseComponent,
friendlyTestDescription,
hbsImportStatement,
};
}
});
},

_useNamedHbsImport() {
let htmlbarsAddon = this.project.addons.find((a) => a.name === 'ember-cli-htmlbars');

if (htmlbarsAddon && semver.gte(htmlbarsAddon.pkg.version, '4.0.0-alpha.1')) {
return true;
}

return false;
},

afterInstall: function (options) {
if (
!options.dryRun &&
options.testType === 'integration' &&
!this._useNamedHbsImport() &&
isPackageMissing(this, 'ember-cli-htmlbars-inline-precompile')
) {
return this.addPackagesToProject([
{ name: 'ember-cli-htmlbars-inline-precompile', target: '^0.3.1' },
]);
}
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ describe('<%= friendlyTestDescription %>', function() {
it('renders', function() {
<% if (testType === 'integration' ) { %>// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });

this.render(hbs`<%= selfCloseComponent(componentName) %>`);
expect(this.$()).to.have.length(1);

// Template block usage:
// this.render(hbs`
// {{#<%= dasherizedModuleName %>}}
// template content
// {{/<%= dasherizedModuleName %>}}
// `);
this.render(hbs`
<%= openComponent(componentName) %>
template block text
<%= closeComponent(componentName) %>
`);

this.render(hbs`{{<%= dasherizedModuleName %>}}`);
expect(this.$()).to.have.length(1);<% } else if(testType === 'unit') { %>// creates the component instance
expect(this.$().text().trim()).to.equal('template block text');<% } else if(testType === 'unit') { %>// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component).to.be.ok;
expect(this.$()).to.have.length(1);<% } %>
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ describeComponent('<%= componentPathName %>', '<%= friendlyTestDescription %>',
it('renders', function() {
<% if (testType === 'integration' ) { %>// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });

this.render(hbs`<%= selfCloseComponent(componentName) %>`);
expect(this.$()).to.have.length(1);

// Template block usage:
// this.render(hbs`
// {{#<%= dasherizedModuleName %>}}
// template content
// {{/<%= dasherizedModuleName %>}}
// `);
this.render(hbs`
<%= openComponent(componentName) %>
template block text
<%= closeComponent(componentName) %>
`);

this.render(hbs`{{<%= dasherizedModuleName %>}}`);
expect(this.$()).to.have.length(1);<% } else if(testType === 'unit') { %>// creates the component instance
expect(this.$().text().trim()).to.equal('template block text');<% } else if(testType === 'unit') { %>// creates the component instance
let component = this.subject();
// renders the component on the page
this.render();
expect(component).to.be.ok;
expect(this.$()).to.have.length(1);<% } %>
});
}
);
);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { describe, it } from 'mocha';
import { setupRenderingTest } from 'ember-mocha';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
<%= hbsImportStatement %>

describe('<%= friendlyTestDescription %>', function() {
setupRenderingTest();
Expand All @@ -11,15 +11,15 @@ describe('<%= friendlyTestDescription %>', function() {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{<%= componentPathName %>}}`);
await render(hbs`<%= selfCloseComponent(componentName) %>`);

expect(this.element.textContent.trim()).to.equal('');

// Template block usage:
await render(hbs`
{{#<%= componentPathName %>}}
<%= openComponent(componentName) %>
template block text
{{/<%= componentPathName %>}}
<%= closeComponent(componentName) %>
`);

expect(this.element.textContent.trim()).to.equal('template block text');
Expand All @@ -35,4 +35,4 @@ describe('<%= friendlyTestDescription %>', function() {
let component = this.owner.factoryFor('component:<%= componentPathName %>').create();
expect(component).to.be.ok;
});
});<% } %>
});<% } %>
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import { moduleForComponent, test } from 'ember-qunit';<% if (testType === 'integration') { %>
import hbs from 'htmlbars-inline-precompile';<% } %>

moduleForComponent('<%= componentPathName %>', '<%= friendlyTestDescription %>', {
<% if (testType === 'integration' ) { %>integration: true<% } else if(testType === 'unit') { %>// Specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar'],
unit: true<% } %>
});

test('it renders', function(assert) {
<% if (testType === 'integration' ) { %>// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });

this.render(hbs`{{<%= componentPathName %>}}`);

assert.equal(this.$().text().trim(), '');

// Template block usage:
this.render(hbs`
{{#<%= componentPathName %>}}
template block text
{{/<%= componentPathName %>}}
`);

assert.equal(this.$().text().trim(), 'template block text');<% } else if(testType === 'unit') { %>
// Creates the component instance
/*let component =*/ this.subject();
// Renders the component to the page
this.render();
assert.equal(this.$().text().trim(), '');<% } %>
});
import hbs from 'htmlbars-inline-precompile';<% } %>
import { TestContext } from 'ember-test-helpers';

type Context = TestContext & {
// add your test properties here
}

moduleForComponent('<%= componentPathName %>', '<%= friendlyTestDescription %>', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thought: while we’re at it, we should, uhh, just get rid of the old-style moduleFor* blueprints. YIKES. I’d forgotten just how out of date our blueprints are. (Doesn’t have to be this PR.)

<% if (testType === 'integration' ) { %>integration: true<% } else if(testType === 'unit') { %>// Specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar'],
unit: true<% } %>
});

test('it renders', function(this: Context, assert: Assert) {
<% if (testType === 'integration' ) { %>// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });

this.render(hbs`<%= selfCloseComponent(componentName) %>`);

assert.equal(this.$().text().trim(), '');

// Template block usage:
this.render(hbs`
<%= openComponent(componentName) %>
template block text
<%= closeComponent(componentName) %>
`);

assert.equal(this.$().text().trim(), 'template block text');<% } else if(testType === 'unit') { %>
// Creates the component instance
/*let component =*/ this.subject();
// Renders the component to the page
this.render();
assert.equal(this.$().text().trim(), '');<% } %>
});
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
<% if (testType === 'integration') { %>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { TestContext } from 'ember-test-helpers';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
<%= hbsImportStatement %>

type Context = TestContext & {
// add your test properties here
}

module('<%= friendlyTestDescription %>', function(hooks) {
setupRenderingTest(hooks);

test('it renders', async function(assert) {
test('it renders', async function(this: Context, assert: Assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`{{<%= componentPathName %>}}`);
await render(hbs`<%= selfCloseComponent(componentName) %>`);

assert.equal(this.element.textContent.trim(), '');

// Template block usage:
await render(hbs`
{{#<%= componentPathName %>}}
<%= openComponent(componentName) %>
template block text
{{/<%= componentPathName %>}}
<%= closeComponent(componentName) %>
`);

assert.equal(this.element.textContent.trim(), 'template block text');
});
});<% } else if (testType === 'unit') { %>import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { TestContext } from 'ember-test-helpers';

type Context = TestContext & {
// add your test properties here
}

module('<%= friendlyTestDescription %>', function(hooks) {
setupTest(hooks);

test('it exists', function(assert) {
test('it exists', function(this: Context, assert: Assert) {
let component = this.owner.factoryFor('component:<%= componentPathName %>').create();
assert.ok(component);
});
});<% } %>
});<% } %>
6 changes: 2 additions & 4 deletions blueprints/component/files/__root__/__path__/__name__.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import Component from '@ember/component';
<%= importTemplate %>
export default class <%= classifiedModuleName %> extends Component.extend({
// anything which *must* be merged to prototype here
}) {<%= contents %>
// normal class body definition here
export default class <%= classifiedModuleName %> extends Component {
// class body definition here
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Component from '@glimmer/component';

interface <%= classifiedModuleName %>Args {}
interface <%= classifiedModuleName %>Args {
// define component arguments here
}

export default class <%= classifiedModuleName %> extends Component<<%= classifiedModuleName %>Args> {}
export default class <%= classifiedModuleName %> extends Component<<%= classifiedModuleName %>Args> {
// class body definition here
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import Component from '@ember/component';

export default class <%= classifiedModuleName %> extends Component.extend({
// anything which *must* be merged to prototype here
}) {
// normal class body definition here
export default class <%= classifiedModuleName %> extends Component {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s delete module unification files as well (again, doesn’t have to be this PR). Module unification is dead, long live template imports. 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure everyone who's using module unification has stopped using it before doing that...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or throw an error with a link to a codemod that migrates the old fashioned folk up to an octane layout

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While that’d be a nice thing to do I don’t think we need to do it. When we do it, we will cut a major release and note that we’ve dropped support for MU. Ember itself stopped supporting it in the blueprints long since, I believe, and we don’t want to support generating more code that way from our POV. We already dropped support for it in a variety of places in the core addon.

// class body definition here
};
1 change: 1 addition & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}