Skip to content

Commit

Permalink
Fix: status for RUNNING tests updates when job status becomes finaliz…
Browse files Browse the repository at this point in the history
…ed (#1094)

* Fix: status for RUNNING tests updates when job status becomes finalized

* Update server/tests/integration/automation-scheduler.test.js

Co-authored-by: Howard Edwards <[email protected]>

---------

Co-authored-by: Howard Edwards <[email protected]>
  • Loading branch information
gnarf and howard-e authored May 16, 2024
1 parent 2af0b88 commit a062f63
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 1 deletion.
15 changes: 14 additions & 1 deletion server/controllers/AutomationController.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ const updateJobStatus = async (req, res) => {
};

// When new status is considered "final" ('COMPLETED' or 'ERROR' or 'CANCELLED')
// update any CollectionJobTestStatus children still 'QUEUED' to be 'CANCELLED'
if (isJobStatusFinal(status)) {
// update any CollectionJobTestStatus children still 'QUEUED' to be 'CANCELLED'
await updateCollectionJobTestStatusByQuery({
where: {
collectionJobId: req.params.jobID,
Expand All @@ -111,6 +111,19 @@ const updateJobStatus = async (req, res) => {
values: { status: COLLECTION_JOB_STATUS.CANCELLED },
transaction: req.transaction
});
// update any CollectionJobTestStatus children still 'RUNNING' to be 'ERROR' or 'CANCELLED'
let runningTestNewStatus =
status === COLLECTION_JOB_STATUS.ERROR
? COLLECTION_JOB_STATUS.ERROR
: COLLECTION_JOB_STATUS.CANCELLED;
await updateCollectionJobTestStatusByQuery({
where: {
collectionJobId: req.params.jobID,
status: COLLECTION_JOB_STATUS.RUNNING
},
values: { status: runningTestNewStatus },
transaction: req.transaction
});
}

const graphqlResponse = await updateCollectionJobById({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ const cancelCollectionJobResolver = async (
values: { status: COLLECTION_JOB_STATUS.CANCELLED },
transaction
});
await updateCollectionJobTestStatusByQuery({
where: { collectionJobId, status: COLLECTION_JOB_STATUS.RUNNING },
values: { status: COLLECTION_JOB_STATUS.CANCELLED },
transaction
});
return updateCollectionJobById({
id: collectionJobId,
values: { status: COLLECTION_JOB_STATUS.CANCELLED },
Expand Down
268 changes: 268 additions & 0 deletions server/tests/integration/automation-scheduler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,274 @@ describe('Automation controller', () => {
});
});

it('should convert RUNNING test status to ERROR when job state becomes ERROR', async () => {
await apiServer.sessionAgentDbCleaner(async transaction => {
const { scheduleCollectionJob: job } =
await scheduleCollectionJobByMutation({ transaction });
const collectionJob = await getCollectionJobById({
id: job.id,
transaction
});
// flag overall job as RUNNING
const externalLogsUrl = 'https://example.com/test/log/url';
await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({ status: 'RUNNING', externalLogsUrl })
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);

const { tests } =
collectionJob.testPlanRun.testPlanReport.testPlanVersion;
const selectedTestIndex = 0;
const selectedTestRowNumber = 1;
const selectedTest = tests[selectedTestIndex];
let response = await sessionAgent
.post(`/api/jobs/${job.id}/test/${selectedTestRowNumber}`)
.send({
status: COLLECTION_JOB_STATUS.RUNNING
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

let { collectionJob: storedCollectionJob } =
await getTestCollectionJob(job.id, { transaction });
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('RUNNING');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
let foundStatus = false;
for (const testStatus of storedCollectionJob.testStatus) {
let expectedStatus = COLLECTION_JOB_STATUS.QUEUED;
if (testStatus.test.id === selectedTest.id) {
foundStatus = true;
expectedStatus = COLLECTION_JOB_STATUS.RUNNING;
}
expect(testStatus.status).toEqual(expectedStatus);
}
expect(foundStatus).toEqual(true);

// Leave our test RUNNING but ERROR the job

response = await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({
// avoiding sending externalLogsUrl here to test that when
// missing it is not overwritten/emptied.
status: COLLECTION_JOB_STATUS.ERROR
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

storedCollectionJob = (
await getTestCollectionJob(job.id, { transaction })
).collectionJob;
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('ERROR');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
foundStatus = false;
for (const testStatus of storedCollectionJob.testStatus) {
let expectedStatus = COLLECTION_JOB_STATUS.CANCELLED;
if (testStatus.test.id === selectedTest.id) {
foundStatus = true;
expectedStatus = COLLECTION_JOB_STATUS.ERROR;
}
expect(testStatus.status).toEqual(expectedStatus);
}
expect(foundStatus).toEqual(true);
});
});

it('should convert RUNNING test status to CANCELLED when job state becomes CANCELLED', async () => {
await apiServer.sessionAgentDbCleaner(async transaction => {
const { scheduleCollectionJob: job } =
await scheduleCollectionJobByMutation({ transaction });
const collectionJob = await getCollectionJobById({
id: job.id,
transaction
});
// flag overall job as RUNNING
const externalLogsUrl = 'https://example.com/test/log/url';
await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({ status: 'RUNNING', externalLogsUrl })
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);

const { tests } =
collectionJob.testPlanRun.testPlanReport.testPlanVersion;
const selectedTestIndex = 0;
const selectedTestRowNumber = 1;
const selectedTest = tests[selectedTestIndex];
let response = await sessionAgent
.post(`/api/jobs/${job.id}/test/${selectedTestRowNumber}`)
.send({
status: COLLECTION_JOB_STATUS.RUNNING
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

let { collectionJob: storedCollectionJob } =
await getTestCollectionJob(job.id, { transaction });
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('RUNNING');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
let foundStatus = false;
for (const testStatus of storedCollectionJob.testStatus) {
let expectedStatus = COLLECTION_JOB_STATUS.QUEUED;
if (testStatus.test.id === selectedTest.id) {
foundStatus = true;
expectedStatus = COLLECTION_JOB_STATUS.RUNNING;
}
expect(testStatus.status).toEqual(expectedStatus);
}
expect(foundStatus).toEqual(true);

// Leave our test RUNNING but CANCELLED the job

response = await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({
// avoiding sending externalLogsUrl here to test that when
// missing it is not overwritten/emptied.
status: COLLECTION_JOB_STATUS.CANCELLED
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

storedCollectionJob = (
await getTestCollectionJob(job.id, { transaction })
).collectionJob;
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('CANCELLED');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
for (const testStatus of storedCollectionJob.testStatus) {
expect(testStatus.status).toEqual(
COLLECTION_JOB_STATUS.CANCELLED
);
}
});
});

it('should convert RUNNING test status to CANCELLED when job state becomes COMPLETED', async () => {
await apiServer.sessionAgentDbCleaner(async transaction => {
const { scheduleCollectionJob: job } =
await scheduleCollectionJobByMutation({ transaction });
const collectionJob = await getCollectionJobById({
id: job.id,
transaction
});
// flag overall job as RUNNING
const externalLogsUrl = 'https://example.com/test/log/url';
await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({ status: 'RUNNING', externalLogsUrl })
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);

const { tests } =
collectionJob.testPlanRun.testPlanReport.testPlanVersion;
const selectedTestIndex = 0;
const selectedTestRowNumber = 1;
const selectedTest = tests[selectedTestIndex];
let response = await sessionAgent
.post(`/api/jobs/${job.id}/test/${selectedTestRowNumber}`)
.send({
status: COLLECTION_JOB_STATUS.RUNNING
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

let { collectionJob: storedCollectionJob } =
await getTestCollectionJob(job.id, { transaction });
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('RUNNING');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
let foundStatus = false;
for (const testStatus of storedCollectionJob.testStatus) {
let expectedStatus = COLLECTION_JOB_STATUS.QUEUED;
if (testStatus.test.id === selectedTest.id) {
foundStatus = true;
expectedStatus = COLLECTION_JOB_STATUS.RUNNING;
}
expect(testStatus.status).toEqual(expectedStatus);
}
expect(foundStatus).toEqual(true);

// Leave our test RUNNING but COMPLETED the job

response = await sessionAgent
.post(`/api/jobs/${job.id}`)
.send({
// avoiding sending externalLogsUrl here to test that when
// missing it is not overwritten/emptied.
status: COLLECTION_JOB_STATUS.COMPLETED
})
.set(
'x-automation-secret',
process.env.AUTOMATION_SCHEDULER_SECRET
)
.set('x-transaction-id', transaction.id);
expect(response.statusCode).toBe(200);

storedCollectionJob = (
await getTestCollectionJob(job.id, { transaction })
).collectionJob;
expect(storedCollectionJob.id).toEqual(job.id);
expect(storedCollectionJob.status).toEqual('COMPLETED');
expect(storedCollectionJob.externalLogsUrl).toEqual(
externalLogsUrl
);
foundStatus = false;
for (const testStatus of storedCollectionJob.testStatus) {
let expectedStatus = COLLECTION_JOB_STATUS.CANCELLED;
if (testStatus.test.id === selectedTest.id) {
foundStatus = true;
expectedStatus = COLLECTION_JOB_STATUS.CANCELLED;
}
expect(testStatus.status).toEqual(expectedStatus);
}
expect(foundStatus).toEqual(true);
});
});

it('should copy assertion results when updating with results that match historical results', async () => {
await apiServer.sessionAgentDbCleaner(async transaction => {
const context = getGraphQLContext({
Expand Down

0 comments on commit a062f63

Please sign in to comment.