Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 4 additions & 41 deletions __tests__/httpServer/apiV1.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ jest.mock('../../src/cli/workflows', () => ({
}))

const request = require('supertest')
const { generateStaticReports } = require('../../src/reports')
const knexInit = require('knex')
const { getConfig } = require('../../src/config')
const { resetDatabase, initializeStore } = require('../../__utils__')
Expand Down Expand Up @@ -183,7 +182,8 @@ describe('HTTP Server API V1', () => {
id: 'test-workflow',
description: 'Test workflow'
})
expect(mockWorkflowFn).toHaveBeenCalledWith({ some: 'data' })
// The first argument (...calls[0][0]) is Knex and we ignore it due framework limitations
expect(mockWorkflowFn.mock.calls[0][1]).toEqual({ some: 'data' })
})

test('should return 404 for invalid workflow ID', async () => {
Expand Down Expand Up @@ -216,47 +216,10 @@ describe('HTTP Server API V1', () => {
description: 'Test workflow'
})
expect(response.body.errors[0].message).toMatch(/Failed to run workflow: Something went wrong/)
expect(mockWorkflowFn).toHaveBeenCalledWith({ some: 'data' })
// The first argument (...calls[0][0]) is Knex and we ignore it due framework limitations
expect(mockWorkflowFn.mock.calls[0][1]).toEqual({ some: 'data' })
})

test.todo('should return 500 when workflow execution times out')
})

describe('POST /api/v1/generate-reports', () => {
test('should return status completed when report generation succeeds', async () => {
generateStaticReports.mockResolvedValueOnce()

const response = await app.post('/api/v1/generate-reports')

expect(generateStaticReports).toHaveBeenCalledWith(expect.anything(), { clearPreviousReports: true })
expect(response.status).toBe(202)
expect(response.body).toHaveProperty('status', 'completed')
expect(response.body).toHaveProperty('startedAt')
expect(response.body).toHaveProperty('finishedAt')

const startedAt = new Date(response.body.startedAt)
const finishedAt = new Date(response.body.finishedAt)
expect(startedAt.toISOString()).toBe(response.body.startedAt)
expect(finishedAt.toISOString()).toBe(response.body.finishedAt)
expect(finishedAt.getTime()).toBeGreaterThanOrEqual(startedAt.getTime())
})

test('should return status failed when report generation fails', async () => {
generateStaticReports.mockRejectedValueOnce(new Error('Report generation failed'))

const response = await app.post('/api/v1/generate-reports')

expect(generateStaticReports).toHaveBeenCalledWith(expect.anything(), { clearPreviousReports: true })
expect(response.status).toBe(500)
expect(response.body).toHaveProperty('status', 'failed')
expect(response.body).toHaveProperty('startedAt')
expect(response.body).toHaveProperty('finishedAt')

const startedAt = new Date(response.body.startedAt)
const finishedAt = new Date(response.body.finishedAt)
expect(startedAt.toISOString()).toBe(response.body.startedAt)
expect(finishedAt.toISOString()).toBe(response.body.finishedAt)
expect(finishedAt.getTime()).toBeGreaterThanOrEqual(startedAt.getTime())
})
})
})
25 changes: 3 additions & 22 deletions src/httpServer/routers/apiV1.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const { generateStaticReports } = require('../../reports')
const pkg = require('../../../package.json')
const { logger } = require('../../utils')
const { initializeStore } = require('../../store')
Expand All @@ -8,7 +7,7 @@ const { getWorkflowsDetails } = require('../../cli/workflows')

const HTTP_DEFAULT_TIMEOUT = 30 * 1000 // 30 seconds

const runWorkflow = (workflowName, data) => new Promise((resolve, reject) => {
const runWorkflow = ({ workflowName, knex, data } = {}) => new Promise((resolve, reject) => {
const { workflows } = getWorkflowsDetails()
const workflow = workflows[workflowName]
if (!workflow || typeof workflow.workflow !== 'function') {
Expand All @@ -21,7 +20,7 @@ const runWorkflow = (workflowName, data) => new Promise((resolve, reject) => {
}, HTTP_DEFAULT_TIMEOUT)

Promise.resolve()
.then(() => workflow.workflow(data))
.then(() => workflow.workflow(knex, data))
.then(() => resolve(workflow))
.catch(err => reject(new Error(`Failed to run workflow: ${err.message}`)))
.finally(() => clearTimeout(timeout))
Expand Down Expand Up @@ -91,7 +90,7 @@ function createApiRouter (knex, express) {
// @TODO: We need to delegate the workflow execution to a worker and provide and endpoint to check the status
// This is a temporary solution to run the workflow within the HTTP timeout
// data validation is done in the workflow itself
const wf = await runWorkflow(id, data)
const wf = await runWorkflow({ workflowName: id, knex, data })
res.status(202).json({ status: 'completed', workflow: { id, description: wf.description } })
} catch (error) {
logger.error(error)
Expand All @@ -105,24 +104,6 @@ function createApiRouter (knex, express) {
}
})

router.post('/generate-reports', async (req, res) => {
const startTs = new Date().toISOString()
try {
await generateStaticReports(knex, { clearPreviousReports: true })
res.status(202).json({
status: 'completed',
startedAt: startTs,
finishedAt: new Date().toISOString()
})
} catch (error) {
logger.error(error)
res.status(500).json({
status: 'failed',
startedAt: startTs,
finishedAt: new Date().toISOString()
})
}
})
return router
}

Expand Down
56 changes: 0 additions & 56 deletions src/httpServer/swagger/api-v1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,62 +197,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/generate-reports:
post:
summary: Generate static reports
description: Triggers the generation of static reports
operationId: generateReports
tags:
- Reports
responses:
'202':
description: Report generation accepted
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
status:
type: string
enum: [completed, failed]
example: completed
startedAt:
type: string
format: date-time
example: '2025-05-03T07:20:16.000Z'
finishedAt:
type: string
format: date-time
example: '2025-05-03T07:20:20.000Z'
required:
- status
- startedAt
- finishedAt
'500':
description: Report generation failed
content:
application/json:
schema:
type: object
additionalProperties: false
properties:
status:
type: string
enum: [failed]
example: failed
startedAt:
type: string
format: date-time
example: '2025-05-03T07:20:16.000Z'
finishedAt:
type: string
format: date-time
example: '2025-05-03T07:20:20.000Z'
required:
- status
- startedAt
- finishedAt

components:
schemas:
Expand Down
Loading