Skip to content

Commit c61dd24

Browse files
committed
Add test
1 parent a90c6c7 commit c61dd24

File tree

3 files changed

+92
-18
lines changed

3 files changed

+92
-18
lines changed

src/components/cylc/table/Table.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,13 @@ const headers = ref([
253253
])
254254
255255
/**
256-
* Ensure that empty/nullish values are always sorted last regardless of sort order.
256+
* A comparator that ensures empty/nullish values are always sorted last regardless of sort order.
257+
*
258+
* @param {string} key - The key for the column being sorted.
259+
* @param {function} sortFunc - The comparator function to use if both values are truthy or zero.
260+
* @param {any} a - The first value to compare.
261+
* @param {any} b - The second value to compare.
262+
* @returns {number} A number > 0 if a > b, or < 0 if a < b, or 0 if a === b
257263
*/
258264
function nullSorter (key, sortFunc, a, b) {
259265
const x = isTruthyOrZero(a)

tests/e2e/specs/table.cy.js

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717

1818
import TaskState from '@/model/TaskState.model'
1919

20+
// Get cell text for a column by header name, as an array
21+
Cypress.Commands.add('getColumnValues', (header) => {
22+
return cy.get('.c-table th')
23+
.contains(header)
24+
.parents('th')
25+
.then(($th) => cy.get(`.c-table tr > td:nth-child(${$th.index() + 1})`))
26+
.then(($cells) => Array.from($cells, (cell) => cell.innerText.trim()))
27+
})
28+
2029
const initialNumRows = 7
2130

2231
describe('Table view', () => {
@@ -30,7 +39,7 @@ describe('Table view', () => {
3039
.should('be.visible')
3140
})
3241

33-
describe('Filters', () => {
42+
describe('Filters & sorting', () => {
3443
it('Should filter by ID', () => {
3544
cy.get('.c-table table > tbody > tr')
3645
.should('have.length', initialNumRows)
@@ -51,6 +60,7 @@ describe('Table view', () => {
5160
.should('be.visible')
5261
}
5362
})
63+
5464
it('Should filter by task state', () => {
5565
cy
5666
.get('.c-table table > tbody > tr')
@@ -73,6 +83,7 @@ describe('Table view', () => {
7383
.should('have.length', 1)
7484
.should('be.visible')
7585
})
86+
7687
it('Should filter by ID and states', () => {
7788
cy
7889
.get('.c-table table > tbody > tr')
@@ -95,6 +106,7 @@ describe('Table view', () => {
95106
.get('td [data-cy-task-name=eventually_succeeded]')
96107
.should('be.visible')
97108
})
109+
98110
it('displays and sorts latest job run time', () => {
99111
const nonzeroValues = [
100112
'00:00:01',
@@ -107,27 +119,48 @@ describe('Table view', () => {
107119
cy.get('.c-table')
108120
.contains('th', 'Run Time').as('dTHeader')
109121
.click()
110-
.get('tbody tr td:nth-child(10)') // 10th column
111-
.then(($cells) => {
112-
expect(Array.from($cells, (cell) => cell.innerText.trim())).to.deep.equal([
113-
...nonzeroValues,
114-
'', // no value sorted after numbers
115-
'',
116-
])
117-
})
122+
cy.getColumnValues('Run Time').should('deep.equal', [
123+
...nonzeroValues,
124+
'', // no value sorted after numbers
125+
'',
126+
])
118127
// sort dt-mean descending
119128
cy.get('@dTHeader')
120129
.click()
121-
.get('tbody tr td:nth-child(10)')
122-
.then(($cells) => {
123-
expect(Array.from($cells, (cell) => cell.innerText.trim())).to.deep.equal([
124-
...nonzeroValues.slice().reverse(),
125-
'', // no value still sorted after numbers
126-
'',
127-
])
128-
})
130+
cy.getColumnValues('Run Time').should('deep.equal', [
131+
...nonzeroValues.slice().reverse(),
132+
'', // no value still sorted after numbers
133+
'',
134+
])
129135
})
130136
})
137+
138+
it('sorts finish time including estimates', () => {
139+
const nonzeroValues = [
140+
'2020-11-08T22:57:16Z',
141+
'2020-11-08T22:57:19Z',
142+
'2020-11-08T22:57:33Z',
143+
'2020-11-08T22:57:41Z',
144+
'2020-11-08T23:00:36Z',
145+
]
146+
// sort finish time ascending
147+
cy.get('.c-table')
148+
.contains('th', 'Finish').as('header')
149+
.click()
150+
cy.getColumnValues('Finish').should('deep.equal', [
151+
...nonzeroValues,
152+
'', // no value sorted after numbers
153+
'',
154+
])
155+
// sort finish time descending
156+
cy.get('@header')
157+
.click()
158+
cy.getColumnValues('Finish').should('deep.equal', [
159+
...nonzeroValues.slice().reverse(),
160+
'', // no value still sorted after numbers
161+
'',
162+
])
163+
})
131164
})
132165

133166
function addView (view) {

tests/unit/components/cylc/table/table.vue.spec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,40 @@ describe('Table component', () => {
8383
{ order: expected }
8484
])
8585
})
86+
87+
describe('nullSorter', () => {
88+
it.each([
89+
['a', 'b', 'asc', -1],
90+
['a', 'b', 'desc', 1],
91+
['a', '', 'asc', -1],
92+
['a', '', 'desc', 1],
93+
['a', null, 'asc', -1],
94+
['a', null, 'desc', 1],
95+
[null, 'a', 'asc', 1],
96+
[null, 'a', 'desc', -1],
97+
['a', undefined, 'asc', -1],
98+
['a', undefined, 'desc', 1],
99+
[0, null, 'asc', -1],
100+
[0, null, 'desc', 1],
101+
[null, null, 'asc', 0],
102+
[null, null, 'desc', 0],
103+
['', null, 'asc', 0],
104+
['', null, 'desc', 0],
105+
])('$2: $0, $1 -> $3', (a, b, order, expected) => {
106+
const key = 'key'
107+
const wrapper = mountFunction({
108+
props: {
109+
tasks: [],
110+
initialOptions: {
111+
sortBy: [{ key, order }]
112+
}
113+
}
114+
})
115+
const comparator = (x, y) => {
116+
return order === 'asc' ? x.localeCompare(y) : y.localeCompare(x)
117+
}
118+
expect(wrapper.vm.nullSorter(key, comparator, a, b)).toEqual(expected)
119+
})
120+
})
86121
})
87122
})

0 commit comments

Comments
 (0)