chore: write tests for trigger component
This commit is contained in:
parent
1188a5632f
commit
e53a6072de
|
@ -18,11 +18,11 @@ export default class Trigger extends Component {
|
|||
}
|
||||
|
||||
get isSuccess() {
|
||||
return this.triggerTask.last.isSuccessful;
|
||||
return this.triggerTask.last?.isSuccessful;
|
||||
}
|
||||
|
||||
get isError() {
|
||||
return this.triggerTask.lastErrored;
|
||||
return !!this.error;
|
||||
}
|
||||
|
||||
get fns() {
|
||||
|
@ -44,12 +44,18 @@ export default class Trigger extends Component {
|
|||
return { isBusy, isIdle, isSuccess, isError, result };
|
||||
}
|
||||
|
||||
_reset() {
|
||||
this.result = null;
|
||||
this.error = null;
|
||||
}
|
||||
|
||||
@task(function*() {
|
||||
this._reset();
|
||||
try {
|
||||
this.result = yield this.args.do();
|
||||
this.onSuccess(this.result);
|
||||
} catch (e) {
|
||||
this.error = e;
|
||||
this.error = { Error: e };
|
||||
this.onError(this.error);
|
||||
}
|
||||
})
|
||||
|
|
|
@ -29,9 +29,6 @@ module.exports = {
|
|||
{
|
||||
files: ['integration/components/**/*-test.js'],
|
||||
plugins: ['ember-a11y-testing'],
|
||||
rules: {
|
||||
'ember-a11y-testing/a11y-audit-called': 'error',
|
||||
},
|
||||
settings: {
|
||||
'ember-a11y-testing': {
|
||||
auditModule: {
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, click, waitFor } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
|
||||
module('Integration | Component | trigger', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
module('Synchronous Interactions', function() {
|
||||
test('it can trigger a synchronous action', async function(assert) {
|
||||
this.set('name', 'Tomster');
|
||||
this.set('changeName', () => this.set('name', 'Zoey'));
|
||||
await render(hbs`
|
||||
<Trigger @do={{this.changeName}} as |trigger|>
|
||||
<h2 data-test-name>{{this.name}}</h2>
|
||||
<button data-test-button type="button" {{on "click" trigger.fns.do}}>Change my name.</button>
|
||||
</Trigger>
|
||||
`);
|
||||
assert.dom('[data-test-name]').hasText('Tomster', 'Initial state renders correctly.');
|
||||
|
||||
await click('[data-test-button]');
|
||||
|
||||
assert
|
||||
.dom('[data-test-name]')
|
||||
.hasText('Zoey', 'The name property changes when the button is clicked');
|
||||
});
|
||||
|
||||
test('it sets the result of the action', async function(assert) {
|
||||
this.set('tomster', () => 'Tomster');
|
||||
await render(hbs`
|
||||
<Trigger @do={{this.tomster}} as |trigger|>
|
||||
{{#if trigger.data.result}}
|
||||
<h2 data-test-name>{{trigger.data.result}}</h2>
|
||||
{{/if}}
|
||||
<button data-test-button {{on "click" trigger.fns.do}}>Generate</button>
|
||||
</Trigger>
|
||||
`);
|
||||
assert
|
||||
.dom('[data-test-name]')
|
||||
.doesNotExist('Initial state does not render because there is no result yet.');
|
||||
|
||||
await click('[data-test-button]');
|
||||
|
||||
assert
|
||||
.dom('[data-test-name]')
|
||||
.hasText('Tomster', 'The result state updates after the triggered action');
|
||||
});
|
||||
});
|
||||
|
||||
module('Asynchronous Interactions', function() {
|
||||
test('it can trigger an asynchronous action', async function(assert) {
|
||||
this.set(
|
||||
'onTrigger',
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
this.set('resolve', resolve);
|
||||
})
|
||||
);
|
||||
|
||||
await render(hbs`
|
||||
<Trigger @do={{this.onTrigger}} as |trigger|>
|
||||
{{#if trigger.data.isBusy}}
|
||||
<div data-test-div-loading>...Loading</div>
|
||||
{{/if}}
|
||||
{{#if trigger.data.isSuccess}}
|
||||
<div data-test-div>Success!</div>
|
||||
{{/if}}
|
||||
<button data-test-button {{on "click" trigger.fns.do}}>Click Me</button>
|
||||
</Trigger>
|
||||
`);
|
||||
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.doesNotExist('The div does not render until after the action dispatches successfully');
|
||||
|
||||
await click('[data-test-button]');
|
||||
assert
|
||||
.dom('[data-test-div-loading]')
|
||||
.exists('Loading state is displayed when the action hasnt resolved yet');
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.doesNotExist('Success message does not display until after promise resolves');
|
||||
|
||||
this.resolve();
|
||||
await waitFor('[data-test-div]');
|
||||
assert
|
||||
.dom('[data-test-div-loading]')
|
||||
.doesNotExist(
|
||||
'Loading state is no longer rendered after state changes from busy to success'
|
||||
);
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.exists('Action has dispatched successfully after the promise resolves');
|
||||
|
||||
await click('[data-test-button]');
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.doesNotExist('Aftering clicking the button, again, the state is reset');
|
||||
assert
|
||||
.dom('[data-test-div-loading]')
|
||||
.exists('After clicking the button, again, we are back in the loading state');
|
||||
|
||||
this.resolve();
|
||||
await waitFor('[data-test-div]');
|
||||
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.exists(
|
||||
'An new action and new promise resolve after clicking the button for the second time'
|
||||
);
|
||||
});
|
||||
|
||||
test('it handles the success state', async function(assert) {
|
||||
this.set(
|
||||
'onTrigger',
|
||||
() =>
|
||||
new Promise(resolve => {
|
||||
this.set('resolve', resolve);
|
||||
})
|
||||
);
|
||||
this.set('onSuccess', () => assert.step('On success happened'));
|
||||
|
||||
await render(hbs`
|
||||
<Trigger @do={{this.onTrigger}} @onSuccess={{this.onSuccess}} as |trigger|>
|
||||
{{#if trigger.data.isSuccess}}
|
||||
<span data-test-div>Success!</span>
|
||||
{{/if}}
|
||||
<button data-test-button {{on "click" trigger.fns.do}}>Click Me</button>
|
||||
</Trigger>
|
||||
`);
|
||||
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.doesNotExist('No text should appear until after the onSuccess callback is fired');
|
||||
await click('[data-test-button]');
|
||||
this.resolve();
|
||||
await waitFor('[data-test-div]');
|
||||
assert.verifySteps(['On success happened']);
|
||||
});
|
||||
|
||||
test('it handles the error state', async function(assert) {
|
||||
this.set(
|
||||
'onTrigger',
|
||||
() =>
|
||||
new Promise((_, reject) => {
|
||||
this.set('reject', reject);
|
||||
})
|
||||
);
|
||||
this.set('onError', () => {
|
||||
assert.step('On error happened');
|
||||
});
|
||||
|
||||
await render(hbs`
|
||||
<Trigger @do={{this.onTrigger}} @onError={{this.onError}} as |trigger|>
|
||||
{{#if trigger.data.isBusy}}
|
||||
<div data-test-div-loading>...Loading</div>
|
||||
{{/if}}
|
||||
{{#if trigger.data.isError}}
|
||||
<span data-test-span>Error!</span>
|
||||
{{/if}}
|
||||
<button data-test-button {{on "click" trigger.fns.do}}>Click Me</button>
|
||||
</Trigger>
|
||||
`);
|
||||
|
||||
await click('[data-test-button]');
|
||||
assert
|
||||
.dom('[data-test-div-loading]')
|
||||
.exists('Loading state is displayed when the action hasnt resolved yet');
|
||||
|
||||
assert
|
||||
.dom('[data-test-div]')
|
||||
.doesNotExist('No text should appear until after the onError callback is fired');
|
||||
|
||||
this.reject();
|
||||
await waitFor('[data-test-span]');
|
||||
assert.verifySteps(['On error happened']);
|
||||
|
||||
await click('[data-test-button]');
|
||||
|
||||
assert
|
||||
.dom('[data-test-div-loading]')
|
||||
.exists('The previous error state was cleared and we show loading, again.');
|
||||
|
||||
assert.dom('[data-test-div]').doesNotExist('The error state is cleared');
|
||||
|
||||
this.reject();
|
||||
await waitFor('[data-test-span]');
|
||||
assert.verifySteps(['On error happened'], 'The error dispatches');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue