From 919279d9cd421a842bff3f44eef7c61a7696442d Mon Sep 17 00:00:00 2001 From: Ben Helleman Date: Wed, 5 Feb 2025 11:55:13 -0500 Subject: [PATCH 1/5] fix(sites-28856): update shared-data schema to include type in options --- .gitignore | 3 ++ package-lock.json | 2 +- .../src/models/import-job/import-job.model.js | 6 +++ .../models/import-job/import-job.schema.js | 9 ++++ .../test/it/import-job/import-job.test.js | 52 ++++++++++++++----- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index d698a9bad..7c926da81 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,6 @@ junit # Mac OS .DS_Store + +# NVM (Node Version Manager) +.nvmrc diff --git a/package-lock.json b/package-lock.json index 1f9a51135..a6c240aa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20186,7 +20186,7 @@ }, "packages/spacecat-shared-content-client": { "name": "@adobe/spacecat-shared-content-client", - "version": "1.3.17", + "version": "1.3.18", "license": "Apache-2.0", "dependencies": { "@adobe/helix-universal": "5.0.8", diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js index 714b2d8c6..d3faefe63 100644 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js @@ -47,6 +47,12 @@ class ImportJob extends BaseModel { static ImportOptions = { ENABLE_JAVASCRIPT: 'enableJavascript', PAGE_LOAD_TIMEOUT: 'pageLoadTimeout', + TYPE: 'type', + }; + + static ImportOptionTypes = { + DOC: 'doc', + XWALK: 'xwalk', }; // add your custom methods or overrides here diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js index f5bd5cbb7..cbd1cde5b 100755 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js @@ -17,6 +17,7 @@ import { isIsoDate, isNumber, isObject, + isString, isValidUrl, } from '@adobe/spacecat-shared-utils'; @@ -35,6 +36,14 @@ const ImportOptionTypeValidator = { throw new Error(`Invalid value for ${ImportJob.ImportOptions.PAGE_LOAD_TIMEOUT}: ${value}`); } }, + [ImportJob.ImportOptions.TYPE]: (value) => { + if (!isString(value)) { + throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); + } + if (!Object.values(ImportJob.ImportOptionTypes).includes(value)) { + throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); + } + }, }; const validateOptions = (options) => { diff --git a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js index bdf4431f8..897884be8 100644 --- a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js +++ b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js @@ -15,9 +15,11 @@ import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; +import { ElectroValidationError } from 'electrodb'; import ImportJobModel from '../../../src/models/import-job/import-job.model.js'; import { getDataAccess } from '../util/db.js'; import { seedDatabase } from '../util/seed.js'; +import { DataAccessError } from '../../../src/index.js'; use(chaiAsPromised); @@ -41,16 +43,15 @@ function checkImportJob(importJob) { describe('ImportJob IT', async () => { let sampleData; let ImportJob; + let newJobData; before(async () => { sampleData = await seedDatabase(); const dataAccess = getDataAccess(); ImportJob = dataAccess.ImportJob; - }); - it('adds a new import job', async () => { - const data = { + newJobData = { importQueueId: 'some-queue-id', hashedApiKey: 'some-hashed-api-key', baseURL: 'https://example-some.com/cars', @@ -62,18 +63,45 @@ describe('ImportJob IT', async () => { hasCustomImportJs: false, hasCustomHeaders: true, }; - const importJob = await ImportJob.create(data); + }); + + it('adds a new import job', async () => { + const importJob = await ImportJob.create(newJobData); + + checkImportJob(importJob); + + expect(importJob.getImportQueueId()).to.equal(newJobData.importQueueId); + expect(importJob.getHashedApiKey()).to.equal(newJobData.hashedApiKey); + expect(importJob.getBaseURL()).to.equal(newJobData.baseURL); + expect(importJob.getStartedAt()).to.equal(newJobData.startedAt); + expect(importJob.getStatus()).to.equal(newJobData.status); + expect(importJob.getInitiatedBy()).to.eql(newJobData.initiatedBy); + expect(importJob.getHasCustomImportJs()).to.equal(newJobData.hasCustomImportJs); + expect(importJob.getHasCustomHeaders()).to.equal(newJobData.hasCustomHeaders); + }); + + it('adds a new import job with valid options', async () => { + let data = { ...newJobData, options: { type: 'xwalk' } }; + let importJob = await ImportJob.create(data); + + checkImportJob(importJob); + expect(importJob.getOptions()).to.eql({ type: 'xwalk' }); + + data = { ...newJobData, options: { type: 'doc' } }; + importJob = await ImportJob.create(data); checkImportJob(importJob); + expect(importJob.getOptions()).to.eql({ type: 'doc' }); + }); - expect(importJob.getImportQueueId()).to.equal(data.importQueueId); - expect(importJob.getHashedApiKey()).to.equal(data.hashedApiKey); - expect(importJob.getBaseURL()).to.equal(data.baseURL); - expect(importJob.getStartedAt()).to.equal(data.startedAt); - expect(importJob.getStatus()).to.equal(data.status); - expect(importJob.getInitiatedBy()).to.eql(data.initiatedBy); - expect(importJob.getHasCustomImportJs()).to.equal(data.hasCustomImportJs); - expect(importJob.getHasCustomHeaders()).to.equal(data.hasCustomHeaders); + it('throws an error when adding a new import job with invalid options', async () => { + const data = { ...newJobData, options: { type: 'invalid' } }; + + await ImportJob.create(data).catch((err) => { + expect(err).to.be.instanceOf(DataAccessError); + expect(err.cause).to.be.instanceOf(ElectroValidationError); + expect(err.cause.message).to.contain('Invalid value for type: invalid'); + }); }); it('updates an existing import job', async () => { From 8a3c4ba514a414d24acb34c2a21ffbbc9223a9a6 Mon Sep 17 00:00:00 2001 From: Ben Helleman Date: Wed, 5 Feb 2025 12:02:57 -0500 Subject: [PATCH 2/5] fix(sites-28856): update shared-data schema to include type in options * simplify condition --- .../src/models/import-job/import-job.schema.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js index cbd1cde5b..c5f35f357 100755 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js @@ -37,10 +37,7 @@ const ImportOptionTypeValidator = { } }, [ImportJob.ImportOptions.TYPE]: (value) => { - if (!isString(value)) { - throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); - } - if (!Object.values(ImportJob.ImportOptionTypes).includes(value)) { + if (!isString(value) || !Object.values(ImportJob.ImportOptionTypes).includes(value)) { throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); } }, From eabc05440441059472c253d4b18786a667aaf2a0 Mon Sep 17 00:00:00 2001 From: Ben Helleman Date: Wed, 5 Feb 2025 16:53:44 -0500 Subject: [PATCH 3/5] fix(sites-28856): update shared-data schema to include type in options --- .../src/models/import-job/import-job.schema.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js index c5f35f357..15a989c51 100755 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js @@ -17,7 +17,6 @@ import { isIsoDate, isNumber, isObject, - isString, isValidUrl, } from '@adobe/spacecat-shared-utils'; @@ -37,7 +36,7 @@ const ImportOptionTypeValidator = { } }, [ImportJob.ImportOptions.TYPE]: (value) => { - if (!isString(value) || !Object.values(ImportJob.ImportOptionTypes).includes(value)) { + if (!Object.values(ImportJob.ImportOptionTypes).includes(value)) { throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); } }, From 1c5c511828aace2ad54d6eec4d3b02405cf7d917 Mon Sep 17 00:00:00 2001 From: Ben Helleman Date: Thu, 6 Feb 2025 11:52:06 -0500 Subject: [PATCH 4/5] fix(sites-28856): update shared-data schema to include type in options * include a data attribute on options --- .../src/models/import-job/import-job.model.js | 1 + .../models/import-job/import-job.schema.js | 5 +++++ .../test/it/import-job/import-job.test.js | 20 +++++++++++++++++-- .../import-job/import-job.model.test.js | 19 ++++++++++++++++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js index d3faefe63..60ab5d54f 100644 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.model.js @@ -48,6 +48,7 @@ class ImportJob extends BaseModel { ENABLE_JAVASCRIPT: 'enableJavascript', PAGE_LOAD_TIMEOUT: 'pageLoadTimeout', TYPE: 'type', + DATA: 'data', }; static ImportOptionTypes = { diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js index 15a989c51..2cb147821 100755 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js @@ -40,6 +40,11 @@ const ImportOptionTypeValidator = { throw new Error(`Invalid value for ${ImportJob.ImportOptions.TYPE}: ${value}`); } }, + [ImportJob.ImportOptions.DATA]: (value) => { + if (!isObject(value)) { + throw new Error(`Invalid value for ${ImportJob.ImportOptions.DATA}: ${value}`); + } + }, }; const validateOptions = (options) => { diff --git a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js index 897884be8..f598fce57 100644 --- a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js +++ b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js @@ -81,17 +81,33 @@ describe('ImportJob IT', async () => { }); it('adds a new import job with valid options', async () => { - let data = { ...newJobData, options: { type: 'xwalk' } }; + const options = { + type: 'xwalk', + data: { + siteName: 'xwalk', + assetFolder: 'xwalk', + }, + }; + + let data = { ...newJobData, options }; let importJob = await ImportJob.create(data); checkImportJob(importJob); - expect(importJob.getOptions()).to.eql({ type: 'xwalk' }); + expect(importJob.getOptions()).to.equal(data.options); data = { ...newJobData, options: { type: 'doc' } }; importJob = await ImportJob.create(data); checkImportJob(importJob); expect(importJob.getOptions()).to.eql({ type: 'doc' }); + + // test to make sure data error is thrown if data is not an object + data = { ...newJobData, options: { data: 'not-an-object' } }; + await ImportJob.create(data).catch((err) => { + expect(err).to.be.instanceOf(DataAccessError); + expect(err.cause).to.be.instanceOf(ElectroValidationError); + expect(err.cause.message).to.contain('Invalid value for data: not-an-object'); + }); }); it('throws an error when adding a new import job with invalid options', async () => { diff --git a/packages/spacecat-shared-data-access/test/unit/models/import-job/import-job.model.test.js b/packages/spacecat-shared-data-access/test/unit/models/import-job/import-job.model.test.js index c2643d80f..b0035f48a 100755 --- a/packages/spacecat-shared-data-access/test/unit/models/import-job/import-job.model.test.js +++ b/packages/spacecat-shared-data-access/test/unit/models/import-job/import-job.model.test.js @@ -47,13 +47,17 @@ describe('ImportJobModel', () => { userAgent: 'someUserAgent', }, options: { - someOption: 'someValue', + type: 'xwalk', }, redirectCount: 0, status: 'RUNNING', startedAt: '2022-01-01T00:00:00.000Z', successCount: 0, urlCount: 0, + data: { + siteName: 'xwalk', + assetFolder: 'xwalk', + }, }; ({ @@ -189,8 +193,13 @@ describe('ImportJobModel', () => { }); describe('options', () => { + it('no options', () => { + instance.setOptions(undefined); + expect(instance.getOptions()).to.be.undefined; + }); + it('gets options', () => { - expect(instance.getOptions()).to.deep.equal({ someOption: 'someValue' }); + expect(instance.getOptions()).to.deep.equal({ type: 'xwalk' }); }); it('sets options', () => { @@ -198,6 +207,12 @@ describe('ImportJobModel', () => { instance.setOptions(newOptions); expect(instance.getOptions()).to.deep.equal(newOptions); }); + + it('sets options with data attribute', () => { + const newOptions = { data: { siteFolder: 'xwalk', assetFolder: 'xwalk' } }; + instance.setOptions(newOptions); + expect(instance.getOptions()).to.deep.equal(newOptions); + }); }); describe('redirectCount', () => { From 3dd778ede91fdc76c32d7cc74a0d5e2725e35cd4 Mon Sep 17 00:00:00 2001 From: Ben Helleman Date: Thu, 6 Feb 2025 13:04:35 -0500 Subject: [PATCH 5/5] fix(sites-28856): update shared-data schema to include type in options --- .../src/models/import-job/import-job.schema.js | 3 ++- .../test/it/import-job/import-job.test.js | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js index 2cb147821..addc76852 100755 --- a/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js +++ b/packages/spacecat-shared-data-access/src/models/import-job/import-job.schema.js @@ -15,6 +15,7 @@ import { isInteger, isIsoDate, + isNonEmptyObject, isNumber, isObject, isValidUrl, @@ -41,7 +42,7 @@ const ImportOptionTypeValidator = { } }, [ImportJob.ImportOptions.DATA]: (value) => { - if (!isObject(value)) { + if (value && !isNonEmptyObject(value)) { throw new Error(`Invalid value for ${ImportJob.ImportOptions.DATA}: ${value}`); } }, diff --git a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js index f598fce57..08d903cc0 100644 --- a/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js +++ b/packages/spacecat-shared-data-access/test/it/import-job/import-job.test.js @@ -108,6 +108,14 @@ describe('ImportJob IT', async () => { expect(err.cause).to.be.instanceOf(ElectroValidationError); expect(err.cause.message).to.contain('Invalid value for data: not-an-object'); }); + + // test to make sure data is not an empty object + data = { ...newJobData, options: { data: { } } }; + await ImportJob.create(data).catch((err) => { + expect(err).to.be.instanceOf(DataAccessError); + expect(err.cause).to.be.instanceOf(ElectroValidationError); + expect(err.cause.message).to.contain('Invalid value for data'); + }); }); it('throws an error when adding a new import job with invalid options', async () => {