diff --git a/.github/workflows/featureDeploy.yml b/.github/workflows/featureDeploy.yml index acd59b32..7e77d25c 100644 --- a/.github/workflows/featureDeploy.yml +++ b/.github/workflows/featureDeploy.yml @@ -30,10 +30,10 @@ jobs: strategy: matrix: environment: ${{ fromJSON(needs.detect-environments.outputs.environments) }} - if: ${{ matrix.environment != 'production' }} + if: ${{ inputs.environment != 'production' }} uses: ./.github/workflows/deploy.yml with: - environment: '${{ matrix.environment }}' + environment: '${{ inputs.environment }}' secrets: inherit diff --git a/src/assets/js/list-filter.js b/src/assets/js/list-filter.js index edc18066..02b0a2d9 100644 --- a/src/assets/js/list-filter.js +++ b/src/assets/js/list-filter.js @@ -5,6 +5,8 @@ /* eslint-disable no-var */ //= require govuk_publishing_components/vendor/polyfills/closest +const keyPauseTime = 20 + window.GOVUK = window.GOVUK || {} window.GOVUK.Modules = window.GOVUK.Modules || {}; @@ -34,7 +36,7 @@ window.GOVUK.Modules = window.GOVUK.Modules || {}; clearTimeout(this.filterTimeout) this.filterTimeout = setTimeout(function () { this.$module.filterList(searchTerm) - }.bind(this), 200) + }.bind(this), keyPauseTime) }.bind(this)) } diff --git a/src/controllers/OrganisationsController.js b/src/controllers/OrganisationsController.js index 5b65911c..c4d388fc 100644 --- a/src/controllers/OrganisationsController.js +++ b/src/controllers/OrganisationsController.js @@ -1,3 +1,4 @@ +import datasette from '../services/datasette.js' import performanceDbApi from '../services/performanceDbApi.js' // Assume you have an API service module import logger from '../utils/logger.js' import { dataSubjects } from '../utils/utils.js' @@ -70,85 +71,36 @@ const organisationsController = { } }, + /** + * Handles the GET /organisations request + * + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next + */ async getOrganisations (req, res, next) { - const alphabetisedOrgs = { - A: [ - { - name: 'Aberdeen' - }, - { - name: 'Aylesbury' - }, - { - name: 'Ashford' - } - ], - B: [ - { - name: 'Bath' - }, - { - name: 'Birmingham' - }, - { - name: 'Brighton' - } - ], - C: [ - { - name: 'Cambridge' - }, - { - name: 'Cardiff' - }, - { - name: 'Cheltenham' - }, - { - name: 'Chester' - } - ], - D: [ - { - name: 'Derby' - }, - { - name: 'Dundee' - } - ], - E: [ - { - name: 'Edinburgh' - }, - { - name: 'Epsom' - } - ], - G: [ - { - name: 'Glasgow' - }, - { - name: 'Gloucester' - } - ], - H: [ - { - name: 'Hull' - } - ], - L: [ - { - name: 'Leeds' - }, - { - name: 'London' - } - ] - } + try { + const sql = 'select name, organisation from organisation' + const result = await datasette.runQuery(sql) + + const sortedResults = result.formattedData.sort((a, b) => { + return a.name.localeCompare(b.name) + }) - res.render('organisations/find.html', { alphabetisedOrgs }) + const alphabetisedOrgs = sortedResults.reduce((acc, current) => { + const firstLetter = current.name.charAt(0).toUpperCase() + acc[firstLetter] = acc[firstLetter] || [] + acc[firstLetter].push(current) + return acc + }, {}) + + res.render('organisations/find.html', { alphabetisedOrgs }) + } catch (err) { + logger.warn(err) + next(err) + } } + } export default organisationsController diff --git a/src/views/organisations/find.html b/src/views/organisations/find.html index 6db1c7ff..ffd58b8e 100644 --- a/src/views/organisations/find.html +++ b/src/views/organisations/find.html @@ -29,7 +29,6 @@

{{ pageName }}

