From eca0e7bf566f8d531e23a4353cb598ac2f7c450e Mon Sep 17 00:00:00 2001 From: Phil Renaud Date: Thu, 22 Sep 2022 10:58:52 -0400 Subject: [PATCH] [ui] task logs in sidebar (#14612) * button styles * Further styles including global toggle adjustment * sidebar funcs and header * Functioning task logs in high-level sidebars * same-lineify the show tasks toggle * Changelog * Full-height sidebar calc in css, plz drop soon container queries * Active status and query params for allocations page * Reactive shouldShowLogs getter and added to client and task group pages * Higher order func passing, thanks @DingoEatingFuzz * Non-service job types get allocation params passed * Keyframe animation for task log sidebar * Acceptance test * A few more sub-row tests * Lintfix --- .changelog/14612.txt | 3 + .../components/allocation-service-sidebar.js | 2 +- ui/app/components/streaming-file.js | 9 ++- ui/app/components/task-context-sidebar.hbs | 44 +++++++++++ ui/app/components/task-context-sidebar.js | 16 ++++ ui/app/components/task-log.js | 2 + ui/app/components/task-sub-row.hbs | 25 +++++-- ui/app/components/task-sub-row.js | 18 +++++ ui/app/controllers/clients/client/index.js | 11 +++ ui/app/controllers/jobs/job/allocations.js | 11 +++ ui/app/controllers/jobs/job/index.js | 13 +++- ui/app/controllers/jobs/job/task-group.js | 11 +++ ui/app/styles/components/boxed-section.scss | 3 + ui/app/styles/components/sidebar.scss | 75 +++++++++++++++++++ ui/app/styles/components/task-sub-row.scss | 41 +++++++--- ui/app/styles/components/toggle.scss | 4 +- ui/app/templates/application.hbs | 2 + ui/app/templates/clients/client/index.hbs | 5 +- ui/app/templates/components/job-page.hbs | 2 +- .../templates/components/job-page/batch.hbs | 2 +- .../job-page/parameterized-child.hbs | 2 +- .../job-page/parts/recent-allocations.hbs | 3 +- .../components/job-page/periodic-child.hbs | 2 +- .../templates/components/job-page/service.hbs | 2 +- .../components/job-page/sysbatch.hbs | 2 +- .../templates/components/job-page/system.hbs | 2 +- ui/app/templates/components/task-log.hbs | 2 +- ui/app/templates/jobs/job/allocations.hbs | 2 +- ui/app/templates/jobs/job/index.hbs | 2 + ui/app/templates/jobs/job/task-group.hbs | 5 +- ui/tests/acceptance/task-logs-test.js | 39 +++++++++- .../components/task-sub-row-test.js | 22 +++++- ui/tests/pages/allocations/task/logs.js | 2 + 33 files changed, 342 insertions(+), 44 deletions(-) create mode 100644 .changelog/14612.txt create mode 100644 ui/app/components/task-context-sidebar.hbs create mode 100644 ui/app/components/task-context-sidebar.js diff --git a/.changelog/14612.txt b/.changelog/14612.txt new file mode 100644 index 000000000..282b62c3b --- /dev/null +++ b/.changelog/14612.txt @@ -0,0 +1,3 @@ +```release-note:improvement +ui: adds a sidebar to show in-page logs for a given task, accessible via job, client, or task group routes +``` diff --git a/ui/app/components/allocation-service-sidebar.js b/ui/app/components/allocation-service-sidebar.js index bab46f0ed..13ce37e2a 100644 --- a/ui/app/components/allocation-service-sidebar.js +++ b/ui/app/components/allocation-service-sidebar.js @@ -10,7 +10,7 @@ export default class AllocationServiceSidebarComponent extends Component { } keyCommands = [ { - label: 'Close Evaluations Sidebar', + label: 'Close Service Sidebar', pattern: ['Escape'], action: () => this.args.fns.closeSidebar(), }, diff --git a/ui/app/components/streaming-file.js b/ui/app/components/streaming-file.js index 8239aedf8..73fb390a4 100644 --- a/ui/app/components/streaming-file.js +++ b/ui/app/components/streaming-file.js @@ -22,6 +22,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) { isStreaming = true; logger = null; follow = true; + shouldFillHeight = true; // Internal bookkeeping to avoid multiple scroll events on one frame requestFrame = true; @@ -89,7 +90,9 @@ export default class StreamingFile extends Component.extend(WindowResizable) { didInsertElement() { super.didInsertElement(...arguments); - this.fillAvailableHeight(); + if (this.shouldFillHeight) { + this.fillAvailableHeight(); + } this.set('_scrollHandler', this.scrollHandler.bind(this)); this.element.addEventListener('scroll', this._scrollHandler); @@ -105,7 +108,9 @@ export default class StreamingFile extends Component.extend(WindowResizable) { } windowResizeHandler() { - once(this, this.fillAvailableHeight); + if (this.shouldFillHeight) { + once(this, this.fillAvailableHeight); + } } fillAvailableHeight() { diff --git a/ui/app/components/task-context-sidebar.hbs b/ui/app/components/task-context-sidebar.hbs new file mode 100644 index 000000000..523e3c118 --- /dev/null +++ b/ui/app/components/task-context-sidebar.hbs @@ -0,0 +1,44 @@ + + + \ No newline at end of file diff --git a/ui/app/components/task-context-sidebar.js b/ui/app/components/task-context-sidebar.js new file mode 100644 index 000000000..31ce73aa3 --- /dev/null +++ b/ui/app/components/task-context-sidebar.js @@ -0,0 +1,16 @@ +// @ts-check +import Component from '@glimmer/component'; + +export default class TaskContextSidebarComponent extends Component { + get isSideBarOpen() { + return !!this.args.task; + } + + keyCommands = [ + { + label: 'Close Task Logs Sidebar', + pattern: ['Escape'], + action: () => this.args.fns.closeSidebar(), + }, + ]; +} diff --git a/ui/app/components/task-log.js b/ui/app/components/task-log.js index 2ed7325d0..cf27d928f 100644 --- a/ui/app/components/task-log.js +++ b/ui/app/components/task-log.js @@ -35,6 +35,8 @@ export default class TaskLog extends Component { isStreaming = true; streamMode = 'streaming'; + shouldFillHeight = true; + @alias('userSettings.logMode') mode; @computed('allocation.{id,node.httpAddr}', 'useServer') diff --git a/ui/app/components/task-sub-row.hbs b/ui/app/components/task-sub-row.hbs index 203fd6555..09e65a872 100644 --- a/ui/app/components/task-sub-row.hbs +++ b/ui/app/components/task-sub-row.hbs @@ -1,16 +1,16 @@ - - / - - {{this.task.name}} - - {{!-- TODO: in-page logs --}} - {{!-- --}} +
+ {{this.task.name}} + +
{{#if this.task.isRunning}} @@ -76,4 +76,13 @@ -{{yield}} \ No newline at end of file +{{yield}} + +{{#if this.shouldShowLogs}} + +{{/if}} diff --git a/ui/app/components/task-sub-row.js b/ui/app/components/task-sub-row.js index 1499c2edf..5eec51214 100644 --- a/ui/app/components/task-sub-row.js +++ b/ui/app/components/task-sub-row.js @@ -71,4 +71,22 @@ export default class TaskSubRowComponent extends Component { } while (this.enablePolling); }).drop()) fetchStats; + + //#region Logs Sidebar + + @alias('args.active') shouldShowLogs; + + @action handleTaskLogsClick(task) { + if (this.args.onSetActiveTask) { + this.args.onSetActiveTask(task); + } + } + + @action closeSidebar() { + if (this.args.onSetActiveTask) { + this.args.onSetActiveTask(null); + } + } + + //#endregion Logs Sidebar } diff --git a/ui/app/controllers/clients/client/index.js b/ui/app/controllers/clients/client/index.js index 1775a0727..dc29fc709 100644 --- a/ui/app/controllers/clients/client/index.js +++ b/ui/app/controllers/clients/client/index.js @@ -47,6 +47,7 @@ export default class ClientController extends Controller.extend( { qpStatus: 'status', }, + 'activeTask', ]; // Set in the route @@ -57,6 +58,7 @@ export default class ClientController extends Controller.extend( qpStatus = ''; currentPage = 1; pageSize = 8; + activeTask = null; sortProperty = 'modifyIndex'; sortDescending = true; @@ -266,4 +268,13 @@ export default class ClientController extends Controller.extend( setFacetQueryParam(queryParam, selection) { this.set(queryParam, serialize(selection)); } + + @action + setActiveTaskQueryParam(task) { + if (task) { + this.set('activeTask', `${task.allocation.id}-${task.name}`); + } else { + this.set('activeTask', null); + } + } } diff --git a/ui/app/controllers/jobs/job/allocations.js b/ui/app/controllers/jobs/job/allocations.js index 33ee81bdb..68c84487a 100644 --- a/ui/app/controllers/jobs/job/allocations.js +++ b/ui/app/controllers/jobs/job/allocations.js @@ -41,6 +41,7 @@ export default class AllocationsController extends Controller.extend( { qpTaskGroup: 'taskGroup', }, + 'activeTask', ]; qpStatus = ''; @@ -48,6 +49,7 @@ export default class AllocationsController extends Controller.extend( qpTaskGroup = ''; currentPage = 1; pageSize = 25; + activeTask = null; sortProperty = 'modifyIndex'; sortDescending = true; @@ -159,4 +161,13 @@ export default class AllocationsController extends Controller.extend( setFacetQueryParam(queryParam, selection) { this.set(queryParam, serialize(selection)); } + + @action + setActiveTaskQueryParam(task) { + if (task) { + this.set('activeTask', `${task.allocation.id}-${task.name}`); + } else { + this.set('activeTask', null); + } + } } diff --git a/ui/app/controllers/jobs/job/index.js b/ui/app/controllers/jobs/job/index.js index f066ac554..ed5fc0cae 100644 --- a/ui/app/controllers/jobs/job/index.js +++ b/ui/app/controllers/jobs/job/index.js @@ -3,7 +3,7 @@ import { alias } from '@ember/object/computed'; import { inject as service } from '@ember/service'; import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting'; import classic from 'ember-classic-decorator'; - +import { action } from '@ember/object'; @classic export default class IndexController extends Controller.extend( WithNamespaceResetting @@ -20,6 +20,7 @@ export default class IndexController extends Controller.extend( { sortDescending: 'desc', }, + 'activeTask', ]; currentPage = 1; @@ -28,4 +29,14 @@ export default class IndexController extends Controller.extend( sortProperty = 'name'; sortDescending = false; + activeTask = null; + + @action + setActiveTaskQueryParam(task) { + if (task) { + this.set('activeTask', `${task.allocation.id}-${task.name}`); + } else { + this.set('activeTask', null); + } + } } diff --git a/ui/app/controllers/jobs/job/task-group.js b/ui/app/controllers/jobs/job/task-group.js index 763fa5b3d..004970a1c 100644 --- a/ui/app/controllers/jobs/job/task-group.js +++ b/ui/app/controllers/jobs/job/task-group.js @@ -43,6 +43,7 @@ export default class TaskGroupController extends Controller.extend( { qpClient: 'client', }, + 'activeTask', ]; currentPage = 1; @@ -52,6 +53,7 @@ export default class TaskGroupController extends Controller.extend( qpClient = ''; sortProperty = 'modifyIndex'; sortDescending = true; + activeTask = null; @computed get searchProps() { @@ -186,4 +188,13 @@ export default class TaskGroupController extends Controller.extend( args: ['jobs.job.task-group', job, name], }; } + + @action + setActiveTaskQueryParam(task) { + if (task) { + this.set('activeTask', `${task.allocation.id}-${task.name}`); + } else { + this.set('activeTask', null); + } + } } diff --git a/ui/app/styles/components/boxed-section.scss b/ui/app/styles/components/boxed-section.scss index 901dc7503..4ac5b726a 100644 --- a/ui/app/styles/components/boxed-section.scss +++ b/ui/app/styles/components/boxed-section.scss @@ -26,6 +26,9 @@ .is-padded { padding: 0em 0em 0em 1em; } + .is-one-line { + white-space: nowrap; + } } .is-fixed-width { diff --git a/ui/app/styles/components/sidebar.scss b/ui/app/styles/components/sidebar.scss index 357a42fd2..21c08bf1e 100644 --- a/ui/app/styles/components/sidebar.scss +++ b/ui/app/styles/components/sidebar.scss @@ -56,3 +56,78 @@ $subNavOffset: 49px; padding: 10px; width: 100px; } + +.task-context-sidebar { + animation-name: slideFromRight; + animation-duration: 150ms; + animation-fill-mode: both; + + header { + display: grid; + justify-content: left; + grid-template-columns: 1fr auto auto; + gap: 2rem; + border-bottom: 1px solid $grey-blue; + padding-bottom: 1rem; + margin-bottom: 24px; + height: 50px; + + .title { + margin-bottom: unset; + } + + .link { + align-self: center; + } + + .state { + font-size: 1rem; + font-weight: normal; + margin-left: 1rem; + text-transform: capitalize; + + &:before { + content: ''; + display: inline-block; + height: 1rem; + width: 1rem; + margin-right: 5px; + border-radius: 4px; + position: relative; + top: 2px; + } + + &.running:before { + background-color: $green; + } + &.dead:before { + background-color: $red; + } + &.pending:before { + background-color: $grey-lighter; + } + } + } + + // Instead of trying to calculate on the fly with JS, let's use vh and offset nav and headers above. + // We can make this a LOT more streamlined when CSS Container Queries are available. + $sidebarTopOffset: 161px; + $sidebarInnerPadding: 48px; + $sidebarHeaderOffset: 74px; + $cliHeaderOffset: 54.5px; + .cli-window { + height: calc( + 100vh - $sidebarTopOffset - $sidebarInnerPadding - $sidebarHeaderOffset - + $cliHeaderOffset + ); + } +} + +@keyframes slideFromRight { + from { + transform: translateX(100%); + } + to { + transform: translateX(0%); + } +} diff --git a/ui/app/styles/components/task-sub-row.scss b/ui/app/styles/components/task-sub-row.scss index e8334b03d..5d7796858 100644 --- a/ui/app/styles/components/task-sub-row.scss +++ b/ui/app/styles/components/task-sub-row.scss @@ -1,16 +1,39 @@ table tbody .task-sub-row { td { border-top: 2px solid white; - } - td:nth-child(1) { - padding-left: 4rem; - a { - margin-right: 1rem; - } - svg.flight-icon { - position: relative; - top: 3px; + .name-grid { + display: inline-grid; + grid-template-columns: auto 1fr; + margin-left: 4rem; + gap: 1rem; + + .task-name { + display: block; + width: 150px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + &:before { + color: black; + content: '/'; + display: inline-block; + margin-right: 0.5rem; + text-decoration: none; + } + } + + .logs-sidebar-trigger { + color: $blue; + text-decoration: underline; + font-weight: normal; + svg { + color: black; + margin-right: 5px; + position: relative; + top: 3px; + } + } } } } diff --git a/ui/app/styles/components/toggle.scss b/ui/app/styles/components/toggle.scss index efa07688e..612041b94 100644 --- a/ui/app/styles/components/toggle.scss +++ b/ui/app/styles/components/toggle.scss @@ -31,7 +31,9 @@ $size: 12px; .toggler { display: inline-block; position: relative; - vertical-align: middle; + vertical-align: baseline; + position: relative; + top: 1px; width: $size * 2; height: $size; border-radius: $size; diff --git a/ui/app/templates/application.hbs b/ui/app/templates/application.hbs index 3492b2a9e..8a16c4f2d 100644 --- a/ui/app/templates/application.hbs +++ b/ui/app/templates/application.hbs @@ -26,6 +26,8 @@ + + {{#if this.error}}
diff --git a/ui/app/templates/clients/client/index.hbs b/ui/app/templates/clients/client/index.hbs index 22056e0b2..61e277018 100644 --- a/ui/app/templates/clients/client/index.hbs +++ b/ui/app/templates/clients/client/index.hbs @@ -497,9 +497,8 @@ @class="is-padded" /> - + {{#if this.showSubTasks}} {{#each row.model.states as |task|}} - + {{/each}} {{/if}} diff --git a/ui/app/templates/components/job-page.hbs b/ui/app/templates/components/job-page.hbs index 564524cd7..2b094a903 100644 --- a/ui/app/templates/components/job-page.hbs +++ b/ui/app/templates/components/job-page.hbs @@ -19,7 +19,7 @@ "job-page/parts/latest-deployment" job=@job handleError=this.handleError ) TaskGroups=(component "job-page/parts/task-groups" job=@job) - RecentAllocations=(component "job-page/parts/recent-allocations" job=@job) + RecentAllocations=(component "job-page/parts/recent-allocations" job=@job activeTask=@activeTask setActiveTaskQueryParam=@setActiveTaskQueryParam) Meta=(component "job-page/parts/meta" job=@job) DasRecommendations=(component "job-page/parts/das-recommendations" job=@job diff --git a/ui/app/templates/components/job-page/batch.hbs b/ui/app/templates/components/job-page/batch.hbs index 12712b17b..1ed2b2af2 100644 --- a/ui/app/templates/components/job-page/batch.hbs +++ b/ui/app/templates/components/job-page/batch.hbs @@ -6,7 +6,7 @@ - + \ No newline at end of file diff --git a/ui/app/templates/components/job-page/parameterized-child.hbs b/ui/app/templates/components/job-page/parameterized-child.hbs index 49a65c67e..9c80a7617 100644 --- a/ui/app/templates/components/job-page/parameterized-child.hbs +++ b/ui/app/templates/components/job-page/parameterized-child.hbs @@ -21,7 +21,7 @@ - +
{{#if @job.meta}} diff --git a/ui/app/templates/components/job-page/parts/recent-allocations.hbs b/ui/app/templates/components/job-page/parts/recent-allocations.hbs index e91aca79f..31e91729d 100644 --- a/ui/app/templates/components/job-page/parts/recent-allocations.hbs +++ b/ui/app/templates/components/job-page/parts/recent-allocations.hbs @@ -3,7 +3,6 @@ Recent Allocations + {{/each}} {{/if}} diff --git a/ui/app/templates/components/job-page/periodic-child.hbs b/ui/app/templates/components/job-page/periodic-child.hbs index 316492680..69eef3292 100644 --- a/ui/app/templates/components/job-page/periodic-child.hbs +++ b/ui/app/templates/components/job-page/periodic-child.hbs @@ -21,7 +21,7 @@ - + \ No newline at end of file diff --git a/ui/app/templates/components/job-page/service.hbs b/ui/app/templates/components/job-page/service.hbs index 233e85d3f..2927e6423 100644 --- a/ui/app/templates/components/job-page/service.hbs +++ b/ui/app/templates/components/job-page/service.hbs @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/ui/app/templates/components/job-page/sysbatch.hbs b/ui/app/templates/components/job-page/sysbatch.hbs index 2b9c7e0c0..01f63b41c 100644 --- a/ui/app/templates/components/job-page/sysbatch.hbs +++ b/ui/app/templates/components/job-page/sysbatch.hbs @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/ui/app/templates/components/job-page/system.hbs b/ui/app/templates/components/job-page/system.hbs index 693e74bcc..1728d6eed 100644 --- a/ui/app/templates/components/job-page/system.hbs +++ b/ui/app/templates/components/job-page/system.hbs @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/ui/app/templates/components/task-log.hbs b/ui/app/templates/components/task-log.hbs index b1209a021..7bb124e29 100644 --- a/ui/app/templates/components/task-log.hbs +++ b/ui/app/templates/components/task-log.hbs @@ -25,5 +25,5 @@
- +
diff --git a/ui/app/templates/jobs/job/allocations.hbs b/ui/app/templates/jobs/job/allocations.hbs index d655a9e8f..a7f520adb 100644 --- a/ui/app/templates/jobs/job/allocations.hbs +++ b/ui/app/templates/jobs/job/allocations.hbs @@ -71,7 +71,7 @@ @context="job" @onClick={{action "gotoAllocation" row.model}} /> {{#each row.model.states as |task|}} - + {{/each}} diff --git a/ui/app/templates/jobs/job/index.hbs b/ui/app/templates/jobs/job/index.hbs index 0ff6bd3ac..a1426d21f 100644 --- a/ui/app/templates/jobs/job/index.hbs +++ b/ui/app/templates/jobs/job/index.hbs @@ -5,4 +5,6 @@ sortProperty=this.sortProperty sortDescending=this.sortDescending currentPage=this.currentPage + activeTask=this.activeTask + setActiveTaskQueryParam=this.setActiveTaskQueryParam }} \ No newline at end of file diff --git a/ui/app/templates/jobs/job/task-group.hbs b/ui/app/templates/jobs/job/task-group.hbs index ef5fedd12..57091b930 100644 --- a/ui/app/templates/jobs/job/task-group.hbs +++ b/ui/app/templates/jobs/job/task-group.hbs @@ -149,9 +149,8 @@ @class="is-padded" @inputClass="is-compact" /> - + {{#if this.showSubTasks}} {{#each row.model.states as |task|}} - + {{/each}} {{/if}} diff --git a/ui/tests/acceptance/task-logs-test.js b/ui/tests/acceptance/task-logs-test.js index 90ca1e9b3..54b8a4e38 100644 --- a/ui/tests/acceptance/task-logs-test.js +++ b/ui/tests/acceptance/task-logs-test.js @@ -1,23 +1,27 @@ /* eslint-disable qunit/require-expect */ -import { currentURL } from '@ember/test-helpers'; +import { click, currentURL } from '@ember/test-helpers'; import { run } from '@ember/runloop'; import { module, test } from 'qunit'; import { setupApplicationTest } from 'ember-qunit'; import { setupMirage } from 'ember-cli-mirage/test-support'; import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit'; import TaskLogs from 'nomad-ui/tests/pages/allocations/task/logs'; +import percySnapshot from '@percy/ember'; +import faker from 'nomad-ui/mirage/faker'; let allocation; let task; +let job; module('Acceptance | task logs', function (hooks) { setupApplicationTest(hooks); setupMirage(hooks); hooks.beforeEach(async function () { + faker.seed(1); server.create('agent'); server.create('node', 'forceIPv4'); - const job = server.create('job', { createAllocations: false }); + job = server.create('job', { createAllocations: false }); allocation = server.create('allocation', { jobId: job.id, @@ -26,14 +30,15 @@ module('Acceptance | task logs', function (hooks) { task = server.db.taskStates.where({ allocationId: allocation.id })[0]; run.later(run, run.cancelTimers, 1000); - await TaskLogs.visit({ id: allocation.id, name: task.name }); }); test('it passes an accessibility audit', async function (assert) { + await TaskLogs.visit({ id: allocation.id, name: task.name }); await a11yAudit(assert); }); test('/allocation/:id/:task_name/logs should have a log component', async function (assert) { + await TaskLogs.visit({ id: allocation.id, name: task.name }); assert.equal( currentURL(), `/allocations/${allocation.id}/${task.name}/logs`, @@ -44,6 +49,7 @@ module('Acceptance | task logs', function (hooks) { }); test('the stdout log immediately starts streaming', async function (assert) { + await TaskLogs.visit({ id: allocation.id, name: task.name }); const node = server.db.nodes.find(allocation.nodeId); const logUrlRegex = new RegExp( `${node.httpAddr}/v1/client/fs/logs/${allocation.id}` @@ -55,4 +61,31 @@ module('Acceptance | task logs', function (hooks) { 'Log requests were made' ); }); + + test('logs are accessible in a sidebar context', async function (assert) { + await TaskLogs.visitParentJob({ + id: job.id, + allocationId: allocation.id, + name: task.name, + }); + assert.notOk(TaskLogs.sidebarIsPresent, 'Sidebar is not present'); + + run.later(() => { + run.cancelTimers(); + }, 500); + + await click('button.logs-sidebar-trigger'); + + assert.ok(TaskLogs.sidebarIsPresent, 'Sidebar is present'); + assert + .dom('.task-context-sidebar h1.title') + .includesText(task.name, 'Sidebar title is correct'); + assert + .dom('.task-context-sidebar h1.title') + .includesText(task.state, 'Task state is correctly displayed'); + await percySnapshot(assert); + + await click('.sidebar button.close'); + assert.notOk(TaskLogs.sidebarIsPresent, 'Sidebar is not present'); + }); }); diff --git a/ui/tests/integration/components/task-sub-row-test.js b/ui/tests/integration/components/task-sub-row-test.js index 05b38eec3..7eb7b2f62 100644 --- a/ui/tests/integration/components/task-sub-row-test.js +++ b/ui/tests/integration/components/task-sub-row-test.js @@ -51,10 +51,28 @@ const mockTask = { module('Integration | Component | task-sub-row', function (hooks) { setupRenderingTest(hooks); test('it renders', async function (assert) { - assert.expect(2); + assert.expect(6); this.set('task', mockTask); await render(hbs``); - assert.dom(this.element).hasText(`/ ${mockTask.name}`); + assert.ok( + this.element.textContent.includes(`${mockTask.name}`), + 'Task name is rendered' + ); + assert.dom('.task-sub-row').doesNotHaveClass('is-active'); + + await render(hbs``); + assert.dom('.task-sub-row').hasClass('is-active'); + + await render( + hbs`` + ); + assert.dom('.task-sub-row td:nth-child(1)').hasAttribute('colspan', '5'); + + await render( + hbs`` + ); + assert.dom('.task-sub-row td:nth-child(1)').hasAttribute('colspan', '9'); + await componentA11yAudit(this.element, assert); }); }); diff --git a/ui/tests/pages/allocations/task/logs.js b/ui/tests/pages/allocations/task/logs.js index 12a091459..f436aa624 100644 --- a/ui/tests/pages/allocations/task/logs.js +++ b/ui/tests/pages/allocations/task/logs.js @@ -2,6 +2,8 @@ import { create, isPresent, visitable } from 'ember-cli-page-object'; export default create({ visit: visitable('/allocations/:id/:name/logs'), + visitParentJob: visitable('/jobs/:id/allocations'), hasTaskLog: isPresent('[data-test-task-log]'), + sidebarIsPresent: isPresent('.sidebar.task-context-sidebar'), });