Merge pull request #3280 from hashicorp/b-ui-links-in-tables

Links in table rows should get click priority over table rows
This commit is contained in:
Michael Lange 2017-09-29 09:37:18 -07:00 committed by GitHub
commit c9220969f9
24 changed files with 364 additions and 254 deletions

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { lazyClick } from '../helpers/lazy-click';
const { Component } = Ember;
@ -15,6 +16,6 @@ export default Component.extend({
onClick() {},
click(event) {
this.get('onClick')(event);
lazyClick([this.get('onClick'), event]);
},
});

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { lazyClick } from '../helpers/lazy-click';
const { Component } = Ember;
@ -11,7 +12,7 @@ export default Component.extend({
onClick() {},
click(event) {
this.get('onClick')(event);
lazyClick([this.get('onClick'), event]);
},
didReceiveAttrs() {

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { lazyClick } from '../helpers/lazy-click';
const { Component } = Ember;
@ -11,7 +12,7 @@ export default Component.extend({
onClick() {},
click(event) {
this.get('onClick')(event);
lazyClick([this.get('onClick'), event]);
},
didReceiveAttrs() {

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { lazyClick } from '../helpers/lazy-click';
const { Component, inject, computed } = Ember;
@ -28,6 +29,7 @@ export default Component.extend({
}),
click() {
this.get('router').transitionTo('servers.server', this.get('agent'));
const transition = () => this.get('router').transitionTo('servers.server', this.get('agent'));
lazyClick([transition, event]);
},
});

View File

@ -1,4 +1,5 @@
import Ember from 'ember';
import { lazyClick } from '../helpers/lazy-click';
const { Component } = Ember;
@ -12,6 +13,6 @@ export default Component.extend({
onClick() {},
click(event) {
this.get('onClick')(event);
lazyClick([this.get('onClick'), event]);
},
});

View File

@ -0,0 +1,19 @@
import Ember from 'ember';
const { Helper, $ } = Ember;
/**
* Lazy Click Event
*
* Usage: {{lazy-click action}}
*
* Calls the provided action only if the target isn't an anchor
* that should be handled instead.
*/
export function lazyClick([onClick, event]) {
if (!$(event.target).is('a')) {
onClick(event);
}
}
export default Helper.helper(lazyClick);

View File

@ -69,7 +69,7 @@
Attributes
</div>
<div class="boxed-section-body is-full-bleed">
{{attributes-table attributes=model.attributes.attributesStructured}}
{{attributes-table attributes=model.attributes.attributesStructured class="attributes-table"}}
</div>
</div>
</section>

View File

@ -59,6 +59,7 @@
"ember-href-to": "^1.13.0",
"ember-load-initializers": "^1.0.0",
"ember-moment": "^7.3.1",
"ember-native-dom-helpers": "^0.5.4",
"ember-resolver": "^4.0.0",
"ember-sinon": "^0.7.0",
"ember-source": "~2.14.0",

View File

@ -1,7 +1,11 @@
import Ember from 'ember';
import { click, findAll, currentURL, find, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
import moment from 'moment';
const { $ } = Ember;
let job;
let node;
let allocation;
@ -23,32 +27,27 @@ moduleForAcceptance('Acceptance | allocation detail', {
test('/allocation/:id should name the allocation and link to the corresponding job and node', function(
assert
) {
assert.ok(find('h1').textContent.includes(allocation.name), 'Allocation name is in the heading');
assert.ok(find('h3').textContent.includes(job.name), 'Job name is in the subheading');
assert.ok(
find('h1')
.text()
.includes(allocation.name),
'Allocation name is in the heading'
);
assert.ok(
find('h3')
.text()
.includes(job.name),
'Job name is in the subheading'
);
assert.ok(
find('h3')
.text()
.includes(node.id.split('-')[0]),
find('h3').textContent.includes(node.id.split('-')[0]),
'Node short id is in the subheading'
);
click('h3 a:eq(0)');
andThen(() => {
click(findAll('h3 a')[0]);
});
andThen(() => {
assert.equal(currentURL(), `/jobs/${job.id}`, 'Job link navigates to the job');
});
visit(`/allocations/${allocation.id}`);
click('h3 a:eq(1)');
andThen(() => {
click(findAll('h3 a')[1]);
});
andThen(() => {
assert.equal(currentURL(), `/nodes/${node.id}`, 'Node link navigates to the node');
});
@ -56,7 +55,7 @@ test('/allocation/:id should name the allocation and link to the corresponding j
test('/allocation/:id should list all tasks for the allocation', function(assert) {
assert.equal(
find('.tasks tbody tr').length,
findAll('.tasks tbody tr').length,
server.db.taskStates.where({ allocationId: allocation.id }).length,
'Table lists all tasks'
);
@ -68,7 +67,7 @@ test('each task row should list high-level information for the task', function(a
.map(id => server.db.taskResources.find(id))
.sortBy('name')[0];
const reservedPorts = taskResources.resources.Networks[0].ReservedPorts;
const taskRow = find('.tasks tbody tr:eq(0)');
const taskRow = $(findAll('.tasks tbody tr')[0]);
const events = server.db.taskEvents.where({ taskStateId: task.id });
const event = events[events.length - 1];
@ -117,7 +116,7 @@ test('each task row should list high-level information for the task', function(a
test('/allocation/:id should list recent events for each task', function(assert) {
const tasks = server.db.taskStates.where({ allocationId: allocation.id });
assert.equal(
find('.task-state-events').length,
findAll('.task-state-events').length,
tasks.length,
'A task state event block per task'
);
@ -127,7 +126,7 @@ test('each recent events list should include the name, state, and time info for
assert
) {
const task = server.db.taskStates.where({ allocationId: allocation.id })[0];
const recentEventsSection = find('.task-state-events:eq(0)');
const recentEventsSection = $(findAll('.task-state-events')[0]);
const heading = recentEventsSection
.find('.message-header')
.text()
@ -146,7 +145,7 @@ test('each recent events list should list all recent events for the task', funct
const events = server.db.taskEvents.where({ taskStateId: task.id });
assert.equal(
find('.task-state-events:eq(0) .task-events tbody tr').length,
findAll('.task-state-events')[0].querySelectorAll('.task-events tbody tr').length,
events.length,
`Lists ${events.length} events`
);
@ -157,7 +156,7 @@ test('each recent event should list the time, type, and description of the event
) {
const task = server.db.taskStates.where({ allocationId: allocation.id })[0];
const event = server.db.taskEvents.where({ taskStateId: task.id })[0];
const recentEvent = find('.task-state-events:eq(0) .task-events tbody tr:last');
const recentEvent = $('.task-state-events:eq(0) .task-events tbody tr:last');
assert.equal(
recentEvent

View File

@ -1,6 +1,10 @@
import Ember from 'ember';
import { click, find, findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { $ } = Ember;
let node;
moduleForAcceptance('Acceptance | client detail', {
@ -18,52 +22,45 @@ moduleForAcceptance('Acceptance | client detail', {
});
test('/nodes/:id should have a breadrcumb trail linking back to nodes', function(assert) {
assert.equal(find('.breadcrumb:eq(0)').text(), 'Nodes', 'First breadcrumb says nodes');
assert.equal(findAll('.breadcrumb')[0].textContent, 'Nodes', 'First breadcrumb says nodes');
assert.equal(
find('.breadcrumb:eq(1)').text(),
findAll('.breadcrumb')[1].textContent,
node.id.split('-')[0],
'Second breadcrumb says the node short id'
);
click('.breadcrumb:eq(0)');
click(findAll('.breadcrumb')[0]);
andThen(() => {
assert.equal(currentURL(), '/nodes', 'First breadcrumb links back to nodes');
});
});
test('/nodes/:id should list immediate details for the node in the title', function(assert) {
assert.ok(find('.title').textContent.includes(node.name), 'Title includes name');
assert.ok(find('.title').textContent.includes(node.id), 'Title includes id');
assert.ok(
find('.title')
.text()
.includes(node.name),
'Title includes name'
findAll(`.title .node-status-light.${node.status}`).length,
'Title includes status light'
);
assert.ok(
find('.title')
.text()
.includes(node.id),
'Title includes id'
);
assert.ok(find(`.title .node-status-light.${node.status}`).length, 'Title includes status light');
});
test('/nodes/:id should list additional detail for the node below the title', function(assert) {
assert.equal(
find('.inline-definitions .pair:eq(0)').text(),
findAll('.inline-definitions .pair')[0].textContent,
`Status ${node.status}`,
'Status is in additional details'
);
assert.ok(
find('.inline-definitions .pair:eq(0) .status-text').hasClass(`node-${node.status}`),
$('.inline-definitions .pair:eq(0) .status-text').hasClass(`node-${node.status}`),
'Status is decorated with a status class'
);
assert.equal(
find('.inline-definitions .pair:eq(1)').text(),
findAll('.inline-definitions .pair')[1].textContent,
`Address ${node.httpAddr}`,
'Address is in additional detals'
);
assert.equal(
find('.inline-definitions .pair:eq(2)').text(),
findAll('.inline-definitions .pair')[2].textContent,
`Datacenter ${node.datacenter}`,
'Datacenter is in additional details'
);
@ -72,14 +69,14 @@ test('/nodes/:id should list additional detail for the node below the title', fu
test('/nodes/:id should list all allocations on the node', function(assert) {
const allocationsCount = server.db.allocations.where({ nodeId: node.id }).length;
assert.equal(
find('.allocations tbody tr').length,
findAll('.allocations tbody tr').length,
allocationsCount,
`Allocations table lists all ${allocationsCount} associated allocations`
);
});
test('each allocation should have high-level details for the allocation', function(assert) {
const allocationRow = find('.allocations tbody tr:eq(0)');
const allocationRow = $(findAll('.allocations tbody tr')[0]);
const allocation = server.db.allocations
.where({ nodeId: node.id })
.sortBy('modifyIndex')
@ -156,7 +153,7 @@ test('each allocation should link to the allocation detail page', function(asser
.sortBy('modifyIndex')
.reverse()[0];
click('.allocations tbody tr:eq(0) td:eq(0) a');
click($('.allocations tbody tr:eq(0) td:eq(0) a').get(0));
andThen(() => {
assert.equal(
@ -170,7 +167,7 @@ test('each allocation should link to the allocation detail page', function(asser
test('each allocation should link to the job the allocation belongs to', function(assert) {
const allocation = server.db.allocations.where({ nodeId: node.id })[0];
const job = server.db.jobs.find(allocation.jobId);
click('.allocations tbody tr:eq(0) td:eq(3) a');
click($('.allocations tbody tr:eq(0) td:eq(3) a').get(0));
andThen(() => {
assert.equal(

View File

@ -1,9 +1,10 @@
import { findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
let job;
moduleForAcceptance('Acceptance | job detail', {
moduleForAcceptance('Acceptance | job definition', {
beforeEach() {
server.create('node');
server.create('job');
@ -17,7 +18,7 @@ test('visiting /jobs/:job_id/definition', function(assert) {
});
test('the job definition page contains a json viewer component', function(assert) {
assert.ok(find('.json-viewer').length, 'JSON viewer found');
assert.ok(findAll('.json-viewer').length, 'JSON viewer found');
});
test('the job definition page requests the job to display in an unmutated form', function(assert) {

View File

@ -1,9 +1,10 @@
import { click, findAll, find, visit } from 'ember-native-dom-helpers';
import Ember from 'ember';
import { test } from 'qunit';
import moment from 'moment';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { get } = Ember;
const { get, $ } = Ember;
const sum = (list, key) => list.reduce((sum, item) => sum + get(item, key), 0);
let job;
@ -32,7 +33,7 @@ test('/jobs/:id/deployments should list all job deployments', function(assert) {
visit(`/jobs/${job.id}/deployments`);
andThen(() => {
assert.ok(
find('.timeline-object').length,
findAll('.timeline-object').length,
deployments.length,
'Each deployment gets a row in the timeline'
);
@ -50,7 +51,7 @@ test('each deployment mentions the deployment shortId, status, version, and time
jobId: deployment.jobId,
version: deployment.versionNumber,
});
const deploymentRow = find('.timeline-object:eq(0)');
const deploymentRow = $(findAll('.timeline-object')[0]);
assert.ok(deploymentRow.text().includes(deployment.id.split('-')[0]), 'Short ID');
assert.equal(deploymentRow.find('.tag').text(), deployment.status, 'Status');
@ -89,7 +90,7 @@ test('when the deployment is running and needs promotion, the deployment item sa
visit(`/jobs/${job.id}/deployments`);
andThen(() => {
const deploymentRow = find('.timeline-object:eq(0)');
const deploymentRow = $(findAll('.timeline-object')[0]);
assert.ok(
deploymentRow.find('.badge:contains("Requires Promotion")').length,
'Requires Promotion badge found'
@ -103,11 +104,11 @@ test('each deployment item can be opened to show details', function(assert) {
visit(`/jobs/${job.id}/deployments`);
andThen(() => {
deploymentRow = find('.timeline-object:eq(0)');
deploymentRow = $(findAll('.timeline-object')[0]);
assert.ok(deploymentRow.find('.boxed-section-body').length === 0, 'No deployment body');
click(deploymentRow.find('button'));
click(deploymentRow.find('button').get(0));
andThen(() => {
assert.ok(deploymentRow.find('.boxed-section-body').length, 'Deployment body found');
@ -120,18 +121,18 @@ test('when open, a deployment shows the deployment metrics', function(assert) {
andThen(() => {
const deployment = sortedDeployments.models[0];
const deploymentRow = find('.timeline-object:eq(0)');
const deploymentRow = $(findAll('.timeline-object')[0]);
const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(id =>
server.db.deploymentTaskGroupSummaries.find(id)
);
click(deploymentRow.find('button'));
click(deploymentRow.find('button').get(0));
andThen(() => {
assert.equal(
find('.deployment-metrics .label:contains("Canaries") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Canaries") + .value')
.get(0)
.textContent.trim(),
`${sum(taskGroupSummaries, 'placedCanaries')} / ${sum(
taskGroupSummaries,
'desiredCanaries'
@ -140,41 +141,39 @@ test('when open, a deployment shows the deployment metrics', function(assert) {
);
assert.equal(
find('.deployment-metrics .label:contains("Placed") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Placed") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'placedAllocs'),
'Placed allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Desired") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Desired") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'desiredTotal'),
'Desired allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Healthy") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Healthy") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'healthyAllocs'),
'Healthy allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Unhealthy") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Unhealthy") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'unhealthyAllocs'),
'Unhealthy allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .notification')
.text()
.trim(),
find('.deployment-metrics .notification').textContent.trim(),
deployment.statusDescription,
'Status description is in the metrics block'
);
@ -189,12 +188,12 @@ test('when open, a deployment shows a list of all task groups and their respecti
andThen(() => {
const deployment = sortedDeployments.models[0];
const deploymentRow = find('.timeline-object:eq(0)');
const deploymentRow = $(findAll('.timeline-object')[0]);
const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(id =>
server.db.deploymentTaskGroupSummaries.find(id)
);
click(deploymentRow.find('button'));
click(deploymentRow.find('button').get(0));
andThen(() => {
assert.ok(
@ -282,13 +281,13 @@ test('when open, a deployment shows a list of all allocations for the deployment
andThen(() => {
const deployment = sortedDeployments.models[0];
const deploymentRow = find('.timeline-object:eq(0)');
const deploymentRow = $(findAll('.timeline-object')[0]);
// TODO: Make this less brittle. This logic is copied from the mirage config,
// since there is no reference to allocations on the deployment model.
const allocations = server.db.allocations.where({ jobId: deployment.jobId }).slice(0, 3);
click(deploymentRow.find('button'));
click(deploymentRow.find('button').get(0));
andThen(() => {
assert.ok(

View File

@ -1,9 +1,10 @@
import { click, findAll, currentURL, find, visit } from 'ember-native-dom-helpers';
import Ember from 'ember';
import moment from 'moment';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { get } = Ember;
const { get, $ } = Ember;
const sum = (list, key) => list.reduce((sum, item) => sum + get(item, key), 0);
let job;
@ -22,39 +23,28 @@ test('visiting /jobs/:job_id', function(assert) {
});
test('breadcrumbs includes job name and link back to the jobs list', function(assert) {
assert.equal(find('.breadcrumb:eq(0)').text(), 'Jobs', 'First breadcrumb says jobs');
assert.equal(find('.breadcrumb:eq(1)').text(), job.name, 'Second breadcrumb says the job name');
assert.equal(findAll('.breadcrumb')[0].textContent, 'Jobs', 'First breadcrumb says jobs');
assert.equal(
findAll('.breadcrumb')[1].textContent,
job.name,
'Second breadcrumb says the job name'
);
click('.breadcrumb:eq(0)');
click(findAll('.breadcrumb')[0]);
andThen(() => {
assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs');
});
});
test('the job detail page should contain basic information about the job', function(assert) {
assert.ok(
find('.title .tag:eq(0)')
.text()
.includes(job.status),
'Status'
);
assert.ok(
find('.job-stats span:eq(0)')
.text()
.includes(job.type),
'Type'
);
assert.ok(
find('.job-stats span:eq(1)')
.text()
.includes(job.priority),
'Priority'
);
assert.ok(findAll('.title .tag')[0].textContent.includes(job.status), 'Status');
assert.ok(findAll('.job-stats span')[0].textContent.includes(job.type), 'Type');
assert.ok(findAll('.job-stats span')[1].textContent.includes(job.priority), 'Priority');
});
test('the job detail page should list all task groups', function(assert) {
assert.equal(
find('.task-group-row').length,
findAll('.task-group-row').length,
server.db.taskGroups.where({ jobId: job.id }).length
);
});
@ -63,7 +53,7 @@ test('each row in the task group table should show basic information about the t
assert
) {
const taskGroup = job.taskGroupIds.map(id => server.db.taskGroups.find(id)).sortBy('name')[0];
const taskGroupRow = find('.task-group-row:eq(0)');
const taskGroupRow = $(findAll('.task-group-row')[0]);
const tasks = server.db.tasks.where({ taskGroupId: taskGroup.id });
const sum = (list, key) => list.reduce((sum, item) => sum + get(item, key), 0);
@ -104,37 +94,37 @@ test('the allocations diagram lists all allocation status figures', function(ass
);
assert.equal(
legend.find('li.queued .value').text(),
legend.querySelector('li.queued .value').textContent,
statusCounts.queued,
`${statusCounts.queued} are queued`
);
assert.equal(
legend.find('li.starting .value').text(),
legend.querySelector('li.starting .value').textContent,
statusCounts.starting,
`${statusCounts.starting} are starting`
);
assert.equal(
legend.find('li.running .value').text(),
legend.querySelector('li.running .value').textContent,
statusCounts.running,
`${statusCounts.running} are running`
);
assert.equal(
legend.find('li.complete .value').text(),
legend.querySelector('li.complete .value').textContent,
statusCounts.complete,
`${statusCounts.complete} are complete`
);
assert.equal(
legend.find('li.failed .value').text(),
legend.querySelector('li.failed .value').textContent,
statusCounts.failed,
`${statusCounts.failed} are failed`
);
assert.equal(
legend.find('li.lost .value').text(),
legend.querySelector('li.lost .value').textContent,
statusCounts.lost,
`${statusCounts.lost} are lost`
);
@ -149,7 +139,7 @@ test('there is no active deployment section when the job has no active deploymen
visit(`/jobs/${job.id}`);
andThen(() => {
assert.ok(find('.active-deployment').length === 0, 'No active deployment');
assert.ok(findAll('.active-deployment').length === 0, 'No active deployment');
});
});
@ -168,27 +158,27 @@ test('the active deployment section shows up for the currently running deploymen
visit(`/jobs/${job.id}`);
andThen(() => {
assert.ok(find('.active-deployment').length === 1, 'Active deployment');
assert.ok(findAll('.active-deployment').length === 1, 'Active deployment');
assert.equal(
find('.active-deployment > .boxed-section-head .badge')
.text()
.trim(),
$('.active-deployment > .boxed-section-head .badge')
.get(0)
.textContent.trim(),
deployment.id.split('-')[0],
'The active deployment is the most recent running deployment'
);
assert.equal(
find('.active-deployment > .boxed-section-head .submit-time')
.text()
.trim(),
$('.active-deployment > .boxed-section-head .submit-time')
.get(0)
.textContent.trim(),
moment(version.submitTime / 1000000).fromNow(),
'Time since the job was submitted is in the active deployment header'
);
assert.equal(
find('.deployment-metrics .label:contains("Canaries") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Canaries") + .value')
.get(0)
.textContent.trim(),
`${sum(taskGroupSummaries, 'placedCanaries')} / ${sum(
taskGroupSummaries,
'desiredCanaries'
@ -197,41 +187,41 @@ test('the active deployment section shows up for the currently running deploymen
);
assert.equal(
find('.deployment-metrics .label:contains("Placed") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Placed") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'placedAllocs'),
'Placed allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Desired") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Desired") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'desiredTotal'),
'Desired allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Healthy") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Healthy") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'healthyAllocs'),
'Healthy allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .label:contains("Unhealthy") + .value')
.text()
.trim(),
$('.deployment-metrics .label:contains("Unhealthy") + .value')
.get(0)
.textContent.trim(),
sum(taskGroupSummaries, 'unhealthyAllocs'),
'Unhealthy allocs aggregates across task groups'
);
assert.equal(
find('.deployment-metrics .notification')
.text()
.trim(),
$('.deployment-metrics .notification')
.get(0)
.textContent.trim(),
deployment.statusDescription,
'Status description is in the metrics block'
);
@ -246,24 +236,26 @@ test('the active deployment section can be expanded to show task groups and allo
andThen(() => {
assert.ok(
find('.active-deployment .boxed-section-head:contains("Task Groups")').length === 0,
$('.active-deployment .boxed-section-head:contains("Task Groups")').length === 0,
'Task groups not found'
);
assert.ok(
find('.active-deployment .boxed-section-head:contains("Allocations")').length === 0,
$('.active-deployment .boxed-section-head:contains("Allocations")').length === 0,
'Allocations not found'
);
});
click('.active-deployment-details-toggle');
andThen(() => {
click('.active-deployment-details-toggle');
});
andThen(() => {
assert.ok(
find('.active-deployment .boxed-section-head:contains("Task Groups")').length === 1,
$('.active-deployment .boxed-section-head:contains("Task Groups")').length === 1,
'Task groups found'
);
assert.ok(
find('.active-deployment .boxed-section-head:contains("Allocations")').length === 1,
$('.active-deployment .boxed-section-head:contains("Allocations")').length === 1,
'Allocations found'
);
});

View File

@ -1,7 +1,11 @@
import Ember from 'ember';
import { findAll, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
import moment from 'moment';
const { $ } = Ember;
let job;
let versions;
@ -16,7 +20,7 @@ moduleForAcceptance('Acceptance | job versions', {
test('/jobs/:id/versions should list all job versions', function(assert) {
assert.ok(
find('.timeline-object').length,
findAll('.timeline-object').length,
versions.length,
'Each version gets a row in the timeline'
);
@ -26,7 +30,7 @@ test('each version mentions the version number, the stability, and the submitted
assert
) {
const version = versions.sortBy('submitTime').reverse()[0];
const versionRow = find('.timeline-object:eq(0)');
const versionRow = $(findAll('.timeline-object')[0]);
assert.ok(versionRow.text().includes(`Version #${version.version}`), 'Version #');
assert.equal(

View File

@ -1,6 +1,10 @@
import Ember from 'ember';
import { click, findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { $ } = Ember;
moduleForAcceptance('Acceptance | jobs list', {
beforeEach() {
// Required for placing allocations (a result of creating jobs)
@ -25,10 +29,10 @@ test('/jobs should list the first page of jobs sorted by modify index', function
andThen(() => {
const sortedJobs = server.db.jobs.sortBy('modifyIndex').reverse();
assert.equal(find('.job-row').length, pageSize);
assert.equal(findAll('.job-row').length, pageSize);
for (var jobNumber = 0; jobNumber < pageSize; jobNumber++) {
assert.equal(
find(`.job-row:eq(${jobNumber}) td:eq(0)`).text(),
$(`.job-row:eq(${jobNumber}) td:eq(0)`).text(),
sortedJobs[jobNumber].name,
'Jobs are ordered'
);
@ -44,11 +48,18 @@ test('each job row should contain information about the job', function(assert) {
visit('/jobs');
andThen(() => {
const jobRow = find('.job-row:eq(0)');
const jobRow = $(findAll('.job-row')[0]);
assert.equal(jobRow.find('td:eq(0)').text(), job.name, 'Name');
assert.equal(jobRow.find('td:eq(0) a').attr('href'), `/ui/jobs/${job.id}`, 'Detail Link');
assert.equal(jobRow.find('td:eq(1)').text().trim(), job.status, 'Status');
assert.equal(
jobRow
.find('td:eq(1)')
.text()
.trim(),
job.status,
'Status'
);
assert.equal(jobRow.find('td:eq(2)').text(), job.type, 'Type');
assert.equal(jobRow.find('td:eq(3)').text(), job.priority, 'Priority');
assert.equal(jobRow.find('td:eq(4)').text(), taskGroups.length, '# Groups');
@ -60,7 +71,10 @@ test('each job row should link to the corresponding job', function(assert) {
const job = server.db.jobs[0];
visit('/jobs');
click('.job-row:eq(0) td:eq(0) a');
andThen(() => {
click($('.job-row:eq(0) td:eq(0) a').get(0));
});
andThen(() => {
assert.equal(currentURL(), `/jobs/${job.id}`);

View File

@ -1,8 +1,12 @@
import Ember from 'ember';
import { click, findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
import { findLeader } from '../../mirage/config';
import ipParts from 'nomad-ui/utils/ip-parts';
const { $ } = Ember;
function minimumSetup() {
server.createList('node', 1);
server.createList('agent', 1);
@ -21,14 +25,14 @@ test('/nodes should list one page of clients', function(assert) {
visit('/nodes');
andThen(() => {
assert.equal(find('.client-node-row').length, pageSize);
assert.ok(find('.pagination').length, 'Pagination found on the page');
assert.equal(findAll('.client-node-row').length, pageSize);
assert.ok(findAll('.pagination').length, 'Pagination found on the page');
const sortedNodes = server.db.nodes.sortBy('modifyIndex').reverse();
for (var nodeNumber = 0; nodeNumber < pageSize; nodeNumber++) {
assert.equal(
find(`.client-node-row:eq(${nodeNumber}) td:eq(0)`).text(),
$(`.client-node-row:eq(${nodeNumber}) td:eq(0)`).text(),
sortedNodes[nodeNumber].id.split('-')[0],
'Nodes are ordered'
);
@ -43,7 +47,7 @@ test('each client record should show high-level info of the client', function(as
visit('/nodes');
andThen(() => {
const nodeRow = find('.client-node-row:eq(0)');
const nodeRow = $(findAll('.client-node-row')[0]);
const allocations = server.db.allocations.where({ nodeId: node.id });
const { address, port } = ipParts(node.httpAddr);
@ -62,7 +66,9 @@ test('each client should link to the client detail page', function(assert) {
const node = server.db.nodes[0];
visit('/nodes');
click('.client-node-row:eq(0)');
andThen(() => {
click(findAll('.client-node-row')[0]);
});
andThen(() => {
assert.equal(currentURL(), `/nodes/${node.id}`);
@ -81,7 +87,7 @@ test('/servers should list all servers', function(assert) {
visit('/servers');
andThen(() => {
assert.equal(find('.server-agent-row').length, pageSize);
assert.equal(findAll('.server-agent-row').length, pageSize);
const sortedAgents = server.db.agents
.sort((a, b) => {
@ -96,7 +102,7 @@ test('/servers should list all servers', function(assert) {
for (var agentNumber = 0; agentNumber < 8; agentNumber++) {
assert.equal(
find(`.server-agent-row:eq(${agentNumber}) td:eq(0)`).text(),
$(`.server-agent-row:eq(${agentNumber}) td:eq(0)`).text(),
sortedAgents[agentNumber].name,
'Clients are ordered'
);
@ -111,7 +117,7 @@ test('each server should show high-level info of the server', function(assert) {
visit('/servers');
andThen(() => {
const agentRow = find('.server-agent-row:eq(0)');
const agentRow = $(findAll('.server-agent-row')[0]);
assert.equal(agentRow.find('td:eq(0)').text(), agent.name, 'Name');
assert.equal(agentRow.find('td:eq(1)').text(), agent.status, 'Status');
@ -127,7 +133,9 @@ test('each server should link to the server detail page', function(assert) {
const agent = server.db.agents[0];
visit('/servers');
click('.server-agent-row:eq(0)');
andThen(() => {
click(findAll('.server-agent-row')[0]);
});
andThen(() => {
assert.equal(currentURL(), `/servers/${agent.name}`);

View File

@ -1,6 +1,10 @@
import Ember from 'ember';
import { findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { $ } = Ember;
let agent;
moduleForAcceptance('Acceptance | server detail', {
@ -18,22 +22,22 @@ test('visiting /servers/:server_name', function(assert) {
test('the server detail page should list all tags for the server', function(assert) {
const tags = agent.tags;
assert.equal(find('.server-tags tbody tr').length, Object.keys(tags).length, '# of tags');
assert.equal(findAll('.server-tags tbody tr').length, Object.keys(tags).length, '# of tags');
Object.keys(tags).forEach((key, index) => {
const row = find(`.server-tags tbody tr:eq(${index})`);
const row = $(`.server-tags tbody tr:eq(${index})`);
assert.equal(row.find('td:eq(0)').text(), key, `Label: ${key}`);
assert.equal(row.find('td:eq(1)').text(), tags[key], `Value: ${tags[key]}`);
});
});
test('the list of servers from /servers should still be present', function(assert) {
assert.equal(find('.server-agent-row').length, server.db.agents.length, '# of servers');
assert.equal(findAll('.server-agent-row').length, server.db.agents.length, '# of servers');
});
test('the active server should be denoted in the table', function(assert) {
assert.equal(find('.server-agent-row.is-active').length, 1, 'Only one active server');
assert.equal(findAll('.server-agent-row.is-active').length, 1, 'Only one active server');
assert.equal(
find('.server-agent-row.is-active td:eq(0)').text(),
findAll('.server-agent-row.is-active td')[0].textContent,
agent.name,
'Active server matches current route'
);

View File

@ -1,6 +1,10 @@
import Ember from 'ember';
import { click, findAll, currentURL, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
const { $ } = Ember;
let job;
let taskGroup;
let tasks;
@ -10,6 +14,7 @@ const sum = (total, n) => total + n;
moduleForAcceptance('Acceptance | task group detail', {
beforeEach() {
server.create('agent');
server.create('node', 'forceIPv4');
job = server.create('job', {
@ -46,39 +51,43 @@ test('/jobs/:id/:task-group should list high-level metrics for the allocation',
const totalDisk = taskGroup.ephemeralDisk.SizeMB;
assert.equal(
find('.inline-definitions .pair:eq(0)').text(),
findAll('.inline-definitions .pair')[0].textContent,
`# Tasks ${tasks.length}`,
'# Tasks'
);
assert.equal(
find('.inline-definitions .pair:eq(1)').text(),
findAll('.inline-definitions .pair')[1].textContent,
`Reserved CPU ${totalCPU} MHz`,
'Aggregated CPU reservation for all tasks'
);
assert.equal(
find('.inline-definitions .pair:eq(2)').text(),
findAll('.inline-definitions .pair')[2].textContent,
`Reserved Memory ${totalMemory} MiB`,
'Aggregated Memory reservation for all tasks'
);
assert.equal(
find('.inline-definitions .pair:eq(3)').text(),
findAll('.inline-definitions .pair')[3].textContent,
`Reserved Disk ${totalDisk} MiB`,
'Aggregated Disk reservation for all tasks'
);
});
test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', function(assert) {
assert.equal(find('.breadcrumb:eq(0)').text(), 'Jobs', 'First breadcrumb says jobs');
assert.equal(find('.breadcrumb:eq(1)').text(), job.name, 'Second breadcrumb says the job name');
assert.equal(findAll('.breadcrumb')[0].textContent, 'Jobs', 'First breadcrumb says jobs');
assert.equal(
find('.breadcrumb:eq(2)').text(),
findAll('.breadcrumb')[1].textContent,
job.name,
'Second breadcrumb says the job name'
);
assert.equal(
findAll('.breadcrumb')[2].textContent,
taskGroup.name,
'Third breadcrumb says the job name'
);
});
test('/jobs/:id/:task-group first breadcrumb should link to jobs', function(assert) {
click('.breadcrumb:eq(0)');
click(findAll('.breadcrumb')[0]);
andThen(() => {
assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs');
});
@ -87,7 +96,7 @@ test('/jobs/:id/:task-group first breadcrumb should link to jobs', function(asse
test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', function(
assert
) {
click('.breadcrumb:eq(1)');
click(findAll('.breadcrumb')[1]);
andThen(() => {
assert.equal(
currentURL(),
@ -117,7 +126,7 @@ test('/jobs/:id/:task-group should list one page of allocations for the task gro
);
assert.equal(
find('.allocations tbody tr').length,
findAll('.allocations tbody tr').length,
pageSize,
'All allocations for the task group'
);
@ -126,7 +135,7 @@ test('/jobs/:id/:task-group should list one page of allocations for the task gro
test('each allocation should show basic information about the allocation', function(assert) {
const allocation = allocations.sortBy('name')[0];
const allocationRow = find('.allocations tbody tr:eq(0)');
const allocationRow = $(findAll('.allocations tbody tr')[0]);
assert.equal(
allocationRow
@ -158,15 +167,21 @@ test('each allocation should show basic information about the allocation', funct
.text()
.trim(),
server.db.nodes.find(allocation.nodeId).id.split('-')[0],
'Node name'
'Node ID'
);
click(allocationRow.find('td:eq(3) a').get(0));
andThen(() => {
assert.equal(currentURL(), `/nodes/${allocation.nodeId}`, 'Node links to node page');
});
});
test('each allocation should show stats about the allocation, retrieved directly from the node', function(
assert
) {
const allocation = allocations.sortBy('name')[0];
const allocationRow = find('.allocations tbody tr:eq(0)');
const allocationRow = $(findAll('.allocations tbody tr')[0]);
const allocStats = server.db.clientAllocationStats.find(allocation.id);
const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));

View File

@ -1,3 +1,4 @@
import { fillIn, visit } from 'ember-native-dom-helpers';
import { test } from 'qunit';
import moduleForAcceptance from 'nomad-ui/tests/helpers/module-for-acceptance';
@ -22,14 +23,18 @@ test('the token form sets the token in session storage', function(assert) {
assert.ok(window.sessionStorage.nomadTokenSecret == null, 'No token secret set');
assert.ok(window.sessionStorage.nomadTokenAccessor == null, 'No token accessor set');
fillIn('.token-secret', secret);
andThen(() => {
fillIn('.token-secret', secret);
});
andThen(() => {
assert.equal(window.sessionStorage.nomadTokenSecret, secret, 'Token secret was set');
assert.ok(window.sessionStorage.nomadTokenAccessor == null, 'Token accessor was not set');
});
fillIn('.token-accessor', accessor);
andThen(() => {
fillIn('.token-accessor', accessor);
});
andThen(() => {
assert.equal(window.sessionStorage.nomadTokenAccessor, accessor, 'Token accessor was set');
@ -55,7 +60,9 @@ test('the X-Nomad-Token header gets sent with requests once it is set', function
});
visit('/settings/tokens');
fillIn('.token-secret', secret);
andThen(() => {
fillIn('.token-secret', secret);
});
visit(`/jobs/${job.id}`);
visit(`/nodes/${node.id}`);

View File

@ -1,3 +1,4 @@
import { findAll } from 'ember-native-dom-helpers';
import { test, moduleForComponent } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import flat from 'npm:flat';
@ -42,23 +43,39 @@ test('should render the full path of key/value pair from the root of the object'
this.render(hbs`{{attributes-table attributes=attributes}}`);
assert.equal(
this.$('tbody tr:eq(0) td:eq(0)').text().trim(),
this.$('tbody tr:eq(0) td')
.get(0)
.textContent.trim(),
'key',
'Simple row renders only the key'
);
assert.equal(this.$('tbody tr:eq(0) td:eq(1)').text().trim(), 'value');
assert.equal(
this.$('tbody tr:eq(0) td')
.get(1)
.textContent.trim(),
'value'
);
assert.equal(
this.$('tbody tr:eq(8) td:eq(0)').text().trim(),
this.$('tbody tr:eq(8) td')
.get(0)
.textContent.trim(),
'so.are.deeply.nested',
'Complex row renders the full path to the key'
);
assert.equal(
this.$('tbody tr:eq(8) td:eq(0) .is-faded').text().trim(),
this.$('tbody tr:eq(8) td:eq(0) .is-faded')
.get(0)
.textContent.trim(),
'so.are.deeply.',
'The prefix is faded to put emphasis on the attribute'
);
assert.equal(this.$('tbody tr:eq(8) td:eq(1)').text().trim(), 'properties');
assert.equal(
this.$('tbody tr:eq(8) td')
.get(1)
.textContent.trim(),
'properties'
);
});
test('should render a row for key/value pairs even when the value is another object', function(
@ -69,7 +86,7 @@ test('should render a row for key/value pairs even when the value is another obj
const countOfParentRows = countOfParentKeys(commonAttributes);
assert.equal(
this.$('tbody tr td[colspan="2"]').length,
findAll('tbody tr td[colspan="2"]').length,
countOfParentRows,
'Each key for a nested object gets a row with no value'
);

View File

@ -1,3 +1,4 @@
import { findAll, find } from 'ember-native-dom-helpers';
import { test, moduleForComponent } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@ -28,22 +29,22 @@ test('job field diffs', function(assert) {
this.render(commonTemplate);
assert.equal(
this.$('.diff-section-label').length,
findAll('.diff-section-label').length,
5,
'A section label for each line, plus one for the group'
);
assert.equal(
cleanWhitespace(this.$('.diff-section-label .diff-section-label.is-added').text()),
cleanWhitespace(find('.diff-section-label .diff-section-label.is-added').textContent),
'+ Added Field: "Foobar"',
'Added field is rendered correctly'
);
assert.equal(
cleanWhitespace(this.$('.diff-section-label .diff-section-label.is-edited').text()),
cleanWhitespace(find('.diff-section-label .diff-section-label.is-edited').textContent),
'+/- Edited Field: "256" => "512"',
'Edited field is rendered correctly'
);
assert.equal(
cleanWhitespace(this.$('.diff-section-label .diff-section-label.is-deleted').text()),
cleanWhitespace(find('.diff-section-label .diff-section-label.is-deleted').textContent),
'- Removed Field: "12"',
'Removed field is rendered correctly'
);
@ -96,51 +97,51 @@ test('job object diffs', function(assert) {
this.render(commonTemplate);
assert.ok(
cleanWhitespace(this.$('.diff-section-label > .diff-section-label.is-added').text()).startsWith(
'+ DeepConfiguration {'
),
cleanWhitespace(
find('.diff-section-label > .diff-section-label.is-added').textContent
).startsWith('+ DeepConfiguration {'),
'Added object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
this.$('.diff-section-label > .diff-section-label.is-edited').text()
find('.diff-section-label > .diff-section-label.is-edited').textContent
).startsWith('+/- ComplexProperty {'),
'Edited object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
this.$('.diff-section-label > .diff-section-label.is-deleted').text()
find('.diff-section-label > .diff-section-label.is-deleted').textContent
).startsWith('- DatedStuff {'),
'Removed object starts with a JSON block'
);
assert.ok(
cleanWhitespace(this.$('.diff-section-label > .diff-section-label.is-added').text()).endsWith(
'}'
),
cleanWhitespace(
find('.diff-section-label > .diff-section-label.is-added').textContent
).endsWith('}'),
'Added object ends the JSON block'
);
assert.ok(
cleanWhitespace(this.$('.diff-section-label > .diff-section-label.is-edited').text()).endsWith(
'}'
),
cleanWhitespace(
find('.diff-section-label > .diff-section-label.is-edited').textContent
).endsWith('}'),
'Edited object starts with a JSON block'
);
assert.ok(
cleanWhitespace(this.$('.diff-section-label > .diff-section-label.is-deleted').text()).endsWith(
'}'
),
cleanWhitespace(
find('.diff-section-label > .diff-section-label.is-deleted').textContent
).endsWith('}'),
'Removed object ends the JSON block'
);
assert.equal(
this.$('.diff-section-label > .diff-section-label.is-added > .diff-section-label').length,
findAll('.diff-section-label > .diff-section-label.is-added > .diff-section-label').length,
this.get('diff').Objects[1].Objects.length + this.get('diff').Objects[1].Fields.length,
'Edited block contains each nested field and object'
);
assert.equal(
this.$(
findAll(
'.diff-section-label > .diff-section-label.is-added > .diff-section-label > .diff-section-label .diff-section-table-row'
).length,
this.get('diff').Objects[1].Objects[0].Fields.length,

View File

@ -1,3 +1,4 @@
import { findAll, find } from 'ember-native-dom-helpers';
import { test, skip, moduleForComponent } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@ -12,7 +13,9 @@ const defaults = {
spread: 2,
};
const list100 = Array(100).fill(null).map((_, i) => i);
const list100 = Array(100)
.fill(null)
.map((_, i) => i);
test('the source property', function(assert) {
this.set('source', list100);
@ -33,31 +36,31 @@ test('the source property', function(assert) {
{{/list-pagination}}
`);
assert.ok(!this.$('.first').length, 'On the first page, there is no first link');
assert.ok(!this.$('.prev').length, 'On the first page, there is no prev link');
assert.ok(!findAll('.first').length, 'On the first page, there is no first link');
assert.ok(!findAll('.prev').length, 'On the first page, there is no prev link');
assert.equal(
this.$('.link').length,
findAll('.link').length,
defaults.spread + 1,
'Pages links spread to the right by the spread amount'
);
for (var pageNumber = 1; pageNumber <= defaults.spread + 1; pageNumber++) {
assert.ok(this.$(`.link.page-${pageNumber}`).length, `Page link includes ${pageNumber}`);
assert.ok(findAll(`.link.page-${pageNumber}`).length, `Page link includes ${pageNumber}`);
}
assert.ok(this.$('.next').length, 'While not on the last page, there is a next link');
assert.ok(this.$('.last').length, 'While not on the last page, there is a last link');
assert.ok(findAll('.next').length, 'While not on the last page, there is a next link');
assert.ok(findAll('.last').length, 'While not on the last page, there is a last link');
assert.ok(
this.$('.item').length,
findAll('.item').length,
defaults.size,
`Only ${defaults.size} (the default) number of items are rendered`
);
for (var item = 0; item < defaults.size; item++) {
assert.equal(
this.$(`.item:eq(${item})`).text(),
findAll('.item')[item].textContent,
item,
'Rendered items are in the current page'
);
@ -76,7 +79,7 @@ test('the size property', function(assert) {
`);
const totalPages = Math.ceil(this.get('source').length / this.get('size'));
assert.equal(this.$('.page-info').text(), `1 of ${totalPages}`, `${totalPages} total pages`);
assert.equal(find('.page-info').textContent, `1 of ${totalPages}`, `${totalPages} total pages`);
});
test('the spread property', function(assert) {
@ -144,14 +147,14 @@ test('there are no pagination links when source is less than page size', functio
{{/list-pagination}}
`);
assert.ok(!this.$('.first').length, 'No first link');
assert.ok(!this.$('.prev').length, 'No prev link');
assert.ok(!this.$('.next').length, 'No next link');
assert.ok(!this.$('.last').length, 'No last link');
assert.ok(!findAll('.first').length, 'No first link');
assert.ok(!findAll('.prev').length, 'No prev link');
assert.ok(!findAll('.next').length, 'No next link');
assert.ok(!findAll('.last').length, 'No last link');
assert.equal(this.$('.page-info').text(), '1 of 1', 'Only one page');
assert.equal(find('.page-info').textContent, '1 of 1', 'Only one page');
assert.equal(
this.$('.item').length,
findAll('.item').length,
this.get('source.length'),
'Number of items equals length of source'
);
@ -180,10 +183,10 @@ test('when there are no items in source', function(assert) {
`);
assert.ok(
!this.$('.page-info, .first, .prev, .link, .next, .last, .item').length,
!findAll('.page-info, .first, .prev, .link, .next, .last, .item').length,
'Nothing in the yield renders'
);
assert.ok(this.$('.empty-state').length, 'Empty state is rendered');
assert.ok(findAll('.empty-state').length, 'Empty state is rendered');
});
// when there is less pages than the total spread amount
@ -210,13 +213,13 @@ test('when there is less pages than the total spread amount', function(assert) {
{{/list-pagination}}
`);
assert.ok(this.$('.first').length, 'First page still exists');
assert.ok(this.$('.prev').length, 'Prev page still exists');
assert.ok(this.$('.next').length, 'Next page still exists');
assert.ok(this.$('.last').length, 'Last page still exists');
assert.equal(this.$('.link').length, totalPages, 'Every page gets a page link');
assert.ok(findAll('.first').length, 'First page still exists');
assert.ok(findAll('.prev').length, 'Prev page still exists');
assert.ok(findAll('.next').length, 'Next page still exists');
assert.ok(findAll('.last').length, 'Last page still exists');
assert.equal(findAll('.link').length, totalPages, 'Every page gets a page link');
for (var pageNumber = 1; pageNumber < totalPages; pageNumber++) {
assert.ok(this.$(`.link.page-${pageNumber}`).length, `Page link for ${pageNumber} exists`);
assert.ok(findAll(`.link.page-${pageNumber}`).length, `Page link for ${pageNumber} exists`);
}
});
@ -224,7 +227,7 @@ function testSpread(assert) {
const { spread, currentPage } = this.getProperties('spread', 'currentPage');
for (var pageNumber = currentPage - spread; pageNumber <= currentPage + spread; pageNumber++) {
assert.ok(
this.$(`.link.page-${pageNumber}`).length,
findAll(`.link.page-${pageNumber}`).length,
`Page links for currentPage (${currentPage}) +/- spread of ${spread} (${pageNumber})`
);
}
@ -234,7 +237,7 @@ function testItems(assert) {
const { currentPage, size } = this.getProperties('currentPage', 'size');
for (var item = 0; item < size; item++) {
assert.equal(
this.$(`.item:eq(${item})`).text(),
findAll('.item')[item].textContent,
item + (currentPage - 1) * size,
`Rendered items are in the current page, ${currentPage} (${item + (currentPage - 1) * size})`
);

View File

@ -1,3 +1,4 @@
import { findAll, find } from 'ember-native-dom-helpers';
import { test, skip, moduleForComponent } from 'ember-qunit';
import { faker } from 'ember-cli-mirage';
import hbs from 'htmlbars-inline-precompile';
@ -6,11 +7,13 @@ moduleForComponent('list-table', 'Integration | Component | list table', {
integration: true,
});
const commonTable = Array(10).fill(null).map(() => ({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
age: faker.random.number({ min: 18, max: 60 }),
}));
const commonTable = Array(10)
.fill(null)
.map(() => ({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
age: faker.random.number({ min: 18, max: 60 }),
}));
// thead
test('component exposes a thead contextual component', function(assert) {
@ -25,12 +28,8 @@ test('component exposes a thead contextual component', function(assert) {
{{/list-table}}
`);
assert.ok(this.$('.head').length, 'Table head is rendered');
assert.equal(
this.$('.head').prop('tagName').toLowerCase(),
'thead',
'Table head is a thead element'
);
assert.ok(findAll('.head').length, 'Table head is rendered');
assert.equal(find('.head').tagName.toLowerCase(), 'thead', 'Table head is a thead element');
});
// tbody
@ -52,22 +51,39 @@ test('component exposes a tbody contextual component', function(assert) {
{{/list-table}}
`);
assert.ok(this.$('.body').length, 'Table body is rendered');
assert.equal(
this.$('.body').prop('tagName').toLowerCase(),
'tbody',
'Table body is a tbody element'
);
assert.ok(findAll('.body').length, 'Table body is rendered');
assert.equal(find('.body').tagName.toLowerCase(), 'tbody', 'Table body is a tbody element');
assert.equal(this.$('.item').length, this.get('source.length'), 'Each item gets its own row');
assert.equal(findAll('.item').length, this.get('source.length'), 'Each item gets its own row');
// list-table is not responsible for sorting, only dispatching sort events. The table is still
// rendered in index-order.
this.get('source').forEach((item, index) => {
const $item = this.$(`.item:eq(${index})`);
assert.equal($item.find('td:eq(0)').text().trim(), item.firstName, 'First name');
assert.equal($item.find('td:eq(1)').text().trim(), item.lastName, 'Last name');
assert.equal($item.find('td:eq(2)').text().trim(), item.age, 'Age');
assert.equal(
$item
.find('td:eq(0)')
.text()
.trim(),
item.firstName,
'First name'
);
assert.equal(
$item
.find('td:eq(1)')
.text()
.trim(),
item.lastName,
'Last name'
);
assert.equal(
$item
.find('td:eq(2)')
.text()
.trim(),
item.age,
'Age'
);
});
});

View File

@ -3103,6 +3103,13 @@ ember-moment@^7.3.1:
ember-getowner-polyfill "^2.0.1"
ember-macro-helpers "^0.15.1"
ember-native-dom-helpers@^0.5.4:
version "0.5.4"
resolved "https://registry.yarnpkg.com/ember-native-dom-helpers/-/ember-native-dom-helpers-0.5.4.tgz#0bc1506a643fb7adc0abf1d09c44a7914459296b"
dependencies:
broccoli-funnel "^1.1.0"
ember-cli-babel "^6.6.0"
ember-qunit@^2.1.3:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ember-qunit/-/ember-qunit-2.2.0.tgz#3cdf400031c93a38de781a7304819738753b7f99"