Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle components with empty tag name #323

Merged
merged 3 commits into from
Mar 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,49 @@ export default Ember.Component({
As with `data-test-*` attributes in the templates, these properties, whether
computed or not, will be removed automatically in production builds.

### Usage with tagless components

Since tagless components do not have a root element, `data-test-*` attributes
passed to them cannot be bound to the DOM. If you try to pass a `data-test-*`
attribute to a tagless component, or define one in its Javascript class,
`ember-test-selectors` will throw an assertion error.

However, there are some cases where you might want to pass a `data-test-*`
attribute to a tagless component, for example a tagless wrapper component:

```js
// comment-wrapper.js
export default Ember.Component({
tagName: ''
})
```

```hbs
{{!-- comment-wrapper.hbs --}}
Comment:
{{comment-list-item comment=comment data-test-comment-id=data-test-comment-id}}
```

```handlebars
{{!-- comment-list.hbs --}}
{{#each comments as |comment|}}
{{comment-wrapper comment=comment data-test-comment-id=comment.id}}
{{/each}}
```

In this case, to prevent the assertion on the specific `comment-wrapper`
component, you can specify `supportsDataTestProperties` on the class:

```js
// comment-wrapper.js
export default Ember.Component({
tagName: '',
supportsDataTestProperties: true
})
```

`supportsDataTestProperties`, like `data-test-*` properties, will be stripped
from the build.

Configuration
------------------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion addon/utils/bind-data-test-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ export default function bindDataTestAttributes(component) {

let tagName = component.get('tagName');

if (component.get('supportsDataTestProperties') && tagName === '') {
return;
}

let message = `ember-test-selectors could not bind data-test-* properties on ${component} ` +
`automatically because tagName is empty.`;
`automatically because tagName is empty. If you did this intentionally, see ` +
`https://github.com/simplabs/ember-test-selectors#usage-in-computed-properties ` +
`for instructions on how to disable this assertion.`;

assert(message, tagName !== '', {
id: 'ember-test-selectors.empty-tag-name',
Expand Down
5 changes: 4 additions & 1 deletion node-tests/fixtures/default/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ exports['default'] = _ember2['default'].Component.extend({
'data-test': 'test',
'metadata-test-foo': 'metadata'
});
module.exports = exports['default'];
var c2 = _ember2['default'].Component.extend({
foo: 'foo'
});
exports.c2 = c2;
4 changes: 4 additions & 0 deletions node-tests/fixtures/default/expected6.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ export default Ember.Component.extend({
'data-test': 'test',
'metadata-test-foo': 'metadata'
});

export let c2 = Ember.Component.extend({
foo: 'foo'
});
3 changes: 3 additions & 0 deletions node-tests/fixtures/default/expected7.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ export default Ember.Component.extend({
'data-test': 'test',
'metadata-test-foo': 'metadata'
});
export let c2 = Ember.Component.extend({
foo: 'foo'
});
6 changes: 6 additions & 0 deletions node-tests/fixtures/default/fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ export default Ember.Component.extend({
'data-test-foobar': Ember.computed('data-test-foo', function() {
return `${this.get('data-test-foo')}bar`
}),
supportsDataTestProperties: true
});

export let c2 = Ember.Component.extend({
foo: 'foo',
'supportsDataTestProperties': true
});
4 changes: 3 additions & 1 deletion strip-data-test-properties-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
/* eslint-env node */

let TEST_SELECTOR_PREFIX = /^data-test-.*/;
let SUPPORTS_DATA_TEST_PROP = 'supportsDataTestProperties';

function StripDataTestPropertiesPlugin(babel) {
return new babel.Plugin('ember-test-selectors', {
visitor: {
Property(node) {
if (TEST_SELECTOR_PREFIX.test(node.key.value)) {
let nodeName = node.key.name || node.key.value;
if (TEST_SELECTOR_PREFIX.test(nodeName) || nodeName === SUPPORTS_DATA_TEST_PROP) {
this.dangerouslyRemove();
}
},
Expand Down
4 changes: 3 additions & 1 deletion strip-data-test-properties-plugin6.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
/* eslint-env node */

let TEST_SELECTOR_PREFIX = /^data-test-.*/;
let SUPPORTS_DATA_TEST_PROP = 'supportsDataTestProperties';

function StripDataTestPropertiesPlugin() {
return {
visitor: {
Property(path) {
if (TEST_SELECTOR_PREFIX.test(path.node.key.value)) {
let nodeName = path.node.key.name || path.node.key.value;
if (TEST_SELECTOR_PREFIX.test(nodeName) || nodeName === SUPPORTS_DATA_TEST_PROP) {
path.remove();
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,9 @@ if (!config.stripTestSelectors) {
assert.dom('.test-link-to-block a').hasAttribute('data-test-foo', 'bar');
assert.dom('.test-link-to-inline a').hasAttribute('data-test-foo', 'bar');
});

test('it handles the tagless components without assert when `supportsDataTestProperties` is set', function(assert) {
assert.dom('.test12 div[data-test-with-boolean-value]').doesNotExist('data-test-with-boolean-value does not exist');
assert.dom('.test13 div[data-test-without-value]').doesNotExist('data-test-without-value does not exist');
});
}
9 changes: 9 additions & 0 deletions tests/dummy/app/components/tagless-component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Component from '@ember/component';

export default Component.extend({
// we're explicitly setting attributeBindings here to test that
// we are correctly slice()ing the frozen array if it exists already
attributeBindings: [],
tagName: '',
supportsDataTestProperties: true,
});
6 changes: 5 additions & 1 deletion tests/dummy/app/templates/bind-test.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@

<div class="test-link-to-block">{{#link-to "index" data-test-foo="bar"}}Label{{/link-to}}</div>

<div class="test-link-to-inline">{{link-to "Label" "index" data-test-foo="bar"}}</div>
<div class="test-link-to-inline">{{link-to "Label" "index" data-test-foo="bar"}}</div>

<div class="test12">{{tagless-component data-test-with-boolean-value=true}}</div>

<div class="test13">{{tagless-component data-test-without-value}}</div>
4 changes: 4 additions & 0 deletions tests/dummy/app/templates/components/tagless-component.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"Please disperse. Nothing to see here." - Frank Drebin

This component only exists so we can convenietly use moduleForComponent for the
tests which check that data-test-* attributes are stripped.
15 changes: 15 additions & 0 deletions tests/unit/utils/bind-data-test-attributes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ test('it breaks if tagName is empty', function(assert) {
assert.throws(() => bindDataTestAttributes(instance));
});

test('it does not breaks if tagName is empty and supportsDataTestProperties is set', function(assert) {
assert.expect(0);

let Fixture = EmberObject.extend({
tagName: '',
supportsDataTestProperties: true,
'data-test-from-factory': 'foo',
});
let instance = Fixture.create({
'data-test-from-invocation': 'bar',
});

bindDataTestAttributes(instance);
});

test('issue #106', function(assert) {
let Component = EmberObject.extend({});

Expand Down