- {% for letter, orgs in alphabetisedOrgs %}
diff --git a/test/unit/organisationsController.test.js b/test/unit/organisationsController.test.js index a36c3be7..67dbc892 100644 --- a/test/unit/organisationsController.test.js +++ b/test/unit/organisationsController.test.js @@ -1,6 +1,7 @@ import { describe, it, vi, expect, beforeEach } from 'vitest' -import LpaOverviewController from '../../src/controllers/OrganisationsController.js' +import organisationsController from '../../src/controllers/OrganisationsController.js' import performanceDbApi from '../../src/services/performanceDbApi.js' +import datasette from '../../src/services/datasette.js' vi.mock('../../src/services/performanceDbApi.js') vi.mock('../../src/utils/utils.js', () => { @@ -8,6 +9,7 @@ vi.mock('../../src/utils/utils.js', () => { dataSubjects: {} } }) +vi.mock('../../src/services/datasette.js') describe('OrganisationsController.js', () => { beforeEach(() => { @@ -31,7 +33,7 @@ describe('OrganisationsController.js', () => { performanceDbApi.getLpaOverview = vi.fn().mockResolvedValue(expectedResponse) - await LpaOverviewController.getOverview(req, res, next) + await organisationsController.getOverview(req, res, next) expect(res.render).toHaveBeenCalledTimes(1) expect(res.render).toHaveBeenCalledWith('organisations/overview.html', expect.objectContaining({ @@ -57,7 +59,7 @@ describe('OrganisationsController.js', () => { vi.mocked(performanceDbApi.getLpaOverview).mockRejectedValue(error) - await LpaOverviewController.getOverview(req, res, next) + await organisationsController.getOverview(req, res, next) expect(next).toHaveBeenCalledTimes(1) expect(next).toHaveBeenCalledWith(error) @@ -65,10 +67,75 @@ describe('OrganisationsController.js', () => { }) describe('find', () => { - it.todo('should render the find page', () => { + it('should call render with the find page', async () => { + const req = {} + const res = { render: vi.fn() } + const next = vi.fn() + + vi.mocked(datasette.runQuery).mockResolvedValue({ formattedData: [] }) + + await organisationsController.getOrganisations(req, res, next) + + expect(res.render).toHaveBeenCalledTimes(1) + expect(res.render).toHaveBeenCalledWith('organisations/find.html', expect.objectContaining({ + alphabetisedOrgs: {} + })) + }) + + it('should correctly sort and restructure the data recieved from datasette, then pass it on to the template', async () => { + const req = {} + const res = { render: vi.fn() } + const next = vi.fn() + + const datasetteResponse = [ + { name: 'Aardvark Healthcare', organisation: 'Aardvark Healthcare' }, + { name: 'Bath NHS Trust', organisation: 'Bath NHS Trust' }, + { name: 'Bristol Hospital', organisation: 'Bristol Hospital' }, + { name: 'Cardiff Health Board', organisation: 'Cardiff Health Board' }, + { name: 'Derbyshire Healthcare', organisation: 'Derbyshire Healthcare' }, + { name: 'East Sussex NHS Trust', organisation: 'East Sussex NHS Trust' } + ] + + vi.mocked(datasette.runQuery).mockResolvedValue({ formattedData: datasetteResponse }) + await organisationsController.getOrganisations(req, res, next) + + expect(res.render).toHaveBeenCalledTimes(1) + expect(res.render).toHaveBeenCalledWith('organisations/find.html', expect.objectContaining({ + alphabetisedOrgs: { + A: [ + { name: 'Aardvark Healthcare', organisation: 'Aardvark Healthcare' } + ], + B: [ + { name: 'Bath NHS Trust', organisation: 'Bath NHS Trust' }, + { name: 'Bristol Hospital', organisation: 'Bristol Hospital' } + ], + C: [ + { name: 'Cardiff Health Board', organisation: 'Cardiff Health Board' } + ], + D: [ + { name: 'Derbyshire Healthcare', organisation: 'Derbyshire Healthcare' } + ], + E: [ + { name: 'East Sussex NHS Trust', organisation: 'East Sussex NHS Trust' } + ] + } + })) }) - it.todo('should catch errors and pass them onto the next function') + it('should catch errors and pass them onto the next function', async () => { + const req = {} + const res = {} + const next = vi.fn() + + const error = new Error('Test error') + + vi.mocked(datasette.runQuery).mockRejectedValue(error) + + await organisationsController.getOrganisations(req, res, next) + + expect(next).toHaveBeenCalledTimes(1) + expect(next).toHaveBeenCalledWith(error) + }) }) })