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

Continue to flesh out more tests for new API's. #224

Merged
merged 4 commits into from
Oct 17, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions tests/helpers/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ function isFocusable(el) {
return focusableTags.indexOf(tagName) > -1 || el.contentEditable === 'true';
}

export function click(el, options = {}) {
run(() => fireEvent(el, 'mousedown', options));
focus(el);
run(() => fireEvent(el, 'mouseup', options));
run(() => fireEvent(el, 'click', options));
}

export function focus(el) {
if (!el) {
return;
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/setup-context-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ module('setupContext', function(hooks) {
test('it calls setContext with the provided context', function(assert) {
assert.equal(getContext(), context);
});

test('can be used for unit style testing', function(assert) {
context.owner.register(
'service:foo',
Service.extend({
someMethod() {
return 'hello thar!';
},
})
);

let subject = context.owner.lookup('service:Foo');
Copy link
Member

Choose a reason for hiding this comment

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

I suppose the uppercase Foo was deliberate? could probably use a comment in that case

Copy link
Member Author

Choose a reason for hiding this comment

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

Haha, nope, not intentional. Will fix.


assert.equal(subject.someMethod(), 'hello thar!');
});
Copy link
Member

Choose a reason for hiding this comment

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

should we test this.inject('foo') here too?

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, that API is no longer present (see examples and reasoning in the RFC), but I will add an example to both these tests and the rendering tests that will be a better demo of the go forward way to do it...

});

module('with custom options', function() {
Expand Down
185 changes: 185 additions & 0 deletions tests/unit/setup-rendering-context-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { module, test, skip } from 'qunit';
import Service from '@ember/service';
import Component from '@ember/component';
import TextField from '@ember/component/text-field';
import { helper } from '@ember/component/helper';
import {
setupContext,
Expand All @@ -11,6 +12,7 @@ import {
import hasEmberVersion from 'ember-test-helpers/has-ember-version';
import hasjQuery from '../helpers/has-jquery';
import { setResolverRegistry } from '../helpers/resolver';
import { focus, blur, fireEvent, click } from '../helpers/events';
import hbs from 'htmlbars-inline-precompile';

module('setupRenderingContext', function(hooks) {
Expand Down Expand Up @@ -115,4 +117,187 @@ module('setupRenderingContext', function(hooks) {

assert.equal(this.element.textContent, 'outerinnerouter');
});

test('can use the component helper in its layout', async function(assert) {
this.owner.register('template:components/x-foo', hbs`x-foo here`);

await this.render(hbs`{{component 'x-foo'}}`);

assert.equal(this.element.textContent, 'x-foo here');
});

test('can create a component instance for direct testing without a template', function(assert) {
this.owner.register(
'component:foo-bar',
Component.extend({
someMethod() {
return 'hello thar!';
},
})
);

let subject;
if (hasEmberVersion(2, 12)) {
subject = this.owner.lookup('component:foo-bar');
} else {
subject = this.owner._lookupFactory('component:foo-bar').create();
}

assert.equal(subject.someMethod(), 'hello thar!');
});

test('can handle a click event', async function(assert) {
assert.expect(2);

this.owner.register(
'component:x-foo',
Component.extend({
click() {
assert.ok(true, 'click was fired');
},
})
);
this.owner.register('template:components/x-foo', hbs`<button>Click me!</button>`);

await this.render(hbs`{{x-foo}}`);

assert.equal(this.element.textContent, 'Click me!', 'precond - component was rendered');
click(this.element.querySelector('button'));
});

test('can use action based event handling', async function(assert) {
assert.expect(2);

this.owner.register(
'component:x-foo',
Component.extend({
actions: {
clicked() {
assert.ok(true, 'click was fired');
},
},
})
);
this.owner.register(
'template:components/x-foo',
hbs`<button {{action 'clicked'}}>Click me!</button>`
);

await this.render(hbs`{{x-foo}}`);

assert.equal(this.element.textContent, 'Click me!', 'precond - component was rendered');
click(this.element.querySelector('button'));
Copy link
Member

Choose a reason for hiding this comment

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

I assume at some point passing in just a CSS selector will also be supported?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ya, these event helpers are only internal test things for now. My next RFC will be for adding the real ones here (and they will essentially have the same API as ember-native-dom-helpers).

Copy link
Member

Choose a reason for hiding this comment

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

would that mean deprecating ember-native-dom-helpers?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don’t know, but possibly. The main differences from what we need here is that we do not want to defer to Ember’s own internal application test globals. It’s definitely possible to do this transition a number of ways...

});

test('can pass function to be used as a "closure action"', async function(assert) {
assert.expect(2);

this.owner.register(
'template:components/x-foo',
hbs`<button onclick={{action clicked}}>Click me!</button>`
);

this.set('clicked', () => assert.ok(true, 'action was triggered'));
await this.render(hbs`{{x-foo clicked=clicked}}`);

assert.equal(this.element.textContent, 'Click me!', 'precond - component was rendered');
click(this.element.querySelector('button'));
});

test('can update a passed in argument with an <input>', async function(assert) {
this.owner.register(
'component:my-input',
TextField.extend({
value: null,
})
);

await this.render(hbs`{{my-input value=value}}`);

let input = this.element.querySelector('input');
input.value = '1';

fireEvent(input, 'change');
assert.equal(this.get('value'), '1');
Copy link
Member

Choose a reason for hiding this comment

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

precondition assertion might make sense here

});

test('it supports dom triggered focus events', async function(assert) {
this.owner.register(
'component:my-input',
TextField.extend({
init() {
this._super(...arguments);

this.set('value', 'init');
},
focusIn() {
this.set('value', 'focusin');
},
focusOut() {
this.set('value', 'focusout');
},
})
);
await this.render(hbs`{{my-input}}`);

let input = this.element.querySelector('input');
assert.equal(input.value, 'init');

focus(input);
assert.equal(input.value, 'focusin');

blur(input);
assert.equal(input.value, 'focusout');
});

test('two way bound arguments are updated', async function(assert) {
this.owner.register(
'component:my-component',
Component.extend({
actions: {
clicked() {
this.set('foo', 'updated!');
},
},
})
);
this.owner.register(
'template:components/my-component',
hbs`<button {{action 'clicked'}}>{{foo}}</button>`
);

this.set('foo', 'original');
await this.render(hbs`{{my-component foo=foo}}`);
assert.equal(this.element.textContent, 'original', 'value after initial render');

click(this.element.querySelector('button'));
assert.equal(this.element.textContent, 'updated!', 'value after updating');
assert.equal(this.get('foo'), 'updated!');
});

test('two way bound arguments are available after clearRender is called', async function(assert) {
this.owner.register(
'component:my-component',
Component.extend({
actions: {
clicked() {
this.set('foo', 'updated!');
this.set('bar', 'updated bar!');
},
},
})
);
this.owner.register(
'template:components/my-component',
hbs`<button {{action 'clicked'}}>{{foo}}</button>`
);

await this.render(hbs`{{my-component foo=foo bar=bar}}`);
click(this.element.querySelector('button'));

await this.clearRender();

assert.equal(this.get('foo'), 'updated!');
assert.equal(this.get('bar'), 'updated bar!');
Copy link
Member

Choose a reason for hiding this comment

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

why two properties? because one of them is rendered and the other is not? might need a comment 🤔

Copy link
Member Author

@rwjblue rwjblue Oct 17, 2017

Choose a reason for hiding this comment

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

Comment added...

});
});