github.com/hernad/nomad@v1.6.112/ui/tests/integration/components/trigger-test.js (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 6 /* eslint-disable ember-a11y-testing/a11y-audit-called */ 7 import { module, test } from 'qunit'; 8 import { setupRenderingTest } from 'ember-qunit'; 9 import { render, click, waitFor } from '@ember/test-helpers'; 10 import { hbs } from 'ember-cli-htmlbars'; 11 12 module('Integration | Component | trigger', function (hooks) { 13 setupRenderingTest(hooks); 14 15 module('Synchronous Interactions', function () { 16 test('it can trigger a synchronous action', async function (assert) { 17 this.set('name', 'Tomster'); 18 this.set('changeName', () => this.set('name', 'Zoey')); 19 await render(hbs` 20 <Trigger @do={{this.changeName}} as |trigger|> 21 <h2 data-test-name>{{this.name}}</h2> 22 <button data-test-button type="button" {{on "click" trigger.fns.do}}>Change my name.</button> 23 </Trigger> 24 `); 25 assert 26 .dom('[data-test-name]') 27 .hasText('Tomster', 'Initial state renders correctly.'); 28 29 await click('[data-test-button]'); 30 31 assert 32 .dom('[data-test-name]') 33 .hasText( 34 'Zoey', 35 'The name property changes when the button is clicked' 36 ); 37 }); 38 39 test('it sets the result of the action', async function (assert) { 40 this.set('tomster', () => 'Tomster'); 41 await render(hbs` 42 <Trigger @do={{this.tomster}} as |trigger|> 43 {{#if trigger.data.result}} 44 <h2 data-test-name>{{trigger.data.result}}</h2> 45 {{/if}} 46 <button data-test-button {{on "click" trigger.fns.do}}>Generate</button> 47 </Trigger> 48 `); 49 assert 50 .dom('[data-test-name]') 51 .doesNotExist( 52 'Initial state does not render because there is no result yet.' 53 ); 54 55 await click('[data-test-button]'); 56 57 assert 58 .dom('[data-test-name]') 59 .hasText( 60 'Tomster', 61 'The result state updates after the triggered action' 62 ); 63 }); 64 }); 65 66 module('Asynchronous Interactions', function () { 67 test('it can trigger an asynchronous action', async function (assert) { 68 this.set( 69 'onTrigger', 70 () => 71 new Promise((resolve) => { 72 this.set('resolve', resolve); 73 }) 74 ); 75 76 await render(hbs` 77 <Trigger @do={{this.onTrigger}} as |trigger|> 78 {{#if trigger.data.isBusy}} 79 <div data-test-div-loading>...Loading</div> 80 {{/if}} 81 {{#if trigger.data.isSuccess}} 82 <div data-test-div>Success!</div> 83 {{/if}} 84 <button data-test-button {{on "click" trigger.fns.do}}>Click Me</button> 85 </Trigger> 86 `); 87 88 assert 89 .dom('[data-test-div]') 90 .doesNotExist( 91 'The div does not render until after the action dispatches successfully' 92 ); 93 94 await click('[data-test-button]'); 95 assert 96 .dom('[data-test-div-loading]') 97 .exists( 98 'Loading state is displayed when the action hasnt resolved yet' 99 ); 100 assert 101 .dom('[data-test-div]') 102 .doesNotExist( 103 'Success message does not display until after promise resolves' 104 ); 105 106 this.resolve(); 107 await waitFor('[data-test-div]'); 108 assert 109 .dom('[data-test-div-loading]') 110 .doesNotExist( 111 'Loading state is no longer rendered after state changes from busy to success' 112 ); 113 assert 114 .dom('[data-test-div]') 115 .exists( 116 'Action has dispatched successfully after the promise resolves' 117 ); 118 119 await click('[data-test-button]'); 120 assert 121 .dom('[data-test-div]') 122 .doesNotExist( 123 'Aftering clicking the button, again, the state is reset' 124 ); 125 assert 126 .dom('[data-test-div-loading]') 127 .exists( 128 'After clicking the button, again, we are back in the loading state' 129 ); 130 131 this.resolve(); 132 await waitFor('[data-test-div]'); 133 134 assert 135 .dom('[data-test-div]') 136 .exists( 137 'An new action and new promise resolve after clicking the button for the second time' 138 ); 139 }); 140 141 test('it handles the success state', async function (assert) { 142 this.set( 143 'onTrigger', 144 () => 145 new Promise((resolve) => { 146 this.set('resolve', resolve); 147 }) 148 ); 149 this.set('onSuccess', () => assert.step('On success happened')); 150 151 await render(hbs` 152 <Trigger @do={{this.onTrigger}} @onSuccess={{this.onSuccess}} as |trigger|> 153 {{#if trigger.data.isSuccess}} 154 <span data-test-div>Success!</span> 155 {{/if}} 156 <button data-test-button {{on "click" trigger.fns.do}}>Click Me</button> 157 </Trigger> 158 `); 159 160 assert 161 .dom('[data-test-div]') 162 .doesNotExist( 163 'No text should appear until after the onSuccess callback is fired' 164 ); 165 await click('[data-test-button]'); 166 this.resolve(); 167 await waitFor('[data-test-div]'); 168 assert.verifySteps(['On success happened']); 169 }); 170 171 test('it handles the error state', async function (assert) { 172 this.set( 173 'onTrigger', 174 () => 175 new Promise((_, reject) => { 176 this.set('reject', reject); 177 }) 178 ); 179 this.set('onError', () => { 180 assert.step('On error happened'); 181 }); 182 183 await render(hbs` 184 <Trigger @do={{this.onTrigger}} @onError={{this.onError}} as |trigger|> 185 {{#if trigger.data.isBusy}} 186 <div data-test-div-loading>...Loading</div> 187 {{/if}} 188 {{#if trigger.data.isError}} 189 <span data-test-span>Error!</span> 190 {{/if}} 191 <button data-test-button {{on "click" trigger.fns.do}}>Click Me</button> 192 </Trigger> 193 `); 194 195 await click('[data-test-button]'); 196 assert 197 .dom('[data-test-div-loading]') 198 .exists( 199 'Loading state is displayed when the action hasnt resolved yet' 200 ); 201 202 assert 203 .dom('[data-test-div]') 204 .doesNotExist( 205 'No text should appear until after the onError callback is fired' 206 ); 207 208 this.reject(); 209 await waitFor('[data-test-span]'); 210 assert.verifySteps(['On error happened']); 211 212 await click('[data-test-button]'); 213 214 assert 215 .dom('[data-test-div-loading]') 216 .exists( 217 'The previous error state was cleared and we show loading, again.' 218 ); 219 220 assert.dom('[data-test-div]').doesNotExist('The error state is cleared'); 221 222 this.reject(); 223 await waitFor('[data-test-span]'); 224 assert.verifySteps(['On error happened'], 'The error dispatches'); 225 }); 226 }); 227 });