Skip to content

Commit

Permalink
Merge pull request #266 from digital-land/feat/endpointError/query
Browse files Browse the repository at this point in the history
Feat/endpoint error/query

skipping review as already reviewed
  • Loading branch information
GeorgeGoodall authored Aug 13, 2024
2 parents 084612a + 1e435bd commit b2dda9c
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 20 deletions.
72 changes: 53 additions & 19 deletions src/controllers/OrganisationsController.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,59 @@ const organisationsController = {
}
},

async getEndpointError (req, res, next, { resourceStatus }) {
const { lpa, dataset: datasetId } = req.params

try {
const organisationResult = await datasette.runQuery(`SELECT name FROM organisation WHERE organisation = '${lpa}'`)
const organisation = organisationResult.formattedData[0]

const datasetResult = await datasette.runQuery(`SELECT name FROM dataset WHERE dataset = '${datasetId}'`)
const dataset = datasetResult.formattedData[0]

const daysSince200 = resourceStatus.days_since_200
const today = new Date()
const last200Date = new Date(today.getTime() - (daysSince200 * 24 * 60 * 60 * 1000))
const last200Datetime = last200Date.toISOString().slice(0, 19) + 'Z'

const params = {
organisation: {
name: organisation.name
},
dataset: {
name: dataset.name
},
errorData: {
endpoint_url: resourceStatus.endpoint_url,
http_status: resourceStatus.status,
latest_log_entry_date: resourceStatus.latest_log_entry_date,
latest_200_date: last200Datetime
}
}
res.render('organisations/http-error.html', params)
} catch (e) {
logger.warn(`conditionalTaskListHandler() failed for lpa='${lpa}', datasetId='${datasetId}'`, { type: types.App })
next(e)
}
},

async conditionalTaskListHandler (req, res, next) {
const { lpa, dataset: datasetId } = req.params

try {
const resourceStatus = await performanceDbApi.getResourceStatus(lpa, datasetId)

if (resourceStatus.status !== '200') {
return await organisationsController.getEndpointError(req, res, next, { resourceStatus })
} else {
return await organisationsController.getDatasetTaskList(req, res, next)
}
} catch (e) {
logger.warn(`conditionalTaskListHandler() failed for lpa='${lpa}', datasetId='${datasetId}'`, { type: types.App })
next(e)
}
},

