From 663e3b9e0c0f2bc10037d3a83f951494b4e27b64 Mon Sep 17 00:00:00 2001 From: Alex Anderson <191496+alxndrsn@users.noreply.github.com> Date: Wed, 4 Dec 2024 12:11:26 +0300 Subject: [PATCH] test/purge: assert database state after purging (#1178) --- test/integration/task/purge.js | 128 ++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 35 deletions(-) diff --git a/test/integration/task/purge.js b/test/integration/task/purge.js index 5e8b2e25e..8ac9a5a54 100644 --- a/test/integration/task/purge.js +++ b/test/integration/task/purge.js @@ -1,4 +1,7 @@ const appRoot = require('app-root-path'); +const assert = require('node:assert'); +const { isEmpty } = require('ramda'); +const { sql } = require('slonik'); const { testTask } = require('../setup'); const { purgeTask } = require(appRoot + '/lib/task/purge'); @@ -6,26 +9,62 @@ const { purgeTask } = require(appRoot + '/lib/task/purge'); // of purged forms, but the full functionality is more thoroughly tested in // test/integration/other/form-purging.js and test/integration/other/submission-purging.js. +const withDeleteChecks = container => { + const confirm = { + form: {}, + forms: {}, + }; + + const getDbFormRow = (projectId, xmlFormName) => container.maybeOne(sql` + SELECT * FROM forms WHERE "projectId"=${projectId} AND "xmlFormId"=${xmlFormName} + `); + + confirm.forms.softDeleted = async expected => { + const actual = await container.oneFirst(sql`SELECT COUNT(*) FROM forms WHERE "deletedAt" IS NOT NULL`); + assert.equal(actual, expected); + }; + + confirm.form.softDeleted = async (projectId, xmlFormName) => { + const maybeForm = await getDbFormRow(projectId, xmlFormName); + assert.equal(isEmpty(maybeForm), false, 'Form has been hard-deleted or never existed.'); + const { deletedAt } = maybeForm.get(); + assert.ok(deletedAt, 'Form exists but has not been marked as deleted.'); + }; + + confirm.form.hardDeleted = async (projectId, xmlFormName) => { + const maybeForm = await getDbFormRow(projectId, xmlFormName); + assert.ok(isEmpty(maybeForm), 'Form should have been deleted, but still exists in DB!'); + }; + + return { ...container, confirm }; +}; + +const testPurgeTask = fn => testTask(container => fn(withDeleteChecks(container))); + describe('task: purge deleted resources (forms and submissions)', () => { describe('forms', () => { describe('force flag', () => { - it('should not purge recently deleted forms by default', testTask(({ Forms }) => + it('should not purge recently deleted forms by default', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) - .then(() => purgeTask({ mode: 'forms' })) - .then((message) => { - message.should.equal('Forms purged: 0'); - })))); + .then(() => confirm.form.softDeleted(1, 'simple'))) + .then(() => purgeTask({ mode: 'forms' })) + .then((message) => { + message.should.equal('Forms purged: 0'); + }) + .then(() => confirm.form.softDeleted(1, 'simple')))); - it('should purge recently deleted form if forced', testTask(({ Forms }) => + it('should purge recently deleted form if forced', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) - .then(() => purgeTask({ mode: 'forms', force: true })) - .then((message) => { - message.should.equal('Forms purged: 1'); - })))); + .then(() => confirm.form.softDeleted(1, 'simple'))) + .then(() => purgeTask({ mode: 'forms', force: true })) + .then((message) => { + message.should.equal('Forms purged: 1'); + }) + .then(() => confirm.form.hardDeleted(1, 'simple')))); - it('should return message for multiple forms purged', testTask(({ Forms }) => + it('should return message for multiple forms purged', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -33,27 +72,31 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true }) .then((message) => { message.should.equal('Forms purged: 2'); - })))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple')) + .then(() => confirm.form.hardDeleted(1, 'withrepeat'))))); }); describe('form specified by formId', () => { - it('should not purge specific recently deleted form', testTask(({ Forms }) => + it('should not purge specific recently deleted form', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', force: false, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 0'); - })))); + }) + .then(() => confirm.form.softDeleted(1, 'simple'))))); - it('should purge specific recently deleted form if forced', testTask(({ Forms }) => + it('should purge specific recently deleted form if forced', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', force: true, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 1'); - })))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple'))))); - it('should force purge only specific form', testTask(({ Forms }) => + it('should force purge only specific form', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -61,27 +104,31 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 1'); - }))))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple')) + .then(() => confirm.form.softDeleted(1, 'withrepeat')))))); }); describe('form specified with projectId', () => { - it('should not purge recently deleted forms even if projectId is matched (when not forced', testTask(({ Forms }) => + it('should not purge recently deleted forms even if projectId is matched (when not forced', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', projectId: 1 })) .then((message) => { message.should.equal('Forms purged: 0'); - })))); + }) + .then(() => confirm.form.softDeleted(1, 'simple'))))); - it('should not purge recently deleted forms even if projectId AND formId is matched (when not forced)', testTask(({ Forms }) => + it('should not purge recently deleted forms even if projectId AND formId is matched (when not forced)', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', projectId: 1, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 0'); - })))); + }) + .then(() => confirm.form.softDeleted(1, 'simple'))))); - it('should purge specific form', testTask(({ Forms }) => + it('should purge specific form', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -89,9 +136,11 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true, projectId: 1, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 1'); - }))))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple')) + .then(() => confirm.form.softDeleted(1, 'withrepeat')))))); - it('should not purge specific form if tied to a different project', testTask(({ Forms }) => + it('should not purge specific form if tied to a different project', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -99,9 +148,10 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true, projectId: 2, formId: 1 })) .then((message) => { message.should.equal('Forms purged: 0'); - }))))); + }) + .then(() => confirm.form.softDeleted(1, 'simple')))))); - it('should purge all forms in project if no form ID supplied', testTask(({ Forms }) => + it('should purge all forms in project if no form ID supplied', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -109,9 +159,11 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true, projectId: 1 })) .then((message) => { message.should.equal('Forms purged: 2'); - }))))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple')) + .then(() => confirm.form.hardDeleted(1, 'withrepeat')))))); - it('should not purge multiple forms if tied to a different project', testTask(({ Forms }) => + it('should not purge multiple forms if tied to a different project', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get())) .then(() => Forms.getByProjectAndXmlFormId(1, 'withrepeat') @@ -119,32 +171,38 @@ describe('task: purge deleted resources (forms and submissions)', () => { .then(() => purgeTask({ mode: 'forms', force: true, projectId: 2 })) .then((message) => { message.should.equal('Forms purged: 0'); - }))))); + }) + .then(() => confirm.forms.softDeleted(2)) + .then(() => confirm.form.softDeleted(1, 'simple')) + .then(() => confirm.form.softDeleted(1, 'withrepeat')))))); }); describe('with xmlFormId', () => { - it('should throw error if xmlFormId specified without projectId', testTask(async ({ Forms }) => { + it('should throw error if xmlFormId specified without projectId', testPurgeTask(async ({ confirm, Forms }) => { const form = await Forms.getByProjectAndXmlFormId(1, 'simple'); await Forms.del(form.get()); const message = await purgeTask({ mode: 'forms', force: true, xmlFormId: 'simple' }); message.should.equal('Must also specify projectId when using xmlFormId'); + await confirm.form.softDeleted(1, 'simple'); })); - it('should force purge form by project and xmlFormId', testTask(({ Forms }) => + it('should force purge form by project and xmlFormId', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', force: true, projectId: 1, xmlFormId: 'simple' })) .then((message) => { message.should.equal('Forms purged: 1'); - })))); + }) + .then(() => confirm.form.hardDeleted(1, 'simple'))))); - it('should not purge form by project and xmlFormId if form deleted recently and not forced', testTask(({ Forms }) => + it('should not purge form by project and xmlFormId if form deleted recently and not forced', testPurgeTask(({ confirm, Forms }) => Forms.getByProjectAndXmlFormId(1, 'simple') .then((form) => Forms.del(form.get()) .then(() => purgeTask({ mode: 'forms', force: false, projectId: 1, xmlFormId: 'simple' })) .then((message) => { message.should.equal('Forms purged: 0'); - })))); + }) + .then(() => confirm.form.softDeleted(1, 'simple'))))); }); });