Skip to content
This repository was archived by the owner on Dec 31, 2022. It is now read-only.

improve component blueprint for octane #213

Closed
wants to merge 14 commits into from
Closed
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-env node */
module.exports = {
root: true,
parserOptions: {
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ language: node_js
node_js:
# we recommend testing addons with the same minimum supported node version as Ember CLI
# so that your addon works for all apps
- "8"
- "12"

sudo: false
dist: trusty
Expand Down
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);
});
});<% } %>
});<% } %>
5 changes: 1 addition & 4 deletions blueprints/component/files/__root__/__path__/__name__.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
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 {
};
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
};

This file was deleted.

This file was deleted.

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"]}
12 changes: 6 additions & 6 deletions lib/utilities/update-paths-for-addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ module.exports = function(paths, addonName, appName, options) {
appStarPaths = paths[appNameStar] = paths[appNameStar] || [];

if (options.removePaths) {
if (paths.hasOwnProperty(addonName)) {
if (Object.prototype.hasOwnProperty.call(paths, addonName)) {
delete paths[addonName];
}
if (paths.hasOwnProperty(addonNameStar)) {
if (Object.prototype.hasOwnProperty.call(paths, addonNameStar)) {
delete paths[addonNameStar]
}
let addonAppPathIndex = appStarPaths.indexOf([addonAppPath, '*'].join('/'));
Expand All @@ -26,16 +26,16 @@ module.exports = function(paths, addonName, appName, options) {
paths[appNameStar] = appStarPaths;
}
} else {
if (!paths.hasOwnProperty(addonName)) {
if (!Object.prototype.hasOwnProperty.call(paths, addonName)) {
paths[addonName] = [ addonAddonPath ];
}
if (!paths.hasOwnProperty(addonNameStar)) {
if (!Object.prototype.hasOwnProperty.call(paths, addonNameStar)) {
paths[addonNameStar] = [ [addonAddonPath, '*'].join('/') ];
}
if (!paths.hasOwnProperty(addonTestSupportPath)) {
if (!Object.prototype.hasOwnProperty.call(paths, addonTestSupportPath)) {
paths[addonTestSupportPath] = [ [addonPath, 'addon-test-support'].join('/') ];
}
if (!paths.hasOwnProperty(addonTestSupportStarPath)) {
if (!Object.prototype.hasOwnProperty.call(paths, addonTestSupportStarPath)) {
paths[addonTestSupportStarPath] = [ [addonPath, 'addon-test-support', '*'].join('/') ];
}
if (appStarPaths.indexOf(addonAppPath) === -1) {
Expand Down
Loading