diff --git a/.eslintrc.js b/.eslintrc.js
index 008c09a6..20afbd86 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,4 @@
+/* eslint-env node */
module.exports = {
root: true,
parserOptions: {
diff --git a/blueprints/-addon-import.js b/blueprints/-addon-import.js
new file mode 100644
index 00000000..27cf4f7f
--- /dev/null
+++ b/blueprints/-addon-import.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const stringUtil = require('ember-cli-string-utils');
+const path = require('path');
+const inflector = require('inflection');
+
+module.exports = {
+ description: 'Generates an import wrapper.',
+
+ fileMapTokens: function () {
+ return {
+ __name__: function (options) {
+ return options.dasherizedModuleName;
+ },
+ __path__: function (options) {
+ return inflector.pluralize(options.locals.blueprintName);
+ },
+ __root__: function (options) {
+ if (options.inRepoAddon) {
+ return path.join('lib', options.inRepoAddon, 'app');
+ }
+ return 'app';
+ },
+ };
+ },
+
+ locals: function (options) {
+ let addonRawName = options.inRepoAddon ? options.inRepoAddon : options.project.name();
+ let addonName = stringUtil.dasherize(addonRawName);
+ let fileName = stringUtil.dasherize(options.entity.name);
+ let blueprintName = options.originBlueprintName;
+ let modulePathSegments = [
+ addonName,
+ inflector.pluralize(options.originBlueprintName),
+ fileName,
+ ];
+
+ if (blueprintName.match(/-addon/)) {
+ blueprintName = blueprintName.substr(0, blueprintName.indexOf('-addon'));
+ modulePathSegments = [addonName, inflector.pluralize(blueprintName), fileName];
+ }
+
+ return {
+ modulePath: modulePathSegments.join('/'),
+ blueprintName: blueprintName,
+ };
+ },
+};
diff --git a/blueprints/component-addon/files/__root__/__path__/__name__.js b/blueprints/component-addon/files/__root__/__path__/__name__.js
new file mode 100644
index 00000000..71a8b71c
--- /dev/null
+++ b/blueprints/component-addon/files/__root__/__path__/__name__.js
@@ -0,0 +1 @@
+export { default } from '<%= modulePath %>';
\ No newline at end of file
diff --git a/blueprints/component-addon/index.js b/blueprints/component-addon/index.js
new file mode 100644
index 00000000..a3f30e40
--- /dev/null
+++ b/blueprints/component-addon/index.js
@@ -0,0 +1,76 @@
+'use strict';
+
+const path = require('path');
+const stringUtil = require('ember-cli-string-utils');
+const getPathOption = require('ember-cli-get-component-path-option');
+const normalizeEntityName = require('ember-cli-normalize-entity-name');
+const useEditionDetector = require('../edition-detector');
+
+module.exports = useEditionDetector({
+ description: 'Generates a component.',
+
+ fileMapTokens: function () {
+ return {
+ __path__: function (options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ }
+ return 'components';
+ },
+ __name__: function (options) {
+ if (options.pod) {
+ return 'component';
+ }
+ return options.dasherizedModuleName;
+ },
+ __root__: function (options) {
+ if (options.inRepoAddon) {
+ return path.join('lib', options.inRepoAddon, 'app');
+ }
+ return 'app';
+ },
+ __templatepath__: function (options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ }
+ return 'templates/components';
+ },
+ __templatename__: function (options) {
+ if (options.pod) {
+ return 'template';
+ }
+ return options.dasherizedModuleName;
+ },
+ };
+ },
+
+ normalizeEntityName: function (entityName) {
+ return normalizeEntityName(entityName);
+ },
+
+ locals: function (options) {
+ let addonRawName = options.inRepoAddon ? options.inRepoAddon : options.project.name();
+ let addonName = stringUtil.dasherize(addonRawName);
+ let fileName = stringUtil.dasherize(options.entity.name);
+ let importPathName = [addonName, 'components', fileName].join('/');
+ let templatePath = '';
+
+ if (options.pod) {
+ importPathName = [addonName, 'components', fileName, 'component'].join('/');
+ }
+
+ if (this.project.isEmberCLIAddon() || (options.inRepoAddon && !options.inDummy)) {
+ if (options.pod) {
+ templatePath = './template';
+ } else {
+ templatePath = [addonName, 'templates/components', fileName].join('/');
+ }
+ }
+
+ return {
+ modulePath: importPathName,
+ templatePath,
+ path: getPathOption(options),
+ };
+ },
+});
diff --git a/blueprints/component-addon/native-files/__root__/__path__/__name__.js b/blueprints/component-addon/native-files/__root__/__path__/__name__.js
new file mode 100644
index 00000000..71a8b71c
--- /dev/null
+++ b/blueprints/component-addon/native-files/__root__/__path__/__name__.js
@@ -0,0 +1 @@
+export { default } from '<%= modulePath %>';
\ No newline at end of file
diff --git a/blueprints/component-class-addon/files/__root__/__path__/__name__.js b/blueprints/component-class-addon/files/__root__/__path__/__name__.js
new file mode 100644
index 00000000..71a8b71c
--- /dev/null
+++ b/blueprints/component-class-addon/files/__root__/__path__/__name__.js
@@ -0,0 +1 @@
+export { default } from '<%= modulePath %>';
\ No newline at end of file
diff --git a/blueprints/component-class-addon/index.js b/blueprints/component-class-addon/index.js
new file mode 100644
index 00000000..19272db5
--- /dev/null
+++ b/blueprints/component-class-addon/index.js
@@ -0,0 +1,54 @@
+'use strict';
+
+const path = require('path');
+const stringUtil = require('ember-cli-string-utils');
+const getPathOption = require('ember-cli-get-component-path-option');
+const normalizeEntityName = require('ember-cli-normalize-entity-name');
+const useEditionDetector = require('../edition-detector');
+
+module.exports = useEditionDetector({
+ description: 'Generates a component class.',
+
+ fileMapTokens: function () {
+ return {
+ __path__: function (options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ }
+ return 'components';
+ },
+ __name__: function (options) {
+ if (options.pod) {
+ return 'component';
+ }
+ return options.dasherizedModuleName;
+ },
+ __root__: function (options) {
+ if (options.inRepoAddon) {
+ return path.join('lib', options.inRepoAddon, 'app');
+ }
+ return 'app';
+ },
+ };
+ },
+
+ normalizeEntityName: function (entityName) {
+ return normalizeEntityName(entityName);
+ },
+
+ locals: function (options) {
+ let addonRawName = options.inRepoAddon ? options.inRepoAddon : options.project.name();
+ let addonName = stringUtil.dasherize(addonRawName);
+ let fileName = stringUtil.dasherize(options.entity.name);
+ let importPathName = [addonName, 'components', fileName].join('/');
+
+ if (options.pod) {
+ importPathName = [addonName, 'components', fileName, 'component'].join('/');
+ }
+
+ return {
+ modulePath: importPathName,
+ path: getPathOption(options),
+ };
+ },
+});
diff --git a/blueprints/component-class-addon/native-files/__root__/__path__/__name__.js b/blueprints/component-class-addon/native-files/__root__/__path__/__name__.js
new file mode 100644
index 00000000..71a8b71c
--- /dev/null
+++ b/blueprints/component-class-addon/native-files/__root__/__path__/__name__.js
@@ -0,0 +1 @@
+export { default } from '<%= modulePath %>';
\ No newline at end of file
diff --git a/blueprints/component-class/files/__root__/__path__/__name__.js b/blueprints/component-class/files/__root__/__path__/__name__.js
new file mode 100644
index 00000000..777e6155
--- /dev/null
+++ b/blueprints/component-class/files/__root__/__path__/__name__.js
@@ -0,0 +1,3 @@
+<%= importComponent %>
+<%= importTemplate %>
+export default <%= defaultExport %>
diff --git a/blueprints/component-class/index.js b/blueprints/component-class/index.js
new file mode 100644
index 00000000..697d5b0b
--- /dev/null
+++ b/blueprints/component-class/index.js
@@ -0,0 +1,175 @@
+'use strict';
+
+const path = require('path');
+const SilentError = require('silent-error');
+const stringUtil = require('ember-cli-string-utils');
+const pathUtil = require('ember-cli-path-utils');
+const getPathOption = require('ember-cli-get-component-path-option');
+const normalizeEntityName = require('ember-cli-normalize-entity-name');
+const { EOL } = require('os');
+const { has } = require('@ember/edition-utils');
+
+const OCTANE = has('octane');
+
+// TODO: this should be reading from the @ember/canary-features module
+// need to refactor broccoli/features.js to be able to work more similarly
+// to https://github.com/emberjs/data/pull/6231
+const EMBER_GLIMMER_SET_COMPONENT_TEMPLATE = true;
+
+// intentionally avoiding use-edition-detector
+module.exports = {
+ description: 'Generates a component class.',
+
+ availableOptions: [
+ {
+ name: 'path',
+ type: String,
+ default: 'components',
+ aliases: [{ 'no-path': '' }],
+ },
+ {
+ name: 'component-class',
+ type: ['@ember/component', '@glimmer/component', '@ember/component/template-only'],
+ default: OCTANE ? '@glimmer/component' : '@ember/component',
+ aliases: [
+ { cc: '@ember/component' },
+ { gc: '@glimmer/component' },
+ { tc: '@ember/component/template-only' },
+ ],
+ },
+ {
+ name: 'component-structure',
+ type: OCTANE ? ['flat', 'nested', 'classic'] : ['classic'],
+ default: OCTANE ? 'flat' : 'classic',
+ aliases: OCTANE ? [{ fs: 'flat' }, { ns: 'nested' }, { cs: 'classic' }] : [{ cs: 'classic' }],
+ },
+ ],
+
+ init() {
+ this._super && this._super.init.apply(this, arguments);
+ let isOctane = has('octane');
+
+ this.availableOptions.forEach((option) => {
+ if (option.name === 'component-class') {
+ if (isOctane) {
+ option.default = '@glimmer/component';
+ } else {
+ option.default = '@ember/component';
+ }
+ } else if (option.name === 'component-structure') {
+ if (isOctane) {
+ option.type = ['flat', 'nested', 'classic'];
+ option.default = 'flat';
+ option.aliases = [{ fs: 'flat' }, { ns: 'nested' }, { cs: 'classic' }];
+ } else {
+ option.type = ['classic'];
+ option.default = 'classic';
+ option.aliases = [{ cs: 'classic' }];
+ }
+ }
+ });
+
+ this.EMBER_GLIMMER_SET_COMPONENT_TEMPLATE = EMBER_GLIMMER_SET_COMPONENT_TEMPLATE || isOctane;
+ },
+
+ install() {
+ if (!this.EMBER_GLIMMER_SET_COMPONENT_TEMPLATE) {
+ throw new SilentError(
+ 'Usage of `ember generate component-class` is only available on canary'
+ );
+ }
+
+ return this._super.install.apply(this, arguments);
+ },
+
+ fileMapTokens(options) {
+ let commandOptions = this.options;
+
+ if (commandOptions.pod) {
+ return {
+ __path__() {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ },
+ __name__() {
+ return 'component';
+ },
+ };
+ } else if (
+ commandOptions.componentStructure === 'classic' ||
+ commandOptions.componentStructure === 'flat'
+ ) {
+ return {
+ __path__() {
+ return 'components';
+ },
+ };
+ } else if (commandOptions.componentStructure === 'nested') {
+ return {
+ __path__() {
+ return `components/${options.dasherizedModuleName}`;
+ },
+ __name__() {
+ return 'index';
+ },
+ };
+ }
+ },
+
+ normalizeEntityName(entityName) {
+ return normalizeEntityName(
+ entityName.replace(/\.js$/, '') //Prevent generation of ".js.js" files
+ );
+ },
+
+ locals(options) {
+ let sanitizedModuleName = options.entity.name.replace(/\//g, '-');
+ let classifiedModuleName = stringUtil.classify(sanitizedModuleName);
+
+ let templatePath = '';
+ let importComponent = '';
+ let importTemplate = '';
+ let defaultExport = '';
+
+ // if we're in an addon, build import statement
+ if (options.project.isEmberCLIAddon() || (options.inRepoAddon && !options.inDummy)) {
+ if (options.pod) {
+ templatePath = './template';
+ } else {
+ templatePath =
+ pathUtil.getRelativeParentPath(options.entity.name) +
+ 'templates/components/' +
+ stringUtil.dasherize(options.entity.name);
+ }
+ }
+
+ let componentClass = options.componentClass;
+
+ switch (componentClass) {
+ case '@ember/component':
+ importComponent = `import Component from '@ember/component';`;
+ if (templatePath) {
+ importTemplate = `import layout from '${templatePath}';${EOL}`;
+ defaultExport = `Component.extend({${EOL} layout${EOL}});`;
+ } else {
+ defaultExport = `Component.extend({${EOL}});`;
+ }
+ break;
+ case '@glimmer/component':
+ importComponent = `import Component from '@glimmer/component';`;
+ defaultExport = `class ${classifiedModuleName}Component extends Component {\n}`;
+ break;
+ case '@ember/component/template-only':
+ importComponent = `import templateOnly from '@ember/component/template-only';`;
+ defaultExport = `templateOnly();`;
+ break;
+ }
+
+ return {
+ importTemplate,
+ importComponent,
+ defaultExport,
+ path: getPathOption(options),
+ componentClass,
+ };
+ },
+};
diff --git a/blueprints/component-test/index.js b/blueprints/component-test/index.js
new file mode 100644
index 00000000..dbd546ef
--- /dev/null
+++ b/blueprints/component-test/index.js
@@ -0,0 +1,81 @@
+'use strict';
+
+const path = require('path');
+const stringUtil = require('ember-cli-string-utils');
+const getPathOption = require('ember-cli-get-component-path-option');
+
+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.',
+
+ availableOptions: [
+ {
+ name: 'test-type',
+ type: ['integration', 'unit'],
+ default: 'integration',
+ aliases: [
+ { i: 'integration' },
+ { u: 'unit' },
+ { integration: 'integration' },
+ { unit: 'unit' },
+ ],
+ },
+ ],
+
+ fileMapTokens: function () {
+ return {
+ __root__() {
+ return 'tests';
+ },
+ __testType__(options) {
+ return options.locals.testType || 'integration';
+ },
+ __path__(options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ }
+ return 'components';
+ },
+ };
+ },
+
+ locals: function (options) {
+ let dasherizedModuleName = stringUtil.dasherize(options.entity.name);
+ let componentPathName = dasherizedModuleName;
+ let testType = options.testType || 'integration';
+
+ let friendlyTestDescription = [
+ testType === 'unit' ? 'Unit' : 'Integration',
+ 'Component',
+ dasherizedModuleName,
+ ].join(' | ');
+
+ if (options.pod && options.path !== 'components' && options.path !== '') {
+ componentPathName = [options.path, dasherizedModuleName].filter(Boolean).join('/');
+ }
+
+ 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,
+ componentName,
+ componentPathName,
+ templateInvocation,
+ openComponent,
+ closeComponent,
+ selfCloseComponent,
+ friendlyTestDescription,
+ };
+ }
+});
\ No newline at end of file
diff --git a/blueprints/component-test/mocha-files/__root__/__testType__/__path__/__test__.ts b/blueprints/component-test/mocha-files/__root__/__testType__/__path__/__test__.ts
new file mode 100644
index 00000000..e2b6cd3f
--- /dev/null
+++ b/blueprints/component-test/mocha-files/__root__/__testType__/__path__/__test__.ts
@@ -0,0 +1,27 @@
+import { expect } from 'chai';
+import { describe, it } from 'mocha';
+import { setupRenderingTest } from 'ember-mocha';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+describe('<%= friendlyTestDescription %>', function() {
+ setupRenderingTest();
+
+ it('renders', async function() {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs`<%= selfCloseComponent(componentName) %>`);
+
+ expect(this.element.textContent.trim()).to.equal('');
+
+ // Template block usage:
+ await render(hbs`
+ <%= openComponent(componentName) %>
+ template block text
+ <%= closeComponent(componentName) %>
+ `);
+
+ expect(this.element.textContent.trim()).to.equal('template block text');
+ });
+});
\ No newline at end of file
diff --git a/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.ts b/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.ts
new file mode 100644
index 00000000..6fd18705
--- /dev/null
+++ b/blueprints/component-test/qunit-files/__root__/__testType__/__path__/__test__.ts
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | <%= dasherizedModuleName %>', function(hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs`<<%= templateInvocation %> />`);
+
+ assert.equal(this.element.textContent.trim(), '');
+
+ // Template block usage:
+ await render(hbs`
+ <<%= templateInvocation %>>
+ template block text
+ <%= templateInvocation %>>
+ `);
+
+ assert.equal(this.element.textContent.trim(), 'template block text');
+ });
+});
diff --git a/blueprints/component/files/__root__/__path__/__name__.ts b/blueprints/component/files/__root__/__path__/__name__.ts
new file mode 100644
index 00000000..777e6155
--- /dev/null
+++ b/blueprints/component/files/__root__/__path__/__name__.ts
@@ -0,0 +1,3 @@
+<%= importComponent %>
+<%= importTemplate %>
+export default <%= defaultExport %>
diff --git a/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs b/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs
new file mode 100644
index 00000000..fb5c4b15
--- /dev/null
+++ b/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs
@@ -0,0 +1 @@
+{{yield}}
\ No newline at end of file
diff --git a/blueprints/component/glimmer-files/__root__/__path__/__name__.hbs b/blueprints/component/glimmer-files/__root__/__path__/__name__.hbs
new file mode 100644
index 00000000..fb5c4b15
--- /dev/null
+++ b/blueprints/component/glimmer-files/__root__/__path__/__name__.hbs
@@ -0,0 +1 @@
+{{yield}}
\ No newline at end of file
diff --git a/blueprints/component/glimmer-files/__root__/__path__/__name__.ts b/blueprints/component/glimmer-files/__root__/__path__/__name__.ts
new file mode 100644
index 00000000..d5b3ea97
--- /dev/null
+++ b/blueprints/component/glimmer-files/__root__/__path__/__name__.ts
@@ -0,0 +1,7 @@
+import Component from '@glimmer/component';
+
+interface <%= componentName %>Args {
+}
+
+export default class <%= componentName %> extends Component<<%= componentName %>Args> {
+};
\ No newline at end of file
diff --git a/blueprints/component/index.js b/blueprints/component/index.js
new file mode 100644
index 00000000..6b81f8d2
--- /dev/null
+++ b/blueprints/component/index.js
@@ -0,0 +1,97 @@
+'use strict';
+
+const path = require('path');
+const stringUtil = require('ember-cli-string-utils');
+const pathUtil = require('ember-cli-path-utils');
+const getPathOption = require('ember-cli-get-component-path-option');
+const normalizeEntityName = require('ember-cli-normalize-entity-name');
+const EOL = require('os').EOL;
+
+function componentNameFor(options) {
+ let parts = options.entity.name.split('/');
+ return parts.map((p) => stringUtil.classify(p)).join("");
+}
+
+module.exports = {
+ description: 'Generates a component.',
+
+ availableOptions: [
+ {
+ name: 'path',
+ type: String,
+ default: 'components',
+ aliases: [{ 'no-path': '' }],
+ },
+ ],
+
+ filesPath: function() {
+ let filesDirectory = 'files';
+ let dependencies = this.project.dependencies();
+
+ if ('@glimmer/component' in dependencies) {
+ filesDirectory = 'glimmer-files';
+ }
+
+ return path.join(this.path, filesDirectory);
+ },
+
+ fileMapTokens: function() {
+ return {
+ __path__: function(options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ } else {
+ return 'components';
+ }
+ },
+ __templatepath__: function(options) {
+ if (options.pod) {
+ return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
+ }
+ return 'templates/components';
+ },
+ __templatename__: function(options) {
+ if (options.pod) {
+ return 'template';
+ }
+ return options.dasherizedModuleName;
+ },
+ };
+ },
+
+ normalizeEntityName: function(entityName) {
+ return normalizeEntityName(entityName);
+ },
+
+ locals: function(options) {
+ let templatePath = '';
+ let importTemplate = '';
+ let contents = '';
+
+ let classifiedModuleName = stringUtil.dasherize(options.entity.name);
+
+ let componentName = componentNameFor(options);
+
+ // if we're in an addon, build import statement
+ if (options.project.isEmberCLIAddon() || (options.inRepoAddon && !options.inDummy)) {
+ if (options.pod) {
+ templatePath = './template';
+ } else {
+ templatePath =
+ pathUtil.getRelativeParentPath(options.entity.name) +
+ 'templates/components/' +
+ classifiedModuleName;
+ }
+ importTemplate = '// @ts-ignore: Ignore import of compiled template' + EOL + 'import layout from \'' + templatePath + '\';' + EOL;
+ contents = EOL + ' layout = layout;';
+ }
+
+ return {
+ importTemplate: importTemplate,
+ contents: contents,
+ path: getPathOption(options),
+ classifiedModuleName,
+ componentName
+ };
+ },
+};
diff --git a/blueprints/edition-detector.js b/blueprints/edition-detector.js
new file mode 100644
index 00000000..4e37fcf1
--- /dev/null
+++ b/blueprints/edition-detector.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const { has } = require('@ember/edition-utils');
+const path = require('path');
+
+module.exports = function (blueprint) {
+ blueprint.filesPath = function () {
+ let rootPath = has('octane') ? 'native-files' : 'files';
+ return path.join(this.path, rootPath);
+ };
+
+ return blueprint;
+};
diff --git a/blueprints/helper-test/mocha-files/tests/__testType__/helpers/__name__-test.ts b/blueprints/helper-test/mocha-files/tests/__testType__/helpers/__name__-test.ts
index 8a36c684..4088a058 100644
--- a/blueprints/helper-test/mocha-files/tests/__testType__/helpers/__name__-test.ts
+++ b/blueprints/helper-test/mocha-files/tests/__testType__/helpers/__name__-test.ts
@@ -1,7 +1,7 @@
import { expect } from 'chai';
<% if (testType == 'integration') { %>import { describe, it } from 'mocha';
import { setupComponentTest } from 'ember-mocha';
-import hbs from 'htmlbars-inline-precompile';
+import { hbs } from 'ember-cli-htmlbars';
describe('<%= friendlyTestName %>', function() {
setupComponentTest('<%= dasherizedModuleName %>', {
@@ -21,7 +21,7 @@ describe('<%= friendlyTestName %>', function() {
this.render(hbs`{{<%= dasherizedModuleName %> inputValue}}`);
- expect(this.$().text().trim()).to.equal('1234');
+ expect(this.element.text().trim()).to.equal('1234');
});
});
<% } else if (testType == 'unit') { %>import { describe, it } from 'mocha';
diff --git a/blueprints/helper-test/qunit-files/tests/__testType__/helpers/__name__-test.ts b/blueprints/helper-test/qunit-files/tests/__testType__/helpers/__name__-test.ts
index 28a173e3..d894396b 100644
--- a/blueprints/helper-test/qunit-files/tests/__testType__/helpers/__name__-test.ts
+++ b/blueprints/helper-test/qunit-files/tests/__testType__/helpers/__name__-test.ts
@@ -1,7 +1,7 @@
<% if (testType === 'integration') { %>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
-import hbs from 'htmlbars-inline-precompile';
+import { hbs } from 'ember-cli-htmlbars';
module('<%= friendlyTestName %>', function(hooks) {
setupRenderingTest(hooks);
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 00000000..f408cac8
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1 @@
+{"compilerOptions":{"target":"es6","experimentalDecorators":true},"exclude":["node_modules","bower_components","tmp","vendor",".git","dist"]}
\ No newline at end of file
diff --git a/lib/utilities/update-paths-for-addon.js b/lib/utilities/update-paths-for-addon.js
index 02ddcb05..8edf7e6d 100644
--- a/lib/utilities/update-paths-for-addon.js
+++ b/lib/utilities/update-paths-for-addon.js
@@ -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('/'));
@@ -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) {
diff --git a/node-tests/blueprints/component-addon-test.js b/node-tests/blueprints/component-addon-test.js
new file mode 100644
index 00000000..b2f898f3
--- /dev/null
+++ b/node-tests/blueprints/component-addon-test.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
+const setupTestHooks = blueprintHelpers.setupTestHooks;
+const emberNew = blueprintHelpers.emberNew;
+const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
+
+const chai = require('ember-cli-blueprint-test-helpers/chai');
+const expect = chai.expect;
+
+describe('Blueprint: component-addon', function () {
+ setupTestHooks(this);
+
+ describe('in addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'addon' });
+ });
+
+ it('component-addon foo', function () {
+ return emberGenerateDestroy(['component-addon', 'foo'], (_file) => {
+ expect(_file('app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ });
+ });
+ it('component-addon foo-bar', function () {
+ return emberGenerateDestroy(['component-addon', 'foo-bar'], (_file) => {
+ expect(_file('app/components/foo-bar.js')).to.contain(
+ "export { default } from 'my-addon/components/foo-bar';"
+ );
+ });
+ });
+ });
+});
diff --git a/node-tests/blueprints/component-class-addon-test.js b/node-tests/blueprints/component-class-addon-test.js
new file mode 100644
index 00000000..1dcdd80c
--- /dev/null
+++ b/node-tests/blueprints/component-class-addon-test.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
+const setupTestHooks = blueprintHelpers.setupTestHooks;
+const emberNew = blueprintHelpers.emberNew;
+const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
+
+const chai = require('ember-cli-blueprint-test-helpers/chai');
+const expect = chai.expect;
+
+describe('Blueprint: component-class-addon', function () {
+ setupTestHooks(this);
+
+ describe('in addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'addon' });
+ });
+
+ it('component-addon foo', function () {
+ return emberGenerateDestroy(['component-class-addon', 'foo'], (_file) => {
+ expect(_file('app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ });
+ });
+ it('component-addon foo-bar', function () {
+ return emberGenerateDestroy(['component-class-addon', 'foo-bar'], (_file) => {
+ expect(_file('app/components/foo-bar.js')).to.contain(
+ "export { default } from 'my-addon/components/foo-bar';"
+ );
+ });
+ });
+ });
+});
diff --git a/node-tests/blueprints/component-class-test.js b/node-tests/blueprints/component-class-test.js
new file mode 100644
index 00000000..72d588e4
--- /dev/null
+++ b/node-tests/blueprints/component-class-test.js
@@ -0,0 +1,730 @@
+'use strict';
+
+const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
+const setupTestHooks = blueprintHelpers.setupTestHooks;
+const emberNew = blueprintHelpers.emberNew;
+const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
+const setupPodConfig = blueprintHelpers.setupPodConfig;
+const modifyPackages = blueprintHelpers.modifyPackages;
+
+const chai = require('ember-cli-blueprint-test-helpers/chai');
+const expect = chai.expect;
+
+const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest');
+const fixture = require('../helpers/fixture');
+
+const setupTestEnvironment = require('../helpers/setup-test-environment');
+const enableOctane = setupTestEnvironment.enableOctane;
+
+const { EMBER_SET_COMPONENT_TEMPLATE } = require('../../blueprints/component');
+
+const glimmerComponentContents = `import Component from '@glimmer/component';
+
+export default class FooComponent extends Component {
+}
+`;
+
+const emberComponentContents = `import Component from '@ember/component';
+
+export default Component.extend({
+});
+`;
+
+const templateOnlyContents = `import templateOnly from '@ember/component/template-only';
+
+export default templateOnly();
+`;
+
+describe('Blueprint: component-class', function () {
+ setupTestHooks(this);
+
+ describe('in app', function () {
+ beforeEach(function () {
+ return emberNew()
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo'], (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(emberComponentContents);
+ });
+ });
+
+ if (EMBER_SET_COMPONENT_TEMPLATE) {
+ // classic default
+ it('component-class foo --component-structure=classic --component-class=@ember/component', function () {
+ return emberGenerateDestroy(
+ [
+ 'component-class',
+ 'foo',
+ '--component-structure',
+ 'classic',
+ '--component-class',
+ '@ember/component',
+ ],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(emberComponentContents);
+ }
+ );
+ });
+
+ // Octane default
+ it('component-class foo --component-structure=flat --component-class=@glimmer/component', function () {
+ return emberGenerateDestroy(
+ [
+ 'component-class',
+ '--component-structure',
+ 'flat',
+ '--component-class',
+ '@glimmer/component',
+ 'foo',
+ ],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(glimmerComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-structure=flat', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-structure', 'flat', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(emberComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-structure=nested', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-structure', 'nested', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo/index.js')).to.equal(emberComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-structure=classic', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-structure', 'classic', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(emberComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-class=@ember/component', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-class', '@ember/component', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(emberComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-class=@glimmer/component', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-class', '@glimmer/component', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(glimmerComponentContents);
+ }
+ );
+ });
+
+ it('component-class foo --component-class=@ember/component/template-only', function () {
+ return emberGenerateDestroy(
+ ['component-class', '--component-class', '@ember/component/template-only', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(templateOnlyContents);
+ }
+ );
+ });
+ }
+
+ it('component-class x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo'], (_file) => {
+ expect(_file('app/components/x-foo.js')).to.equal(fixture('component/component-dash.js'));
+ });
+ });
+
+ it('component-class foo/x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo'], (_file) => {
+ expect(_file('app/components/foo/x-foo.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ });
+ });
+
+ it('component-class x-foo --path foo', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--path', 'foo'], (_file) => {
+ expect(_file('app/components/x-foo.js')).to.equal(fixture('component/component-dash.js'));
+ });
+ });
+
+ it('component-class foo.js', function () {
+ return emberGenerateDestroy(['component-class', 'foo.js'], (_file) => {
+ expect(_file('app/components/foo.js.js')).to.not.exist;
+ expect(_file('app/components/foo.js')).to.equal(fixture('component/component.js'));
+ });
+ });
+
+ it('component-class x-foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--pod'], (_file) => {
+ expect(_file('app/components/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ });
+ });
+
+ it('component-class foo/x-foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo', '--pod'], (_file) => {
+ expect(_file('app/components/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ });
+ });
+
+ it('component-class x-foo --pod --path foo', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--pod', '--path', 'foo'],
+ (_file) => {
+ expect(_file('app/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --pod --path bar', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '--path', 'bar'],
+ (_file) => {
+ expect(_file('app/bar/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --pod --path bar/foo', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--pod', '--path', 'bar/foo'],
+ (_file) => {
+ expect(_file('app/bar/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --pod --path bar/baz', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '--path', 'bar/baz'],
+ (_file) => {
+ expect(_file('app/bar/baz/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/x-foo/component.js')).to.equal(fixture('component/component-dash.js'));
+ });
+ });
+
+ it('component-class foo/x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '-no-path'],
+ (_file) => {
+ expect(_file('app/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo.js --pod', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo.js', '--pod'], (_file) => {
+ expect(_file('app/components/x-foo.js/component.js')).to.not.exist;
+ expect(_file('app/components/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ });
+ });
+
+ describe('with podModulePrefix', function () {
+ beforeEach(function () {
+ setupPodConfig({ podModulePrefix: true });
+ });
+
+ it('component-class foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/foo/component.js')).to.equal(
+ fixture('component/component.js')
+ );
+ });
+ });
+
+ it('component-class x-foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ });
+ });
+
+ it('component-class foo/x-foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ });
+ });
+
+ it('component-class x-foo --pod --path foo', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--pod', '--path', 'foo'],
+ (_file) => {
+ expect(_file('app/pods/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --pod --path bar', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '--path', 'bar'],
+ (_file) => {
+ expect(_file('app/pods/bar/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --pod --path bar/foo', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--pod', '--path', 'bar/foo'],
+ (_file) => {
+ expect(_file('app/pods/bar/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --pod --path bar/baz', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '--path', 'bar/baz'],
+ (_file) => {
+ expect(_file('app/pods/bar/baz/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/pods/x-foo/component.js')).to.equal(
+ fixture('component/component-dash.js')
+ );
+ });
+ });
+
+ it('component-class foo/x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--pod', '-no-path'],
+ (_file) => {
+ expect(_file('app/pods/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-nested.js')
+ );
+ }
+ );
+ });
+ });
+ });
+
+ describe('in app - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew()
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo'], (_file) => {
+ expect(_file('app/components/foo.js')).to.equal(glimmerComponentContents);
+ });
+ });
+
+ it('component-class x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo'], (_file) => {
+ expect(_file('app/components/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'XFooComponent')
+ );
+ });
+ });
+
+ it('component-class x-foo.js', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo.js'], (_file) => {
+ expect(_file('app/components/x-foo.js.js')).to.not.exist;
+ expect(_file('app/components/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'XFooComponent')
+ );
+ });
+ });
+
+ it('component-class foo/x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo'], (_file) => {
+ expect(_file('app/components/foo/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'FooXFooComponent')
+ );
+ });
+ });
+
+ it('component-class foo/x-foo --component-class="@glimmer/component"', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--component-class', '@glimmer/component'],
+ (_file) => {
+ expect(_file('app/components/foo/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'FooXFooComponent')
+ );
+ }
+ );
+ });
+ });
+
+ describe('in addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo'], (_file) => {
+ expect(_file('addon/components/foo.js')).to.equal(fixture('component/component-addon.js'));
+ expect(_file('app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ });
+ });
+
+ it('component-class x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo'], (_file) => {
+ expect(_file('addon/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ });
+ });
+
+ it('component-class x-foo.js', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo.js'], (_file) => {
+ expect(_file('addon/components/x-foo.js.js')).to.not.exist;
+ expect(_file('app/components/x-foo.js.js')).to.not.exist;
+ expect(_file('addon/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ });
+ });
+
+ it('component-class foo/x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo'], (_file) => {
+ expect(_file('addon/components/foo/x-foo.js')).to.equal(
+ fixture('component/component-addon-nested.js')
+ );
+ expect(_file('app/components/foo/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+ });
+ });
+
+ it('component-class x-foo --dummy', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('app/components/x-foo.js')).to.not.exist;
+ });
+ });
+
+ it('component-class foo/x-foo --dummy', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/foo/x-foo.js')).to.equal(
+ fixture('component/component-addon-nested.js')
+ );
+ expect(_file('app/components/foo/x-foo.js')).to.not.exist;
+ });
+ });
+
+ it('component-class x-foo.js --dummy', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo.js', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.js.js')).to.not.exist;
+ expect(_file('app/components/x-foo.js.js')).to.not.exist;
+ expect(_file('tests/dummy/app/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('app/components/x-foo.js')).to.not.exist;
+ });
+ });
+
+ it('component-class x-foo --pod', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--pod'], (_file) => {
+ expect(_file('addon/components/x-foo/component.js')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+ expect(_file('app/components/x-foo/component.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+ });
+ });
+ });
+
+ describe('in addon - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew({ target: 'addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo'], (_file) => {
+ expect(_file('addon/components/foo.js')).to.equal(glimmerComponentContents);
+ expect(_file('app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ });
+ });
+
+ it('component-class x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo'], (_file) => {
+ expect(_file('addon/components/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'XFooComponent')
+ );
+ expect(_file('app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ });
+ });
+
+ it('component-class foo/x-foo', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo'], (_file) => {
+ expect(_file('addon/components/foo/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'FooXFooComponent')
+ );
+ expect(_file('app/components/foo/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+ });
+ });
+
+ it('component-class x-foo --dummy', function () {
+ return emberGenerateDestroy(['component-class', 'x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.js')).equal(
+ glimmerComponentContents.replace('FooComponent', 'XFooComponent')
+ );
+ expect(_file('app/components/x-foo.js')).to.not.exist;
+ });
+ });
+
+ it('component-class foo/x-foo --dummy', function () {
+ return emberGenerateDestroy(['component-class', 'foo/x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/foo/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'FooXFooComponent')
+ );
+ expect(_file('app/components/foo/x-foo.hbs')).to.not.exist;
+ });
+ });
+ });
+
+ describe('in in-repo-addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'in-repo-addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo.js')).to.equal(
+ fixture('component/component-addon.js')
+ );
+ expect(_file('lib/my-addon/app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('lib/my-addon/app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo.js --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo.js', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.js.js')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/x-foo.js.js')).to.not.exist;
+
+ expect(_file('lib/my-addon/addon/components/x-foo.js')).to.equal(
+ fixture('component/component-addon-dash.js')
+ );
+ expect(_file('lib/my-addon/app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo/x-foo.js')).to.equal(
+ fixture('component/component-addon-nested.js')
+ );
+ expect(_file('lib/my-addon/app/components/foo/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo/component.js')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+ expect(_file('lib/my-addon/app/components/x-foo/component.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo.js --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo.js', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo/component.js.js')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/x-foo/component.js.js')).to.not.exist;
+ expect(_file('lib/my-addon/addon/components/x-foo/component.js')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+ expect(_file('lib/my-addon/app/components/x-foo/component.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+ }
+ );
+ });
+
+ it('component-class foo/x-foo --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo/x-foo', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo/x-foo/component.js')).to.equal(
+ fixture('component/component-addon-nested-pod.ts')
+ );
+ expect(_file('lib/my-addon/app/components/foo/x-foo/component.js')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo/component';"
+ );
+ }
+ );
+ });
+ });
+
+ describe('in in-repo-addon - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew({ target: 'in-repo-addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component-class foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo.js')).to.equal(glimmerComponentContents);
+ expect(_file('lib/my-addon/app/components/foo.js')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+ }
+ );
+ });
+
+ it('component-class x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component-class', 'x-foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.js')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'XFooComponent')
+ );
+ expect(_file('lib/my-addon/app/components/x-foo.js')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+ }
+ );
+ });
+ });
+});
diff --git a/node-tests/blueprints/component-test-test.js b/node-tests/blueprints/component-test-test.js
new file mode 100644
index 00000000..dcfc7fac
--- /dev/null
+++ b/node-tests/blueprints/component-test-test.js
@@ -0,0 +1,103 @@
+'use strict';
+
+const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
+const setupTestHooks = blueprintHelpers.setupTestHooks;
+const emberNew = blueprintHelpers.emberNew;
+const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
+const modifyPackages = blueprintHelpers.modifyPackages;
+
+const chai = require('ember-cli-blueprint-test-helpers/chai');
+const expect = chai.expect;
+
+const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest');
+const fixture = require('../helpers/fixture');
+
+describe('Blueprint: component-test', function() {
+ setupTestHooks(this);
+
+ describe('in app', function() {
+ beforeEach(function() {
+ return emberNew();
+ });
+
+ describe('with ember-cli-qunit@4.6.0', function() {
+ beforeEach(function() {
+ generateFakePackageManifest('ember-cli-qunit', '4.2.0');
+ });
+
+ it('component-test x-foo', function() {
+ return emberGenerateDestroy(['component-test', 'x-foo'], _file => {
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/qunit.ts')
+ );
+ });
+ });
+
+ });
+
+ describe('with ember-mocha@0.16.0', function() {
+ beforeEach(function() {
+ modifyPackages([
+ { name: 'ember-cli-qunit', delete: true },
+ { name: 'ember-mocha', dev: true },
+ ]);
+ generateFakePackageManifest('ember-mocha', '0.16.0');
+ });
+
+ it('component-test x-foo', function() {
+ return emberGenerateDestroy(['component-test', 'x-foo'], _file => {
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/mocha.ts')
+ );
+ });
+ });
+ });
+ });
+
+ describe('in addon', function() {
+ beforeEach(function() {
+ return emberNew({ target: 'addon' }).then(() =>
+ generateFakePackageManifest('ember-qunit', '4.6.0')
+ );
+ });
+
+ it('component-test x-foo', function() {
+ return emberGenerateDestroy(['component-test', 'x-foo'], _file => {
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/qunit.ts')
+ );
+
+ expect(_file('app/component-test/x-foo.ts')).to.not.exist;
+ });
+ });
+
+ it('component-test x-foo --dummy', function() {
+ return emberGenerateDestroy(['component-test', 'x-foo', '--dummy'], _file => {
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/qunit.ts')
+ );
+
+ expect(_file('app/component-test/x-foo.ts')).to.not.exist;
+ });
+ });
+ });
+
+ describe('in in-repo-addon', function() {
+ beforeEach(function() {
+ return emberNew({ target: 'in-repo-addon' }).then(() =>
+ generateFakePackageManifest('ember-qunit', '4.6.0')
+ );
+ });
+
+ it('component-test x-foo --in-repo-addon=my-addon', function() {
+ return emberGenerateDestroy(
+ ['component-test', 'x-foo', '--in-repo-addon=my-addon'],
+ _file => {
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/qunit.ts')
+ );
+ }
+ );
+ });
+ });
+});
diff --git a/node-tests/blueprints/component-test.js b/node-tests/blueprints/component-test.js
new file mode 100644
index 00000000..f1da2e5a
--- /dev/null
+++ b/node-tests/blueprints/component-test.js
@@ -0,0 +1,1369 @@
+'use strict';
+
+const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
+const setupTestHooks = blueprintHelpers.setupTestHooks;
+const emberNew = blueprintHelpers.emberNew;
+const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
+const setupPodConfig = blueprintHelpers.setupPodConfig;
+const modifyPackages = blueprintHelpers.modifyPackages;
+
+const chai = require('ember-cli-blueprint-test-helpers/chai');
+const expect = chai.expect;
+
+const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest');
+const fixture = require('../helpers/fixture');
+
+const setupTestEnvironment = require('../helpers/setup-test-environment');
+const enableOctane = setupTestEnvironment.enableOctane;
+
+const { EMBER_SET_COMPONENT_TEMPLATE } = require('../../blueprints/component');
+
+const glimmerComponentContents = `import Component from '@glimmer/component';
+
+export default class FooComponent extends Component {
+}
+`;
+
+const emberComponentContents = `import Component from '@ember/component';
+
+export default Component.extend({
+});
+`;
+
+const templateOnlyContents = `import templateOnly from '@ember/component/template-only';
+
+export default templateOnly();
+`;
+
+describe('Blueprint: component', function () {
+ setupTestHooks(this);
+
+ describe('in app', function () {
+ beforeEach(function () {
+ return emberNew()
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo', function () {
+ return emberGenerateDestroy(['component', 'foo'], (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ if (EMBER_SET_COMPONENT_TEMPLATE) {
+ // classic default
+ it('component foo --component-structure=classic --component-class=@ember/component', function () {
+ return emberGenerateDestroy(
+ [
+ 'component',
+ 'foo',
+ '--component-structure',
+ 'classic',
+ '--component-class',
+ '@ember/component',
+ ],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ // Octane default
+ it('component foo --component-structure=flat --component-class=@glimmer/component', function () {
+ return emberGenerateDestroy(
+ [
+ 'component',
+ '--component-structure',
+ 'flat',
+ '--component-class',
+ '@glimmer/component',
+ 'foo',
+ ],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(glimmerComponentContents);
+
+ expect(_file('app/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-structure=flat', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-structure', 'flat', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-structure=nested', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-structure', 'nested', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo/index.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/components/foo/index.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-structure=classic', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-structure', 'classic', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-class=@ember/component', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-class', '@ember/component', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(emberComponentContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-class=@glimmer/component', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-class', '@glimmer/component', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(glimmerComponentContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --component-class=@ember/component/template-only', function () {
+ return emberGenerateDestroy(
+ ['component', '--component-class', '@ember/component/template-only', 'foo'],
+ (_file) => {
+ expect(_file('app/components/foo.ts')).to.equal(templateOnlyContents);
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo --no-component-class', function () {
+ return emberGenerateDestroy(['component', '--no-component-class', 'foo'], (_file) => {
+ expect(_file('app/components/foo.ts')).to.not.exist;
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+ }
+ it('component x-foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo'], (_file) => {
+ expect(_file('app/components/x-foo.ts')).to.equal(fixture('component/component-dash.ts'));
+
+ expect(_file('app/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => {
+ expect(_file('app/components/foo/x-foo.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/templates/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --path foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--path', 'foo'], (_file) => {
+ expect(_file('app/components/x-foo.ts')).to.equal(fixture('component/component-dash.ts'));
+
+ expect(_file('app/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo.ts', function () {
+ return emberGenerateDestroy(['component', 'foo.ts'], (_file) => {
+ expect(_file('app/components/foo.js.ts')).to.not.exist;
+ expect(_file('app/templates/components/foo.js.hbs')).to.not.exist;
+ expect(_file('tests/integration/components/foo.js-test.ts')).to.not.exist;
+
+ expect(_file('app/components/foo.ts')).to.equal(fixture('component/component.ts'));
+
+ expect(_file('app/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --pod', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod'], (_file) => {
+ expect(_file('app/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--pod'], (_file) => {
+ expect(_file('app/components/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/components/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --pod --path foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod', '--path', 'foo'], (_file) => {
+ expect(_file('app/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ path: 'foo/',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod --path bar', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--pod', '--path', 'bar'], (_file) => {
+ expect(_file('app/bar/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/bar/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/bar/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ path: 'bar/',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --pod --path bar/foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod', '--path', 'bar/foo'], (_file) => {
+ expect(_file('app/bar/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/bar/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/bar/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ path: 'bar/foo/',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod --path bar/baz', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--pod', '--path', 'bar/baz'],
+ (_file) => {
+ expect(_file('app/bar/baz/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/bar/baz/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/bar/baz/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ path: 'bar/baz/',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/x-foo/component.ts')).to.equal(fixture('component/component-dash.ts'));
+
+ expect(_file('app/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo.js --pod', function () {
+ return emberGenerateDestroy(['component', 'x-foo.ts', '--pod'], (_file) => {
+ expect(_file('app/components/x-foo.js/component.ts')).to.not.exist;
+ expect(_file('app/components/x-foo.js/template.hbs')).to.not.exist;
+ expect(_file('tests/integration/components/x-foo.js/component-test.ts')).to.not.exist;
+
+ expect(_file('app/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ describe('with podModulePrefix', function () {
+ beforeEach(function () {
+ setupPodConfig({ podModulePrefix: true });
+ });
+
+ it('component foo --pod', function () {
+ return emberGenerateDestroy(['component', 'foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/foo/component.ts')).to.equal(
+ fixture('component/component.ts')
+ );
+
+ expect(_file('app/pods/components/foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/components/foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --pod', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/pods/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--pod'], (_file) => {
+ expect(_file('app/pods/components/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/pods/components/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/components/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --pod --path foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod', '--path', 'foo'], (_file) => {
+ expect(_file('app/pods/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/pods/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ path: 'foo/',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod --path bar', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--pod', '--path', 'bar'],
+ (_file) => {
+ expect(_file('app/pods/bar/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/pods/bar/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/bar/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ path: 'bar/',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component x-foo --pod --path bar/foo', function () {
+ return emberGenerateDestroy(
+ ['component', 'x-foo', '--pod', '--path', 'bar/foo'],
+ (_file) => {
+ expect(_file('app/pods/bar/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/pods/bar/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+ expect(_file('tests/integration/pods/bar/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ path: 'bar/foo/',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo/x-foo --pod --path bar/baz', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--pod', '--path', 'bar/baz'],
+ (_file) => {
+ expect(_file('app/pods/bar/baz/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/pods/bar/baz/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/bar/baz/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ path: 'bar/baz/',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/pods/x-foo/component.ts')).to.equal(
+ fixture('component/component-dash.ts')
+ );
+
+ expect(_file('app/pods/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --pod -no-path', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--pod', '-no-path'], (_file) => {
+ expect(_file('app/pods/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-nested.ts')
+ );
+
+ expect(_file('app/pods/foo/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/pods/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+ });
+ });
+
+ describe('in app - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew()
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo', function () {
+ return emberGenerateDestroy(['component', 'foo'], (_file) => {
+ expect(_file('app/components/foo.ts')).to.not.exist;
+ expect(_file('app/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo'], (_file) => {
+ expect(_file('app/components/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo.ts', function () {
+ return emberGenerateDestroy(['component', 'x-foo.ts'], (_file) => {
+ expect(_file('app/components/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('app/templates/components/x-foo.js.hbs')).to.not.exist;
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.not.exist;
+
+ expect(_file('app/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => {
+ expect(_file('app/components/foo/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo --component-class="@glimmer/component"', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--component-class', '@glimmer/component'],
+ (_file) => {
+ expect(_file('app/components/foo/x-foo.ts')).to.equal(
+ glimmerComponentContents.replace('FooComponent', 'FooXFooComponent')
+ );
+ expect(_file('app/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+ });
+
+ describe('in addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo', function () {
+ return emberGenerateDestroy(['component', 'foo'], (_file) => {
+ expect(_file('addon/components/foo.ts')).to.equal(fixture('component/component-addon.ts'));
+
+ expect(_file('addon/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo'], (_file) => {
+ expect(_file('addon/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('addon/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo.ts', function () {
+ return emberGenerateDestroy(['component', 'x-foo.ts'], (_file) => {
+ expect(_file('addon/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('addon/templates/components/x-foo.js.hbs')).to.not.exist;
+ expect(_file('app/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('tests/integration/components/x-foo.js-test.ts')).to.not.exist;
+
+ expect(_file('addon/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('addon/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => {
+ expect(_file('addon/components/foo/x-foo.ts')).to.equal(
+ fixture('component/component-addon-nested.ts')
+ );
+
+ expect(_file('addon/templates/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/foo/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --dummy', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('tests/dummy/app/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/unit/components/x-foo-test.ts')).to.not.exist;
+ });
+ });
+
+ it('component foo/x-foo --dummy', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/foo/x-foo.ts')).to.equal(
+ fixture('component/component-addon-nested.ts')
+ );
+
+ expect(_file('tests/dummy/app/templates/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/foo/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/unit/components/foo/x-foo-test.ts')).to.not.exist;
+ });
+ });
+
+ it('component x-foo.js --dummy', function () {
+ return emberGenerateDestroy(['component', 'x-foo.ts', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('tests/dummy/app/templates/components/x-foo.js.hbs')).to.not.exist;
+ expect(_file('app/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('tests/unit/components/x-foo.js-test.ts')).to.not.exist;
+
+ expect(_file('tests/dummy/app/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('tests/dummy/app/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/unit/components/x-foo-test.ts')).to.not.exist;
+ });
+ });
+
+ it('component x-foo --pod', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--pod'], (_file) => {
+ expect(_file('addon/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+
+ expect(_file('addon/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo/component.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+ });
+
+ describe('in addon - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew({ target: 'addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo', function () {
+ return emberGenerateDestroy(['component', 'foo'], (_file) => {
+ expect(_file('addon/components/foo.ts')).to.not.exist;
+
+ expect(_file('addon/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+
+ expect(_file('app/templates/components/foo.ts')).to.not.exist;
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo', function () {
+ return emberGenerateDestroy(['component', 'x-foo'], (_file) => {
+ expect(_file('addon/components/x-foo.ts')).to.not.exist;
+
+ expect(_file('addon/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('app/templates/components/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/x-foo.hbs')).to.not.exist;
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component foo/x-foo', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo'], (_file) => {
+ expect(_file('addon/components/foo/x-foo.ts')).to.not.exist;
+
+ expect(_file('addon/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/foo/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+
+ expect(_file('app/templates/components/foo/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --dummy', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/dummy/app/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('app/components/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/x-foo.hbs')).to.not.exist;
+ expect(_file('app/templates/components/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.not.exist;
+ });
+ });
+
+ it('component foo/x-foo --dummy', function () {
+ return emberGenerateDestroy(['component', 'foo/x-foo', '--dummy'], (_file) => {
+ expect(_file('tests/dummy/app/components/foo/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/dummy/app/components/foo/x-foo.hbs')).to.equal('{{yield}}');
+ expect(_file('tests/dummy/app/templates/components/foo/x-foo.hbs')).to.not.exist;
+
+ expect(_file('app/components/foo/x-foo.ts')).to.not.exist;
+ expect(_file('app/components/foo/x-foo.hbs')).to.not.exist;
+ expect(_file('app/templates/components/foo/x-foo.ts')).to.not.exist;
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.not.exist;
+ });
+ });
+ });
+
+ describe('in in-repo-addon', function () {
+ beforeEach(function () {
+ return emberNew({ target: 'in-repo-addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(['component', 'foo', '--in-repo-addon=my-addon'], (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo.ts')).to.equal(
+ fixture('component/component-addon.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/templates/components/foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('lib/my-addon/app/components/foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--in-repo-addon=my-addon'], (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('lib/my-addon/app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo.js --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component', 'x-foo.ts', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('lib/my-addon/addon/templates/components/x-foo.js.hbs')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/x-foo.js.ts')).to.not.exist;
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.not.exist;
+
+ expect(_file('lib/my-addon/addon/components/x-foo.ts')).to.equal(
+ fixture('component/component-addon-dash.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/templates/components/x-foo.hbs')).to.equal('{{yield}}');
+
+ expect(_file('lib/my-addon/app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo/x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--in-repo-addon=my-addon'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo/x-foo.ts')).to.equal(
+ fixture('component/component-addon-nested.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/templates/components/foo/x-foo.hbs')).to.equal(
+ '{{yield}}'
+ );
+
+ expect(_file('lib/my-addon/app/components/foo/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo';"
+ );
+
+ expect(_file('tests/integration/components/foo/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component x-foo --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component', 'x-foo', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('lib/my-addon/app/components/x-foo/component.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component x-foo.js --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component', 'x-foo.ts', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo/component.js.ts')).to.not.exist;
+ expect(_file('lib/my-addon/addon/components/x-foo/template.js.hbs')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/x-foo/component.js.ts')).to.not.exist;
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.not.exist;
+
+ expect(_file('lib/my-addon/addon/components/x-foo/component.ts')).to.equal(
+ fixture('component/component-addon-dash-pod.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/components/x-foo/template.hbs')).to.equal('{{yield}}');
+
+ expect(_file('lib/my-addon/app/components/x-foo/component.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo/component';"
+ );
+
+ expect(_file('tests/integration/components/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+
+ it('component foo/x-foo --in-repo-addon=my-addon --pod', function () {
+ return emberGenerateDestroy(
+ ['component', 'foo/x-foo', '--in-repo-addon=my-addon', '--pod'],
+ (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo/x-foo/component.ts')).to.equal(
+ fixture('component/component-addon-nested-pod.ts')
+ );
+
+ expect(_file('lib/my-addon/addon/components/foo/x-foo/template.hbs')).to.equal(
+ '{{yield}}'
+ );
+
+ expect(_file('lib/my-addon/app/components/foo/x-foo/component.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo/x-foo/component';"
+ );
+
+ expect(_file('tests/integration/components/foo/x-foo/component-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo/x-foo',
+ componentInvocation: 'Foo::XFoo',
+ },
+ })
+ );
+ }
+ );
+ });
+ });
+
+ describe('in in-repo-addon - octane', function () {
+ enableOctane();
+
+ beforeEach(function () {
+ return emberNew({ target: 'in-repo-addon' })
+ .then(() =>
+ modifyPackages([
+ { name: 'ember-qunit', delete: true },
+ { name: 'ember-cli-qunit', dev: true },
+ ])
+ )
+ .then(() => generateFakePackageManifest('ember-cli-qunit', '4.1.0'));
+ });
+
+ it('component foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(['component', 'foo', '--in-repo-addon=my-addon'], (_file) => {
+ expect(_file('lib/my-addon/addon/components/foo.ts')).to.not.exist;
+ expect(_file('lib/my-addon/addon/components/foo.hbs')).to.equal('{{yield}}');
+ expect(_file('lib/my-addon/addon/templates/components/foo.hbs')).to.not.exist;
+
+ expect(_file('lib/my-addon/app/components/foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/foo';"
+ );
+
+ expect(_file('lib/my-addon/app/templates/components/foo.ts')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/foo.hbs')).to.not.exist;
+
+ expect(_file('tests/integration/components/foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'foo',
+ componentInvocation: 'Foo',
+ },
+ })
+ );
+ });
+ });
+
+ it('component x-foo --in-repo-addon=my-addon', function () {
+ return emberGenerateDestroy(['component', 'x-foo', '--in-repo-addon=my-addon'], (_file) => {
+ expect(_file('lib/my-addon/addon/components/x-foo.ts')).to.not.exist;
+ expect(_file('lib/my-addon/addon/components/x-foo.hbs')).to.equal('{{yield}}');
+ expect(_file('lib/my-addon/addon/templates/components/x-foo.hbs')).to.not.exist;
+
+ expect(_file('lib/my-addon/app/components/x-foo.ts')).to.contain(
+ "export { default } from 'my-addon/components/x-foo';"
+ );
+
+ expect(_file('lib/my-addon/app/templates/components/x-foo.ts')).to.not.exist;
+ expect(_file('lib/my-addon/app/components/x-foo.hbs')).to.not.exist;
+
+ expect(_file('tests/integration/components/x-foo-test.ts')).to.equal(
+ fixture('component-test/default-template.ts', {
+ replace: {
+ component: 'x-foo',
+ componentInvocation: 'XFoo',
+ },
+ })
+ );
+ });
+ });
+ });
+});
diff --git a/node-tests/fixtures/component-test/default-template.ts b/node-tests/fixtures/component-test/default-template.ts
new file mode 100644
index 00000000..72df2c7f
--- /dev/null
+++ b/node-tests/fixtures/component-test/default-template.ts
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('<%= path =%><%= component =%>', 'Integration | Component | <%= component =%>', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });
+
+ this.render(hbs`<<%= componentInvocation =%> />`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:
+ this.render(hbs`
+ <<%= componentInvocation =%>>
+ template block text
+ <%= componentInvocation =%>>
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
diff --git a/node-tests/fixtures/component-test/default.ts b/node-tests/fixtures/component-test/default.ts
new file mode 100644
index 00000000..fc4c11ce
--- /dev/null
+++ b/node-tests/fixtures/component-test/default.ts
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('x-foo', 'Integration | Component | x-foo', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });
+
+ this.render(hbs``);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:
+ this.render(hbs`
+
+ template block text
+
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
diff --git a/node-tests/fixtures/component-test/mocha.ts b/node-tests/fixtures/component-test/mocha.ts
new file mode 100644
index 00000000..87c62720
--- /dev/null
+++ b/node-tests/fixtures/component-test/mocha.ts
@@ -0,0 +1,27 @@
+import { expect } from 'chai';
+import { describe, it } from 'mocha';
+import { setupRenderingTest } from 'ember-mocha';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+describe('x-foo', 'Integration | Component | x-foo', function() {
+ setupRenderingTest();
+
+ it('renders', async function() {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ expect(this.element.textContent.trim()).to.equal('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ expect(this.element.textContent.trim()).to.equal('template block text');
+ });
+});
diff --git a/node-tests/fixtures/component-test/qunit.ts b/node-tests/fixtures/component-test/qunit.ts
new file mode 100644
index 00000000..dbebc793
--- /dev/null
+++ b/node-tests/fixtures/component-test/qunit.ts
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | x-foo', function(hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.equal(this.element.textContent.trim(), '');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.equal(this.element.textContent.trim(), 'template block text');
+ });
+});
diff --git a/node-tests/fixtures/component/component-addon-dash-pod.ts b/node-tests/fixtures/component/component-addon-dash-pod.ts
new file mode 100644
index 00000000..6dfbdd55
--- /dev/null
+++ b/node-tests/fixtures/component/component-addon-dash-pod.ts
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+// @ts-ignore: Ignore import of compiled template
+import layout from './template';
+
+export default class XFoo extends Component {
+ layout = layout;
+};
diff --git a/node-tests/fixtures/component/component-addon-dash.ts b/node-tests/fixtures/component/component-addon-dash.ts
new file mode 100644
index 00000000..7fd9a3b5
--- /dev/null
+++ b/node-tests/fixtures/component/component-addon-dash.ts
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+// @ts-ignore: Ignore import of compiled template
+import layout from '../templates/components/x-foo';
+
+export default class XFoo extends Component {
+ layout = layout;
+};
diff --git a/node-tests/fixtures/component/component-addon-nested-pod.ts b/node-tests/fixtures/component/component-addon-nested-pod.ts
new file mode 100644
index 00000000..b84869b7
--- /dev/null
+++ b/node-tests/fixtures/component/component-addon-nested-pod.ts
@@ -0,0 +1,10 @@
+import Component from '@ember/component';
+// @ts-ignore: Ignore import of compiled template
+import layout from './template';
+
+export default class FooXFoo extends Component.extend({
+ // anything which *must* be merged to prototype here
+}) {
+ layout = layout;
+ // normal class body definition here
+};
diff --git a/node-tests/fixtures/component/component-addon-nested.ts b/node-tests/fixtures/component/component-addon-nested.ts
new file mode 100644
index 00000000..b8d2c8a9
--- /dev/null
+++ b/node-tests/fixtures/component/component-addon-nested.ts
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+// @ts-ignore: Ignore import of compiled template
+import layout from '../../templates/components/foo/x-foo';
+
+export default class FooXFoo extends Component {
+ layout = layout;
+}
diff --git a/node-tests/fixtures/component/component-addon.ts b/node-tests/fixtures/component/component-addon.ts
new file mode 100644
index 00000000..8cc7412f
--- /dev/null
+++ b/node-tests/fixtures/component/component-addon.ts
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+// @ts-ignore: Ignore import of compiled template
+import layout from '../templates/components/foo';
+
+export default class Foo extends Component {
+ layout = layout;
+}
diff --git a/node-tests/fixtures/component/component-dash.ts b/node-tests/fixtures/component/component-dash.ts
new file mode 100644
index 00000000..c978f988
--- /dev/null
+++ b/node-tests/fixtures/component/component-dash.ts
@@ -0,0 +1,4 @@
+import Component from '@ember/component';
+
+export default class XFoo extends Component {
+}
diff --git a/node-tests/fixtures/component/component-nested.ts b/node-tests/fixtures/component/component-nested.ts
new file mode 100644
index 00000000..760840ce
--- /dev/null
+++ b/node-tests/fixtures/component/component-nested.ts
@@ -0,0 +1,4 @@
+import Component from '@ember/component';
+
+export default class FooXFoo extends Component {
+}
diff --git a/node-tests/fixtures/component/component.ts b/node-tests/fixtures/component/component.ts
new file mode 100644
index 00000000..9ffdf650
--- /dev/null
+++ b/node-tests/fixtures/component/component.ts
@@ -0,0 +1,4 @@
+import Component from '@ember/component';
+
+export default class Foo extends Component {
+};
diff --git a/node-tests/fixtures/component/glimmer-component-dash.ts b/node-tests/fixtures/component/glimmer-component-dash.ts
new file mode 100644
index 00000000..312a6b5f
--- /dev/null
+++ b/node-tests/fixtures/component/glimmer-component-dash.ts
@@ -0,0 +1,7 @@
+import Component from '@glimmer/component';
+
+interface XFooArgs {}
+
+export default class XFoo extends Component {
+
+}
diff --git a/node-tests/fixtures/component/glimmer-component-nested.ts b/node-tests/fixtures/component/glimmer-component-nested.ts
new file mode 100644
index 00000000..1bd26c76
--- /dev/null
+++ b/node-tests/fixtures/component/glimmer-component-nested.ts
@@ -0,0 +1,5 @@
+import Component from '@glimmer/component';
+
+interface FooXFooArgs {}
+
+export default class FooXFoo extends Component {}
diff --git a/node-tests/fixtures/component/glimmer-component.ts b/node-tests/fixtures/component/glimmer-component.ts
new file mode 100644
index 00000000..b77f74d9
--- /dev/null
+++ b/node-tests/fixtures/component/glimmer-component.ts
@@ -0,0 +1,5 @@
+import Component from '@glimmer/component';
+
+interface FooArgs {}
+
+export default class Foo extends Component {}
diff --git a/node-tests/fixtures/helper-test/integration.ts b/node-tests/fixtures/helper-test/integration.ts
index 8ce8201b..f9b2db03 100644
--- a/node-tests/fixtures/helper-test/integration.ts
+++ b/node-tests/fixtures/helper-test/integration.ts
@@ -1,7 +1,7 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
-import hbs from 'htmlbars-inline-precompile';
+import { hbs } from 'ember-cli-htmlbars';
module('Integration | Helper | foo/bar-baz', function(hooks) {
setupRenderingTest(hooks);
diff --git a/node-tests/fixtures/helper-test/mocha.ts b/node-tests/fixtures/helper-test/mocha.ts
index feca3336..ec2202a1 100644
--- a/node-tests/fixtures/helper-test/mocha.ts
+++ b/node-tests/fixtures/helper-test/mocha.ts
@@ -1,7 +1,7 @@
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { setupComponentTest } from 'ember-mocha';
-import hbs from 'htmlbars-inline-precompile';
+import { hbs } from 'ember-cli-htmlbars';
describe('Integration | Helper | foo/bar-baz', function() {
setupComponentTest('foo/bar-baz', {
@@ -21,6 +21,6 @@ describe('Integration | Helper | foo/bar-baz', function() {
this.render(hbs`{{foo/bar-baz inputValue}}`);
- expect(this.$().text().trim()).to.equal('1234');
+ expect(this.element.text().trim()).to.equal('1234');
});
});
diff --git a/node-tests/helpers/expect-error.js b/node-tests/helpers/expect-error.js
index c96aab1e..e9eda641 100644
--- a/node-tests/helpers/expect-error.js
+++ b/node-tests/helpers/expect-error.js
@@ -8,7 +8,7 @@ module.exports = function expectError(promise, expectedErrorText) {
.then(() => {
throw new Error('the command should raise an exception');
})
- .catch(error => {
- expect(error.message || error).to.equal(expectedErrorText);
+ .catch((error) => {
+ expect(error.message).to.equal(expectedErrorText);
});
};
diff --git a/node-tests/helpers/fixture.js b/node-tests/helpers/fixture.js
index 4b9c83b1..b55cde25 100644
--- a/node-tests/helpers/fixture.js
+++ b/node-tests/helpers/fixture.js
@@ -4,12 +4,14 @@ const path = require('path');
const file = require('ember-cli-blueprint-test-helpers/chai').file;
const fs = require('fs');
-module.exports = function(filePath, options) {
+module.exports = function (filePath, options) {
if (!options) {
return file(path.join(__dirname, '../fixtures', filePath));
}
- let content = fs.readFileSync(path.join(__dirname, '../fixtures', filePath), { encoding: 'utf-8' });
+ let content = fs.readFileSync(path.join(__dirname, '../fixtures', filePath), {
+ encoding: 'utf-8',
+ });
if (options.replace) {
content = content.replace(/<%= (\w+) =%>/g, (_match, key) => options.replace[key] || '');
}
diff --git a/node-tests/helpers/generate-fake-package-manifest.js b/node-tests/helpers/generate-fake-package-manifest.js
index 50a3c664..ad521a48 100644
--- a/node-tests/helpers/generate-fake-package-manifest.js
+++ b/node-tests/helpers/generate-fake-package-manifest.js
@@ -1,22 +1,16 @@
-// @ts-check
-const { writeFileSync } = require('fs');
-const { ensureDirSync } = require('fs-extra');
-const path = require('path');
+const fs = require('fs');
-/**
- * Create fake package manifests on the file system to use in ensuring that the
- * blueprint generator is well-behaved with different test environments (e.g.
- * qunit and mocha).
- *
- * @param {string} name
- * @param {string} version
- */
-function generateFakePackageManifest(name, version) {
- const targetDir = path.join('node_modules', name);
- ensureDirSync(targetDir);
-
- const pkgFilePath = path.join(targetDir, 'package.json');
- writeFileSync(pkgFilePath, JSON.stringify({ version }));
-}
-
-module.exports = generateFakePackageManifest;
+module.exports = function generateFakePackageManifest(name, version) {
+ if (!fs.existsSync('node_modules')) {
+ fs.mkdirSync('node_modules');
+ }
+ if (!fs.existsSync('node_modules/' + name)) {
+ fs.mkdirSync('node_modules/' + name);
+ }
+ fs.writeFileSync(
+ 'node_modules/' + name + '/package.json',
+ JSON.stringify({
+ version: version,
+ })
+ );
+};
diff --git a/node-tests/helpers/setup-test-environment.js b/node-tests/helpers/setup-test-environment.js
new file mode 100644
index 00000000..25d9a60d
--- /dev/null
+++ b/node-tests/helpers/setup-test-environment.js
@@ -0,0 +1,15 @@
+const { setEdition, clearEdition } = require('@ember/edition-utils');
+
+function enableOctane() {
+ beforeEach(function () {
+ setEdition('octane');
+ });
+
+ afterEach(function () {
+ clearEdition();
+ });
+}
+
+module.exports = {
+ enableOctane,
+};
diff --git a/package.json b/package.json
index 4cbd1d5c..c30a8f5c 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"silent-error": "^1.1.0"
},
"devDependencies": {
+ "@babel/core": "^7.12.3",
"@typed-ember/renovate-config": "1.2.1",
"broccoli-asset-rev": "3.0.0",
"ember-ajax": "5.0.0",
@@ -44,7 +45,6 @@
"ember-cli-eslint": "5.1.0",
"ember-cli-htmlbars": "5.3.1",
"ember-cli-inject-live-reload": "2.0.2",
- "ember-qunit": "4.6.0",
"ember-cli-shims": "1.2.0",
"ember-cli-sri": "2.1.1",
"ember-cli-uglify": "3.0.0",
@@ -52,10 +52,12 @@
"ember-export-application-global": "2.0.1",
"ember-load-initializers": "2.1.2",
"ember-maybe-import-regenerator": "0.1.6",
+ "ember-qunit": "4.6.0",
"ember-resolver": "8.0.2",
"ember-source": "3.23.0",
"ember-source-channel-url": "3.0.0",
"ember-try": "1.4.0",
+ "eslint": "^7.13.0",
"eslint-plugin-ember": "9.6.0",
"eslint-plugin-node": "11.1.0",
"loader.js": "4.7.0",
diff --git a/yarn.lock b/yarn.lock
index 65c5c3fa..b3e5a9c6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -23,7 +23,7 @@
invariant "^2.2.4"
semver "^5.5.0"
-"@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.3.4", "@babel/core@^7.8.4":
+"@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.3.4", "@babel/core@^7.8.4":
version "7.12.3"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.3.tgz#1b436884e1e3bff6fb1328dc02b208759de92ad8"
integrity sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==
@@ -1472,6 +1472,22 @@
ember-cli-htmlbars-inline-precompile "^2.1.0"
ember-test-waiters "^1.1.1"
+"@eslint/eslintrc@^0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c"
+ integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.1.1"
+ espree "^7.3.0"
+ globals "^12.1.0"
+ ignore "^4.0.6"
+ import-fresh "^3.2.1"
+ js-yaml "^3.13.1"
+ lodash "^4.17.19"
+ minimatch "^3.0.4"
+ strip-json-comments "^3.1.1"
+
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
@@ -1640,16 +1656,36 @@ acorn-jsx@^5.0.0:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.0.tgz#958584ddb60990c02c97c1bd9d521fce433bb101"
integrity sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg==
+acorn-jsx@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+ integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
+
acorn@^6.0.2:
version "6.4.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
+acorn@^7.4.0:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
+ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
ajv@^6.5.3:
version "6.5.5"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.5.tgz#cf97cdade71c6399a92c6d6c4177381291b781a1"
@@ -1680,7 +1716,7 @@ amdefine@>=0.0.4:
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
-ansi-colors@4.1.1:
+ansi-colors@4.1.1, ansi-colors@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
@@ -1710,6 +1746,11 @@ ansi-regex@^4.1.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+ansi-regex@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
+ integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
+
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -1868,6 +1909,11 @@ ast-types@0.13.1:
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.1.tgz#9461428a270c5a27fda44b738dd3bab2e9353003"
integrity sha512-b+EeK0WlzrSmpMw5jktWvQGxblpWnvMrV+vOp69RLjzGiHwWV0vgq75DPKtUjppKni3yWwSW8WLGV3Ch/XIWcQ==
+astral-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+ integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
async-disk-cache@^1.2.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/async-disk-cache/-/async-disk-cache-1.3.3.tgz#6040486660b370e4051cd9fa9fee275e1fae3728"
@@ -3372,7 +3418,7 @@ callsites@^0.2.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=
-callsites@^3.1.0:
+callsites@^3.0.0, callsites@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
@@ -3894,7 +3940,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^7.0.0:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -3997,7 +4043,7 @@ deep-extend@^0.6.0:
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-deep-is@~0.1.3:
+deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
@@ -4112,6 +4158,13 @@ doctrine@^2.1.0:
dependencies:
esutils "^2.0.2"
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
dot-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.3.tgz#21d3b52efaaba2ea5fda875bb1aa8124521cf4aa"
@@ -4829,6 +4882,13 @@ engine.io@~3.2.0:
engine.io-parser "~2.1.0"
ws "~3.3.1"
+enquirer@^2.3.5:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+ integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+ dependencies:
+ ansi-colors "^4.1.1"
+
ensure-posix-path@^1.0.0, ensure-posix-path@^1.0.1, ensure-posix-path@^1.0.2, ensure-posix-path@^1.1.0, ensure-posix-path@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce"
@@ -4916,6 +4976,14 @@ eslint-scope@^4.0.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
eslint-utils@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
@@ -4928,11 +4996,28 @@ eslint-utils@^2.0.0:
dependencies:
eslint-visitor-keys "^1.1.0"
+eslint-utils@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
+ integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
+ dependencies:
+ eslint-visitor-keys "^1.1.0"
+
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
+eslint-visitor-keys@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+ integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+
+eslint-visitor-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+ integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+
eslint@^5.6.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.9.0.tgz#b234b6d15ef84b5849c6de2af43195a2d59d408e"
@@ -4977,6 +5062,49 @@ eslint@^5.6.0:
table "^5.0.2"
text-table "^0.2.0"
+eslint@^7.13.0:
+ version "7.13.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da"
+ integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@eslint/eslintrc" "^0.2.1"
+ ajv "^6.10.0"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
+ debug "^4.0.1"
+ doctrine "^3.0.0"
+ enquirer "^2.3.5"
+ eslint-scope "^5.1.1"
+ eslint-utils "^2.1.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.0"
+ esquery "^1.2.0"
+ esutils "^2.0.2"
+ file-entry-cache "^5.0.1"
+ functional-red-black-tree "^1.0.1"
+ glob-parent "^5.0.0"
+ globals "^12.1.0"
+ ignore "^4.0.6"
+ import-fresh "^3.0.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ js-yaml "^3.13.1"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.4.1"
+ lodash "^4.17.19"
+ minimatch "^3.0.4"
+ natural-compare "^1.4.0"
+ optionator "^0.9.1"
+ progress "^2.0.0"
+ regexpp "^3.1.0"
+ semver "^7.2.1"
+ strip-ansi "^6.0.0"
+ strip-json-comments "^3.1.0"
+ table "^5.2.3"
+ text-table "^0.2.0"
+ v8-compile-cache "^2.0.3"
+
esm@^3.2.4:
version "3.2.25"
resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
@@ -4991,6 +5119,15 @@ espree@^4.0.0:
acorn-jsx "^5.0.0"
eslint-visitor-keys "^1.0.0"
+espree@^7.3.0:
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348"
+ integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==
+ dependencies:
+ acorn "^7.4.0"
+ acorn-jsx "^5.2.0"
+ eslint-visitor-keys "^1.3.0"
+
esprima@^4.0.0, esprima@~4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@@ -5008,6 +5145,13 @@ esquery@^1.0.1:
dependencies:
estraverse "^4.0.0"
+esquery@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
+ integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
+ dependencies:
+ estraverse "^5.1.0"
+
esrecurse@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
@@ -5015,11 +5159,23 @@ esrecurse@^4.1.0:
dependencies:
estraverse "^4.1.0"
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=
+estraverse@^5.1.0, estraverse@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+ integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@@ -5202,6 +5358,11 @@ fast-deep-equal@^2.0.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
fast-glob@^3.0.3:
version "3.2.4"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3"
@@ -5219,7 +5380,7 @@ fast-json-stable-stringify@^2.0.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
-fast-levenshtein@~2.0.4:
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@@ -5295,6 +5456,13 @@ file-entry-cache@^2.0.0:
flat-cache "^1.2.1"
object-assign "^4.0.1"
+file-entry-cache@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
+ integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
+ dependencies:
+ flat-cache "^2.0.1"
+
filesize@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00"
@@ -5451,11 +5619,25 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
+flat-cache@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
+ integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+ dependencies:
+ flatted "^2.0.0"
+ rimraf "2.6.3"
+ write "1.0.3"
+
flat@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+flatted@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
+ integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+
follow-redirects@^1.0.0:
version "1.5.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.6.tgz#44eb4fe1981dff25e2bd86b7d4033abcdb81e965"
@@ -5748,7 +5930,7 @@ git-write-pkt-line@0.1.0:
bops "0.0.3"
through "~2.2.7"
-glob-parent@^5.1.0, glob-parent@~5.1.0:
+glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
@@ -5803,6 +5985,13 @@ globals@^11.1.0, globals@^11.7.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249"
integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==
+globals@^12.1.0:
+ version "12.4.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
+ integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
+ dependencies:
+ type-fest "^0.8.1"
+
globals@^9.18.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
@@ -6160,6 +6349,14 @@ ignore@^5.1.1:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.1.tgz#2fc6b8f518aff48fef65a7f348ed85632448e4a5"
integrity sha512-DWjnQIFLenVrwyRCKZT+7a7/U4Cqgar4WG8V++K3hw+lrW1hc/SIwdiGmtxKCVACmHULTuGeBbHJmbwW7/sAvA==
+import-fresh@^3.0.0, import-fresh@^3.2.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e"
+ integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -6721,6 +6918,14 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
line-stream@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/line-stream/-/line-stream-0.0.0.tgz#888b7cc7951c6a05ce4d696dd1e6b8262371bb45"
@@ -7798,6 +8003,18 @@ optionator@^0.8.2:
type-check "~0.3.2"
wordwrap "~1.0.0"
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
+
ora@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318"
@@ -7917,6 +8134,13 @@ package-json@^4.0.1:
registry-url "^3.0.3"
semver "^5.1.0"
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
parse-passwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
@@ -8073,6 +8297,11 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -8375,6 +8604,11 @@ regexpp@^3.0.0:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e"
integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==
+regexpp@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
+ integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+
regexpu-core@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
@@ -8523,6 +8757,11 @@ resolve-from@^1.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
resolve-package-path@^1.0.11, resolve-package-path@^1.2.6:
version "1.2.7"
resolved "https://registry.yarnpkg.com/resolve-package-path/-/resolve-package-path-1.2.7.tgz#2a7bc37ad96865e239330e3102c31322847e652e"
@@ -8585,6 +8824,13 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+rimraf@2.6.3, rimraf@~2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+ integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+ dependencies:
+ glob "^7.1.3"
+
rimraf@^2.1.4, rimraf@^2.2.8, rimraf@^2.3.4, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
@@ -8599,13 +8845,6 @@ rimraf@^3.0.0, rimraf@^3.0.1, rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
-rimraf@~2.6.2:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- dependencies:
- glob "^7.1.3"
-
rsvp@^3.0.14, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
@@ -8697,7 +8936,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-semver@^7.0.0, semver@^7.3.2:
+semver@^7.0.0, semver@^7.2.1, semver@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
@@ -8831,6 +9070,15 @@ slice-ansi@1.0.0:
dependencies:
is-fullwidth-code-point "^2.0.0"
+slice-ansi@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
+ integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
+ dependencies:
+ ansi-styles "^3.2.0"
+ astral-regex "^1.0.0"
+ is-fullwidth-code-point "^2.0.0"
+
snake-case@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.3.tgz#c598b822ab443fcbb145ae8a82c5e43526d5bbee"
@@ -9140,6 +9388,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
+strip-ansi@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
+ integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
+ dependencies:
+ ansi-regex "^5.0.0"
+
strip-bom@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
@@ -9155,7 +9410,7 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-strip-json-comments@3.1.1:
+strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -9240,6 +9495,16 @@ table@^5.0.2:
slice-ansi "1.0.0"
string-width "^2.1.1"
+table@^5.2.3:
+ version "5.4.6"
+ resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
+ integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==
+ dependencies:
+ ajv "^6.10.2"
+ lodash "^4.17.14"
+ slice-ansi "^2.1.0"
+ string-width "^3.0.0"
+
tap-parser@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/tap-parser/-/tap-parser-7.0.0.tgz#54db35302fda2c2ccc21954ad3be22b2cba42721"
@@ -9506,6 +9771,13 @@ tslib@^1.10.0, tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -9533,6 +9805,11 @@ type-fest@^0.11.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
+type-fest@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
@@ -9720,6 +9997,11 @@ uuid@^8.3.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
+v8-compile-cache@^2.0.3:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132"
+ integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==
+
validate-npm-package-name@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
@@ -9830,6 +10112,11 @@ wide-align@1.1.3, wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2"
+word-wrap@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
wordwrap@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@@ -9890,6 +10177,13 @@ write-file-atomic@^3.0.0:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
+write@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
+ integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
+ dependencies:
+ mkdirp "^0.5.1"
+
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"