diff --git a/src/controllers/OrganisationsController.js b/src/controllers/OrganisationsController.js index 8c254f27..7e60719e 100644 --- a/src/controllers/OrganisationsController.js +++ b/src/controllers/OrganisationsController.js @@ -3,6 +3,7 @@ import performanceDbApi from '../services/performanceDbApi.js' // Assume you hav import logger from '../utils/logger.js' import { types } from '../utils/logging.js' import { dataSubjects } from '../utils/utils.js' +import { statusToTagClass } from '../filters/filters.js' // get a list of available datasets const availableDatasets = Object.values(dataSubjects) @@ -19,17 +20,10 @@ const availableDatasets = Object.values(dataSubjects) * @returns {object} - An object with a `tag` property containing the text label and CSS class. */ function getStatusTag (status) { - const statusToTagClass = { - Error: 'govuk-tag--red', - 'Needs fixing': 'govuk-tag--yellow', - Warning: 'govuk-tag--blue', - Issue: 'govuk-tag--blue' - } - return { tag: { text: status, - classes: statusToTagClass[status] + classes: statusToTagClass(status) } } } @@ -46,6 +40,9 @@ const organisationsController = { try { const lpa = req.params.lpa + const organisationResult = await datasette.runQuery(`SELECT name, organisation FROM organisation WHERE organisation = '${lpa}'`) + const organisation = organisationResult.formattedData[0] + const datasetsFilter = ['article-4-direction', 'article-4-direction-area', 'conservation-area', @@ -73,24 +70,23 @@ const organisationsController = { if (!keys.includes(dataset)) { datasets.push({ slug: dataset, - endpoint: null + endpoint: null, + issue_count: 0, + status: 'Not submitted' }) } }) const totalDatasets = datasets.length const [datasetsWithEndpoints, datasetsWithIssues, datasetsWithErrors] = datasets.reduce((accumulator, dataset) => { - if (dataset.endpoint !== null) accumulator[0]++ - if (dataset.issue) accumulator[1]++ - if (dataset.error) accumulator[2]++ + if (dataset.endpoint) accumulator[0]++ + if (dataset.status === 'Needs fixing') accumulator[1]++ + if (dataset.status === 'Error') accumulator[2]++ return accumulator }, [0, 0, 0]) const params = { - organisation: { - name: lpaOverview.name, - organisation: lpaOverview.organisation - }, + organisation, datasets, totalDatasets, datasetsWithEndpoints, @@ -100,7 +96,7 @@ const organisationsController = { res.render('organisations/overview.html', params) } catch (error) { - logger.error(error) + logger.warn('organisationsController.getOverview(): ' + error.message ?? error.errorMessage, { type: types.App }) next(error) } }, @@ -130,7 +126,7 @@ const organisationsController = { res.render('organisations/find.html', { alphabetisedOrgs }) } catch (err) { - logger.warn(err) + logger.warn('organisationsController.getOrganisations(): ' + err.message ?? err.errorMessage, { type: types.App }) next(err) } }, @@ -183,7 +179,7 @@ const organisationsController = { const datasetId = req.params.dataset try { - const organisationResult = await datasette.runQuery(`SELECT name FROM organisation WHERE organisation = '${lpa}'`) + const organisationResult = await datasette.runQuery(`SELECT name, organisation FROM organisation WHERE organisation = '${lpa}'`) const organisation = organisationResult.formattedData[0] const datasetResult = await datasette.runQuery(`SELECT name FROM dataset WHERE dataset = '${datasetId}'`) @@ -377,7 +373,8 @@ const organisationsController = { dataset, errorHeading, issueItems, - entry + entry, + issueType } res.render('organisations/issueDetails.html', params) diff --git a/src/filters/filters.js b/src/filters/filters.js index 2ce7bdb5..0dcdb5cb 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -6,6 +6,23 @@ import prettifyColumnName from './prettifyColumnName.js' import getFullServiceName from './getFullServiceName.js' import { makeDatasetSlugToReadableNameFilter } from './makeDatasetSlugToReadableNameFilter.js' +/** maps dataset status (as returned by performanceDbApi/getLpaOverview()) to a + * CSS class used by the govuk-tag component + */ +const statusToTagClassMapping = { + Error: 'govuk-tag--red', + 'Not submitted': 'govuk-tag--red', + 'Needs fixing': 'govuk-tag--yellow', + Warning: 'govuk-tag--blue', + Issue: 'govuk-tag--blue', // deprecated + Live: 'govuk-tag--green' +} + +export function statusToTagClass (status) { + console.assert(status in statusToTagClassMapping, `statusToTagClass: unknown status ${status}`) + return statusToTagClassMapping[status] +} + const { govukMarkdown, govukDateTime } = xGovFilters const addFilters = (nunjucksEnv, { datasetNameMapping }) => { @@ -20,6 +37,7 @@ const addFilters = (nunjucksEnv, { datasetNameMapping }) => { nunjucksEnv.addFilter('toErrorList', toErrorList) nunjucksEnv.addFilter('prettifyColumnName', prettifyColumnName) nunjucksEnv.addFilter('getFullServiceName', getFullServiceName) + nunjucksEnv.addFilter('statusToTagClass', statusToTagClass) } export default addFilters diff --git a/src/services/datasette.js b/src/services/datasette.js index 0048269b..976b1bb9 100644 --- a/src/services/datasette.js +++ b/src/services/datasette.js @@ -8,7 +8,7 @@ export default { * Executes a SQL query on the Datasette instance and returns the results. * * @param {string} query - The SQL query to execute. - * @returns {Promise<{data: object, formattedData: object}>} - A promise that resolves to an object with the following properties: + * @returns {Promise<{data: object, formattedData: object[]}>} - A promise that resolves to an object with the following properties: * - `data`: The raw data returned by Datasette. * - `formattedData`: The formatted data, with columns and rows parsed into a usable format. * @throws {Error} If the query fails or there is an error communicating with Datasette. diff --git a/src/services/performanceDbApi.js b/src/services/performanceDbApi.js index 830d3606..82d9013a 100644 --- a/src/services/performanceDbApi.js +++ b/src/services/performanceDbApi.js @@ -2,6 +2,7 @@ * Performance DB API service */ import datasette from './datasette.js' +import logger from '../utils/logger.js' // =========================================== @@ -41,14 +42,14 @@ fs.createReadStream('src/content/entityIssueMessages.csv') /** * @typedef {object} Dataset + * @property {'Not submitted' | 'Error' | 'Needs fixing' | 'Warning' | 'Live' } status * @property {string} endpoint + * @property {number} issue_count * @property {?string} error - * @property {?string} issue */ /** * @typedef {object} LpaOverview - * @property {string} name * @property {{ [dataset: string]: Dataset }} datasets */ @@ -80,27 +81,32 @@ export default { rle.resource, rle.exception, rle.status as http_status, - case - when (rle.status != '200') then 'Error' - when (it.severity = 'error') then 'Issue' - when (it.severity = 'warning') then 'Warning' - else 'No issues' - end as status, + case + when (rle.status is null) then 'Not Submitted' + when (rle.status != '200') then 'Error' + when (it.severity = 'error') then 'Needs fixing' + when (it.severity = 'warning') then 'Warning' + else 'Live' + end as status, case - when (it.severity = 'info') then '' - else i.issue_type - end as issue_type, - case - when (it.severity = 'info') then '' - else it.severity - end as severity, - it.responsibility, - COUNT( - case - when it.severity != 'info' then 1 - else null - end - ) as issue_count + when ((cast(rle.status as integer) > 200)) then format('There was a %s error accessing the data URL', rle.status) + else null + end as error, + case + when (it.severity = 'info') then '' + else i.issue_type + end as issue_type, + case + when (it.severity = 'info') then '' + else it.severity + end as severity, + it.responsibility, + COUNT( + case + when it.severity != 'info' then 1 + else null + end + ) as issue_count FROM provision p LEFT JOIN @@ -126,33 +132,22 @@ ORDER BY p.organisation, o.name; ` - const result = await datasette.runQuery(query) + if (result.formattedData.length === 0) { + logger.info(`No records found for LPA=${lpa}`) + } const datasets = result.formattedData.reduce((accumulator, row) => { - let error - if (row.http_status !== '200' || row.exception) { - error = row.exception ? row.exception : `endpoint returned with a status of ${row.http_status}` - } - - let issue - if (row.issue_count > 0) { - issue = `There are ${row.issue_count} issues in this dataset` - } - accumulator[row.dataset] = { endpoint: row.endpoint, - error, - issue + status: row.status, + issue_count: row.issue_count, + error: row.error } return accumulator }, {}) - return { - name: result.formattedData[0].name, - organisation: result.formattedData[0].organisation, - datasets - } + return { datasets } }, getResourceStatus: async (lpa, datasetId) => { @@ -206,13 +201,9 @@ ORDER BY ORDER BY it.severity` const result = await datasette.runQuery(sql) - return result.formattedData.map((row) => { - return { - num_issues: row.num_issues, - issue_type: row.issue_type, - resource: row.resource, - status: row.status - } + /* eslint camelcase: "off" */ + return result.formattedData.map(({ num_issues, issue_type, resource, status }) => { + return { num_issues, issue_type, resource, status } }) }, diff --git a/src/views/organisations/datasetTaskList.html b/src/views/organisations/datasetTaskList.html index 26d30fb9..20d9c916 100644 --- a/src/views/organisations/datasetTaskList.html +++ b/src/views/organisations/datasetTaskList.html @@ -1,3 +1,5 @@ +{% from "govuk/components/breadcrumbs/macro.njk" import govukBreadcrumbs %} + {% extends "layouts/main.html" %} {% from 'govuk/components/task-list/macro.njk' import govukTaskList %} @@ -10,6 +12,26 @@ {{ super() }} +{{ govukBreadcrumbs({ + items: [ + { + text: "Home", + href: "/manage" + }, + { + text: "Organisations", + href: '/organisations' + }, + { + text: organisation.name, + href: '/organisations/' + organisation.organisation + }, + { + text: dataset.name + } + ] +}) }} + {% endblock %} {% block content %} @@ -45,7 +67,7 @@

  1. Fix the errors indicated
  2. -
  3. Use the check service to make sure the data meets +
  4. Use the check service to make sure the data meets the standard
  5. Publish the updated data on the data URL
