diff --git a/packages/spacecat-shared-data-access/src/index.d.ts b/packages/spacecat-shared-data-access/src/index.d.ts index 6c53343b..8243a215 100644 --- a/packages/spacecat-shared-data-access/src/index.d.ts +++ b/packages/spacecat-shared-data-access/src/index.d.ts @@ -684,6 +684,9 @@ export interface DataAccess { removeAuditsForSite: ( siteId: string, ) => Promise; + updateLatestAudit: ( + audit: Audit, + ) => Promise; getSites: () => Promise; getSitesByDeliveryType: ( deliveryType: string, diff --git a/packages/spacecat-shared-data-access/src/service/audits/accessPatterns.js b/packages/spacecat-shared-data-access/src/service/audits/accessPatterns.js index 2936f756..4b8b46c4 100644 --- a/packages/spacecat-shared-data-access/src/service/audits/accessPatterns.js +++ b/packages/spacecat-shared-data-access/src/service/audits/accessPatterns.js @@ -256,6 +256,47 @@ async function removeAudits( await Promise.all(removeAuditPromises); } +/** + * Updates existing latest audit. + * This can be used for adding suggestions for example. + * @param dynamoClient - The DynamoDB client. + * @param config - The data access config. + * @param log - The logger. + * @param auditData - The audit data. + * @returns {Promise>} + */ +export const updateLatestAudit = async ( + dynamoClient, + config, + log, + auditData, +) => { + const newAudit = createAudit(auditData); + const existingAudit = await getLatestAuditForSite( + dynamoClient, + config, + log, + newAudit.getSiteId(), + newAudit.getAuditType(), + ); + + if (!isObject(existingAudit)) { + throw new Error('Audit to update not found'); + } + + await dynamoClient.putItem( + config.tableNameLatestAudits, + AuditDto.toDynamoItem(newAudit, true), + ); + + await dynamoClient.putItem( + config.tableNameAudits, + AuditDto.toDynamoItem(newAudit), + ); + + return newAudit; +}; + /** * Removes all audits for a specified site and the latest audit entry. * diff --git a/packages/spacecat-shared-data-access/src/service/audits/index.js b/packages/spacecat-shared-data-access/src/service/audits/index.js index ecc87fae..74bbdaac 100644 --- a/packages/spacecat-shared-data-access/src/service/audits/index.js +++ b/packages/spacecat-shared-data-access/src/service/audits/index.js @@ -18,6 +18,7 @@ import { getLatestAudits, getLatestAuditsForSite, removeAuditsForSite, + updateLatestAudit, } from './accessPatterns.js'; export const auditFunctions = (dynamoClient, config, log) => ({ @@ -69,4 +70,10 @@ export const auditFunctions = (dynamoClient, config, log) => ({ log, siteId, ), + updateLatestAudit: (auditData) => updateLatestAudit( + dynamoClient, + config, + log, + auditData, + ), }); diff --git a/packages/spacecat-shared-data-access/test/unit/service/audits/index.test.js b/packages/spacecat-shared-data-access/test/unit/service/audits/index.test.js index 518dd017..15f33c8a 100644 --- a/packages/spacecat-shared-data-access/test/unit/service/audits/index.test.js +++ b/packages/spacecat-shared-data-access/test/unit/service/audits/index.test.js @@ -328,5 +328,58 @@ describe('Audit Access Pattern Tests', () => { await expect(exportedFunctions.removeAuditsForSite('some-id')).to.be.rejectedWith(errorMessage); }); + + it('successfully updates the latest audit', async () => { + const mockAuditData = { + siteId: 'siteId', + auditType: 'broken-backlinks', + auditedAt: new Date().toISOString(), + fullAuditRef: 'https://someurl.com', + auditResult: { + brokenBacklinks: [ + { + title: 'Broken Link 1', + url_to: 'https://brokenlink1.com', + url_from: 'https://site1.com', + traffic_domain: 123, + }, + { + title: 'Broken Link 2', + url_to: 'https://brokenlink2.com', + url_from: 'https://site2.com', + traffic_domain: 456, + }, + ], + }, + }; + const updatedAuditData = { + ...mockAuditData, + auditResult: { + ...mockAuditData.auditResult, + brokenBacklinks: mockAuditData.auditResult.brokenBacklinks.map((backlink) => ({ + ...backlink, + urls_suggested: ['https://suggested.com', 'https://suggested2.com', 'https://suggested3.com'], + })), + }, + }; + + mockDynamoClient.getItem.resolves(mockAuditData); + + await exportedFunctions.updateLatestAudit(updatedAuditData); + + expect(mockDynamoClient.putItem.calledTwice).to.be.true; + }); + + it('should throw an error if the latest audit was not found', async () => { + const audit = { + siteId: 'siteId', + auditType: 'broken-backlinks', + auditedAt: new Date().toISOString(), + auditResult: {}, + fullAuditRef: 'https://someurl.com', + }; + + await expect(exportedFunctions.updateLatestAudit(audit)).to.be.rejectedWith('Audit to update not found'); + }); }); }); diff --git a/packages/spacecat-shared-data-access/test/unit/service/index.test.js b/packages/spacecat-shared-data-access/test/unit/service/index.test.js index 07eaa54c..29f892ff 100644 --- a/packages/spacecat-shared-data-access/test/unit/service/index.test.js +++ b/packages/spacecat-shared-data-access/test/unit/service/index.test.js @@ -24,6 +24,7 @@ describe('Data Access Object Tests', () => { 'getLatestAuditForSite', 'getLatestAuditsForSite', 'removeAuditsForSite', + 'updateLatestAudit', ]; const siteFunctions = [ 'addSite',