Skip to content

Commit

Permalink
Merge pull request #1108 from oliver-sanders/etchasketch.dev
Browse files Browse the repository at this point in the history
graph view and central data store
  • Loading branch information
wxtim authored Nov 28, 2022
2 parents 4995dfc + 3d28f92 commit 902a539
Show file tree
Hide file tree
Showing 102 changed files with 5,574 additions and 7,213 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ jobs:
env:
CYPRESS_baseUrl: http://localhost:8080/

- uses: actions/upload-artifact@v2
if: failure()
with:
name: cypress-screenshots
path: tests/e2e/screenshots

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
Expand Down
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,22 @@ ones in. -->

### Enhancements

[#1108](https://github.com/cylc/cylc-ui/pull/1108) -
Graph view: A new view which displays tasks and dependencies as a graph (like
the Cylc 7 graph view).

[#1108](https://github.com/cylc/cylc-ui/pull/1108) -
Tree view: Task messages are now shown along with outputs.

[#1124](https://github.com/cylc/cylc-ui/pull/1075) - Table view: More options
for number of tasks per page.

### Fixes

[#1108](https://github.com/cylc/cylc-ui/pull/1108) -
Tree view: Task outputs are now correctly associated with the jobs that created
them.

[#1075](https://github.com/cylc/cylc-ui/pull/1075) - Reverse default sort order
of the table view so it matches the tree view.

Expand Down
214 changes: 214 additions & 0 deletions cypress/component/cylc-graph-node.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/**
* Copyright (C) NIWA & British Crown (Met Office) & Contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { TaskStateUserOrder, JobStates } from '@/model/TaskState.model'
import GraphNode from '@/components/cylc/GraphNode'
import { Tokens } from '@/utils/uid'
import {
MEAN_ELAPSED_TIME,
getStartTime
} from './utils/task'

function makeTaskNode (id, state, jobStates) {
const tokens = new Tokens(id)
const jobs = []
let itt = 1
let job
for (const jobState of jobStates) {
const jobTokens = tokens.clone({ job: `0${itt}` })
job = {
id: jobTokens.id,
name: jobTokens.job,
node: {
state: jobState
}
}
if (jobState === 'running') { // TODO constant
job.node.startedTime = getStartTime(50)
}
jobs.push(job)
itt++
}

const task = {
id: tokens.id,
name: tokens.task,
tokens,
node: {
cyclePoint: tokens.cycle,
isHeld: false,
state,
task: {
meanElapsedTime: MEAN_ELAPSED_TIME
}
}
}

return [task, jobs]
}

const GraphNodeSVG = {
template: `
<svg id="app" class="job_theme--default" width="100%" height="100%">
<GraphNode :task="task" :jobs="jobs" :maxJobs="maxJobs" />
</svg>
`,
props: {
task: {
required: true
},
jobs: {
required: true
},
maxJobs: {
default: 6,
required: false
}
},
components: { GraphNode }
}

describe('graph node component', () => {
it('Renders with multiple jobs', () => {
const [task, jobs] = makeTaskNode(
'~a/b//20000101T0000Z/task_name',
'running',
['running', 'failed', 'failed', 'failed']
)
cy.mount(
GraphNodeSVG,
{
propsData: { task, jobs }
}
)
// there should be 4 jobs
cy.get('.c-graph-node:last .jobs')
.children()
.should('have.length', 4)
// there shouldn't be a job overflow indicator
cy.get('.c-graph-node:last .job-overflow').should('not.exist')

cy.get('.c-graph-node').last().parent().screenshot(
`graph-node-multiple-jobs`,
{ overwrite: true, disableTimersAndAnimations: false }
)
})

it('Hides excessive numbers of jobs', () => {
const [task, jobs] = makeTaskNode(
'~a/b//20000101T0000Z/task_name',
'running',
['running', 'failed', 'failed', 'failed', 'failed', 'failed']
)
cy.mount(
GraphNodeSVG,
{
propsData: { task, jobs, maxJobs: 4 }
}
)
// there should be <maxJobs> jobs
cy.get('.c-graph-node:last .jobs')
.children()
.should('have.length', 4)
// there should be a job overflow indicator with the number of overflow jobs
cy.get('.c-graph-node:last .job-overflow')
.should('exist')
.get('text')
.contains('+2')

cy.get('.c-graph-node').last().parent().screenshot(
`graph-node-overflow-jobs`,
{ overwrite: true, disableTimersAndAnimations: false }
)
})

it('Renders for each task state', () => {
let task
let jobs
let jobStates
for (const state of TaskStateUserOrder) {
jobStates = []
for (const jobState of JobStates) {
if (state.name === jobState.name) {
jobStates = [state.name]
break
}
}
[task, jobs] = makeTaskNode(
`~a/b//20000101T0000Z/${state.name}`,
state.name,
jobStates
)
console.log(jobs)
cy.mount(GraphNodeSVG, { propsData: { task, jobs } })
cy.get('.c-graph-node').last().parent().screenshot(
`graph-node-${state.name}`,
{ overwrite: true, disableTimersAndAnimations: false }
)
}
})

it('Renders for each task modifier', () => {
let task
let jobs
for (const modifier of ['isHeld', 'isQueued', 'isRunahead']) {
[task, jobs] = makeTaskNode(
`~a/b//20000101T0000Z/${modifier}`,
'waiting',
[]
)
task.node[modifier] = true
cy.mount(GraphNodeSVG, { propsData: { task, jobs } })
cy.get('.c-graph-node').last().parent().screenshot(
`graph-node-${modifier}`,
{ overwrite: true, disableTimersAndAnimations: false }
)
}
})

it('Animates task progress', () => {
let task
let jobs
for (const percent of [0, 25, 50, 75, 100]) {
[task, jobs] = makeTaskNode(
`~a/b//${percent}/running`,
'running',
['running']
)
jobs[0].node.startedTime = getStartTime(percent)
cy.mount(GraphNodeSVG, { propsData: { task, jobs } })
cy.get('.c-graph-node').last().parent().screenshot(
`graph-node-running-${percent}`,
{ overwrite: true, disableTimersAndAnimations: false }
)
// check the progress animation
.get('.c8-task:last .status > .progress')
// the animation duration should be equal to the expected job duration
.should('have.css', 'animation-duration', `${MEAN_ELAPSED_TIME}s`)
// the offset should be set to the "percent" of the expected job duration
.should('have.css', 'animation-delay')
.and('match', /([\d\.]+)s/) // NOTE the delay should be negative
.then((number) => {
// convert the duration string into a number that we can test
cy.wrap(Number(number.match(/([\d\.]+)s/)[1]))
// ensure this number is ±5 from the expected value
// (give it a little bit of margin to allow for timing error)
.should('closeTo', MEAN_ELAPSED_TIME * (percent / 100), 5)
})
}
})
})
Loading

0 comments on commit 902a539

Please sign in to comment.