diff --git a/src/views/organisations/find.html b/src/views/organisations/find.html index eb577631..384cebe2 100644 --- a/src/views/organisations/find.html +++ b/src/views/organisations/find.html @@ -1,3 +1,5 @@ +{% from "govuk/components/breadcrumbs/macro.njk" import govukBreadcrumbs %} + {% extends "layouts/main.html" %} {% set serviceType = 'Submit' %} @@ -7,6 +9,18 @@ {{ super() }} +{{ govukBreadcrumbs({ + items: [ + { + text: "Home", + href: "/manage" + }, + { + text: "Organisations" + } + ] +}) }} + {% endblock %} {% block content %} diff --git a/src/views/organisations/get-started.html b/src/views/organisations/get-started.html index b9678e16..3c607134 100644 --- a/src/views/organisations/get-started.html +++ b/src/views/organisations/get-started.html @@ -79,7 +79,7 @@

  1. - The check service can help you understand + The check service can help you understand if your data is ready to submit or if you need to change anything before you publish it on your website.

    @@ -99,7 +99,7 @@

    1. Check your data + href="/">Check your data

  2. @@ -161,7 +161,7 @@

    -

    Use the submit +

    Use the submit data service to submit your data URL, your documentation URL and that the data is provided under the Open Government Licence.

    @@ -172,7 +172,7 @@

    1. Submit + href="/submit">Submit your data
    @@ -200,12 +200,12 @@

    - Whenever the data changes, update it on your endpoint URL. We will collect data from your endpoint URL + Whenever the data changes, update it on your data URL. We will collect data from your data URL every day.

    - Your endpoint URL needs to remain the same, don’t change it when you make updates. + Your data URL needs to remain the same, don’t change it when you make updates.

    diff --git a/src/views/organisations/issueDetails.html b/src/views/organisations/issueDetails.html index 571096ef..de968c4a 100644 --- a/src/views/organisations/issueDetails.html +++ b/src/views/organisations/issueDetails.html @@ -3,6 +3,7 @@ {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %} {% from "govuk/components/pagination/macro.njk" import govukPagination %} +{% from "govuk/components/breadcrumbs/macro.njk" import govukBreadcrumbs %} {% set serviceType = 'Submit'%} @@ -12,7 +13,39 @@ {% set pageName %}{{organisation.name}} - {{dataset.name}} - Issues{% endset %} {%endif%} +{% block beforeContent %} + +{{ super() }} + +{{ govukBreadcrumbs({ + items: [ + { + text: "Home", + href: "/manage" + }, + { + text: "Organisations", + href: '/organisations' + }, + { + text: organisation.name, + href: '/organisations/' + organisation.organisation + }, + { + text: dataset.name, + href: '/organisations/' + organisation.organisation + '/' + dataset.dataset + }, + { + text: issueType + } + ] +}) }} + +{% endblock %} + {% block content %} + +
    {% include "includes/_dataset-page-header.html" %}
    @@ -51,7 +84,7 @@

    1. Fix the errors indicated
    2. -
    3. Use the check service to make sure the data meets +
    4. Use the check service to make sure the data meets the standard
    5. Publish the updated data on the data URL
    diff --git a/src/views/organisations/overview.html b/src/views/organisations/overview.html index e83a6064..48f43f08 100644 --- a/src/views/organisations/overview.html +++ b/src/views/organisations/overview.html @@ -13,11 +13,14 @@ items: [ { text: "Home", - href: "/overview/start" + href: "/manage" }, { text: "Organisations", - href: "/overview/organisations" + href: "/organisations" + }, + { + text: organisation.name } ] }) }} @@ -40,17 +43,17 @@

    {{datasetsWithEndpoints}}/{{totalDatasets}} - datasets provided + datasets submitted
    {{datasetsWithErrors}} - datasets with errors + data URL with errors
    {{datasetsWithIssues}} - datasets with issues + datasets need fixing

    @@ -66,69 +69,34 @@

    Datasets

    {% endfor %} @@ -137,10 +105,4 @@

    -
    -
    -

    View your task list to fix and improve your datasets

    -
    -
    - {% endblock %} \ No newline at end of file diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js index 7c0315a7..054e48a5 100644 --- a/test/unit/dataset-details.test.js +++ b/test/unit/dataset-details.test.js @@ -3,7 +3,6 @@ import { describe, expect, it } from 'vitest' import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' -import config from '../../config/index.js' import { stripWhitespace } from '../utils/stripWhiteSpace.js' import { testValidationErrorMessage } from './validation-tests.js' import { mockDataSubjects } from './data.js' @@ -35,6 +34,14 @@ function errorTestFn ({ describe('dataset details View', () => { const params = { + organisation: { + name: 'mock org', + organisation: 'mock-org' + }, + dataset: { + name: 'mock dataset', + dataset: 'mock-dataset' + }, values: { dataset: 'mockDataset' }, @@ -42,9 +49,9 @@ describe('dataset details View', () => { } const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) const datasetName = mockDataSubjects.mockDataset.dataSets[0].value + runGenericPageTests(html, { - pageTitle: `Enter ${datasetName.toLowerCase()} details - Submit and update your planning data`, - serviceName: config.serviceNames.submit + pageTitle: `Enter ${datasetName.toLowerCase()} details - Submit and update your planning data` }) it('should render the correct header', () => { diff --git a/test/unit/datasetTaskListPage.test.js b/test/unit/datasetTaskListPage.test.js index 9f5fbfee..459ce7e0 100644 --- a/test/unit/datasetTaskListPage.test.js +++ b/test/unit/datasetTaskListPage.test.js @@ -23,7 +23,8 @@ addFilters(nunjucksEnv, { datasetNameMapping }) describe('Dataset Task List Page', () => { const params = { organisation: { - name: 'fake organisation' + name: 'mock org', + organisation: 'mock-org' }, dataset: { name: 'Article 4 direction area' @@ -73,7 +74,8 @@ describe('Dataset Task List Page', () => { const document = dom.window.document runGenericPageTests(html, { - pageTitle: 'fake organisation - Article 4 direction area - Task list - Submit and update your planning data' + pageTitle: 'mock org - Article 4 direction area - Task list - Submit and update your planning data', + breadcrumbs: [{ text: 'Home', href: '/manage' }, { text: 'Organisations', href: '/organisations' }, { text: 'mock org', href: '/organisations/mock-org' }, { text: 'Article 4 direction area' }] }) it('Renders the correct headings', () => { diff --git a/test/unit/findPage.test.js b/test/unit/findPage.test.js index 3bb18cc2..a6392d8a 100644 --- a/test/unit/findPage.test.js +++ b/test/unit/findPage.test.js @@ -53,7 +53,8 @@ describe('Organisations Find Page', () => { const document = dom.window.document runGenericPageTests(html, { - pageTitle: `Find your organisation - ${config.serviceNames.submit}` + pageTitle: `Find your organisation - ${config.serviceNames.submit}`, + breadcrumbs: [{ text: 'Home', href: '/manage' }, { text: 'Organisations' }] }) it('correct has a form element with the correct data-filter attribute', () => { diff --git a/test/unit/generic-page.js b/test/unit/generic-page.js index c2a901ae..053ca638 100644 --- a/test/unit/generic-page.js +++ b/test/unit/generic-page.js @@ -30,4 +30,20 @@ export const runGenericPageTests = (html, options) => { expect(document.title).toBe(options.pageTitle) }) } + + if (options.breadcrumbs) { + it('has the correct breadcrumbs', () => { + const breadcrumbs = document.querySelector('.govuk-breadcrumbs__list') + const breadcrumbsChildren = breadcrumbs.children + + options.breadcrumbs.forEach((breadcrumb, i) => { + expect(breadcrumbsChildren[i].textContent).toContain(breadcrumb.text) + + if (breadcrumb.href) { + const breadcrumbLink = breadcrumbsChildren[i].children[0] + expect(breadcrumbLink.getAttribute('href')).toEqual(breadcrumb.href) + } + }) + }) + } } diff --git a/test/unit/issueDetailsPage.test.js b/test/unit/issueDetailsPage.test.js index 1ae625be..7e19ed72 100644 --- a/test/unit/issueDetailsPage.test.js +++ b/test/unit/issueDetailsPage.test.js @@ -22,11 +22,13 @@ addFilters(nunjucksEnv, { datasetNameMapping }) describe('issueDetails.html', () => { const organisation = { - name: 'Test Organisation' + name: 'mock org', + organisation: 'mock-org' } const dataset = { - name: 'Test Dataset' + name: 'mock Dataset', + dataset: 'mock-dataset' } const errorHeading = 'Example error heading' @@ -74,12 +76,15 @@ describe('issueDetails.html', () => { ] } + const issueType = 'mock issue' + const params = { organisation, dataset, errorHeading, issueItems, - entry + entry, + issueType } const html = nunjucks.render('organisations/issueDetails.html', params) @@ -87,7 +92,14 @@ describe('issueDetails.html', () => { const document = dom.window.document runGenericPageTests(html, { - pageTitle: `Test Organisation - Test Dataset - Issues - ${config.serviceNames.submit}` + pageTitle: `mock org - mock Dataset - Issues - ${config.serviceNames.submit}`, + breadcrumbs: [ + { text: 'Home', href: '/manage' }, + { text: 'Organisations', href: '/organisations' }, + { text: 'mock org', href: '/organisations/mock-org' }, + { text: 'mock Dataset', href: '/organisations/mock-org/mock-dataset' }, + { text: 'mock issue' } + ] }) it('Renders the correct headings', () => { @@ -127,7 +139,14 @@ describe('issueDetails.html', () => { // const multiPageDom = new JSDOM(multiPageHtml) // const multiPageDocument = multiPageDom.window.document runGenericPageTests(multiPageHtml, { - pageTitle: `Test Organisation - Test Dataset - Issues (Page 2 of 3) - ${config.serviceNames.submit}` + pageTitle: `mock org - mock Dataset - Issues (Page 2 of 3) - ${config.serviceNames.submit}`, + breadcrumbs: [ + { text: 'Home', href: '/manage' }, + { text: 'Organisations', href: '/organisations' }, + { text: 'mock org', href: '/organisations/mock-org' }, + { text: 'mock Dataset', href: '/organisations/mock-org/mock-dataset' }, + { text: 'mock issue' } + ] }) it.todo('correctly renders the pagination', () => { diff --git a/test/unit/lpaOverviewPage.test.js b/test/unit/lpaOverviewPage.test.js index 0f1518ce..2c89567a 100644 --- a/test/unit/lpaOverviewPage.test.js +++ b/test/unit/lpaOverviewPage.test.js @@ -26,7 +26,8 @@ addFilters(nunjucksEnv, { datasetNameMapping }) describe('LPA Overview Page', () => { const params = { organisation: { - name: 'mock org' + name: 'mock org', + organisation: 'mock-org' }, datasetsWithEndpoints: 2, totalDatasets: 8, @@ -35,47 +36,59 @@ describe('LPA Overview Page', () => { datasets: [ { slug: 'article-4-direction', - endpoint: null + endpoint: null, + status: 'Not submitted', + issue_count: 0 }, { slug: 'article-4-direction-area', - endpoint: null + endpoint: null, + status: 'Not submitted' }, { slug: 'conservation-area', endpoint: 'http://conservation-area.json', + status: 'Needs fixing', error: null, - issue: 'Endpoint has not been updated since 21 May 2023' + issue: 'Endpoint has not been updated since 21 May 2023', + issue_count: 1 }, { slug: 'conservation-area-document', endpoint: 'http://conservation-area-document.json', + status: 'Live', error: null, - issue: null + issue_count: 0 }, { slug: 'listed-building-outline', endpoint: 'http://listed-building-outline.json', + status: 'Live', error: null, - issue: null + issue_count: 0 }, { slug: 'tree', endpoint: 'http://tree.json', error: null, - issue: 'There are 20 issues in this dataset' + status: 'Needs fixing', + issue: 'There are 20 issues in this dataset', + issue_count: 1 }, { slug: 'tree-preservation-order', endpoint: 'http://tree-preservation-order.json', - error: 'Error connecting to endpoint', - issue: null + http_error: '404', + error: 'There was 404 error accessing the data URL', + status: 'Error', + issue_count: 0 }, { slug: 'tree-preservation-zone', endpoint: 'http://tree-preservation-zone.json', - error: 'Error connecting to endpoint', - issue: null + status: 'Error', + error: '400', + issue_count: 0 } ] } @@ -85,23 +98,24 @@ describe('LPA Overview Page', () => { const document = dom.window.document runGenericPageTests(html, { - pageTitle: 'mock org overview - Submit and update your planning data' + pageTitle: 'mock org overview - Submit and update your planning data', + breadcrumbs: [{ text: 'Home', href: '/manage' }, { text: 'Organisations', href: '/organisations' }, { text: 'mock org' }] }) const statsBoxes = document.querySelector('.dataset-status').children it('Datasets provided gives the correct value', () => { expect(statsBoxes[0].textContent).toContain('2/8') - expect(statsBoxes[0].textContent).toContain('datasets provided') + expect(statsBoxes[0].textContent).toContain('datasets submitted') }) it('Datasets with errors gives the correct value', () => { expect(statsBoxes[1].textContent).toContain('2') - expect(statsBoxes[1].textContent).toContain('datasets with errors') + expect(statsBoxes[1].textContent).toContain('data URL with errors') }) it('Datasets with issues gives the correct value', () => { expect(statsBoxes[2].textContent).toContain('2') - expect(statsBoxes[2].textContent).toContain('datasets with issues') + expect(statsBoxes[2].textContent).toContain('datasets need fixing') }) const datasetCards = document.querySelector('.govuk-task-list').children @@ -115,10 +129,17 @@ describe('LPA Overview Page', () => { }) }) - it('The dataset cards are rendered with the correct hints', () => { - params.datasets.forEach((dataset, i) => { - const expectedHint = !dataset.endpoint ? 'Endpoint not provided' : dataset.error ? dataset.error : dataset.issue ? dataset.issue : 'Endpoint provided' - expect(datasetCards[i].querySelector('.govuk-task-list__hint').textContent).toContain(expectedHint) + params.datasets.forEach((dataset, i) => { + it(`dataset cards are rendered with correct hints for dataset='${dataset.slug}'`, () => { + let expectedHint = 'Data URL submitted' + if (dataset.status === 'Not submitted') { + expectedHint = 'Data URL not submitted' + } else if (dataset.error) { + expectedHint = dataset.error + } else if (dataset.issue_count > 0) { + expectedHint = `There are ${dataset.issue_count} issues in this dataset` + } + expect(datasetCards[i].querySelector('.govuk-task-list__hint').textContent.trim()).toContain(expectedHint) }) }) @@ -136,22 +157,22 @@ describe('LPA Overview Page', () => { if (dataset.endpoint) { expectedActions.push({ text: 'View data', href: '/taskLists/taskChecklist' }) } - - const actions = datasetCards[i].querySelector('.planning-data-actions').children - expectedActions.forEach((expectedAction, j) => { - expect(actions[j].textContent, `expect action ${expectedAction.text} for dataset ${dataset.slug}`).toContain(expectedAction.text) - const actionLink = actions[j].querySelector('a') - expect(actionLink.href).toBe(expectedAction.href) - }) }) }) - it('Renders the correct status on each dataset card', () => { - params.datasets.forEach((dataset, i) => { - const expectedHint = !dataset.endpoint ? 'Not provided' : dataset.error ? 'Error' : dataset.issue ? 'Issues' : 'No issues' + params.datasets.forEach((dataset, i) => { + it(`Renders the correct status on each dataset card for dataset='${dataset.slug}'`, () => { + let expectedHint = 'Live' + if (dataset.status === 'Not submitted') { + expectedHint = 'Not submitted' + } else if (dataset.status === 'Error') { + expectedHint = dataset.status + } else if (dataset.status === 'Needs fixing') { + expectedHint = 'Needs fixing' + } const statusIndicator = datasetCards[i].querySelector('.govuk-task-list__status') - expect(statusIndicator.textContent).toContain(expectedHint) + expect(statusIndicator.textContent.trim()).toContain(expectedHint) }) }) }) diff --git a/test/unit/organisationsController.test.js b/test/unit/organisationsController.test.js index a2fca79e..c185e3f1 100644 --- a/test/unit/organisationsController.test.js +++ b/test/unit/organisationsController.test.js @@ -29,25 +29,27 @@ describe('OrganisationsController.js', () => { const next = vi.fn() const expectedResponse = { - name: 'Test LPA', + name: 'test LPA', datasets: { - dataset1: { endpoint: 'https://example.com', issue: false, error: false }, - dataset2: { endpoint: null, issue: true, error: false }, - dataset3: { endpoint: 'https://example.com', issue: false, error: true } + dataset1: { endpoint: 'https://example.com', status: 'Live' }, + dataset2: { endpoint: null, status: 'Needs fixing' }, + dataset3: { endpoint: 'https://example.com', status: 'Error' } } } + vi.mocked(datasette.runQuery).mockResolvedValue({ formattedData: [{ name: 'Test lpa', organisation: 'test-lpa' }] }) + performanceDbApi.getLpaOverview = vi.fn().mockResolvedValue(expectedResponse) await organisationsController.getOverview(req, res, next) expect(res.render).toHaveBeenCalledTimes(1) expect(res.render).toHaveBeenCalledWith('organisations/overview.html', expect.objectContaining({ - organisation: { name: 'Test LPA' }, + organisation: { name: 'Test lpa', organisation: 'test-lpa' }, datasets: expect.arrayContaining([ - { endpoint: 'https://example.com', issue: false, error: false, slug: 'dataset1' }, - { endpoint: null, issue: true, error: false, slug: 'dataset2' }, - { endpoint: 'https://example.com', issue: false, error: true, slug: 'dataset3' } + { endpoint: 'https://example.com', status: 'Live', slug: 'dataset1' }, + { endpoint: null, status: 'Needs fixing', slug: 'dataset2' }, + { endpoint: 'https://example.com', status: 'Error', slug: 'dataset3' } ]), totalDatasets: 3, datasetsWithEndpoints: 2, @@ -63,6 +65,7 @@ describe('OrganisationsController.js', () => { const error = new Error('Test error') + vi.mocked(datasette.runQuery).mockResolvedValue({ formattedData: [{ name: 'Test lpa', organisation: 'test-lpa' }] }) vi.mocked(performanceDbApi.getLpaOverview).mockRejectedValue(error) await organisationsController.getOverview(req, res, next) @@ -388,7 +391,8 @@ describe('OrganisationsController.js', () => { classes: '' } ] - } + }, + issueType: 'test-issue-type' }) }) diff --git a/test/unit/performanceDbApi.test.js b/test/unit/performanceDbApi.test.js index 71740cd7..82dd6fd2 100644 --- a/test/unit/performanceDbApi.test.js +++ b/test/unit/performanceDbApi.test.js @@ -14,42 +14,19 @@ describe('performanceDbApi', () => { dataset: 'dataset-slug-1', endpoint: 'https://example.com/endpoint-1', exception: null, - http_status: '404' - }, - { - organisation: 'some-organisation', - name: 'Some Organisation', - dataset: 'dataset-slug-2', - endpoint: 'https://example.com/endpoint-2', - exception: 'resource not found', - http_status: '404' - }, - { - organisation: 'some-organisation', - name: 'Some Organisation', - dataset: 'dataset-slug-3', - endpoint: 'https://example.com/endpoint-3', - http_status: '200', - issue_count: 4 + http_status: undefined, + error: undefined, + status: 'Live' } ] } vi.spyOn(datasette, 'runQuery').mockResolvedValue(mockResponse) - const result = await performanceDbApi.getLpaOverview(lpa) + await performanceDbApi.getLpaOverview(lpa) expect(datasette.runQuery).toHaveBeenCalledTimes(1) expect(datasette.runQuery).toHaveBeenCalledWith(expect.stringContaining(lpa)) - expect(result).toEqual({ - name: 'Some Organisation', - organisation: 'some-organisation', - datasets: { - 'dataset-slug-1': { endpoint: 'https://example.com/endpoint-1', error: 'endpoint returned with a status of 404', issue: undefined }, - 'dataset-slug-2': { endpoint: 'https://example.com/endpoint-2', error: 'resource not found', issue: undefined }, - 'dataset-slug-3': { endpoint: 'https://example.com/endpoint-3', error: undefined, issue: 'There are 4 issues in this dataset' } - } - }) }) it('adds the filter if a dataset list is passed into the params', async () => {