Skip to content

Commit

Permalink
Export project interactions Sort by functionality (#7500)
Browse files Browse the repository at this point in the history
* Layout test scenarios - Sort export project interaction list

Sort a default company export interaction list

* Added test coverage for company export interaction

* Added export interaction collection list test

* Update sandbox server `/v4/export/:exportId` endpoint error response

* Fix export interaction tab navigation failing test

* Moved a constant functions declaration

Is a best practice to declare constant functions in the beginning of the codebase before calling, in order the javascript interpreter can locate.
This action being reverted and noted as part of flakiness/tech debt.

* Use interaction `subject` rather than export `title`

Amend the current implementation of export interaction list by using `subject` rather than export interaction `title` on the list because is already on the header and repetitive each details .
  • Loading branch information
dredmonds committed Feb 11, 2025
1 parent 50da652 commit 110857c
Show file tree
Hide file tree
Showing 13 changed files with 265 additions and 63 deletions.
6 changes: 3 additions & 3 deletions src/client/modules/ExportPipeline/Export.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ const StyledLink = styled('a')({

export const CompanyLink = (props) => (
<ExportResource.Inline {...props}>
{(exportProject) => (
{({ company }) => (
<StyledLink
data-test="export-company-link"
href={urls.companies.detail(exportProject.company.id)}
href={urls.companies.detail(company.id)}
>
{exportProject.company.name.toUpperCase()}
{company.name.toUpperCase()}
</StyledLink>
)}
</ExportResource.Inline>
Expand Down
45 changes: 24 additions & 21 deletions src/client/modules/ExportPipeline/ExportInteractionsList/index.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import React from 'react'

import { LEVEL_SIZE } from '@govuk-react/constants'
import { H2 } from 'govuk-react'

import Interactions from '../../../components/Resource/Interactions'
import { formatDate, DATE_FORMAT_FULL } from '../../../utils/date-utils'
import { CollectionItem } from '../../../components'
import { ExportProjectTitle } from '../Export'
import urls from '../../../../lib/urls'
import { SORT_OPTIONS_EXPORT_INTERACTION } from '../constants'

const ExportInteractionsList = ({ interactions = [], exportId }) =>
const ExportInteractionsList = ({ interactions = [] }) =>
interactions.length === 0 ? null : (
<ul data-test="export-interactions-list">
{interactions.map((item) => (
<CollectionItem
key={item.id}
headingText={<ExportProjectTitle id={exportId} />}
headingUrl={urls.exportPipeline.interactions.details(exportId)}
headingText={item.subject}
headingUrl={urls.exportPipeline.interactions.details(item.id)}
metadata={[
{
label: 'Date:',
Expand All @@ -40,21 +43,21 @@ const ExportInteractionsList = ({ interactions = [], exportId }) =>
)

export default ({ exportId }) => (
<Interactions.Paginated
id="export-interactions"
heading="interactions"
shouldPluralize={true}
noResults="You don't have any export interactions."
payload={{ company_export_id: exportId }}
sortOptions={[
// These values are assumed as the BE work hasn't been implemented yet
{ value: 'created_on:desc', name: 'Recently created' },
{ value: 'company.name:asc', name: 'Company A-Z' },
{ value: 'subject:asc', name: 'Subject A-Z' },
]}
>
{(page) => (
<ExportInteractionsList interactions={page} exportId={exportId} />
)}
</Interactions.Paginated>
<>
<H2 size={LEVEL_SIZE[3]}>Interactions</H2>
<p>
An interaction could be a meeting, call, email or another activity
associated with this export.
</p>
<Interactions.Paginated
id="export-interactions"
heading="interactions"
shouldPluralize={true}
noResults="You don't have any export interactions."
payload={{ company_export_id: exportId }}
sortOptions={SORT_OPTIONS_EXPORT_INTERACTION}
>
{(page) => <ExportInteractionsList interactions={page} />}
</Interactions.Paginated>
</>
)
6 changes: 6 additions & 0 deletions src/client/modules/ExportPipeline/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export const SORT_OPTIONS = [
},
]

export const SORT_OPTIONS_EXPORT_INTERACTION = [
{ name: 'Recently created', value: '-created_on' },
{ name: 'Company name A-Z', value: 'company__name' },
{ name: 'Subject A-Z', value: 'subject' },
]

export const EXPORT_POTENTIAL_OPTIONS = [
{ label: 'High', value: 'high' },
{ label: 'Medium', value: 'medium' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe('ExportInteractionsList', () => {
}

const interaction = {
id: 123,
date: '2024-12-23',
contacts: [
{
Expand All @@ -30,6 +31,7 @@ describe('ExportInteractionsList', () => {
service: {
name: 'Account management : General',
},
subject: 'Video call meeting to Baileys',
}

const interactionList = [
Expand All @@ -56,8 +58,8 @@ describe('ExportInteractionsList', () => {

cy.get('@firstItem').within(() => {
cy.get('h3 a')
.should('have.text', 'Baileys export to Brazil')
.and('have.attr', 'href', '/export/1/interactions/details')
.should('have.text', 'Video call meeting to Baileys')
.and('have.attr', 'href', '/export/123/interactions/details')

const items = '[data-test="metadata-item"]'
cy.get(items).should('have.length', 4)
Expand All @@ -77,6 +79,7 @@ describe('ExportInteractionsList', () => {

it('should render a list of multiple contacts', () => {
const interaction = {
id: 224,
date: '2024-12-23',
contacts: [
{
Expand All @@ -93,6 +96,7 @@ describe('ExportInteractionsList', () => {
service: {
name: 'Account management : General',
},
subject: 'Video call meeting to Baileys',
}
cy.mountWithProvider(<ExportInteractionsList />, {
tasks: {
Expand Down Expand Up @@ -138,6 +142,7 @@ describe('ExportInteractionsList', () => {
service: {
name: 'Account management : General',
},
subject: 'Send email to Baileys',
}
cy.mountWithProvider(<ExportInteractionsList />, {
tasks: {
Expand Down
58 changes: 23 additions & 35 deletions test/component/cypress/specs/ExportPipeline/TabNav.cy.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,77 +4,65 @@ import Export from '../../../../../src/client/modules/ExportPipeline/Export'
import { assertBreadcrumbs } from '../../../../functional/cypress/support/assertions'
import { assertTabNav } from '../../../../end-to-end/cypress/support/assertions'
import urls from '../../../../../src/lib/urls'
import fixtures from '../../../../functional/cypress/fixtures'

const exportProject = {
id: '1',
title: 'Rolls Royce to UAE',
company: {
id: '2',
name: 'Rolls Royce',
},
team_members: [
{
name: 'David Jones',
id: '1',
},
],
contacts: [
{
name: 'Johan Person',
email: '[email protected]',
id: '1',
},
],
}
const exportProjectDetails = fixtures.export.exportProjectDetails

describe('Export project tab navigation', () => {
it('should render the breadcrumbs for details', () => {
cy.mountWithProvider(<Export />, {
initialPath: '/export/1/details',
initialPath: `/export/${exportProjectDetails.id}/details`,
tasks: {
Export: () => exportProject,
Export: () => exportProjectDetails,
},
})
assertBreadcrumbs({
Home: urls.exportPipeline.index(),
[exportProject.title]: null,
[exportProjectDetails.title]: null,
})
})

it('should render the same breadcrumbs for interactions', () => {
cy.mountWithProvider(<Export />, {
initialPath: '/export/1/interactions/',
initialPath: `/export/${exportProjectDetails.id}/interactions/`,
tasks: {
Export: () => exportProject,
Export: () => exportProjectDetails,
},
})
assertBreadcrumbs({
Home: urls.exportPipeline.index(),
[exportProject.title]: null,
[exportProjectDetails.title]: null,
})
})

it('should render a company link and page heading', () => {
cy.mountWithProvider(<Export />, {
initialPath: '/export/1/details',
initialPath: `/export/${exportProjectDetails.id}/details`,
tasks: {
Export: () => exportProject,
Export: () => exportProjectDetails,
},
})

cy.get('[data-test=export-company-link]')
.should('have.text', exportProject.company.name.toUpperCase())
.should('have.attr', 'href', `/companies/${exportProject.company.id}`)
.should('have.text', exportProjectDetails.company.name.toUpperCase())
.should(
'have.attr',
'href',
`/companies/${exportProjectDetails.company.id}`
)

cy.get('[data-test="heading"]').should('have.text', 'Rolls Royce to UAE')
cy.get('[data-test="heading"]').should(
'have.text',
exportProjectDetails.title
)
})

it('should render two tabs: Project details and Interactions', () => {
cy.mountWithProvider(<Export />, {
initialPath: '/export/1/details',
initialPath: `/export/${exportProjectDetails.id}/details`,
tasks: {
Export: () => Promise.resolve(exportProject),
TASK_GET_EXPORT_DETAIL: () => Promise.resolve(exportProject),
Export: () => Promise.resolve(exportProjectDetails),
TASK_GET_EXPORT_DETAIL: () => Promise.resolve(exportProjectDetails),
},
})
assertTabNav({
Expand Down
1 change: 1 addition & 0 deletions test/functional/cypress/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ module.exports = {
},
export: {
historyWithInteractions: require('../../../sandbox/fixtures/v4/export/history-with-interactions.json'),
exportProjectDetails: require('../../../sandbox/fixtures/v4/company/company-with-export-project-details.json'),
},

omis: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import fixtures from '../../fixtures'
import { assertUrl } from '../../support/assertions'

const companyExportProject = fixtures.export.exportProjectDetails
const queryParams = '&limit=10&offset=0'

describe('Export project interaction collection list', () => {
context('When export project render with multiple interaction linked', () => {
beforeEach(() => {
cy.intercept(
'GET',
`/api-proxy/v4/interaction?company_export_id=${companyExportProject.id}&sortby=-created_on${queryParams}`
).as('apiRequest')
cy.visit(`/export/${companyExportProject.id}/interactions`)
})

it('should display the interactions list', () => {
cy.get('[data-test="collection-header-name').should(
'contain',
'1,233 interactions'
)
// should show current and total pages
cy.contains('Page 1 of 124').should('be.visible')

// should display 10 interactions per page
cy.get('[data-test="collection-item"]').should('have.length', 10)

// should show the pagination
cy.get('[data-test="pagination"]').should('be.visible')
cy.get('[data-test="page-number-active"]').should('have.text', '1')
cy.get('[data-test="page-number"]').should('contain', '124')
cy.get('[data-test="next"]').should('have.text', 'Next page')
})
})
})

describe('Export interaction collections filters "Sort by"', () => {
context('Sort by filters with default "Recently created"', () => {
const element = '[data-test="sortby"] select'

beforeEach(() => {
cy.intercept(
'GET',
`/api-proxy/v4/interaction?company_export_id=${companyExportProject.id}&sortby=-created_on${queryParams}`
).as('apiRequest')
cy.visit(`/export/${companyExportProject.id}/interactions`)
})

it('should render "Sort by" label', () => {
cy.get('[data-test="sortby"]').should('contain', 'Sort by')
})

it('should have all sort by options', () => {
cy.get('[data-test="sortby"] option').then((options) => {
const sortOptions = [...options].map((o) => ({
value: o.value,
name: o.label,
}))
expect(sortOptions).to.deep.eq([
{ value: '-created_on', name: 'Recently created' },
{ value: 'company__name', name: 'Company name A-Z' },
{ value: 'subject', name: 'Subject A-Z' },
])
})
})

it('should sort by "Company name A-Z"', () => {
cy.get(element).select('Company name A-Z')
assertUrl('sortby=company__name')
})

it('should sort by "Subject A-Z"', () => {
cy.get(element).select('Subject A-Z')
assertUrl('sortby=subject')
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"id": "f5bc555e-0eba-4a7e-abe9-db89a78afc5c",
"company": {
"name": "Venus Ltd",
"id": "0f5216e0-849f-11e6-ae22-56b6b6499611"
},
"owner": {
"name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"dit_team": {
"name": "Agricultural Engineers Association Ltd",
"id": "d2f02898-9698-e211-a939-e4115bead28a"
},
"id": "c0e09068-ce3e-4798-9437-2d258d83881e"
},
"team_members": [
{
"name": "Puck Head",
"id": "e83a608e-84a4-11e6-ae22-56b6b6499611"
},
{
"name": "Jacob Webster",
"id": "b4848b30-f532-4cfc-a063-b064d8435b65"
}
],
"contacts": [
{
"name": "Johnny Cakeman",
"email": "[email protected]",
"id": "9b1138ab-ec7b-497f-b8c3-27fed21694ef"
}
],
"destination_country": {
"name": "Åland Islands",
"id": "ff996375-8adf-459a-b2a6-a477b66c7c6a"
},
"sector": {
"name": "Advanced engineering : Metallurgical process plant",
"id": "a422c9d2-5f95-e211-a939-e4115bead28a"
},
"exporter_experience": {
"name": "Exported in the last 12 months, but has not won an export order by having an export plan",
"id": "8937c359-157e-41dd-8520-679383847ea0"
},
"estimated_win_date": "2025-03-01",
"estimated_export_value_amount": "500000",
"estimated_export_value_years": {
"name": "4 years",
"id": "3f289d56-aec1-4472-a046-10828cad4992"
},
"export_potential": "high",
"created_on": "2025-01-15T10:38:12.694291Z",
"modified_on": "2025-01-15T10:40:30.928565Z",
"archived": false,
"archived_on": null,
"archived_reason": "",
"title": "Export Project for Venus ltd - TEST",
"status": "active",
"notes": "",
"created_by": "c0e09068-ce3e-4798-9437-2d258d83881e",
"modified_by": "c0e09068-ce3e-4798-9437-2d258d83881e",
"archived_by": null
}
Loading

0 comments on commit 110857c

Please sign in to comment.