diff --git a/addon/.eslintrc.js b/addon/.eslintrc.js new file mode 100644 index 00000000..033f9d64 --- /dev/null +++ b/addon/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, + env: { + node: true + }, +}; diff --git a/addon/initializers/ember-test-selectors.js b/addon/initializers/ember-test-selectors.js new file mode 100644 index 00000000..a6487301 --- /dev/null +++ b/addon/initializers/ember-test-selectors.js @@ -0,0 +1,16 @@ +import Ember from 'ember'; +import bindDataTestAttributes from '../utils/bind-data-test-attributes'; + +function initialize(/* application */) { + Ember.Component.reopen({ + init() { + this._super(...arguments); + bindDataTestAttributes(this); + } + }); +} + +export default { + name: 'ember-test-selectors', + initialize +}; diff --git a/addon/utils/bind-data-test-attributes.js b/addon/utils/bind-data-test-attributes.js new file mode 100644 index 00000000..09f8cb9f --- /dev/null +++ b/addon/utils/bind-data-test-attributes.js @@ -0,0 +1,29 @@ +import Ember from 'ember'; + +const TEST_SELECTOR_PREFIX = /data-test-.*/; + +export default function bindDataTestAttributes(component) { + let computedBindings = component.attributeBindings && component.attributeBindings.isDescriptor; + if (computedBindings) { + let message = `ember-test-selectors could not bind data-test-* properties on ${component} ` + + `automatically because attributeBindings is a computed property.`; + + return Ember.warn(message, false, { + id: 'ember-test-selectors.computed-attribute-bindings', + }); + } + + let attributeBindings = component.getWithDefault('attributeBindings', []); + + if (!Ember.isArray(attributeBindings)) { + attributeBindings = [attributeBindings]; + } + + for (let attr in component) { + if (TEST_SELECTOR_PREFIX.test(attr)) { + attributeBindings.push(attr); + } + } + + component.set('attributeBindings', attributeBindings); +} diff --git a/app/.eslintrc.js b/app/.eslintrc.js new file mode 100644 index 00000000..033f9d64 --- /dev/null +++ b/app/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, + env: { + node: true + }, +}; diff --git a/app/initializers/ember-test-selectors.js b/app/initializers/ember-test-selectors.js new file mode 100644 index 00000000..9487acb8 --- /dev/null +++ b/app/initializers/ember-test-selectors.js @@ -0,0 +1 @@ +export { default } from 'ember-test-selectors/initializers/ember-test-selectors'; diff --git a/index.js b/index.js index 5f78a186..da4535ad 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,7 @@ 'use strict'; module.exports = { - name: 'test-selectors', + name: 'ember-test-selectors', _assignOptions: function(app) { var ui = app.project.ui; @@ -37,5 +37,29 @@ module.exports = { }); } } - } + }, + + treeForAddon: function() { + // remove our "addon" folder from the build if we're stripping test selectors + if (!this._stripTestSelectors) { + return this._super.treeForAddon.apply(this, arguments); + } + }, + + treeForApp: function() { + // remove our "app" folder from the build if we're stripping test selectors + if (!this._stripTestSelectors) { + return this._super.treeForApp.apply(this, arguments); + } + }, + + preprocessTree: function(type, tree) { + // remove the unit tests if we're testing ourself and are in strip mode. + // we do this because these tests depend on the "addon" and "app" folders being available, + // which is not the case if they are stripped out of the build. + if (type === 'test' && this._stripTestSelectors && this.project.name() === 'ember-test-selectors') { + tree = require('broccoli-stew').rm(tree, 'dummy/tests/unit/**/*.js'); + } + return tree; + }, }; diff --git a/package.json b/package.json index 7d596e5f..d9fb5506 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "repository": "https://github.com/simplabs/ember-test-selectors", "scripts": { "build": "ember build", - "lint": "eslint config test-support tests *.js", + "lint": "eslint addon app config test-support tests *.js", "start": "ember server", "test": "npm run test:keep && npm run test:strip", "test:all": "ember try:each", @@ -26,6 +26,7 @@ }, "devDependencies": { "broccoli-asset-rev": "^2.4.5", + "broccoli-stew": "^1.4.0", "ember-ajax": "^2.4.1", "ember-cli": "2.10.0", "ember-cli-app-version": "^2.0.0", diff --git a/tests/acceptance/bind-data-test-attributes-in-components-test.js b/tests/acceptance/bind-data-test-attributes-in-components-test.js new file mode 100644 index 00000000..3562f661 --- /dev/null +++ b/tests/acceptance/bind-data-test-attributes-in-components-test.js @@ -0,0 +1,51 @@ +import { test } from 'qunit'; +import moduleForAcceptance from '../../tests/helpers/module-for-acceptance'; + +import config from 'dummy/config/environment'; + +if (!config.stripTestSelectors) { + + /* + * We use an acceptance test here to test the "ember-test-selectors" initializer, + * because initializers are only applied in acceptance tests, but not in + * component integration tests. + */ + moduleForAcceptance('Acceptance | Initializer | ember-test-selectors', { + beforeEach() { + visit('/bind-test'); + }, + }); + + test('it binds data-test-* attributes on components', function (assert) { + assert.equal(find('.test1').find('div[data-test-first]').length, 1, 'data-test-first exists'); + assert.equal(find('.test1').find('div[data-test-first="foobar"]').length, 1, 'data-test-first has correct value'); + }); + + test('it binds data-test-* attributes on components in block form', function (assert) { + assert.equal(find('.test2').find('div[data-test-first]').length, 1, 'data-test-first exists'); + assert.equal(find('.test2').find('div[data-test-first="foobar"]').length, 1, 'data-test-first has correct value'); + }); + + test('it works with multiple data-test-* attributes on components', function (assert) { + assert.equal(find('.test3').find('div[data-test-first]').length, 1, 'data-test-first exists'); + assert.equal(find('.test3').find('div[data-test-first="foobar"]').length, 1, 'data-test-first has correct value'); + assert.equal(find('.test3').find('div[data-test-second]').length, 1, 'data-test-second exists'); + assert.equal(find('.test3').find('div[data-test-second="second"]').length, 1, 'data-test-second has correct value'); + }); + + test('it leaves other data attributes untouched, when a data-test-* attribute is present as well on components', function (assert) { + assert.equal(find('.test4').find('div[data-test-first]').length, 1, 'data-test-first exists'); + assert.equal(find('.test4').find('div[data-test-first="foobar"]').length, 1, 'data-test-first has correct value'); + assert.equal(find('.test4').find('div[data-non-test]').length, 0, 'data-non-test does not exists'); + }); + + test('it leaves data-test attributes untouched on components', function (assert) { + assert.equal(find('.test5').find('div[data-test]').length, 0, 'data-test does not exists'); + }); + + test('it leaves other data attributes untouched on components', function (assert) { + assert.equal(find('.test6').find('div[data-non-test]').length, 0, 'data-non-test does not exists'); + }); + +} + diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index cdc25787..3ae2f797 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -7,6 +7,7 @@ const Router = Ember.Router.extend({ }); Router.map(function() { + this.route('bind-test'); }); export default Router; diff --git a/tests/dummy/app/templates/bind-test.hbs b/tests/dummy/app/templates/bind-test.hbs new file mode 100644 index 00000000..98364b18 --- /dev/null +++ b/tests/dummy/app/templates/bind-test.hbs @@ -0,0 +1,11 @@ +