/**
* Handles GET requests for the issue details page.
*
Expand Down Expand Up @@ -322,26 +375,7 @@ const organisationsController = {
logger.warn(`getIssueDetails() failed for lpa='${lpa}', datasetId='${datasetId}', issue=${issueType}, entityNumber=${entityNumber}, resourceId=${resourceId}`, { type: types.App })
next(e)
}
},

async getEndpointError (req, res, next) {
const params = {
organisation: {
name: 'mock org'
},
dataset: {
name: 'mock dataset'
},
errorData: {
endpoint_url: 'http://fakeUrl.com',
http_status: '404',
latest_log_entry_date: '2024-08-11T00:15:32Z',
latest_200_date: '2024-08-11T00:15:32Z'
}
}
res.render('organisations/http-error.html', params)
}

}

export default organisationsController
2 changes: 1 addition & 1 deletion src/routes/organisations.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const router = express.Router()
router.get('/:lpa/:dataset/get-started', OrganisationsController.getGetStarted)
router.get('/:lpa/:dataset/:issue_type/:entityNumber', OrganisationsController.getIssueDetails)
router.get('/:lpa/:dataset/:issue_type', OrganisationsController.getIssueDetails)
router.get('/:lpa/:dataset', OrganisationsController.getEndpointError)
router.get('/:lpa/:dataset', OrganisationsController.conditionalTaskListHandler)
router.get('/:lpa', OrganisationsController.getOverview)
router.get('/', OrganisationsController.getOrganisations)

Expand Down
11 changes: 11 additions & 0 deletions src/services/performanceDbApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ ORDER BY
}
},

getResourceStatus: async (lpa, datasetId) => {
const sql = `
select endpoint_url, status, latest_log_entry_date, days_since_200 from reporting_latest_endpoints
WHERE REPLACE(organisation, '-eng', '') = '${lpa}'
AND pipeline = '${datasetId}'`

const result = await datasette.runQuery(sql)

return result.formattedData[0]
},

getLpaDatasetIssues: async (lpa, datasetId) => {
const sql = `
SELECT
Expand Down
87 changes: 87 additions & 0 deletions test/unit/organisationsController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,91 @@ describe('OrganisationsController.js', () => {
expect(next).toHaveBeenCalledWith(expect.any(Error))
})
})

describe('getEndpointError', () => {
it('should render http-error.html template with correct params', async () => {
const req = { params: { lpa: 'example-lpa', dataset: 'example-dataset' } }
const res = { render: vi.fn() }
const next = vi.fn()
const resourceStatus = { status: '404', days_since_200: 3, endpoint_url: 'https://example.com', latest_log_entry_date: '2022-01-01T12:00:00.000Z' }

vi.mocked(datasette.runQuery).mockResolvedValueOnce({ formattedData: [{ name: 'Example Organisation' }] })
vi.mocked(datasette.runQuery).mockResolvedValueOnce({ formattedData: [{ name: 'Example Dataset' }] })

await organisationsController.getEndpointError(req, res, next, { resourceStatus })

const dataTimeRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?Z/

expect(res.render).toHaveBeenCalledTimes(1)
const renderArgs = res.render.mock.calls[0]
expect(renderArgs[0]).toEqual('organisations/http-error.html')
expect(renderArgs[1].organisation).toEqual({ name: 'Example Organisation' })
expect(renderArgs[1].dataset).toEqual({ name: 'Example Dataset' })
expect(renderArgs[1].errorData.endpoint_url).toEqual('https://example.com')
expect(renderArgs[1].errorData.http_status).toEqual('404')
expect(renderArgs[1].errorData.latest_log_entry_date).toMatch(dataTimeRegex)
expect(renderArgs[1].errorData.latest_200_date).toMatch(dataTimeRegex)
})

it('should catch errors and pass them to the next function', async () => {
const req = { params: { lpa: 'example-lpa', dataset: 'example-dataset' } }
const res = {}
const next = vi.fn()
const resourceStatus = { status: '404' }

vi.mocked(datasette.runQuery).mockRejectedValueOnce(new Error('example error'))

await organisationsController.getEndpointError(req, res, next, { resourceStatus })

expect(next).toHaveBeenCalledTimes(1)
expect(next).toHaveBeenCalledWith(expect.any(Error))
})
})

describe('conditionalTaskListHandler', () => {
it('should call getEndpointError if resource status is not 200', async () => {
const getResourceStatusSpy = vi.spyOn(organisationsController, 'getEndpointError')
getResourceStatusSpy.mockResolvedValue({})

const req = { params: { lpa: 'example-lpa', dataset: 'example-dataset' } }
const res = { render: vi.fn() }
const next = vi.fn()

vi.mocked(performanceDbApi.getResourceStatus).mockResolvedValueOnce({ status: '404' })

await organisationsController.conditionalTaskListHandler(req, res, next)

expect(organisationsController.getEndpointError).toHaveBeenCalledTimes(1)
expect(organisationsController.getEndpointError).toHaveBeenCalledWith(req, res, next, { resourceStatus: { status: '404' } })
})

it('should call getDatasetTaskList if resource status is 200', async () => {
const getDatasetTaskListSpy = vi.spyOn(organisationsController, 'getDatasetTaskList')
getDatasetTaskListSpy.mockResolvedValue({})

const req = { params: { lpa: 'example-lpa', dataset: 'example-dataset' } }
const res = { render: vi.fn() }
const next = vi.fn()

vi.mocked(performanceDbApi.getResourceStatus).mockResolvedValueOnce({ status: '200' })

await organisationsController.conditionalTaskListHandler(req, res, next)

expect(organisationsController.getDatasetTaskList).toHaveBeenCalledTimes(1)
expect(organisationsController.getDatasetTaskList).toHaveBeenCalledWith(req, res, next)
})

it('should catch errors and pass them to the next function', async () => {
const req = { params: { lpa: 'example-lpa', dataset: 'example-dataset' } }
const res = {}
const next = vi.fn()

vi.mocked(performanceDbApi.getResourceStatus).mockRejectedValueOnce(new Error('example error'))

await organisationsController.conditionalTaskListHandler(req, res, next)

expect(next).toHaveBeenCalledTimes(1)
expect(next).toHaveBeenCalledWith(expect.any(Error))
})
})
})

0 comments on commit b2dda9c

Please sign in to comment.