diff --git a/changes.d/2100.feat.md b/changes.d/2100.feat.md
new file mode 100644
index 000000000..9a40cc43d
--- /dev/null
+++ b/changes.d/2100.feat.md
@@ -0,0 +1 @@
+Adding CPU time and Max RSS to Analysis Tools
diff --git a/public/img/redline.jpg b/public/img/redline.jpg
new file mode 100644
index 000000000..97bb61f86
Binary files /dev/null and b/public/img/redline.jpg differ
diff --git a/src/components/cylc/analysis/AnalysisTable.vue b/src/components/cylc/analysis/AnalysisTable.vue
index 21d99775c..b698074bf 100644
--- a/src/components/cylc/analysis/AnalysisTable.vue
+++ b/src/components/cylc/analysis/AnalysisTable.vue
@@ -56,7 +56,11 @@ along with this program. If not, see .
diff --git a/tests/component/specs/boxPlot.cy.js b/tests/component/specs/boxPlot.cy.js
index 2b770d6e8..eddcfe112 100644
--- a/tests/component/specs/boxPlot.cy.js
+++ b/tests/component/specs/boxPlot.cy.js
@@ -113,4 +113,16 @@ describe('BoxPlot', () => {
.get('.apexcharts-yaxis title')
.should('have.length', 3)
})
+ it('shows tooltip', () => {
+ // see: https://on.cypress.io/mounting-vue
+ cy.mount(BoxPlot, merge(mountOpts, {
+ props: {
+ tasks: [task1, task2],
+ },
+ }))
+ cy.get('.vue-apexcharts')
+ .trigger('mousemove', { clientX: 100, clientY: 100 })
+ .get('.apexcharts-tooltip')
+ .should('be.visible')
+ })
})
diff --git a/tests/e2e/specs/analysis.cy.js b/tests/e2e/specs/analysis.cy.js
index f1b3de733..b0d941d8c 100644
--- a/tests/e2e/specs/analysis.cy.js
+++ b/tests/e2e/specs/analysis.cy.js
@@ -16,7 +16,6 @@
*/
import { analysisTaskQuery } from '@/services/mock/json/index.cjs'
-import { clone } from 'lodash'
const sortedTasks = analysisTaskQuery.data.tasks.map(({ name }) => name).sort()
@@ -138,6 +137,20 @@ describe('Analysis view', () => {
cy
.get('.c-analysis table > tbody > tr')
.should('have.length', numTasks)
+ // Show Max RSS
+ cy
+ .get('#c-analysis-filter-task-timings')
+ .click({ force: true })
+ cy
+ .get('.v-list-item')
+ .contains('Max RSS')
+ .click({ force: true })
+ cy
+ .get('td')
+ .contains('MB')
+ cy
+ .get('.c-analysis table > tbody > tr')
+ .should('have.length', numTasks)
})
it('Should filter by task name, platform and timings', () => {
@@ -213,6 +226,43 @@ describe('Analysis view', () => {
.should('have.length', 1)
.should('be.visible')
})
+ it('Should show Max RSS', () => {
+ cy
+ .get('#c-analysis-filter-task-timings')
+ .click({ force: true })
+ cy
+ .get('.v-list-item')
+ .contains('Max RSS')
+ .click({ force: true })
+ cy
+ .get('td')
+ .contains('MB')
+ .should('be.visible')
+ cy
+ .get('.c-analysis table > tbody > tr')
+ .should('have.length', numTasks)
+ .should('be.visible')
+ cy
+ .get('.v-chip__content')
+ .should('not.exist')
+ })
+ it('Should show CPU Time', () => {
+ cy
+ .get('#c-analysis-filter-task-timings')
+ .click({ force: true })
+ cy
+ .get('.v-list-item')
+ .contains('CPU Time')
+ .click({ force: true })
+ cy
+ .get('td')
+ .contains('00:00:10')
+ .should('be.visible')
+ cy
+ .get('.v-chip__content')
+ .should('exist')
+ .contains('CPU Time')
+ })
})
})
@@ -238,6 +288,38 @@ describe('Analysis view', () => {
.get('.vue-apexcharts')
.should('not.exist')
})
+ it('Should show Max RSS', () => {
+ cy
+ .get('#c-analysis-filter-task-timings')
+ .click({ force: true })
+ cy
+ .get('.v-list-item')
+ .contains('Max RSS')
+ .click({ force: true })
+ cy
+ .get('.apexcharts-yaxis-label')
+ .should('have.length', numTasks)
+ cy
+ .get('.apexcharts-xaxis-label')
+ .contains('MB')
+ .should('be.visible')
+ })
+ it('Should show CPU Time', () => {
+ cy
+ .get('#c-analysis-filter-task-timings')
+ .click({ force: true })
+ cy
+ .get('.v-list-item')
+ .contains('CPU Time')
+ .click({ force: true })
+ cy
+ .get('.apexcharts-yaxis-label')
+ .should('have.length', numTasks)
+ cy
+ .get('.apexcharts-xaxis-label')
+ .contains('00:00:00')
+ .should('be.visible')
+ })
it('refreshes without getting bogus apexcharts error', () => {
// https://github.com/apexcharts/vue3-apexcharts/issues/79
@@ -258,7 +340,7 @@ describe('Analysis view', () => {
.then((els) => {
expect(
Array.from(els, (i) => i.textContent)
- ).to.deep.equal(sortedTasks)
+ ).to.deep.equal(['eventually_succeeded', 'succeeded', 'waiting'])
})
cy.get('[data-cy=box-plot-sort]')
.click()
@@ -266,7 +348,7 @@ describe('Analysis view', () => {
.then((els) => {
expect(
Array.from(els, (i) => i.textContent)
- ).to.deep.equal(clone(sortedTasks).reverse())
+ ).to.deep.equal(['waiting', 'succeeded', 'eventually_succeeded'])
})
})
})
@@ -554,5 +636,29 @@ describe('Filters and Options save state', () => {
.get('[data-cy="box-plot-sort-select"]')
.should('be.visible')
})
+ it('displays correct tooltip content for box plot', () => {
+ cy.get('.c-analysis [data-cy=box-plot-toggle]').click()
+ cy.get('[data-cy=box-plot-chart] .apexcharts-series path')
+ .first()
+ .trigger('mouseover', { force: true })
+ .trigger('mousemove', { force: true })
+
+ // Check tooltip content
+ cy.get('.apexcharts-tooltip')
+ .should('be.visible')
+ .contains('Maximum: 00:00:33')
+ cy.get('.apexcharts-tooltip')
+ .contains('Median')
+ cy.get('.apexcharts-tooltip')
+ .contains('Minimum')
+ // If timingOption is maxRss, check for Memory Allocated
+ cy.get('#c-analysis-filter-task-timings')
+ .invoke('val')
+ .then(val => {
+ if (val === 'Max RSS') {
+ cy.get('.apexcharts-tooltip').contains('Memory Allocated')
+ }
+ })
+ })
})
})
diff --git a/tests/unit/utils/tasks.spec.js b/tests/unit/utils/tasks.spec.js
index 956ae12e4..88a5c3120 100644
--- a/tests/unit/utils/tasks.spec.js
+++ b/tests/unit/utils/tasks.spec.js
@@ -112,8 +112,8 @@ describe('tasks', () => {
expect(formatDuration(0)).to.equal(undefined)
})
it('should change format of 0 seconds based on value of allowZeros', () => {
- expect(formatDuration(0, { allowZeros: false })).to.equal(undefined)
- expect(formatDuration(0, { allowZeros: true })).to.equal('00:00:00')
+ expect(formatDuration(0, false)).to.equal(undefined)
+ expect(formatDuration(0, true)).to.equal('00:00:00')
})
it('should not change format of non-zero values based on allowZeros', () => {
expect(formatDuration(42)).to.equal('00:00:42')