diff --git a/src/middleware/lpa-overview.middleware.js b/src/middleware/lpa-overview.middleware.js index 489e545ea..d5b4ffcd1 100644 --- a/src/middleware/lpa-overview.middleware.js +++ b/src/middleware/lpa-overview.middleware.js @@ -51,6 +51,8 @@ const fetchEntityCounts = fetchOneFromAllDatasets({ * @param {string} [dataset.endpoint] - Optional endpoint URL * @param {string} dataset.status - Dataset status * @param {number} dataset.endpointCount - Number of endpoints + * @param {number} dataset.endpointErrorCount - Number of endpoints with error + * @param {number} dataset.issueCount - Number of issues * @returns {number[]} Updated accumulator */ const orgStatsReducer = (accumulator, dataset) => { @@ -214,6 +216,7 @@ export function prepareDatasetObjects (req, res, next) { } const endpointCount = datasetEndpoints.length + const endpointErrorCount = datasetEndpoints.filter(endpoint => endpoint.latest_status !== '200').length const allError = datasetEndpoints.every(endpoint => endpoint.latest_status !== '200') const someError = datasetEndpoints.some(endpoint => endpoint.latest_status !== '200') const httpStatus = allError ? datasetEndpoints[0]?.latest_status : undefined @@ -230,7 +233,7 @@ export function prepareDatasetObjects (req, res, next) { status = 'Live' } - return { dataset, error, issueCount, status, endpointCount } + return { dataset, error, issueCount, status, endpointCount, endpointErrorCount } }) next() @@ -259,7 +262,6 @@ export function prepareOverviewTemplateParams (req, res, next) { for (const provision of provisions ?? []) { provisionData.set(provision.dataset, provision) } - // add in any of the missing key 8 datasets const keys = new Set(datasets.map(d => d.dataset)) availableDatasets.forEach((dataset) => { @@ -276,10 +278,8 @@ export function prepareOverviewTemplateParams (req, res, next) { }) const isODPMember = provisions.findIndex((p) => p.project === 'open-digital-planning') >= 0 - const totalDatasets = datasets.length const [datasetsWithEndpoints, datasetsWithIssues, datasetsWithErrors] = datasets.reduce(orgStatsReducer, [0, 0, 0]) - const datasetsByReason = _.groupBy(datasets, (ds) => { const reason = provisionData.get(ds.dataset)?.provision_reason switch (reason) { diff --git a/src/routes/schemas.js b/src/routes/schemas.js index e30314c04..af2c006e2 100644 --- a/src/routes/schemas.js +++ b/src/routes/schemas.js @@ -128,7 +128,8 @@ const DatasetItem = v.strictObject({ project: v.optional(v.string()), // synthetic entry, represents a user friendly count (e.g. count missing value in a column as 1 issue) numIssues: v.optional(v.number()), - notice: v.optional(DeadlineNoticeField) + notice: v.optional(DeadlineNoticeField), + endpointErrorCount: v.optional(v.number()) }) export const OrgOverviewPage = v.strictObject({ diff --git a/src/views/organisations/overview.html b/src/views/organisations/overview.html index 7c120fbe9..3c2f4e682 100644 --- a/src/views/organisations/overview.html +++ b/src/views/organisations/overview.html @@ -38,7 +38,8 @@

{{ dataset.error }}

{% endif %} {% elif dataset.status == 'Needs fixing' %} -

There {{ "is" | pluralise(dataset.issueCount) }} {{ dataset.issueCount }} {{ "issue" | pluralise(dataset.issueCount) }} in this dataset

+ {% set totalIssues = (dataset.issueCount or 0) + (dataset.endpointErrorCount or 0) %} +

There {{ "is" | pluralise(totalIssues) }} {{ totalIssues }} {{ "issue" | pluralise(totalIssues) }} in this dataset

{% else %}

Endpoint URL submitted

{% endif %} @@ -111,7 +112,7 @@

{{datasetsWithErrors}} - endpoint URL{{ "s" if (datasetsWithErrors != 1) }} with errors + dataset{{ "s" if (datasetsWithErrors != 1) }} with endpoint errors
diff --git a/test/unit/middleware/lpa-overview.middleware.test.js b/test/unit/middleware/lpa-overview.middleware.test.js index a0617a891..8514047ea 100644 --- a/test/unit/middleware/lpa-overview.middleware.test.js +++ b/test/unit/middleware/lpa-overview.middleware.test.js @@ -30,28 +30,32 @@ const reqTemplate = { issueCount: 0, endpointCount: 1, error: undefined, - status: 'Live' + status: 'Live', + endpointErrorCount: 0 }, { dataset: 'dataset2', issueCount: 0, endpointCount: 0, error: undefined, - status: 'Needs fixing' + status: 'Needs fixing', + endpointErrorCount: 0 }, { dataset: 'dataset3', issueCount: 0, endpointCount: 1, error: undefined, - status: 'Error' + status: 'Error', + endpointErrorCount: 1 }, { dataset: 'dataset4', issueCount: 0, endpointCount: 0, error: 'There was a 404 error', - status: 'Error' + status: 'Error', + endpointErrorCount: 1 } ], @@ -80,6 +84,7 @@ describe('lpa-overview.middleware', () => { describe('prepareOverviewTemplateParams', () => { it('should render the overview page', async () => { const req = structuredClone(reqTemplate) + req.datasets[1].issueCount = 1 const res = { render: vi.fn() } prepareOverviewTemplateParams(req, res, () => { }) @@ -88,12 +93,12 @@ describe('lpa-overview.middleware', () => { organisation: { name: 'Example LPA', organisation: 'LPA' }, datasets: { statutory: expect.arrayContaining([ - { endpointCount: 1, status: 'Live', dataset: 'dataset1', error: undefined, issueCount: 0 }, - { endpointCount: 1, status: 'Error', dataset: 'dataset3', error: undefined, issueCount: 0 } + { endpointCount: 1, status: 'Live', dataset: 'dataset1', error: undefined, issueCount: 0, endpointErrorCount: 0 }, + { endpointCount: 1, status: 'Error', dataset: 'dataset3', error: undefined, issueCount: 0, endpointErrorCount: 1 } ]), other: expect.arrayContaining([ - { endpointCount: 0, status: 'Needs fixing', dataset: 'dataset2', error: undefined, issueCount: 0 }, - { endpointCount: 0, status: 'Error', dataset: 'dataset4', error: 'There was a 404 error', issueCount: 0 } + { endpointCount: 0, status: 'Needs fixing', dataset: 'dataset2', error: undefined, issueCount: 1, endpointErrorCount: 0 }, + { endpointCount: 0, status: 'Error', dataset: 'dataset4', error: 'There was a 404 error', issueCount: 0, endpointErrorCount: 1 } ]) }, totalDatasets: 4, @@ -138,6 +143,33 @@ describe('lpa-overview.middleware', () => { expect(ds4.status).toBe('Error') expect(ds4.error).toBe(req.datasets[3].error) // Error message should be left untouched }) + + it('should display a combined count of issues and endpoint errors in the dataset', () => { + const req = structuredClone(reqTemplate) + req.datasets[1].issueCount = 1 + req.datasets[1].endpointErrorCount = 2 + const res = { render: vi.fn() } + + prepareOverviewTemplateParams(req, res, () => { }) + + const { doc } = getRenderedErrorCards(req.templateParams) + const hint = doc.querySelector('[data-dataset-status="Needs fixing"] .govuk-task-list__hint') + + expect(hint?.textContent.trim()).toBe('There are 3 issues in this dataset') + }) + + it('should display a count of issue when there is only one issue', () => { + const req = structuredClone(reqTemplate) + req.datasets[1].issueCount = 1 + const res = { render: vi.fn() } + + prepareOverviewTemplateParams(req, res, () => { }) + + const { doc } = getRenderedErrorCards(req.templateParams) + const hint = doc.querySelector('[data-dataset-status="Needs fixing"] .govuk-task-list__hint') + + expect(hint?.textContent.trim()).toBe('There is 1 issue in this dataset') + }) }) describe('prepareDatasetObjects()', () => { diff --git a/test/unit/views/organisations/lpaOverviewPage.test.js b/test/unit/views/organisations/lpaOverviewPage.test.js index 92c0cf67b..652f768b9 100644 --- a/test/unit/views/organisations/lpaOverviewPage.test.js +++ b/test/unit/views/organisations/lpaOverviewPage.test.js @@ -58,7 +58,7 @@ describe(`LPA Overview Page (seed: ${seed})`, () => { it('Datasets with errors gives the correct value', () => { expect(statsBoxes[1].textContent).toContain(params.datasetsWithErrors) - expect(statsBoxes[1].textContent).toMatch(/endpoint URLs? with errors/) + expect(statsBoxes[1].textContent).toMatch(/datasets? with endpoint errors/) }) it('Datasets with issues gives the correct value', () => {