From d1f48f1cc5da2012295aacd450a685b4a84c5c9e Mon Sep 17 00:00:00 2001 From: Clara Jordan Date: Tue, 21 Jun 2022 21:12:37 +0100 Subject: [PATCH] Small a11y fixes; test sorting and query strings --- .../src/integration/flows.spec.ts | 83 +++++++++++++ .../src/app/components/flows-table.tsx | 14 ++- libs/hpc-dummy/src/lib/data.ts | 4 +- libs/hpc-dummy/src/lib/dummy.ts | 110 +++++++++++++++++- 4 files changed, 204 insertions(+), 7 deletions(-) diff --git a/apps/hpc-ftsadmin-e2e/src/integration/flows.spec.ts b/apps/hpc-ftsadmin-e2e/src/integration/flows.spec.ts index 8bb06fb5e..13ffc8758 100644 --- a/apps/hpc-ftsadmin-e2e/src/integration/flows.spec.ts +++ b/apps/hpc-ftsadmin-e2e/src/integration/flows.spec.ts @@ -38,4 +38,87 @@ describe('flows', () => { .and('contain.text', 'child') .and('not.contain.text', 'parent'); }); + + describe('sorting', () => { + it('is inititally sorted by updated/created descending', () => { + cy.get('[data-test="header-updatedCreated"]').should( + 'have.attr', + 'aria-sort', + 'descending' + ); + cy.get('[data-test="flows-table-id"]') + .first() + .should('have.text', '1 v1'); + cy.get('[data-test="header-id"]').should('not.have.attr', 'aria-sort'); + }); + + it('one click triggers sorting descending', () => { + cy.get('[data-test="header-id"]').click(); + + cy.get('[data-test="header-id"]').should( + 'have.attr', + 'aria-sort', + 'descending' + ); + cy.get('[data-test="flows-table-id"]') + .first() + .should('have.text', '3 v1'); + }); + + it('two clicks triggers sorting ascending', () => { + cy.get('[data-test="header-id"]').click(); + cy.get('[data-test="header-id"]').click(); + + cy.get('[data-test="header-id"]').should( + 'have.attr', + 'aria-sort', + 'ascending' + ); + cy.get('[data-test="flows-table-id"]') + .first() + .should('have.text', '1 v1'); + }); + + it('can switch to sorting by a different property', () => { + cy.get('[data-test="header-id"]').click(); + cy.get('[data-test="header-sourceOrganization"]').click(); + + cy.get('[data-test="header-sourceOrganization"]').should( + 'have.attr', + 'aria-sort', + 'descending' + ); + cy.get('[data-test="header-id"]').should('not.have.attr', 'aria-sort'); + cy.get('[data-test="flows-table-id"]') + .first() + .should('have.text', '3 v1'); + }); + }); + + describe('query strings', () => { + it('updates query string on sort', () => { + cy.get('[data-test="header-id"]').click(); + cy.location('search').should('include', 'orderBy=flow.id&orderDir=DESC'); + }); + + it('updates query string on changing pagination', () => { + cy.get( + '[data-test="flows-table-pagination"] .MuiTablePagination-select' + ).click(); + cy.get('[data-value="10"]').click(); + cy.location('search').should('include', 'rowsPerPage=10'); + }); + + it('loads correct settings when visiting from a query string link', () => { + cy.visit('/flows?orderBy=flow.id&orderDir=DESC&page=0&rowsPerPage=10'); + cy.get('[data-test="header-id"]').should( + 'have.attr', + 'aria-sort', + 'descending' + ); + cy.get( + '[data-test="flows-table-pagination"] .MuiTablePagination-select' + ).should('have.text', '10'); + }); + }); }); diff --git a/apps/hpc-ftsadmin/src/app/components/flows-table.tsx b/apps/hpc-ftsadmin/src/app/components/flows-table.tsx index d37e6e08e..a03436c73 100644 --- a/apps/hpc-ftsadmin/src/app/components/flows-table.tsx +++ b/apps/hpc-ftsadmin/src/app/components/flows-table.tsx @@ -181,7 +181,17 @@ export default function FlowsTable(props: FlowsTableProps) { {props.headers.map((header) => ( - + {header.sortable ? ( {t.t(lang, (s) => s.components.flowsTable.sortBy)} +
{t.t( lang, @@ -431,6 +442,7 @@ export default function FlowsTable(props: FlowsTableProps) { ({ - flows: this.data.flows, - flowCount: this.data.flows.length.toString(), - }) + async (params: flows.SearchFlowsParams) => { + const { flowSearch } = params; + const { flows } = this.data; + + if (flowSearch.orderBy) { + flows.sort((a, b) => { + let returnVal = 0; + switch (flowSearch.orderBy) { + case 'flow.id': + returnVal = a.id > b.id ? 1 : -1; + break; + case 'flow.versionID': + returnVal = a.versionID > b.versionID ? 1 : -1; + break; + case 'flow.updatedAt': + returnVal = a.updatedAt > b.updatedAt ? 1 : -1; + break; + case 'externalReference.systemID': + if ( + a.externalReference?.systemID && + b.externalReference?.systemID + ) { + returnVal = + a.externalReference?.systemID > + b.externalReference?.systemID + ? 1 + : -1; + } + break; + case 'flow.amountUSD': + returnVal = + parseInt(a.amountUSD) > parseInt(b.amountUSD) ? 1 : -1; + break; + case 'source.organization.name': { + const sourceOrgA = a.organizations?.find( + (org) => org.refDirection === 'source' + ); + const sourceOrgB = a.organizations?.find( + (org) => org.refDirection === 'source' + ); + if (sourceOrgA && sourceOrgB) { + returnVal = sourceOrgA.name > sourceOrgB.name ? 1 : -1; + } + break; + } + case 'destination.organization.name': { + const destOrgA = a.organizations?.find( + (org) => org.refDirection === 'destination' + ); + const destOrgB = a.organizations?.find( + (org) => org.refDirection === 'destination' + ); + if (destOrgA && destOrgB) { + returnVal = destOrgA.name > destOrgB.name ? 1 : -1; + } + break; + } + case 'destination.planVersion.name': { + const planA = a.plans && a.plans[0]; + const planB = b.plans && b.plans[0]; + if (!planA) { + returnVal = -1; + } else if (!planB) { + returnVal = 1; + } else { + returnVal = planA.name > planB.name ? 1 : -1; + } + break; + } + case 'destination.location.name': { + const locationA = a.locations && a.locations[0]; + const locationB = b.locations && b.locations[0]; + if (!locationA) { + returnVal = -1; + } else if (!locationB) { + returnVal = 1; + } else { + returnVal = locationA.name > locationB.name ? 1 : -1; + } + break; + } + case 'destination.usageYear.year': { + const yearA = a.usageYears?.find( + (org) => org.refDirection === 'destination' + ); + const yearB = a.usageYears?.find( + (org) => org.refDirection === 'destination' + ); + if (yearA && yearB) { + returnVal = yearA.year > yearB.year ? 1 : -1; + } + break; + } + } + + return flowSearch.orderDir === 'DESC' + ? returnVal * -1 + : returnVal; + }); + } + + return { + flows, + flowCount: flows.length.toString(), + }; + } ), }, operations: {