From 1147fd6278dae7a267eee767240ea3e2a6ec5d6a Mon Sep 17 00:00:00 2001 From: Buck Doyle Date: Tue, 23 Jul 2019 14:40:32 -0500 Subject: [PATCH] UI: Remove ember-native-dom-helpers (#5959) This also includes migration of some tests to async. --- ui/package.json | 1 - ui/tests/acceptance/token-test.js | 2 +- ui/tests/integration/allocation-row-test.js | 163 ++++----- ui/tests/integration/app-breadcrumbs-test.js | 3 +- ui/tests/integration/attributes-table-test.js | 3 +- ui/tests/integration/job-diff-test.js | 3 +- ui/tests/integration/job-editor-test.js | 122 ++----- ui/tests/integration/job-page/helpers.js | 50 ++- .../integration/job-page/parts/body-test.js | 28 +- .../job-page/parts/children-test.js | 208 +++++------- .../job-page/parts/latest-deployment-test.js | 225 ++++++------- .../job-page/parts/placement-failures-test.js | 93 +++--- .../job-page/parts/summary-test.js | 309 ++++++++---------- .../job-page/parts/task-groups-test.js | 191 +++++------ .../integration/job-page/periodic-test.js | 165 ++++------ ui/tests/integration/job-page/service-test.js | 247 ++++++-------- ui/tests/integration/list-pagination-test.js | 6 +- ui/tests/integration/list-table-test.js | 3 +- .../integration/multi-select-dropdown-test.js | 149 ++++----- ui/tests/integration/page-layout-test.js | 57 ++-- .../integration/placement-failure-test.js | 3 +- ui/tests/integration/primary-metric-test.js | 170 ++++------ .../reschedule-event-timeline-test.js | 160 ++++----- ui/tests/integration/task-log-test.js | 3 +- ui/tests/integration/two-step-button-test.js | 81 ++--- ui/yarn.lock | 2 +- 26 files changed, 969 insertions(+), 1478 deletions(-) diff --git a/ui/package.json b/ui/package.json index 5fa57e079..85f0f2009 100644 --- a/ui/package.json +++ b/ui/package.json @@ -75,7 +75,6 @@ "ember-load-initializers": "^1.1.0", "ember-maybe-import-regenerator": "^0.1.6", "ember-moment": "^7.8.1", - "ember-native-dom-helpers": "^0.5.4", "ember-page-title": "^5.0.2", "ember-power-select": "^2.2.3", "ember-qunit-nice-errors": "^1.2.0", diff --git a/ui/tests/acceptance/token-test.js b/ui/tests/acceptance/token-test.js index 4c295e168..7d78de998 100644 --- a/ui/tests/acceptance/token-test.js +++ b/ui/tests/acceptance/token-test.js @@ -1,4 +1,4 @@ -import { find } from 'ember-native-dom-helpers'; +import { find } from '@ember/test-helpers'; import { module, skip, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import setupMirage from 'ember-cli-mirage/test-support/setup-mirage'; diff --git a/ui/tests/integration/allocation-row-test.js b/ui/tests/integration/allocation-row-test.js index 70b816ac6..4c0d9a83e 100644 --- a/ui/tests/integration/allocation-row-test.js +++ b/ui/tests/integration/allocation-row-test.js @@ -1,13 +1,11 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import generateResources from '../../mirage/data/generate-resources'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; -import { find } from 'ember-native-dom-helpers'; +import { find, render } from '@ember/test-helpers'; import Response from 'ember-cli-mirage/response'; import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; -import { Promise, resolve } from 'rsvp'; module('Integration | Component | allocation row', function(hooks) { setupRenderingTest(hooks); @@ -25,7 +23,7 @@ module('Integration | Component | allocation row', function(hooks) { this.server.shutdown(); }); - test('Allocation row polls for stats, even when it errors or has an invalid response', function(assert) { + test('Allocation row polls for stats, even when it errors or has an invalid response', async function(assert) { const component = this; let currentFrame = 0; @@ -52,41 +50,34 @@ module('Integration | Component | allocation row', function(hooks) { }); this.server.create('allocation', { clientStatus: 'running' }); - this.store.findAll('allocation'); + await this.store.findAll('allocation'); - let allocation; + const allocation = this.store.peekAll('allocation').get('firstObject'); - return settled() - .then(async () => { - allocation = this.store.peekAll('allocation').get('firstObject'); + this.setProperties({ + allocation, + context: 'job', + enablePolling: true, + }); - this.setProperties({ - allocation, - context: 'job', - enablePolling: true, - }); + await render(hbs` + {{allocation-row + allocation=allocation + context=context + enablePolling=enablePolling}} + `); - await render(hbs` - {{allocation-row - allocation=allocation - context=context - enablePolling=enablePolling}} - `); - return settled(); - }) - .then(() => { - assert.equal( - this.server.pretender.handledRequests.filterBy( - 'url', - `/v1/client/allocation/${allocation.get('id')}/stats` - ).length, - frames.length, - 'Requests continue to be made after malformed responses and server errors' - ); - }); + assert.equal( + this.server.pretender.handledRequests.filterBy( + 'url', + `/v1/client/allocation/${allocation.get('id')}/stats` + ).length, + frames.length, + 'Requests continue to be made after malformed responses and server errors' + ); }); - test('Allocation row shows warning when it requires drivers that are unhealthy on the node it is running on', function(assert) { + test('Allocation row shows warning when it requires drivers that are unhealthy on the node it is running on', async function(assert) { const node = this.server.schema.nodes.first(); const drivers = node.drivers; Object.values(drivers).forEach(driver => { @@ -96,38 +87,29 @@ module('Integration | Component | allocation row', function(hooks) { node.update({ drivers }); this.server.create('allocation', { clientStatus: 'running' }); - this.store.findAll('job'); - this.store.findAll('node'); - this.store.findAll('allocation'); + await this.store.findAll('job'); + await this.store.findAll('node'); + await this.store.findAll('allocation'); - let allocation; + const allocation = this.store.peekAll('allocation').get('firstObject'); - return settled() - .then(async () => { - allocation = this.store.peekAll('allocation').get('firstObject'); + this.setProperties({ + allocation, + context: 'job', + }); - this.setProperties({ - allocation, - context: 'job', - }); + await render(hbs` + {{allocation-row + allocation=allocation + context=context}} + `); - await render(hbs` - {{allocation-row - allocation=allocation - context=context}} - `); - return settled(); - }) - .then(() => { - assert.ok(find('[data-test-icon="unhealthy-driver"]'), 'Unhealthy driver icon is shown'); - }); + assert.ok(find('[data-test-icon="unhealthy-driver"]'), 'Unhealthy driver icon is shown'); }); test('Allocation row shows an icon indicator when it was preempted', async function(assert) { const allocId = this.server.create('allocation', 'preempted').id; - const allocation = await this.store.findRecord('allocation', allocId); - await settled(); this.setProperties({ allocation, context: 'job' }); await render(hbs` @@ -135,12 +117,11 @@ module('Integration | Component | allocation row', function(hooks) { allocation=allocation context=context}} `); - await settled(); assert.ok(find('[data-test-icon="preemption"]'), 'Preempted icon is shown'); }); - test('when an allocation is not running, the utilization graphs are omitted', function(assert) { + test('when an allocation is not running, the utilization graphs are omitted', async function(assert) { this.setProperties({ context: 'job', enablePolling: false, @@ -151,56 +132,22 @@ module('Integration | Component | allocation row', function(hooks) { this.server.create('allocation', { clientStatus }) ); - this.store.findAll('allocation'); + await this.store.findAll('allocation'); - return settled().then(() => { - const allocations = this.store.peekAll('allocation'); - return waitForEach( - allocations.map(allocation => async () => { - this.set('allocation', allocation); - await render(hbs` - {{allocation-row - allocation=allocation - context=context - enablePolling=enablePolling}} - `); - return settled().then(() => { - const status = allocation.get('clientStatus'); - assert.notOk(find('[data-test-cpu] .inline-chart'), `No CPU chart for ${status}`); - assert.notOk(find('[data-test-mem] .inline-chart'), `No Mem chart for ${status}`); - }); - }) - ); - }); + const allocations = this.store.peekAll('allocation'); + + for (const allocation of allocations.toArray()) { + this.set('allocation', allocation); + await this.render(hbs` + {{allocation-row + allocation=allocation + context=context + enablePolling=enablePolling}} + `); + + const status = allocation.get('clientStatus'); + assert.notOk(find('[data-test-cpu] .inline-chart'), `No CPU chart for ${status}`); + assert.notOk(find('[data-test-mem] .inline-chart'), `No Mem chart for ${status}`); + } }); - - // A way to loop over asynchronous code. Can be replaced by async/await in the future. - const waitForEach = fns => { - let i = 0; - let done = () => {}; - - // This function is asynchronous and needs to return a promise - const pending = new Promise(resolve => { - done = resolve; - }); - - const step = () => { - // The waitForEach promise and this recursive loop are done once - // all functions have been called. - if (i >= fns.length) { - done(); - return; - } - // Call the current function - const promise = fns[i]() || resolve(true); - // Increment the function position - i++; - // Wait for async behaviors to settle and repeat - promise.then(() => settled()).then(step); - }; - - step(); - - return pending; - }; }); diff --git a/ui/tests/integration/app-breadcrumbs-test.js b/ui/tests/integration/app-breadcrumbs-test.js index c9b710aeb..a42087454 100644 --- a/ui/tests/integration/app-breadcrumbs-test.js +++ b/ui/tests/integration/app-breadcrumbs-test.js @@ -2,8 +2,7 @@ import Service from '@ember/service'; import RSVP from 'rsvp'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { findAll } from 'ember-native-dom-helpers'; +import { findAll, render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import PromiseObject from 'nomad-ui/utils/classes/promise-object'; diff --git a/ui/tests/integration/attributes-table-test.js b/ui/tests/integration/attributes-table-test.js index 626a2c7b7..cc95f80a0 100644 --- a/ui/tests/integration/attributes-table-test.js +++ b/ui/tests/integration/attributes-table-test.js @@ -1,7 +1,6 @@ -import { find, findAll } from 'ember-native-dom-helpers'; +import { find, findAll, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import flat from 'flat'; diff --git a/ui/tests/integration/job-diff-test.js b/ui/tests/integration/job-diff-test.js index b958a26d7..90f228744 100644 --- a/ui/tests/integration/job-diff-test.js +++ b/ui/tests/integration/job-diff-test.js @@ -1,7 +1,6 @@ -import { findAll, find } from 'ember-native-dom-helpers'; +import { findAll, find, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import cleanWhitespace from '../utils/clean-whitespace'; diff --git a/ui/tests/integration/job-editor-test.js b/ui/tests/integration/job-editor-test.js index fd942a911..8e06c91e0 100644 --- a/ui/tests/integration/job-editor-test.js +++ b/ui/tests/integration/job-editor-test.js @@ -1,8 +1,6 @@ import { assign } from '@ember/polyfills'; -import { run } from '@ember/runloop'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { create } from 'ember-cli-page-object'; import sinon from 'sinon'; @@ -95,8 +93,7 @@ module('Integration | Component | job-editor', function(hooks) { const renderNewJob = async (component, job) => { component.setProperties({ job, onSubmit: sinon.spy(), context: 'new' }); - component.render(commonTemplate); - await settled(); + await component.render(commonTemplate); }; const renderEditJob = async (component, job) => { @@ -106,33 +103,22 @@ module('Integration | Component | job-editor', function(hooks) { const planJob = async spec => { await Editor.editor.fillIn(spec); - await settled(); await Editor.plan(); - await settled(); }; test('the default state is an editor with an explanation popup', async function(assert) { - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); assert.ok(Editor.editorHelp.isPresent, 'Editor explanation popup is present'); assert.ok(Editor.editor.isPresent, 'Editor is present'); }); test('the explanation popup can be dismissed', async function(assert) { - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await Editor.editorHelp.dismiss(); - await settled(); assert.notOk(Editor.editorHelp.isPresent, 'Editor explanation popup is gone'); assert.equal( window.localStorage.nomadMessageJobEditor, @@ -144,24 +130,16 @@ module('Integration | Component | job-editor', function(hooks) { test('the explanation popup is not shown once the dismissal state is set in localStorage', async function(assert) { window.localStorage.nomadMessageJobEditor = 'false'; - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); assert.notOk(Editor.editorHelp.isPresent, 'Editor explanation popup is gone'); }); test('submitting a json job skips the parse endpoint', async function(assert) { const spec = jsonJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); const requests = this.server.pretender.handledRequests.mapBy('url'); @@ -171,12 +149,8 @@ module('Integration | Component | job-editor', function(hooks) { test('submitting an hcl job requires the parse endpoint', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); const requests = this.server.pretender.handledRequests.mapBy('url'); @@ -190,12 +164,8 @@ module('Integration | Component | job-editor', function(hooks) { test('when a job is successfully parsed and planned, the plan is shown to the user', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); assert.ok(Editor.planOutput, 'The plan is outputted'); @@ -205,16 +175,11 @@ module('Integration | Component | job-editor', function(hooks) { test('from the plan screen, the cancel button goes back to the editor with the job still in tact', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); await Editor.cancel(); - await settled(); assert.ok(Editor.editor.isPresent, 'The editor is shown again'); assert.equal(Editor.editor.contents, spec, 'The spec that was planned is still in the editor'); }); @@ -222,15 +187,10 @@ module('Integration | Component | job-editor', function(hooks) { test('when parse fails, the parse error message is shown', async function(assert) { const spec = hclJob(); const errorMessage = 'Parse Failed!! :o'; - - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); this.server.pretender.post('/v1/jobs/parse', () => [400, {}, errorMessage]); - await settled(); await renderNewJob(this, job); await planJob(spec); assert.notOk(Editor.planError.isPresent, 'Plan error is not shown'); @@ -247,15 +207,10 @@ module('Integration | Component | job-editor', function(hooks) { test('when plan fails, the plan error message is shown', async function(assert) { const spec = hclJob(); const errorMessage = 'Plan Failed!! :o'; - - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); this.server.pretender.post(`/v1/job/${newJobName}/plan`, () => [400, {}, errorMessage]); - await settled(); await renderNewJob(this, job); await planJob(spec); assert.notOk(Editor.parseError.isPresent, 'Parse error is not shown'); @@ -272,19 +227,13 @@ module('Integration | Component | job-editor', function(hooks) { test('when run fails, the run error message is shown', async function(assert) { const spec = hclJob(); const errorMessage = 'Run Failed!! :o'; - - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); this.server.pretender.post('/v1/jobs', () => [400, {}, errorMessage]); - await settled(); await renderNewJob(this, job); await planJob(spec); await Editor.run(); - await settled(); assert.notOk(Editor.planError.isPresent, 'Plan error is not shown'); assert.notOk(Editor.parseError.isPresent, 'Parse error is not shown'); @@ -298,12 +247,8 @@ module('Integration | Component | job-editor', function(hooks) { test('when the scheduler dry-run has warnings, the warnings are shown to the user', async function(assert) { const spec = jsonJob({ Unschedulable: true }); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); assert.ok( @@ -322,12 +267,8 @@ module('Integration | Component | job-editor', function(hooks) { test('when the scheduler dry-run has no warnings, a success message is shown to the user', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); assert.ok( @@ -342,12 +283,8 @@ module('Integration | Component | job-editor', function(hooks) { test('when a job is submitted in the edit context, a POST request is made to the update job endpoint', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderEditJob(this, job); await planJob(spec); await Editor.run(); @@ -358,12 +295,8 @@ module('Integration | Component | job-editor', function(hooks) { test('when a job is submitted in the new context, a POST request is made to the create job endpoint', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); await Editor.run(); @@ -377,16 +310,11 @@ module('Integration | Component | job-editor', function(hooks) { test('when a job is successfully submitted, the onSubmit hook is called', async function(assert) { const spec = hclJob(); - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); await planJob(spec); await Editor.run(); - await settled(); assert.ok( this.get('onSubmit').calledWith(newJobName, 'default'), 'The onSubmit hook was called with the correct arguments' @@ -394,34 +322,22 @@ module('Integration | Component | job-editor', function(hooks) { }); test('when the job-editor cancelable flag is false, there is no cancel button in the header', async function(assert) { - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderNewJob(this, job); assert.notOk(Editor.cancelEditingIsAvailable, 'No way to cancel editing'); }); test('when the job-editor cancelable flag is true, there is a cancel button in the header', async function(assert) { - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderEditJob(this, job); assert.ok(Editor.cancelEditingIsAvailable, 'Cancel editing button exists'); }); test('when the job-editor cancel button is clicked, the onCancel hook is called', async function(assert) { - let job; - run(() => { - job = this.store.createRecord('job'); - }); + const job = await this.store.createRecord('job'); - await settled(); await renderEditJob(this, job); await Editor.cancelEditing(); assert.ok(this.get('onCancel').calledOnce, 'The onCancel hook was called'); diff --git a/ui/tests/integration/job-page/helpers.js b/ui/tests/integration/job-page/helpers.js index 5e33703df..ddefc9c28 100644 --- a/ui/tests/integration/job-page/helpers.js +++ b/ui/tests/integration/job-page/helpers.js @@ -1,5 +1,4 @@ -import { click, find } from 'ember-native-dom-helpers'; -import { settled } from '@ember/test-helpers'; +import { click, find } from '@ember/test-helpers'; export function jobURL(job, path = '') { const id = job.get('plainId'); @@ -11,20 +10,14 @@ export function jobURL(job, path = '') { return expectedURL; } -export function stopJob() { - click('[data-test-stop] [data-test-idle-button]'); - return settled().then(() => { - click('[data-test-stop] [data-test-confirm-button]'); - return settled(); - }); +export async function stopJob() { + await click('[data-test-stop] [data-test-idle-button]'); + await click('[data-test-stop] [data-test-confirm-button]'); } -export function startJob() { - click('[data-test-start] [data-test-idle-button]'); - return settled().then(() => { - click('[data-test-start] [data-test-confirm-button]'); - return settled(); - }); +export async function startJob() { + await click('[data-test-start] [data-test-idle-button]'); + await click('[data-test-start] [data-test-confirm-button]'); } export function expectStartRequest(assert, server, job) { @@ -39,22 +32,19 @@ export function expectStartRequest(assert, server, job) { assert.ok(requestPayload.Stop == null, 'The Stop signal is not sent in the POST request'); } -export function expectError(assert, title) { - return () => { - assert.equal( - find('[data-test-job-error-title]').textContent, - title, - 'Appropriate error is shown' - ); - assert.ok( - find('[data-test-job-error-body]').textContent.includes('ACL'), - 'The error message mentions ACLs' - ); +export async function expectError(assert, title) { + assert.equal( + find('[data-test-job-error-title]').textContent, + title, + 'Appropriate error is shown' + ); + assert.ok( + find('[data-test-job-error-body]').textContent.includes('ACL'), + 'The error message mentions ACLs' + ); - click('[data-test-job-error-close]'); - assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); - return settled(); - }; + await click('[data-test-job-error-close]'); + assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); } export function expectDeleteRequest(assert, server, job) { @@ -66,6 +56,4 @@ export function expectDeleteRequest(assert, server, job) { .find(req => req.url === expectedURL), 'DELETE URL was made correctly' ); - - return settled(); } diff --git a/ui/tests/integration/job-page/parts/body-test.js b/ui/tests/integration/job-page/parts/body-test.js index 788fa9151..958d549ad 100644 --- a/ui/tests/integration/job-page/parts/body-test.js +++ b/ui/tests/integration/job-page/parts/body-test.js @@ -1,8 +1,6 @@ -import { run } from '@ember/runloop'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { find, findAll } from 'ember-native-dom-helpers'; +import { find, findAll, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; @@ -29,19 +27,14 @@ module('Integration | Component | job-page/parts/body', function(hooks) { {{/job-page/parts/body}} `); - await settled(); assert.ok(find('[data-test-subnav="job"]'), 'Job subnav is rendered'); }); test('the subnav includes the deployments link when the job is a service', async function(assert) { const store = this.owner.lookup('service:store'); - let job; - - run(() => { - job = store.createRecord('job', { - id: 'service-job', - type: 'service', - }); + const job = await store.createRecord('job', { + id: 'service-job', + type: 'service', }); this.set('job', job); @@ -52,7 +45,6 @@ module('Integration | Component | job-page/parts/body', function(hooks) { {{/job-page/parts/body}} `); - await settled(); const subnavLabels = findAll('[data-test-tab]').map(anchor => anchor.textContent); assert.ok(subnavLabels.some(label => label === 'Definition'), 'Definition link'); assert.ok(subnavLabels.some(label => label === 'Versions'), 'Versions link'); @@ -61,13 +53,9 @@ module('Integration | Component | job-page/parts/body', function(hooks) { test('the subnav does not include the deployments link when the job is not a service', async function(assert) { const store = this.owner.lookup('service:store'); - let job; - - run(() => { - job = store.createRecord('job', { - id: 'batch-job', - type: 'batch', - }); + const job = await store.createRecord('job', { + id: 'batch-job', + type: 'batch', }); this.set('job', job); @@ -78,7 +66,6 @@ module('Integration | Component | job-page/parts/body', function(hooks) { {{/job-page/parts/body}} `); - await settled(); const subnavLabels = findAll('[data-test-tab]').map(anchor => anchor.textContent); assert.ok(subnavLabels.some(label => label === 'Definition'), 'Definition link'); assert.ok(subnavLabels.some(label => label === 'Versions'), 'Versions link'); @@ -94,7 +81,6 @@ module('Integration | Component | job-page/parts/body', function(hooks) { {{/job-page/parts/body}} `); - await settled(); assert.ok( find('[data-test-subnav="job"] + .section > .inner-content'), 'Content is rendered immediately after the subnav' diff --git a/ui/tests/integration/job-page/parts/children-test.js b/ui/tests/integration/job-page/parts/children-test.js index 5e3fab931..4879ab8e9 100644 --- a/ui/tests/integration/job-page/parts/children-test.js +++ b/ui/tests/integration/job-page/parts/children-test.js @@ -1,11 +1,9 @@ import { assign } from '@ember/polyfills'; -import { run } from '@ember/runloop'; import hbs from 'htmlbars-inline-precompile'; -import { findAll, find, click } from 'ember-native-dom-helpers'; +import { findAll, find, click, render } from '@ember/test-helpers'; import sinon from 'sinon'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; module('Integration | Component | job-page/parts/children', function(hooks) { @@ -35,139 +33,112 @@ module('Integration | Component | job-page/parts/children', function(hooks) { options ); - test('lists each child', function(assert) { - let parent; - + test('lists each child', async function(assert) { this.server.create('job', 'periodic', { id: 'parent', childrenCount: 3, createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - parent = this.store.peekAll('job').findBy('plainId', 'parent'); - }); + const parent = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties(props(parent)); + this.setProperties(props(parent)); - await render(hbs` - {{job-page/parts/children - job=job - sortProperty=sortProperty - sortDescending=sortDescending - currentPage=currentPage - gotoJob=gotoJob}} - `); + await render(hbs` + {{job-page/parts/children + job=job + sortProperty=sortProperty + sortDescending=sortDescending + currentPage=currentPage + gotoJob=gotoJob}} + `); - return settled().then(() => { - assert.equal( - findAll('[data-test-job-name]').length, - parent.get('children.length'), - 'A row for each child' - ); - }); - }); + assert.equal( + findAll('[data-test-job-name]').length, + parent.get('children.length'), + 'A row for each child' + ); }); - test('eventually paginates', function(assert) { - let parent; - + test('eventually paginates', async function(assert) { this.server.create('job', 'periodic', { id: 'parent', childrenCount: 11, createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - parent = this.store.peekAll('job').findBy('plainId', 'parent'); - }); + const parent = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties(props(parent)); + this.setProperties(props(parent)); - await render(hbs` - {{job-page/parts/children - job=job - sortProperty=sortProperty - sortDescending=sortDescending - currentPage=currentPage - gotoJob=gotoJob}} - `); + await render(hbs` + {{job-page/parts/children + job=job + sortProperty=sortProperty + sortDescending=sortDescending + currentPage=currentPage + gotoJob=gotoJob}} + `); - return settled().then(() => { - const childrenCount = parent.get('children.length'); - assert.ok(childrenCount > 10, 'Parent has more children than one page size'); - assert.equal(findAll('[data-test-job-name]').length, 10, 'Table length maxes out at 10'); - assert.ok(find('.pagination-next'), 'Next button is rendered'); + const childrenCount = parent.get('children.length'); + assert.ok(childrenCount > 10, 'Parent has more children than one page size'); + assert.equal(findAll('[data-test-job-name]').length, 10, 'Table length maxes out at 10'); + assert.ok(find('.pagination-next'), 'Next button is rendered'); - assert.ok( - new RegExp(`1.10.+?${childrenCount}`).test(find('.pagination-numbers').textContent.trim()) - ); - }); - }); + assert.ok( + new RegExp(`1.10.+?${childrenCount}`).test(find('.pagination-numbers').textContent.trim()) + ); }); - test('is sorted based on the sortProperty and sortDescending properties', function(assert) { - let parent; - + test('is sorted based on the sortProperty and sortDescending properties', async function(assert) { this.server.create('job', 'periodic', { id: 'parent', childrenCount: 3, createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - parent = this.store.peekAll('job').findBy('plainId', 'parent'); - }); + const parent = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties(props(parent)); + this.setProperties(props(parent)); - await render(hbs` - {{job-page/parts/children - job=job - sortProperty=sortProperty - sortDescending=sortDescending - currentPage=currentPage - gotoJob=gotoJob}} - `); + await render(hbs` + {{job-page/parts/children + job=job + sortProperty=sortProperty + sortDescending=sortDescending + currentPage=currentPage + gotoJob=gotoJob}} + `); - return settled().then(() => { - const sortedChildren = parent.get('children').sortBy('name'); - const childRows = findAll('[data-test-job-name]'); + const sortedChildren = parent.get('children').sortBy('name'); + const childRows = findAll('[data-test-job-name]'); - sortedChildren.reverse().forEach((child, index) => { - assert.equal( - childRows[index].textContent.trim(), - child.get('name'), - `Child ${index} is ${child.get('name')}` - ); - }); + sortedChildren.reverse().forEach((child, index) => { + assert.equal( + childRows[index].textContent.trim(), + child.get('name'), + `Child ${index} is ${child.get('name')}` + ); + }); - this.set('sortDescending', false); + await this.set('sortDescending', false); - sortedChildren.forEach((child, index) => { - assert.equal( - childRows[index].textContent.trim(), - child.get('name'), - `Child ${index} is ${child.get('name')}` - ); - }); - - return settled(); - }); + sortedChildren.forEach((child, index) => { + assert.equal( + childRows[index].textContent.trim(), + child.get('name'), + `Child ${index} is ${child.get('name')}` + ); }); }); - test('gotoJob is called when a job row is clicked', function(assert) { - let parent; + test('gotoJob is called when a job row is clicked', async function(assert) { const gotoJobSpy = sinon.spy(); this.server.create('job', 'periodic', { @@ -176,35 +147,30 @@ module('Integration | Component | job-page/parts/children', function(hooks) { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - parent = this.store.peekAll('job').findBy('plainId', 'parent'); - }); + const parent = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties( - props(parent, { - gotoJob: gotoJobSpy, - }) - ); + this.setProperties( + props(parent, { + gotoJob: gotoJobSpy, + }) + ); - await render(hbs` - {{job-page/parts/children - job=job - sortProperty=sortProperty - sortDescending=sortDescending - currentPage=currentPage - gotoJob=gotoJob}} - `); + await render(hbs` + {{job-page/parts/children + job=job + sortProperty=sortProperty + sortDescending=sortDescending + currentPage=currentPage + gotoJob=gotoJob}} + `); - return settled().then(() => { - click('tr.job-row'); - assert.ok( - gotoJobSpy.withArgs(parent.get('children.firstObject')).calledOnce, - 'Clicking the job row calls the gotoJob action' - ); - }); - }); + await click('tr.job-row'); + + assert.ok( + gotoJobSpy.withArgs(parent.get('children.firstObject')).calledOnce, + 'Clicking the job row calls the gotoJob action' + ); }); }); diff --git a/ui/tests/integration/job-page/parts/latest-deployment-test.js b/ui/tests/integration/job-page/parts/latest-deployment-test.js index fa1bed2c8..2d4a56352 100644 --- a/ui/tests/integration/job-page/parts/latest-deployment-test.js +++ b/ui/tests/integration/job-page/parts/latest-deployment-test.js @@ -1,7 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { click, find } from 'ember-native-dom-helpers'; +import { click, find, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import moment from 'moment'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; @@ -23,182 +22,156 @@ module('Integration | Component | job-page/parts/latest-deployment', function(ho window.localStorage.clear(); }); - test('there is no latest deployment section when the job has no deployments', function(assert) { + test('there is no latest deployment section when the job has no deployments', async function(assert) { this.server.create('job', { type: 'service', noDeployments: true, createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/latest-deployment job=job}}) - `); + this.set('job', this.store.peekAll('job').get('firstObject')); + await render(hbs` + {{job-page/parts/latest-deployment job=job}}) + `); - return settled().then(() => { - assert.notOk(find('[data-test-active-deployment]'), 'No active deployment'); - }); - }); + assert.notOk(find('[data-test-active-deployment]'), 'No active deployment'); }); - test('the latest deployment section shows up for the currently running deployment', function(assert) { + test('the latest deployment section shows up for the currently running deployment', async function(assert) { this.server.create('job', { type: 'service', createAllocations: false, activeDeployment: true, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/latest-deployment job=job}} - `); + this.set('job', this.store.peekAll('job').get('firstObject')); + await render(hbs` + {{job-page/parts/latest-deployment job=job}} + `); - return settled().then(() => { - const deployment = this.get('job.latestDeployment'); - const version = deployment.get('version'); + const deployment = await this.get('job.latestDeployment'); + const version = await deployment.get('version'); - assert.ok(find('[data-test-active-deployment]'), 'Active deployment'); - assert.ok( - find('[data-test-active-deployment]').classList.contains('is-info'), - 'Running deployment gets the is-info class' - ); - assert.equal( - find('[data-test-active-deployment-stat="id"]').textContent.trim(), - deployment.get('shortId'), - 'The active deployment is the most recent running deployment' - ); + assert.ok(find('[data-test-active-deployment]'), 'Active deployment'); + assert.ok( + find('[data-test-active-deployment]').classList.contains('is-info'), + 'Running deployment gets the is-info class' + ); + assert.equal( + find('[data-test-active-deployment-stat="id"]').textContent.trim(), + deployment.get('shortId'), + 'The active deployment is the most recent running deployment' + ); - assert.equal( - find('[data-test-active-deployment-stat="submit-time"]').textContent.trim(), - moment(version.get('submitTime')).fromNow(), - 'Time since the job was submitted is in the active deployment header' - ); + assert.equal( + find('[data-test-active-deployment-stat="submit-time"]').textContent.trim(), + moment(version.get('submitTime')).fromNow(), + 'Time since the job was submitted is in the active deployment header' + ); - assert.equal( - find('[data-test-deployment-metric="canaries"]').textContent.trim(), - `${deployment.get('placedCanaries')} / ${deployment.get('desiredCanaries')}`, - 'Canaries, both places and desired, are in the metrics' - ); + assert.equal( + find('[data-test-deployment-metric="canaries"]').textContent.trim(), + `${deployment.get('placedCanaries')} / ${deployment.get('desiredCanaries')}`, + 'Canaries, both places and desired, are in the metrics' + ); - assert.equal( - find('[data-test-deployment-metric="placed"]').textContent.trim(), - deployment.get('placedAllocs'), - 'Placed allocs aggregates across task groups' - ); + assert.equal( + find('[data-test-deployment-metric="placed"]').textContent.trim(), + deployment.get('placedAllocs'), + 'Placed allocs aggregates across task groups' + ); - assert.equal( - find('[data-test-deployment-metric="desired"]').textContent.trim(), - deployment.get('desiredTotal'), - 'Desired allocs aggregates across task groups' - ); + assert.equal( + find('[data-test-deployment-metric="desired"]').textContent.trim(), + deployment.get('desiredTotal'), + 'Desired allocs aggregates across task groups' + ); - assert.equal( - find('[data-test-deployment-metric="healthy"]').textContent.trim(), - deployment.get('healthyAllocs'), - 'Healthy allocs aggregates across task groups' - ); + assert.equal( + find('[data-test-deployment-metric="healthy"]').textContent.trim(), + deployment.get('healthyAllocs'), + 'Healthy allocs aggregates across task groups' + ); - assert.equal( - find('[data-test-deployment-metric="unhealthy"]').textContent.trim(), - deployment.get('unhealthyAllocs'), - 'Unhealthy allocs aggregates across task groups' - ); + assert.equal( + find('[data-test-deployment-metric="unhealthy"]').textContent.trim(), + deployment.get('unhealthyAllocs'), + 'Unhealthy allocs aggregates across task groups' + ); - assert.equal( - find('[data-test-deployment-notification]').textContent.trim(), - deployment.get('statusDescription'), - 'Status description is in the metrics block' - ); - }); - }); + assert.equal( + find('[data-test-deployment-notification]').textContent.trim(), + deployment.get('statusDescription'), + 'Status description is in the metrics block' + ); }); - test('when there is no running deployment, the latest deployment section shows up for the last deployment', function(assert) { + test('when there is no running deployment, the latest deployment section shows up for the last deployment', async function(assert) { this.server.create('job', { type: 'service', createAllocations: false, noActiveDeployment: true, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/latest-deployment job=job}} - `); + this.set('job', this.store.peekAll('job').get('firstObject')); + await render(hbs` + {{job-page/parts/latest-deployment job=job}} + `); - return settled().then(() => { - assert.ok(find('[data-test-active-deployment]'), 'Active deployment'); - assert.notOk( - find('[data-test-active-deployment]').classList.contains('is-info'), - 'Non-running deployment does not get the is-info class' - ); - }); - }); + assert.ok(find('[data-test-active-deployment]'), 'Active deployment'); + assert.notOk( + find('[data-test-active-deployment]').classList.contains('is-info'), + 'Non-running deployment does not get the is-info class' + ); }); - test('the latest deployment section can be expanded to show task groups and allocations', function(assert) { + test('the latest deployment section can be expanded to show task groups and allocations', async function(assert) { this.server.create('node'); this.server.create('job', { type: 'service', activeDeployment: true }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/latest-deployment job=job}} - `); + this.set('job', this.store.peekAll('job').get('firstObject')); + await render(hbs` + {{job-page/parts/latest-deployment job=job}} + `); - return settled().then(() => { - assert.notOk(find('[data-test-deployment-task-groups]'), 'Task groups not found'); - assert.notOk(find('[data-test-deployment-allocations]'), 'Allocations not found'); + assert.notOk(find('[data-test-deployment-task-groups]'), 'Task groups not found'); + assert.notOk(find('[data-test-deployment-allocations]'), 'Allocations not found'); - click('[data-test-deployment-toggle-details]'); + await click('[data-test-deployment-toggle-details]'); - return settled().then(() => { - assert.ok(find('[data-test-deployment-task-groups]'), 'Task groups found'); - assert.ok(find('[data-test-deployment-allocations]'), 'Allocations found'); - }); - }); - }); + assert.ok(find('[data-test-deployment-task-groups]'), 'Task groups found'); + assert.ok(find('[data-test-deployment-allocations]'), 'Allocations found'); }); - test('each task group in the expanded task group section shows task group details', function(assert) { + test('each task group in the expanded task group section shows task group details', async function(assert) { this.server.create('node'); this.server.create('job', { type: 'service', activeDeployment: true }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - const job = this.store.peekAll('job').get('firstObject'); + const job = this.store.peekAll('job').get('firstObject'); - this.set('job', job); - await render(hbs` - {{job-page/parts/latest-deployment job=job}} - `); + this.set('job', job); + await render(hbs` + {{job-page/parts/latest-deployment job=job}} + `); - return settled() - .then(() => { - click('[data-test-deployment-toggle-details]'); - return settled(); - }) - .then(() => { - const task = job.get('runningDeployment.taskGroupSummaries.firstObject'); - const findForTaskGroup = selector => - find(`[data-test-deployment-task-group-${selector}]`); - assert.equal(findForTaskGroup('name').textContent.trim(), task.get('name')); - assert.equal( - findForTaskGroup('progress-deadline').textContent.trim(), - moment(task.get('requireProgressBy')).format("MMM DD, 'YY HH:mm:ss ZZ") - ); - }); - }); + await click('[data-test-deployment-toggle-details]'); + + const task = job.get('runningDeployment.taskGroupSummaries.firstObject'); + const findForTaskGroup = selector => find(`[data-test-deployment-task-group-${selector}]`); + assert.equal(findForTaskGroup('name').textContent.trim(), task.get('name')); + assert.equal( + findForTaskGroup('progress-deadline').textContent.trim(), + moment(task.get('requireProgressBy')).format("MMM DD, 'YY HH:mm:ss ZZ") + ); }); }); diff --git a/ui/tests/integration/job-page/parts/placement-failures-test.js b/ui/tests/integration/job-page/parts/placement-failures-test.js index c136e1ef5..1df557068 100644 --- a/ui/tests/integration/job-page/parts/placement-failures-test.js +++ b/ui/tests/integration/job-page/parts/placement-failures-test.js @@ -1,9 +1,7 @@ -import { run } from '@ember/runloop'; import hbs from 'htmlbars-inline-precompile'; -import { findAll, find } from 'ember-native-dom-helpers'; +import { findAll, find, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; @@ -23,69 +21,58 @@ module('Integration | Component | job-page/parts/placement-failures', function(h window.localStorage.clear(); }); - test('when the job has placement failures, they are called out', function(assert) { + test('when the job has placement failures, they are called out', async function(assert) { this.server.create('job', { failedPlacements: true, createAllocations: false }); - this.store.findAll('job').then(jobs => { - jobs.forEach(job => job.reload()); - }); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - this.set('job', this.store.peekAll('job').get('firstObject')); - }); + const job = this.store.peekAll('job').get('firstObject'); + await job.reload(); - await render(hbs` - {{job-page/parts/placement-failures job=job}}) - `); + this.set('job', job); - return settled().then(() => { - const failedEvaluation = this.get('job.evaluations') - .filterBy('hasPlacementFailures') - .sortBy('modifyIndex') - .reverse() - .get('firstObject'); - const failedTGAllocs = failedEvaluation.get('failedTGAllocs'); + await render(hbs` + {{job-page/parts/placement-failures job=job}}) + `); - assert.ok(find('[data-test-placement-failures]'), 'Placement failures section found'); + const failedEvaluation = this.get('job.evaluations') + .filterBy('hasPlacementFailures') + .sortBy('modifyIndex') + .reverse() + .get('firstObject'); + const failedTGAllocs = failedEvaluation.get('failedTGAllocs'); - const taskGroupLabels = findAll('[data-test-placement-failure-task-group]').map(title => - title.textContent.trim() - ); + assert.ok(find('[data-test-placement-failures]'), 'Placement failures section found'); - failedTGAllocs.forEach(alloc => { - const name = alloc.get('name'); - assert.ok( - taskGroupLabels.find(label => label.includes(name)), - `${name} included in placement failures list` - ); - assert.ok( - taskGroupLabels.find(label => label.includes(alloc.get('coalescedFailures') + 1)), - 'The number of unplaced allocs = CoalescedFailures + 1' - ); - }); - }); + const taskGroupLabels = findAll('[data-test-placement-failure-task-group]').map(title => + title.textContent.trim() + ); + + failedTGAllocs.forEach(alloc => { + const name = alloc.get('name'); + assert.ok( + taskGroupLabels.find(label => label.includes(name)), + `${name} included in placement failures list` + ); + assert.ok( + taskGroupLabels.find(label => label.includes(alloc.get('coalescedFailures') + 1)), + 'The number of unplaced allocs = CoalescedFailures + 1' + ); }); }); - test('when the job has no placement failures, the placement failures section is gone', function(assert) { + test('when the job has no placement failures, the placement failures section is gone', async function(assert) { this.server.create('job', { noFailedPlacements: true, createAllocations: false }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - run(() => { - this.set('job', this.store.peekAll('job').get('firstObject')); - }); + const job = this.store.peekAll('job').get('firstObject'); + await job.reload(); - await render(hbs` - {{job-page/parts/placement-failures job=job}}) - `); + this.set('job', job); - return settled().then(() => { - assert.notOk( - find('[data-test-placement-failures]'), - 'Placement failures section not found' - ); - }); - }); + await render(hbs` + {{job-page/parts/placement-failures job=job}}) + `); + + assert.notOk(find('[data-test-placement-failures]'), 'Placement failures section not found'); }); }); diff --git a/ui/tests/integration/job-page/parts/summary-test.js b/ui/tests/integration/job-page/parts/summary-test.js index c4aafbad6..b60d3d5e5 100644 --- a/ui/tests/integration/job-page/parts/summary-test.js +++ b/ui/tests/integration/job-page/parts/summary-test.js @@ -1,8 +1,7 @@ import hbs from 'htmlbars-inline-precompile'; -import { find, click } from 'ember-native-dom-helpers'; +import { find, click, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; @@ -22,262 +21,214 @@ module('Integration | Component | job-page/parts/summary', function(hooks) { window.localStorage.clear(); }); - test('jobs with children use the children diagram', function(assert) { + test('jobs with children use the children diagram', async function(assert) { this.server.create('job', 'periodic', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled().then(() => { - assert.ok(find('[data-test-children-status-bar]'), 'Children status bar found'); - assert.notOk(find('[data-test-allocation-status-bar]'), 'Allocation status bar not found'); - }); - }); + assert.ok(find('[data-test-children-status-bar]'), 'Children status bar found'); + assert.notOk(find('[data-test-allocation-status-bar]'), 'Allocation status bar not found'); }); - test('jobs without children use the allocations diagram', function(assert) { + test('jobs without children use the allocations diagram', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled().then(() => { - assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation status bar found'); - assert.notOk(find('[data-test-children-status-bar]'), 'Children status bar not found'); - }); - }); + assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation status bar found'); + assert.notOk(find('[data-test-children-status-bar]'), 'Children status bar not found'); }); - test('the allocations diagram lists all allocation status figures', function(assert) { + test('the allocations diagram lists all allocation status figures', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled().then(() => { - assert.equal( - find('[data-test-legend-value="queued"]').textContent, - this.get('job.queuedAllocs'), - `${this.get('job.queuedAllocs')} are queued` - ); + assert.equal( + find('[data-test-legend-value="queued"]').textContent, + this.get('job.queuedAllocs'), + `${this.get('job.queuedAllocs')} are queued` + ); - assert.equal( - find('[data-test-legend-value="starting"]').textContent, - this.get('job.startingAllocs'), - `${this.get('job.startingAllocs')} are starting` - ); + assert.equal( + find('[data-test-legend-value="starting"]').textContent, + this.get('job.startingAllocs'), + `${this.get('job.startingAllocs')} are starting` + ); - assert.equal( - find('[data-test-legend-value="running"]').textContent, - this.get('job.runningAllocs'), - `${this.get('job.runningAllocs')} are running` - ); + assert.equal( + find('[data-test-legend-value="running"]').textContent, + this.get('job.runningAllocs'), + `${this.get('job.runningAllocs')} are running` + ); - assert.equal( - find('[data-test-legend-value="complete"]').textContent, - this.get('job.completeAllocs'), - `${this.get('job.completeAllocs')} are complete` - ); + assert.equal( + find('[data-test-legend-value="complete"]').textContent, + this.get('job.completeAllocs'), + `${this.get('job.completeAllocs')} are complete` + ); - assert.equal( - find('[data-test-legend-value="failed"]').textContent, - this.get('job.failedAllocs'), - `${this.get('job.failedAllocs')} are failed` - ); + assert.equal( + find('[data-test-legend-value="failed"]').textContent, + this.get('job.failedAllocs'), + `${this.get('job.failedAllocs')} are failed` + ); - assert.equal( - find('[data-test-legend-value="lost"]').textContent, - this.get('job.lostAllocs'), - `${this.get('job.lostAllocs')} are lost` - ); - }); - }); + assert.equal( + find('[data-test-legend-value="lost"]').textContent, + this.get('job.lostAllocs'), + `${this.get('job.lostAllocs')} are lost` + ); }); - test('the children diagram lists all children status figures', function(assert) { + test('the children diagram lists all children status figures', async function(assert) { this.server.create('job', 'periodic', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled().then(() => { - assert.equal( - find('[data-test-legend-value="queued"]').textContent, - this.get('job.pendingChildren'), - `${this.get('job.pendingChildren')} are pending` - ); + assert.equal( + find('[data-test-legend-value="queued"]').textContent, + this.get('job.pendingChildren'), + `${this.get('job.pendingChildren')} are pending` + ); - assert.equal( - find('[data-test-legend-value="running"]').textContent, - this.get('job.runningChildren'), - `${this.get('job.runningChildren')} are running` - ); + assert.equal( + find('[data-test-legend-value="running"]').textContent, + this.get('job.runningChildren'), + `${this.get('job.runningChildren')} are running` + ); - assert.equal( - find('[data-test-legend-value="complete"]').textContent, - this.get('job.deadChildren'), - `${this.get('job.deadChildren')} are dead` - ); - }); - }); + assert.equal( + find('[data-test-legend-value="complete"]').textContent, + this.get('job.deadChildren'), + `${this.get('job.deadChildren')} are dead` + ); }); - test('the summary block can be collapsed', function(assert) { + test('the summary block can be collapsed', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled(); - }) - .then(() => { - click('[data-test-accordion-toggle]'); - return settled(); - }) - .then(() => { - assert.notOk(find('[data-test-accordion-body]'), 'No accordion body'); - assert.notOk(find('[data-test-legend]'), 'No legend'); - }); + await click('[data-test-accordion-toggle]'); + + assert.notOk(find('[data-test-accordion-body]'), 'No accordion body'); + assert.notOk(find('[data-test-legend]'), 'No legend'); }); - test('when collapsed, the summary block includes an inline version of the chart', function(assert) { + test('when collapsed, the summary block includes an inline version of the chart', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + await this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled(); - }) - .then(() => { - click('[data-test-accordion-toggle]'); - return settled(); - }) - .then(() => { - assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed'); - assert.ok( - find('.inline-chart [data-test-allocation-status-bar]'), - 'Allocation bar is rendered in an inline-chart container' - ); - }); + await click('[data-test-accordion-toggle]'); + + assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed'); + assert.ok( + find('.inline-chart [data-test-allocation-status-bar]'), + 'Allocation bar is rendered in an inline-chart container' + ); }); - test('the collapsed/expanded state is persisted to localStorage', function(assert) { + test('the collapsed/expanded state is persisted to localStorage', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled(); - }) - .then(() => { - assert.notOk(window.localStorage.nomadExpandJobSummary, 'No value in localStorage yet'); - click('[data-test-accordion-toggle]'); - return settled(); - }) - .then(() => { - assert.equal( - window.localStorage.nomadExpandJobSummary, - 'false', - 'Value is stored for the collapsed state' - ); - }); + assert.notOk(window.localStorage.nomadExpandJobSummary, 'No value in localStorage yet'); + await click('[data-test-accordion-toggle]'); + + assert.equal( + window.localStorage.nomadExpandJobSummary, + 'false', + 'Value is stored for the collapsed state' + ); }); - test('the collapsed/expanded state from localStorage is used for the initial state when available', function(assert) { + test('the collapsed/expanded state from localStorage is used for the initial state when available', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); window.localStorage.nomadExpandJobSummary = 'false'; - return settled() - .then(async () => { - this.set('job', this.store.peekAll('job').get('firstObject')); + this.set('job', this.store.peekAll('job').get('firstObject')); - await render(hbs` - {{job-page/parts/summary job=job}} - `); + await render(hbs` + {{job-page/parts/summary job=job}} + `); - return settled(); - }) - .then(() => { - assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed'); - assert.ok( - find('.inline-chart [data-test-allocation-status-bar]'), - 'Allocation bar is rendered in an inline-chart container' - ); + assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed'); + assert.ok( + find('.inline-chart [data-test-allocation-status-bar]'), + 'Allocation bar is rendered in an inline-chart container' + ); - click('[data-test-accordion-toggle]'); - return settled(); - }) - .then(() => { - assert.equal( - window.localStorage.nomadExpandJobSummary, - 'true', - 'localStorage value still toggles' - ); - assert.ok(find('[data-test-accordion-body]'), 'Summary still expands'); - }); + await click('[data-test-accordion-toggle]'); + + assert.equal( + window.localStorage.nomadExpandJobSummary, + 'true', + 'localStorage value still toggles' + ); + assert.ok(find('[data-test-accordion-body]'), 'Summary still expands'); }); }); diff --git a/ui/tests/integration/job-page/parts/task-groups-test.js b/ui/tests/integration/job-page/parts/task-groups-test.js index a36067ec9..5fea0c765 100644 --- a/ui/tests/integration/job-page/parts/task-groups-test.js +++ b/ui/tests/integration/job-page/parts/task-groups-test.js @@ -1,18 +1,15 @@ import { assign } from '@ember/polyfills'; import hbs from 'htmlbars-inline-precompile'; -import { click, findAll, find } from 'ember-native-dom-helpers'; +import { click, findAll, find } from '@ember/test-helpers'; import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import sinon from 'sinon'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; -import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer'; +import { setupRenderingTest } from 'ember-qunit'; module('Integration | Component | job-page/parts/task-groups', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { - fragmentSerializerInitializer(this.owner); window.localStorage.clear(); this.store = this.owner.lookup('service:store'); this.server = startMirage(); @@ -34,135 +31,123 @@ module('Integration | Component | job-page/parts/task-groups', function(hooks) { options ); - test('the job detail page should list all task groups', function(assert) { + test('the job detail page should list all task groups', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job').then(jobs => { + await this.store.findAll('job').then(jobs => { jobs.forEach(job => job.reload()); }); - return settled().then(async () => { - const job = this.store.peekAll('job').get('firstObject'); - this.setProperties(props(job)); + const job = this.store.peekAll('job').get('firstObject'); + this.setProperties(props(job)); - await render(hbs` - {{job-page/parts/task-groups - job=job - sortProperty=sortProperty - sortDescending=sortDescending - gotoTaskGroup=gotoTaskGroup}} - `); + await this.render(hbs` + {{job-page/parts/task-groups + job=job + sortProperty=sortProperty + sortDescending=sortDescending + gotoTaskGroup=gotoTaskGroup}} + `); - return settled().then(() => { - assert.equal( - findAll('[data-test-task-group]').length, - job.get('taskGroups.length'), - 'One row per task group' - ); - }); - }); + assert.equal( + findAll('[data-test-task-group]').length, + job.get('taskGroups.length'), + 'One row per task group' + ); }); - test('each row in the task group table should show basic information about the task group', function(assert) { + test('each row in the task group table should show basic information about the task group', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job').then(jobs => { - jobs.forEach(job => job.reload()); + const job = await this.store.findAll('job').then(async jobs => { + return await jobs.get('firstObject').reload(); }); - return settled().then(async () => { - const job = this.store.peekAll('job').get('firstObject'); - const taskGroup = job - .get('taskGroups') - .sortBy('name') - .reverse() - .get('firstObject'); + const taskGroups = await job.get('taskGroups'); + const taskGroup = taskGroups + .sortBy('name') + .reverse() + .get('firstObject'); - this.setProperties(props(job)); + this.setProperties(props(job)); - await render(hbs` - {{job-page/parts/task-groups - job=job - sortProperty=sortProperty - sortDescending=sortDescending - gotoTaskGroup=gotoTaskGroup}} - `); + await this.render(hbs` + {{job-page/parts/task-groups + job=job + sortProperty=sortProperty + sortDescending=sortDescending + gotoTaskGroup=gotoTaskGroup}} + `); - return settled().then(() => { - const taskGroupRow = find('[data-test-task-group]'); + const taskGroupRow = find('[data-test-task-group]'); - assert.equal( - taskGroupRow.querySelector('[data-test-task-group-name]').textContent.trim(), - taskGroup.get('name'), - 'Name' - ); - assert.equal( - taskGroupRow.querySelector('[data-test-task-group-count]').textContent.trim(), - taskGroup.get('count'), - 'Count' - ); - assert.equal( - taskGroupRow.querySelector('[data-test-task-group-cpu]').textContent.trim(), - `${taskGroup.get('reservedCPU')} MHz`, - 'Reserved CPU' - ); - assert.equal( - taskGroupRow.querySelector('[data-test-task-group-mem]').textContent.trim(), - `${taskGroup.get('reservedMemory')} MiB`, - 'Reserved Memory' - ); - assert.equal( - taskGroupRow.querySelector('[data-test-task-group-disk]').textContent.trim(), - `${taskGroup.get('reservedEphemeralDisk')} MiB`, - 'Reserved Disk' - ); - }); - }); + assert.equal( + taskGroupRow.querySelector('[data-test-task-group-name]').textContent.trim(), + taskGroup.get('name'), + 'Name' + ); + assert.equal( + taskGroupRow.querySelector('[data-test-task-group-count]').textContent.trim(), + taskGroup.get('count'), + 'Count' + ); + assert.equal( + taskGroupRow.querySelector('[data-test-task-group-cpu]').textContent.trim(), + `${taskGroup.get('reservedCPU')} MHz`, + 'Reserved CPU' + ); + assert.equal( + taskGroupRow.querySelector('[data-test-task-group-mem]').textContent.trim(), + `${taskGroup.get('reservedMemory')} MiB`, + 'Reserved Memory' + ); + assert.equal( + taskGroupRow.querySelector('[data-test-task-group-disk]').textContent.trim(), + `${taskGroup.get('reservedEphemeralDisk')} MiB`, + 'Reserved Disk' + ); }); - test('gotoTaskGroup is called when task group rows are clicked', function(assert) { + test('gotoTaskGroup is called when task group rows are clicked', async function(assert) { this.server.create('job', { createAllocations: false, }); - this.store.findAll('job').then(jobs => { - jobs.forEach(job => job.reload()); + const job = await this.store.findAll('job').then(async jobs => { + return await jobs.get('firstObject').reload(); }); - return settled().then(async () => { - const taskGroupSpy = sinon.spy(); - const job = this.store.peekAll('job').get('firstObject'); - const taskGroup = job - .get('taskGroups') - .sortBy('name') - .reverse() - .get('firstObject'); + const taskGroupSpy = sinon.spy(); - this.setProperties( - props(job, { - gotoTaskGroup: taskGroupSpy, - }) - ); + const taskGroups = await job.get('taskGroups'); + const taskGroup = taskGroups + .sortBy('name') + .reverse() + .get('firstObject'); - await render(hbs` - {{job-page/parts/task-groups - job=job - sortProperty=sortProperty - sortDescending=sortDescending - gotoTaskGroup=gotoTaskGroup}} - `); + this.setProperties( + props(job, { + gotoTaskGroup: taskGroupSpy, + }) + ); - return settled().then(() => { - click('[data-test-task-group]'); - assert.ok( - taskGroupSpy.withArgs(taskGroup).calledOnce, - 'Clicking the task group row calls the gotoTaskGroup action' - ); - }); - }); + await this.render(hbs` + {{job-page/parts/task-groups + job=job + sortProperty=sortProperty + sortDescending=sortDescending + gotoTaskGroup=gotoTaskGroup}} + `); + + await click('[data-test-task-group]'); + + assert.ok( + taskGroupSpy.withArgs(taskGroup).calledOnce, + 'Clicking the task group row calls the gotoTaskGroup action' + ); }); }); diff --git a/ui/tests/integration/job-page/periodic-test.js b/ui/tests/integration/job-page/periodic-test.js index 6595b90ee..06a648200 100644 --- a/ui/tests/integration/job-page/periodic-test.js +++ b/ui/tests/integration/job-page/periodic-test.js @@ -1,7 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { click, find, findAll } from 'ember-native-dom-helpers'; +import { click, find, findAll, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import { @@ -45,7 +44,7 @@ module('Integration | Component | job-page/periodic', function(hooks) { gotoJob: () => {}, }); - test('Clicking Force Launch launches a new periodic child job', function(assert) { + test('Clicking Force Launch launches a new periodic child job', async function(assert) { const childrenCount = 3; this.server.create('job', 'periodic', { @@ -54,42 +53,36 @@ module('Integration | Component | job-page/periodic', function(hooks) { createAllocations: false, }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - const job = this.store.peekAll('job').findBy('plainId', 'parent'); + const job = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await this.render(commonTemplate); - return settled().then(() => { - const currentJobCount = server.db.jobs.length; + const currentJobCount = server.db.jobs.length; - assert.equal( - findAll('[data-test-job-name]').length, - childrenCount, - 'The new periodic job launch is in the children list' - ); + assert.equal( + findAll('[data-test-job-name]').length, + childrenCount, + 'The new periodic job launch is in the children list' + ); - click('[data-test-force-launch]'); + await click('[data-test-force-launch]'); - return settled().then(() => { - const expectedURL = jobURL(job, '/periodic/force'); + const expectedURL = jobURL(job, '/periodic/force'); - assert.ok( - this.server.pretender.handledRequests - .filterBy('method', 'POST') - .find(req => req.url === expectedURL), - 'POST URL was correct' - ); + assert.ok( + this.server.pretender.handledRequests + .filterBy('method', 'POST') + .find(req => req.url === expectedURL), + 'POST URL was correct' + ); - assert.equal(server.db.jobs.length, currentJobCount + 1, 'POST request was made'); - }); - }); - }); + assert.equal(server.db.jobs.length, currentJobCount + 1, 'POST request was made'); }); - test('Clicking force launch without proper permissions shows an error message', function(assert) { + test('Clicking force launch without proper permissions shows an error message', async function(assert) { this.server.pretender.post('/v1/job/:id/periodic/force', () => [403, {}, null]); this.server.create('job', 'periodic', { @@ -99,39 +92,33 @@ module('Integration | Component | job-page/periodic', function(hooks) { status: 'running', }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - const job = this.store.peekAll('job').findBy('plainId', 'parent'); + const job = this.store.peekAll('job').findBy('plainId', 'parent'); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await this.render(commonTemplate); - return settled().then(() => { - assert.notOk(find('[data-test-job-error-title]'), 'No error message yet'); + assert.notOk(find('[data-test-job-error-title]'), 'No error message yet'); - click('[data-test-force-launch]'); + await click('[data-test-force-launch]'); - return settled().then(() => { - assert.equal( - find('[data-test-job-error-title]').textContent, - 'Could Not Force Launch', - 'Appropriate error is shown' - ); - assert.ok( - find('[data-test-job-error-body]').textContent.includes('ACL'), - 'The error message mentions ACLs' - ); + assert.equal( + find('[data-test-job-error-title]').textContent, + 'Could Not Force Launch', + 'Appropriate error is shown' + ); + assert.ok( + find('[data-test-job-error-body]').textContent.includes('ACL'), + 'The error message mentions ACLs' + ); - click('[data-test-job-error-close]'); + await click('[data-test-job-error-close]'); - assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); - }); - }); - }); + assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); }); - test('Stopping a job sends a delete request for the job', function(assert) { + test('Stopping a job sends a delete request for the job', async function(assert) { const mirageJob = this.server.create('job', 'periodic', { childrenCount: 0, createAllocations: false, @@ -139,22 +126,18 @@ module('Integration | Component | job-page/periodic', function(hooks) { }); let job; - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); + await stopJob(); - return settled(); - }) - .then(stopJob) - .then(() => expectDeleteRequest(assert, this.server, job)); + expectDeleteRequest(assert, this.server, job); }); - test('Stopping a job without proper permissions shows an error message', function(assert) { + test('Stopping a job without proper permissions shows an error message', async function(assert) { this.server.pretender.delete('/v1/job/:id', () => [403, {}, null]); const mirageJob = this.server.create('job', 'periodic', { @@ -163,45 +146,35 @@ module('Integration | Component | job-page/periodic', function(hooks) { status: 'running', }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(stopJob) - .then(expectError(assert, 'Could Not Stop Job')); + await stopJob(); + expectError(assert, 'Could Not Stop Job'); }); - test('Starting a job sends a post request for the job using the current definition', function(assert) { - let job; - + test('Starting a job sends a post request for the job using the current definition', async function(assert) { const mirageJob = this.server.create('job', 'periodic', { childrenCount: 0, createAllocations: false, status: 'dead', }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(startJob) - .then(() => expectStartRequest(assert, this.server, job)); + await startJob(); + expectStartRequest(assert, this.server, job); }); - test('Starting a job without proper permissions shows an error message', function(assert) { + test('Starting a job without proper permissions shows an error message', async function(assert) { this.server.pretender.post('/v1/job/:id', () => [403, {}, null]); const mirageJob = this.server.create('job', 'periodic', { @@ -209,18 +182,14 @@ module('Integration | Component | job-page/periodic', function(hooks) { createAllocations: false, status: 'dead', }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(startJob) - .then(expectError(assert, 'Could Not Start Job')); + await startJob(); + expectError(assert, 'Could Not Start Job'); }); }); diff --git a/ui/tests/integration/job-page/service-test.js b/ui/tests/integration/job-page/service-test.js index 01e9cd273..7f77f4d24 100644 --- a/ui/tests/integration/job-page/service-test.js +++ b/ui/tests/integration/job-page/service-test.js @@ -1,8 +1,7 @@ import { assign } from '@ember/polyfills'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { click, find } from 'ember-native-dom-helpers'; +import { click, find, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import { startJob, stopJob, expectError, expectDeleteRequest, expectStartRequest } from './helpers'; @@ -57,228 +56,166 @@ module('Integration | Component | job-page/service', function(hooks) { ) ); - test('Stopping a job sends a delete request for the job', function(assert) { - let job; - + test('Stopping a job sends a delete request for the job', async function(assert) { const mirageJob = makeMirageJob(this.server); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(stopJob) - .then(() => expectDeleteRequest(assert, this.server, job)); + await stopJob(); + expectDeleteRequest(assert, this.server, job); }); - test('Stopping a job without proper permissions shows an error message', function(assert) { + test('Stopping a job without proper permissions shows an error message', async function(assert) { this.server.pretender.delete('/v1/job/:id', () => [403, {}, null]); const mirageJob = makeMirageJob(this.server); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(stopJob) - .then(expectError(assert, 'Could Not Stop Job')); + await stopJob(); + expectError(assert, 'Could Not Stop Job'); }); - test('Starting a job sends a post request for the job using the current definition', function(assert) { - let job; - + test('Starting a job sends a post request for the job using the current definition', async function(assert) { const mirageJob = makeMirageJob(this.server, { status: 'dead' }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(startJob) - .then(() => expectStartRequest(assert, this.server, job)); + await startJob(); + expectStartRequest(assert, this.server, job); }); - test('Starting a job without proper permissions shows an error message', function(assert) { + test('Starting a job without proper permissions shows an error message', async function(assert) { this.server.pretender.post('/v1/job/:id', () => [403, {}, null]); const mirageJob = makeMirageJob(this.server, { status: 'dead' }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(startJob) - .then(expectError(assert, 'Could Not Start Job')); + await startJob(); + expectError(assert, 'Could Not Start Job'); }); - test('Recent allocations shows allocations in the job context', function(assert) { - let job; - + test('Recent allocations shows allocations in the job context', async function(assert) { this.server.create('node'); const mirageJob = makeMirageJob(this.server, { createAllocations: true }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(() => { - const allocation = this.server.db.allocations.sortBy('modifyIndex').reverse()[0]; - const allocationRow = Job.allocations.objectAt(0); + const allocation = this.server.db.allocations.sortBy('modifyIndex').reverse()[0]; + const allocationRow = Job.allocations.objectAt(0); - assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID'); - assert.equal(allocationRow.taskGroup, allocation.taskGroup, 'Task Group name'); - }); + assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID'); + assert.equal(allocationRow.taskGroup, allocation.taskGroup, 'Task Group name'); }); - test('Recent allocations caps out at five', function(assert) { - let job; - + test('Recent allocations caps out at five', async function(assert) { this.server.create('node'); const mirageJob = makeMirageJob(this.server); this.server.createList('allocation', 10); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled().then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled().then(() => { - assert.equal(Job.allocations.length, 5, 'Capped at 5 allocations'); - assert.ok( - Job.viewAllAllocations.includes(job.get('allocations.length') + ''), - `View link mentions ${job.get('allocations.length')} allocations` - ); - }); - }); + assert.equal(Job.allocations.length, 5, 'Capped at 5 allocations'); + assert.ok( + Job.viewAllAllocations.includes(job.get('allocations.length') + ''), + `View link mentions ${job.get('allocations.length')} allocations` + ); }); - test('Recent allocations shows an empty message when the job has no allocations', function(assert) { - let job; - + test('Recent allocations shows an empty message when the job has no allocations', async function(assert) { this.server.create('node'); const mirageJob = makeMirageJob(this.server); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - Job.recentAllocationsEmptyState.headline.includes('No Allocations'), - 'No allocations empty message' - ); - }); + assert.ok( + Job.recentAllocationsEmptyState.headline.includes('No Allocations'), + 'No allocations empty message' + ); }); - test('Active deployment can be promoted', function(assert) { - let job; - let deployment; - + test('Active deployment can be promoted', async function(assert) { this.server.create('node'); const mirageJob = makeMirageJob(this.server, { activeDeployment: true }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - deployment = job.get('latestDeployment'); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const deployment = await job.get('latestDeployment'); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(() => { - click('[data-test-promote-canary]'); - return settled(); - }) - .then(() => { - const requests = this.server.pretender.handledRequests; - assert.ok( - requests - .filterBy('method', 'POST') - .findBy('url', `/v1/deployment/promote/${deployment.get('id')}`), - 'A promote POST request was made' - ); - }); + await click('[data-test-promote-canary]'); + + const requests = this.server.pretender.handledRequests; + + assert.ok( + requests + .filterBy('method', 'POST') + .findBy('url', `/v1/deployment/promote/${deployment.get('id')}`), + 'A promote POST request was made' + ); }); - test('When promoting the active deployment fails, an error is shown', function(assert) { + test('When promoting the active deployment fails, an error is shown', async function(assert) { this.server.pretender.post('/v1/deployment/promote/:id', () => [403, {}, null]); - let job; - this.server.create('node'); const mirageJob = makeMirageJob(this.server, { activeDeployment: true }); - this.store.findAll('job'); + await this.store.findAll('job'); - return settled() - .then(async () => { - job = this.store.peekAll('job').findBy('plainId', mirageJob.id); + const job = this.store.peekAll('job').findBy('plainId', mirageJob.id); - this.setProperties(commonProperties(job)); - await render(commonTemplate); + this.setProperties(commonProperties(job)); + await render(commonTemplate); - return settled(); - }) - .then(() => { - click('[data-test-promote-canary]'); - return settled(); - }) - .then(() => { - assert.equal( - find('[data-test-job-error-title]').textContent, - 'Could Not Promote Deployment', - 'Appropriate error is shown' - ); - assert.ok( - find('[data-test-job-error-body]').textContent.includes('ACL'), - 'The error message mentions ACLs' - ); + await click('[data-test-promote-canary]'); - click('[data-test-job-error-close]'); - assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); - return settled(); - }); + assert.equal( + find('[data-test-job-error-title]').textContent, + 'Could Not Promote Deployment', + 'Appropriate error is shown' + ); + assert.ok( + find('[data-test-job-error-body]').textContent.includes('ACL'), + 'The error message mentions ACLs' + ); + + await click('[data-test-job-error-close]'); + + assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable'); }); }); diff --git a/ui/tests/integration/list-pagination-test.js b/ui/tests/integration/list-pagination-test.js index 0aa1301d2..94c12788d 100644 --- a/ui/tests/integration/list-pagination-test.js +++ b/ui/tests/integration/list-pagination-test.js @@ -1,7 +1,6 @@ -import { findAll, find } from 'ember-native-dom-helpers'; +import { findAll, find, render } from '@ember/test-helpers'; import { module, skip, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; module('Integration | Component | list pagination', function(hooks) { @@ -240,7 +239,8 @@ module('Integration | Component | list pagination', function(hooks) { assert.equal( findAll('.item')[item].textContent, item + (currentPage - 1) * size, - `Rendered items are in the current page, ${currentPage} (${item + (currentPage - 1) * size})` + `Rendered items are in the current page, ${currentPage} (${item + + (currentPage - 1) * size})` ); } } diff --git a/ui/tests/integration/list-table-test.js b/ui/tests/integration/list-table-test.js index 7ca418b5e..d039555a0 100644 --- a/ui/tests/integration/list-table-test.js +++ b/ui/tests/integration/list-table-test.js @@ -1,7 +1,6 @@ -import { findAll, find } from 'ember-native-dom-helpers'; +import { findAll, find, render } from '@ember/test-helpers'; import { module, skip, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; import { faker } from 'ember-cli-mirage'; import hbs from 'htmlbars-inline-precompile'; diff --git a/ui/tests/integration/multi-select-dropdown-test.js b/ui/tests/integration/multi-select-dropdown-test.js index cea952703..2f5fc9101 100644 --- a/ui/tests/integration/multi-select-dropdown-test.js +++ b/ui/tests/integration/multi-select-dropdown-test.js @@ -1,7 +1,6 @@ -import { findAll, find, click, focus, keyEvent } from 'ember-native-dom-helpers'; +import { findAll, find, click, focus, render, triggerKeyEvent } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import sinon from 'sinon'; import hbs from 'htmlbars-inline-precompile'; @@ -55,17 +54,12 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - return settled() - .then(() => { - assert.ok(find('[data-test-dropdown-options]'), 'Options are shown now'); - click('[data-test-dropdown-trigger]'); - return settled(); - }) - .then(() => { - assert.notOk(find('[data-test-dropdown-options]'), 'Options are hidden after clicking again'); - }); + await assert.ok(find('[data-test-dropdown-options]'), 'Options are shown now'); + await click('[data-test-dropdown-trigger]'); + + assert.notOk(find('[data-test-dropdown-options]'), 'Options are hidden after clicking again'); }); test('all options are shown in the options dropdown, each with a checkbox input', async function(assert) { @@ -73,19 +67,17 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - return settled().then(() => { - assert.equal( - findAll('[data-test-dropdown-option]').length, - props.options.length, - 'All options are shown' - ); - findAll('[data-test-dropdown-option]').forEach((optionEl, index) => { - const label = props.options[index].label; - assert.equal(optionEl.textContent.trim(), label, `Correct label for ${label}`); - assert.ok(optionEl.querySelector('input[type="checkbox"]'), 'Option contains a checkbox'); - }); + assert.equal( + findAll('[data-test-dropdown-option]').length, + props.options.length, + 'All options are shown' + ); + findAll('[data-test-dropdown-option]').forEach((optionEl, index) => { + const label = props.options[index].label; + assert.equal(optionEl.textContent.trim(), label, `Correct label for ${label}`); + assert.ok(optionEl.querySelector('input[type="checkbox"]'), 'Option contains a checkbox'); }); }); @@ -94,22 +86,16 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-option] label'); - return settled() - .then(() => { - click('[data-test-dropdown-option] label'); - return settled(); - }) - .then(() => { - assert.ok(props.onSelect.called, 'onSelect was called'); - const newSelection = props.onSelect.getCall(0).args[0]; - assert.deepEqual( - newSelection, - [props.options[0].key], - 'onSelect was called with the first option key' - ); - }); + assert.ok(props.onSelect.called, 'onSelect was called'); + const newSelection = props.onSelect.getCall(0).args[0]; + assert.deepEqual( + newSelection, + [props.options[0].key], + 'onSelect was called with the first option key' + ); }); test('the component trigger shows the selection count when there is a selection', async function(assert) { @@ -118,21 +104,22 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - assert.ok(find('[data-test-dropdown-trigger] [data-test-dropdown-count]'), 'The count is shown'); + assert.ok( + find('[data-test-dropdown-trigger] [data-test-dropdown-count]'), + 'The count is shown' + ); assert.equal( find('[data-test-dropdown-trigger] [data-test-dropdown-count]').textContent, props.selection.length, 'The count is accurate' ); - this.set('selection', []); + await this.set('selection', []); - return settled().then(() => { - assert.notOk( - find('[data-test-dropdown-trigger] [data-test-dropdown-count]'), - 'The count is no longer shown when the selection is empty' - ); - }); + assert.notOk( + find('[data-test-dropdown-trigger] [data-test-dropdown-count]'), + 'The count is no longer shown when the selection is empty' + ); }); test('pressing DOWN when the trigger has focus opens the options list', async function(assert) { @@ -140,9 +127,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - focus('[data-test-dropdown-trigger]'); + await focus('[data-test-dropdown-trigger]'); assert.notOk(find('[data-test-dropdown-options]'), 'Options are not shown on focus'); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); assert.ok(find('[data-test-dropdown-options]'), 'Options are now shown'); assert.equal( document.activeElement, @@ -156,9 +143,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - focus('[data-test-dropdown-trigger]'); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await focus('[data-test-dropdown-trigger]'); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); assert.equal( document.activeElement, find('[data-test-dropdown-option]'), @@ -171,9 +158,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - focus('[data-test-dropdown-trigger]'); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); - keyEvent('[data-test-dropdown-trigger]', 'keydown', TAB); + await focus('[data-test-dropdown-trigger]'); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', TAB); assert.equal( document.activeElement, find('[data-test-dropdown-option]'), @@ -186,10 +173,10 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - focus('[data-test-dropdown-option]'); - keyEvent('[data-test-dropdown-option]', 'keydown', ARROW_UP); + await focus('[data-test-dropdown-option]'); + await triggerKeyEvent('[data-test-dropdown-option]', 'keydown', ARROW_UP); assert.equal( document.activeElement, find('[data-test-dropdown-option]'), @@ -202,10 +189,10 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - focus('[data-test-dropdown-option]'); - keyEvent('[data-test-dropdown-option]', 'keydown', ARROW_DOWN); + await focus('[data-test-dropdown-option]'); + await triggerKeyEvent('[data-test-dropdown-option]', 'keydown', ARROW_DOWN); assert.equal( document.activeElement, findAll('[data-test-dropdown-option]')[1], @@ -218,20 +205,26 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - focus('[data-test-dropdown-option]'); + await focus('[data-test-dropdown-option]'); const optionEls = findAll('[data-test-dropdown-option]'); const lastIndex = optionEls.length - 1; - optionEls.forEach((option, index) => { - keyEvent(option, 'keydown', ARROW_DOWN); + + for (const [index, option] of optionEls.entries()) { + await triggerKeyEvent(option, 'keydown', ARROW_DOWN); + if (index < lastIndex) { assert.equal(document.activeElement, optionEls[index + 1], `Option ${index + 1} has focus`); } - }); + } - keyEvent(optionEls[lastIndex], 'keydown', ARROW_DOWN); - assert.equal(document.activeElement, optionEls[lastIndex], `Option ${lastIndex} still has focus`); + await triggerKeyEvent(optionEls[lastIndex], 'keydown', ARROW_DOWN); + assert.equal( + document.activeElement, + optionEls[lastIndex], + `Option ${lastIndex} still has focus` + ); }); test('onSelect gets called when pressing SPACE when a list option is focused', async function(assert) { @@ -239,10 +232,10 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); - focus('[data-test-dropdown-option]'); - keyEvent('[data-test-dropdown-option]', 'keydown', SPACE); + await focus('[data-test-dropdown-option]'); + await triggerKeyEvent('[data-test-dropdown-option]', 'keydown', SPACE); assert.ok(props.onSelect.called, 'onSelect was called'); const newSelection = props.onSelect.getCall(0).args[0]; @@ -258,7 +251,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); findAll('[data-test-dropdown-option]').forEach(option => { assert.ok(parseInt(option.getAttribute('tabindex'), 10) > 0, 'tabindex is a positive value'); @@ -270,7 +263,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); findAll('[data-test-dropdown-option]').forEach(option => { assert.ok( @@ -285,10 +278,10 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - focus('[data-test-dropdown-trigger]'); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); - keyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); - keyEvent('[data-test-dropdown-option]', 'keydown', ESC); + await focus('[data-test-dropdown-trigger]'); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN); + await triggerKeyEvent('[data-test-dropdown-option]', 'keydown', ESC); assert.notOk(find('[data-test-dropdown-options]'), 'The options list is hidden once more'); assert.equal( @@ -304,7 +297,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) { this.setProperties(props); await render(commonTemplate); - click('[data-test-dropdown-trigger]'); + await click('[data-test-dropdown-trigger]'); assert.ok(find('[data-test-dropdown-options]'), 'The dropdown is still shown'); assert.ok(find('[data-test-dropdown-empty]'), 'The empty state is shown'); assert.notOk(find('[data-test-dropdown-option]'), 'No options are shown'); diff --git a/ui/tests/integration/page-layout-test.js b/ui/tests/integration/page-layout-test.js index d27e68d3d..5f8162482 100644 --- a/ui/tests/integration/page-layout-test.js +++ b/ui/tests/integration/page-layout-test.js @@ -1,7 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { find, click } from 'ember-native-dom-helpers'; +import { find, click, render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; @@ -23,54 +22,36 @@ module('Integration | Component | page layout', function(hooks) { find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is not open' ); - click('[data-test-header-gutter-toggle]'); + await click('[data-test-header-gutter-toggle]'); - return settled().then(() => { - assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open'); - }); + assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open'); }); test('the gutter-menu hamburger menu closes the gutter menu', async function(assert) { await render(hbs`{{page-layout}}`); - click('[data-test-header-gutter-toggle]'); + await click('[data-test-header-gutter-toggle]'); - return settled() - .then(() => { - assert.ok( - find('[data-test-gutter-menu]').classList.contains('is-open'), - 'Gutter menu is open' - ); - click('[data-test-gutter-gutter-toggle]'); - return settled(); - }) - .then(() => { - assert.notOk( - find('[data-test-gutter-menu]').classList.contains('is-open'), - 'Gutter menu is not open' - ); - }); + assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open'); + await click('[data-test-gutter-gutter-toggle]'); + + assert.notOk( + find('[data-test-gutter-menu]').classList.contains('is-open'), + 'Gutter menu is not open' + ); }); test('the gutter-menu backdrop closes the gutter menu', async function(assert) { await render(hbs`{{page-layout}}`); - click('[data-test-header-gutter-toggle]'); + await click('[data-test-header-gutter-toggle]'); - return settled() - .then(() => { - assert.ok( - find('[data-test-gutter-menu]').classList.contains('is-open'), - 'Gutter menu is open' - ); - click('[data-test-gutter-backdrop]'); - return settled(); - }) - .then(() => { - assert.notOk( - find('[data-test-gutter-menu]').classList.contains('is-open'), - 'Gutter menu is not open' - ); - }); + assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open'); + await click('[data-test-gutter-backdrop]'); + + assert.notOk( + find('[data-test-gutter-menu]').classList.contains('is-open'), + 'Gutter menu is not open' + ); }); }); diff --git a/ui/tests/integration/placement-failure-test.js b/ui/tests/integration/placement-failure-test.js index abe313a4f..b73a536b9 100644 --- a/ui/tests/integration/placement-failure-test.js +++ b/ui/tests/integration/placement-failure-test.js @@ -1,7 +1,6 @@ -import { find, findAll } from 'ember-native-dom-helpers'; +import { find, findAll, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render } from '@ember/test-helpers'; import { assign } from '@ember/polyfills'; import hbs from 'htmlbars-inline-precompile'; import cleanWhitespace from '../utils/clean-whitespace'; diff --git a/ui/tests/integration/primary-metric-test.js b/ui/tests/integration/primary-metric-test.js index 3f4acd436..80ea704b0 100644 --- a/ui/tests/integration/primary-metric-test.js +++ b/ui/tests/integration/primary-metric-test.js @@ -2,9 +2,8 @@ import EmberObject, { computed } from '@ember/object'; import Service from '@ember/service'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; -import { find } from 'ember-native-dom-helpers'; +import { find, render } from '@ember/test-helpers'; import { task } from 'ember-concurrency'; import sinon from 'sinon'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; @@ -57,144 +56,107 @@ module('Integration | Component | primary metric', function(hooks) { metric=metric}} `; - test('Contains a line chart, a percentage bar, a percentage figure, and an absolute usage figure', function(assert) { + test('Contains a line chart, a percentage bar, a percentage figure, and an absolute usage figure', async function(assert) { let resource; const metric = 'cpu'; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric }); + resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric }); - await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok(find('[data-test-line-chart]'), 'Line chart'); - assert.ok(find('[data-test-percentage-bar]'), 'Percentage bar'); - assert.ok(find('[data-test-percentage]'), 'Percentage figure'); - assert.ok(find('[data-test-absolute-value]'), 'Absolute usage figure'); - }); + await render(commonTemplate); + + assert.ok(find('[data-test-line-chart]'), 'Line chart'); + assert.ok(find('[data-test-percentage-bar]'), 'Percentage bar'); + assert.ok(find('[data-test-percentage]'), 'Percentage figure'); + assert.ok(find('[data-test-absolute-value]'), 'Absolute usage figure'); }); - test('The CPU metric maps to is-info', function(assert) { - let resource; + test('The CPU metric maps to is-info', async function(assert) { const metric = 'cpu'; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric }); + const resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric }); - await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - find('[data-test-line-chart] .canvas').classList.contains('is-info'), - 'Info class for CPU metric' - ); - }); + await render(commonTemplate); + + assert.ok( + find('[data-test-line-chart] .canvas').classList.contains('is-info'), + 'Info class for CPU metric' + ); }); - test('The Memory metric maps to is-danger', function(assert) { - let resource; + test('The Memory metric maps to is-danger', async function(assert) { const metric = 'memory'; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric }); + const resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric }); - await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - find('[data-test-line-chart] .canvas').classList.contains('is-danger'), - 'Danger class for Memory metric' - ); - }); + await render(commonTemplate); + + assert.ok( + find('[data-test-line-chart] .canvas').classList.contains('is-danger'), + 'Danger class for Memory metric' + ); }); - test('Gets the tracker from the tracker registry', function(assert) { - let resource; + test('Gets the tracker from the tracker registry', async function(assert) { const metric = 'cpu'; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric }); + const resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric }); - await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - this.getTrackerSpy.calledWith(resource), - 'Uses the tracker registry to get the tracker for the provided resource' - ); - }); + await render(commonTemplate); + + assert.ok( + this.getTrackerSpy.calledWith(resource), + 'Uses the tracker registry to get the tracker for the provided resource' + ); }); - test('Immediately polls the tracker', function(assert) { - let resource; + test('Immediately polls the tracker', async function(assert) { const metric = 'cpu'; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric }); + const resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric }); - await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok(this.trackerPollSpy.calledOnce, 'The tracker is polled immediately'); - }); + await render(commonTemplate); + + assert.ok(this.trackerPollSpy.calledOnce, 'The tracker is polled immediately'); }); - test('A pause signal is sent to the tracker when the component is destroyed', function(assert) { - let resource; + test('A pause signal is sent to the tracker when the component is destroyed', async function(assert) { const metric = 'cpu'; // Capture a reference to the spy before the component is destroyed const trackerSignalPauseSpy = this.trackerSignalPauseSpy; - this.store.findAll('node'); + await this.store.findAll('node'); - return settled() - .then(async () => { - resource = this.store.peekAll('node').get('firstObject'); - this.setProperties({ resource, metric, showComponent: true }); - await render(hbs` - {{#if showComponent}} - {{primary-metric - resource=resource - metric=metric}} - }} - {{/if}} - `); - return settled(); - }) - .then(() => { - assert.notOk(trackerSignalPauseSpy.called, 'No pause signal has been sent yet'); - // This will toggle the if statement, resulting the primary-metric component being destroyed. - this.set('showComponent', false); - return settled(); - }) - .then(() => { - assert.ok(trackerSignalPauseSpy.calledOnce, 'A pause signal is sent to the tracker'); - }); + const resource = this.store.peekAll('node').get('firstObject'); + this.setProperties({ resource, metric, showComponent: true }); + await render(hbs` + {{#if showComponent}} + {{primary-metric + resource=resource + metric=metric}} + }} + {{/if}} + `); + + assert.notOk(trackerSignalPauseSpy.called, 'No pause signal has been sent yet'); + // This will toggle the if statement, resulting the primary-metric component being destroyed. + this.set('showComponent', false); + + assert.ok(trackerSignalPauseSpy.calledOnce, 'A pause signal is sent to the tracker'); }); }); diff --git a/ui/tests/integration/reschedule-event-timeline-test.js b/ui/tests/integration/reschedule-event-timeline-test.js index 199f9fcf5..6fe3d7955 100644 --- a/ui/tests/integration/reschedule-event-timeline-test.js +++ b/ui/tests/integration/reschedule-event-timeline-test.js @@ -1,7 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { find, findAll } from 'ember-native-dom-helpers'; +import { find, findAll, render } from '@ember/test-helpers'; import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage'; import hbs from 'htmlbars-inline-precompile'; import moment from 'moment'; @@ -25,7 +24,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) { {{reschedule-event-timeline allocation=allocation}} `; - test('when the allocation is running, the timeline shows past allocations', function(assert) { + test('when the allocation is running, the timeline shows past allocations', async function(assert) { const attempts = 2; this.server.create('allocation', 'rescheduled', { @@ -33,53 +32,46 @@ module('Integration | Component | reschedule event timeline', function(hooks) { rescheduleSuccess: true, }); - this.store.findAll('allocation'); - let allocation; + await this.store.findAll('allocation'); - return settled() - .then(async () => { - allocation = this.store - .peekAll('allocation') - .find(alloc => !alloc.get('nextAllocation.content')); + const allocation = this.store + .peekAll('allocation') + .find(alloc => !alloc.get('nextAllocation.content')); - this.set('allocation', allocation); - await render(commonTemplate); + this.set('allocation', allocation); + await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.equal( - findAll('[data-test-allocation]').length, - attempts + 1, - 'Total allocations equals current allocation plus all past allocations' - ); - assert.equal( - find('[data-test-allocation]'), - find(`[data-test-allocation="${allocation.id}"]`), - 'First allocation is the current allocation' - ); + assert.equal( + findAll('[data-test-allocation]').length, + attempts + 1, + 'Total allocations equals current allocation plus all past allocations' + ); + assert.equal( + find('[data-test-allocation]'), + find(`[data-test-allocation="${allocation.id}"]`), + 'First allocation is the current allocation' + ); - assert.notOk(find('[data-test-stop-warning]'), 'No stop warning'); - assert.notOk(find('[data-test-attempt-notice]'), 'No attempt notice'); + assert.notOk(find('[data-test-stop-warning]'), 'No stop warning'); + assert.notOk(find('[data-test-attempt-notice]'), 'No attempt notice'); - assert.equal( - find( - `[data-test-allocation="${allocation.id}"] [data-test-allocation-link]` - ).textContent.trim(), - allocation.get('shortId'), - 'The "this" allocation is correct' - ); - assert.equal( - find( - `[data-test-allocation="${allocation.id}"] [data-test-allocation-status]` - ).textContent.trim(), - allocation.get('clientStatus'), - 'Allocation shows the status' - ); - }); + assert.equal( + find( + `[data-test-allocation="${allocation.id}"] [data-test-allocation-link]` + ).textContent.trim(), + allocation.get('shortId'), + 'The "this" allocation is correct' + ); + assert.equal( + find( + `[data-test-allocation="${allocation.id}"] [data-test-allocation-status]` + ).textContent.trim(), + allocation.get('clientStatus'), + 'Allocation shows the status' + ); }); - test('when the allocation has failed and there is a follow up evaluation, a note with a time is shown', function(assert) { + test('when the allocation has failed and there is a follow up evaluation, a note with a time is shown', async function(assert) { const attempts = 2; this.server.create('allocation', 'rescheduled', { @@ -87,27 +79,20 @@ module('Integration | Component | reschedule event timeline', function(hooks) { rescheduleSuccess: false, }); - this.store.findAll('allocation'); - let allocation; + await this.store.findAll('allocation'); - return settled() - .then(async () => { - allocation = this.store - .peekAll('allocation') - .find(alloc => !alloc.get('nextAllocation.content')); + const allocation = this.store + .peekAll('allocation') + .find(alloc => !alloc.get('nextAllocation.content')); - this.set('allocation', allocation); - await render(commonTemplate); + this.set('allocation', allocation); + await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - find('[data-test-stop-warning]'), - 'Stop warning is shown since the last allocation failed' - ); - assert.notOk(find('[data-test-attempt-notice]'), 'Reschdule attempt notice is not shown'); - }); + assert.ok( + find('[data-test-stop-warning]'), + 'Stop warning is shown since the last allocation failed' + ); + assert.notOk(find('[data-test-attempt-notice]'), 'Reschdule attempt notice is not shown'); }); test('when the allocation has failed and there is no follow up evaluation, a warning is shown', async function(assert) { @@ -128,7 +113,6 @@ module('Integration | Component | reschedule event timeline', function(hooks) { }); await this.store.findAll('allocation'); - await settled(); let allocation = this.store .peekAll('allocation') @@ -136,7 +120,6 @@ module('Integration | Component | reschedule event timeline', function(hooks) { this.set('allocation', allocation); await render(commonTemplate); - await settled(); assert.ok( find('[data-test-attempt-notice]'), @@ -145,7 +128,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) { assert.notOk(find('[data-test-stop-warning]'), 'Stop warning is not shown'); }); - test('when the allocation has a next allocation already, it is shown in the timeline', function(assert) { + test('when the allocation has a next allocation already, it is shown in the timeline', async function(assert) { const attempts = 2; const originalAllocation = this.server.create('allocation', 'rescheduled', { @@ -153,39 +136,32 @@ module('Integration | Component | reschedule event timeline', function(hooks) { rescheduleSuccess: true, }); - this.store.findAll('allocation'); - let allocation; + await this.store.findAll('allocation'); - return settled() - .then(async () => { - allocation = this.store.peekAll('allocation').findBy('id', originalAllocation.id); + const allocation = this.store.peekAll('allocation').findBy('id', originalAllocation.id); - this.set('allocation', allocation); - await render(commonTemplate); + this.set('allocation', allocation); + await render(commonTemplate); - return settled(); - }) - .then(() => { - assert.ok( - find('[data-test-reschedule-label]').textContent.trim(), - 'Next Allocation', - 'The first allocation is the next allocation and labeled as such' - ); + assert.ok( + find('[data-test-reschedule-label]').textContent.trim(), + 'Next Allocation', + 'The first allocation is the next allocation and labeled as such' + ); - assert.equal( - find('[data-test-allocation] [data-test-allocation-link]').textContent.trim(), - allocation.get('nextAllocation.shortId'), - 'The next allocation item is for the correct allocation' - ); + assert.equal( + find('[data-test-allocation] [data-test-allocation-link]').textContent.trim(), + allocation.get('nextAllocation.shortId'), + 'The next allocation item is for the correct allocation' + ); - assert.equal( - findAll('[data-test-allocation]')[1], - find(`[data-test-allocation="${allocation.id}"]`), - 'Second allocation is the current allocation' - ); + assert.equal( + findAll('[data-test-allocation]')[1], + find(`[data-test-allocation="${allocation.id}"]`), + 'Second allocation is the current allocation' + ); - assert.notOk(find('[data-test-stop-warning]'), 'No stop warning'); - assert.notOk(find('[data-test-attempt-notice]'), 'No attempt notice'); - }); + assert.notOk(find('[data-test-stop-warning]'), 'No stop warning'); + assert.notOk(find('[data-test-attempt-notice]'), 'No attempt notice'); }); }); diff --git a/ui/tests/integration/task-log-test.js b/ui/tests/integration/task-log-test.js index b2d17209d..4f2474cae 100644 --- a/ui/tests/integration/task-log-test.js +++ b/ui/tests/integration/task-log-test.js @@ -1,8 +1,7 @@ import { run } from '@ember/runloop'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; -import { find, click } from 'ember-native-dom-helpers'; +import { find, click, render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import Pretender from 'pretender'; import { logEncode } from '../../mirage/data/logs'; diff --git a/ui/tests/integration/two-step-button-test.js b/ui/tests/integration/two-step-button-test.js index 370eec266..7e81afc3e 100644 --- a/ui/tests/integration/two-step-button-test.js +++ b/ui/tests/integration/two-step-button-test.js @@ -1,7 +1,6 @@ -import { find, click } from 'ember-native-dom-helpers'; +import { find, click, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; -import { render, settled } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; import { create } from 'ember-cli-page-object'; @@ -53,23 +52,21 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); + await TwoStepButton.idle(); - return settled().then(() => { - assert.ok(find('[data-test-cancel-button]'), 'Cancel button is rendered'); - assert.equal(TwoStepButton.cancelText, props.cancelText, 'Button is labeled correctly'); + assert.ok(find('[data-test-cancel-button]'), 'Cancel button is rendered'); + assert.equal(TwoStepButton.cancelText, props.cancelText, 'Button is labeled correctly'); - assert.ok(find('[data-test-confirm-button]'), 'Confirm button is rendered'); - assert.equal(TwoStepButton.confirmText, props.confirmText, 'Button is labeled correctly'); + assert.ok(find('[data-test-confirm-button]'), 'Confirm button is rendered'); + assert.equal(TwoStepButton.confirmText, props.confirmText, 'Button is labeled correctly'); - assert.equal( - TwoStepButton.confirmationMessage, - props.confirmationMessage, - 'Confirmation message is shown' - ); + assert.equal( + TwoStepButton.confirmationMessage, + props.confirmationMessage, + 'Confirmation message is shown' + ); - assert.notOk(find('[data-test-idle-button]'), 'No more idle button'); - }); + assert.notOk(find('[data-test-idle-button]'), 'No more idle button'); }); test('canceling in the promptForConfirmation state calls the onCancel hook and resets to the idle state', async function(assert) { @@ -77,16 +74,12 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); + await TwoStepButton.idle(); - return settled().then(() => { - TwoStepButton.cancel(); + await TwoStepButton.cancel(); - return settled().then(() => { - assert.ok(props.onCancel.calledOnce, 'The onCancel hook fired'); - assert.ok(find('[data-test-idle-button]'), 'Idle button is back'); - }); - }); + assert.ok(props.onCancel.calledOnce, 'The onCancel hook fired'); + assert.ok(find('[data-test-idle-button]'), 'Idle button is back'); }); test('confirming the promptForConfirmation state calls the onConfirm hook and resets to the idle state', async function(assert) { @@ -94,16 +87,12 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); + await TwoStepButton.idle(); - return settled().then(() => { - TwoStepButton.confirm(); + await TwoStepButton.confirm(); - return settled().then(() => { - assert.ok(props.onConfirm.calledOnce, 'The onConfirm hook fired'); - assert.ok(find('[data-test-idle-button]'), 'Idle button is back'); - }); - }); + assert.ok(props.onConfirm.calledOnce, 'The onConfirm hook fired'); + assert.ok(find('[data-test-idle-button]'), 'Idle button is back'); }); test('when awaitingConfirmation is true, the cancel and submit buttons are disabled and the submit button is loading', async function(assert) { @@ -112,13 +101,11 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); + await TwoStepButton.idle(); - return settled().then(() => { - assert.ok(TwoStepButton.cancelIsDisabled, 'The cancel button is disabled'); - assert.ok(TwoStepButton.confirmIsDisabled, 'The confirm button is disabled'); - assert.ok(TwoStepButton.isRunning, 'The confirm button is in a loading state'); - }); + assert.ok(TwoStepButton.cancelIsDisabled, 'The cancel button is disabled'); + assert.ok(TwoStepButton.confirmIsDisabled, 'The confirm button is disabled'); + assert.ok(TwoStepButton.isRunning, 'The confirm button is in a loading state'); }); test('when in the prompt state, clicking outside will reset state back to idle', async function(assert) { @@ -126,13 +113,11 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); - await settled(); + await TwoStepButton.idle(); assert.ok(find('[data-test-cancel-button]'), 'In the prompt state'); - click(document.body); - await settled(); + await click(document.body); assert.ok(find('[data-test-idle-button]'), 'Back in the idle state'); }); @@ -142,13 +127,11 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); - await settled(); + await TwoStepButton.idle(); assert.ok(find('[data-test-cancel-button]'), 'In the prompt state'); - click('[data-test-confirmation-message]'); - await settled(); + await click('[data-test-confirmation-message]'); assert.notOk(find('[data-test-idle-button]'), 'Still in the prompt state'); }); @@ -159,13 +142,11 @@ module('Integration | Component | two step button', function(hooks) { this.setProperties(props); await render(commonTemplate); - TwoStepButton.idle(); - await settled(); + await TwoStepButton.idle(); assert.ok(find('[data-test-cancel-button]'), 'In the prompt state'); - click(document.body); - await settled(); + await click(document.body); assert.notOk(find('[data-test-idle-button]'), 'Still in the prompt state'); }); @@ -178,7 +159,7 @@ module('Integration | Component | two step button', function(hooks) { assert.ok(TwoStepButton.isDisabled, 'The idle button is disabled'); - TwoStepButton.idle(); + await TwoStepButton.idle(); assert.ok(find('[data-test-idle-button]'), 'Still in the idle state after clicking'); }); }); diff --git a/ui/yarn.lock b/ui/yarn.lock index c73e49ba9..f513bdaa9 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -4824,7 +4824,7 @@ ember-moment@^7.8.1: ember-getowner-polyfill "^2.2.0" ember-macro-helpers "^2.1.0" -ember-native-dom-helpers@^0.5.3, ember-native-dom-helpers@^0.5.4: +ember-native-dom-helpers@^0.5.3: version "0.5.10" resolved "https://registry.yarnpkg.com/ember-native-dom-helpers/-/ember-native-dom-helpers-0.5.10.tgz#9c7172e4ddfa5dd86830c46a936e2f8eca3e5896" integrity sha512-bPJX49vlgnBGwFn/3WJPPJjjyd7/atvzW5j01u1dbyFf3bXvHg9Rs1qaZJdk8js0qZ1FINadIEC9vWtgN3w7tg==