Skip to content

Commit 221e53e

Browse files
Only disable audits which were enabled when scheduled run is false
1 parent 7aa54d4 commit 221e53e

3 files changed

Lines changed: 175 additions & 6 deletions

File tree

src/tasks/disable-import-audit-processor/handler.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,26 @@ export async function runDisableImportAuditProcessor(message, context) {
6060
site.setConfig(Config.toDynamoItem(siteConfig));
6161

6262
const configuration = await Configuration.findLatest();
63+
const auditsDisabled = [];
6364
for (const auditType of auditTypes) {
64-
configuration.disableHandlerForSite(auditType, site);
65+
if (configuration.isHandlerEnabledForSite(auditType, site)) {
66+
configuration.disableHandlerForSite(auditType, site);
67+
auditsDisabled.push(auditType);
68+
}
6569
}
6670

6771
await site.save();
68-
await configuration.save();
72+
if (auditsDisabled.length > 0) {
73+
await configuration.save();
74+
}
6975
log.info(`For site: ${siteUrl}: Disabled imports and audits`);
7076

7177
const importsText = importTypes.length > 0 ? importTypes.join(', ') : 'None';
72-
const auditsText = auditTypes.length > 0 ? auditTypes.join(', ') : 'None';
78+
const auditsText = auditsDisabled.length > 0 ? auditsDisabled.join(', ') : 'None';
7379

7480
let slackMessage = `:broom: *For site: ${siteUrl}: Disabled imports*: ${importsText} *and audits*: ${auditsText}`;
7581
await say(env, log, slackContext, slackMessage);
76-
slackMessage = ':information_source: The list of enabled imports and audits may differ from the disabled ones because items that are already enabled are not automatically disabled. When schedule run flag is true then no imports and audits are disabled.';
82+
slackMessage = ':information_source: Only audits currently enabled for the site are disabled. Scheduled sites skip disable entirely.';
7783
await say(env, log, slackContext, slackMessage);
7884
} catch (error) {
7985
log.error('Error in disable import and audit processor:', error);

test/tasks/disable-import-audit-processor/disable-import-audit-processor.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ describe('Disable Import Audit Processor', () => {
7171
};
7272

7373
mockConfiguration = {
74+
isHandlerEnabledForSite: sandbox.stub().returns(true),
7475
disableHandlerForSite: sandbox.stub(),
7576
save: sandbox.stub().resolves(),
7677
};
@@ -153,7 +154,7 @@ describe('Disable Import Audit Processor', () => {
153154
context.env,
154155
context.log,
155156
'test-slack-context',
156-
':information_source: The list of enabled imports and audits may differ from the disabled ones because items that are already enabled are not automatically disabled. When schedule run flag is true then no imports and audits are disabled.',
157+
':information_source: Only audits currently enabled for the site are disabled. Scheduled sites skip disable entirely.',
157158
);
158159

159160
// Verify successful completion
@@ -172,7 +173,7 @@ describe('Disable Import Audit Processor', () => {
172173

173174
// Verify saves were still called
174175
expect(mockSite.save).to.have.been.calledOnce;
175-
expect(mockConfiguration.save).to.have.been.calledOnce;
176+
expect(mockConfiguration.save).not.to.have.been.called;
176177

177178
expect(toDynamoItemStub).to.have.been.calledOnceWith(mockSiteConfig);
178179
expect(mockSite.setConfig).to.have.been.calledOnceWith(serializedConfigFixture);
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
* Copyright 2025 Adobe. All rights reserved.
3+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License. You may obtain a copy
5+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software distributed under
8+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
* OF ANY KIND, either express or implied. See the License for the specific language
10+
* governing permissions and limitations under the License.
11+
*/
12+
13+
import { expect, use } from 'chai';
14+
import sinon from 'sinon';
15+
import sinonChai from 'sinon-chai';
16+
import esmock from 'esmock';
17+
18+
use(sinonChai);
19+
20+
describe('disable-import-audit-processor handler', () => {
21+
let sandbox;
22+
let context;
23+
let message;
24+
let mockSite;
25+
let mockSiteConfig;
26+
let mockConfiguration;
27+
let mockSay;
28+
let runDisableImportAuditProcessor;
29+
30+
beforeEach(async () => {
31+
sandbox = sinon.createSandbox();
32+
33+
mockSay = sandbox.stub().resolves();
34+
35+
const handlerModule = await esmock('../../../src/tasks/disable-import-audit-processor/handler.js', {
36+
'../../../src/utils/slack-utils.js': { say: mockSay },
37+
'@adobe/spacecat-shared-data-access': {
38+
Config: { toDynamoItem: sandbox.stub().returns({}) },
39+
},
40+
});
41+
runDisableImportAuditProcessor = handlerModule.runDisableImportAuditProcessor;
42+
43+
mockSiteConfig = {
44+
disableImport: sandbox.stub(),
45+
};
46+
47+
mockSite = {
48+
getConfig: sandbox.stub().returns(mockSiteConfig),
49+
setConfig: sandbox.stub(),
50+
save: sandbox.stub().resolves(),
51+
};
52+
53+
mockConfiguration = {
54+
isHandlerEnabledForSite: sandbox.stub(),
55+
disableHandlerForSite: sandbox.stub(),
56+
save: sandbox.stub().resolves(),
57+
};
58+
59+
context = {
60+
log: {
61+
info: sandbox.stub(),
62+
error: sandbox.stub(),
63+
warn: sandbox.stub(),
64+
},
65+
env: {},
66+
dataAccess: {
67+
Site: { findByBaseURL: sandbox.stub().resolves(mockSite) },
68+
Configuration: { findLatest: sandbox.stub().resolves(mockConfiguration) },
69+
},
70+
};
71+
72+
message = {
73+
siteId: 'site-123',
74+
siteUrl: 'https://example.com',
75+
organizationId: 'org-123',
76+
taskContext: {
77+
importTypes: ['traffic-analysis'],
78+
auditTypes: ['cwv', 'apex'],
79+
scheduledRun: false,
80+
slackContext: null,
81+
},
82+
};
83+
});
84+
85+
afterEach(() => {
86+
sandbox.restore();
87+
});
88+
89+
it('skips all disabling when scheduledRun is true', async () => {
90+
message.taskContext.scheduledRun = true;
91+
92+
const result = await runDisableImportAuditProcessor(message, context);
93+
94+
expect(result.status).to.equal(200);
95+
expect(context.dataAccess.Site.findByBaseURL).not.to.have.been.called;
96+
expect(context.dataAccess.Configuration.findLatest).not.to.have.been.called;
97+
expect(context.log.info.calledWith(sinon.match(/Scheduled run detected/))).to.be.true;
98+
});
99+
100+
it('disables imports and enabled audits for non-scheduled site', async () => {
101+
mockConfiguration.isHandlerEnabledForSite.withArgs('cwv', mockSite).returns(true);
102+
mockConfiguration.isHandlerEnabledForSite.withArgs('apex', mockSite).returns(true);
103+
104+
await runDisableImportAuditProcessor(message, context);
105+
106+
expect(mockSiteConfig.disableImport).to.have.been.calledWith('traffic-analysis');
107+
expect(mockConfiguration.disableHandlerForSite).to.have.been.calledWith('cwv', mockSite);
108+
expect(mockConfiguration.disableHandlerForSite).to.have.been.calledWith('apex', mockSite);
109+
expect(mockConfiguration.save).to.have.been.calledOnce;
110+
expect(mockSite.save).to.have.been.calledOnce;
111+
});
112+
113+
it('is a no-op for audits that are already disabled', async () => {
114+
mockConfiguration.isHandlerEnabledForSite.returns(false);
115+
116+
await runDisableImportAuditProcessor(message, context);
117+
118+
expect(mockConfiguration.disableHandlerForSite).not.to.have.been.called;
119+
expect(mockConfiguration.save).not.to.have.been.called;
120+
});
121+
122+
it('only disables audits that are currently enabled', async () => {
123+
mockConfiguration.isHandlerEnabledForSite.withArgs('cwv', mockSite).returns(true);
124+
mockConfiguration.isHandlerEnabledForSite.withArgs('apex', mockSite).returns(false);
125+
126+
await runDisableImportAuditProcessor(message, context);
127+
128+
expect(mockConfiguration.disableHandlerForSite).to.have.been.calledOnceWith('cwv', mockSite);
129+
expect(mockConfiguration.save).to.have.been.calledOnce;
130+
});
131+
132+
it('skips audit disable when auditTypes is empty', async () => {
133+
message.taskContext.auditTypes = [];
134+
135+
await runDisableImportAuditProcessor(message, context);
136+
137+
expect(mockConfiguration.isHandlerEnabledForSite).not.to.have.been.called;
138+
expect(mockConfiguration.disableHandlerForSite).not.to.have.been.called;
139+
expect(mockConfiguration.save).not.to.have.been.called;
140+
expect(mockSite.save).to.have.been.calledOnce;
141+
});
142+
143+
it('handles missing site gracefully', async () => {
144+
context.dataAccess.Site.findByBaseURL.resolves(null);
145+
146+
const result = await runDisableImportAuditProcessor(message, context);
147+
148+
expect(result.status).to.equal(200);
149+
expect(context.log.error.calledWith(
150+
'Error in disable import and audit processor:',
151+
sinon.match.instanceOf(Error),
152+
)).to.be.true;
153+
});
154+
155+
it('returns 200 on success', async () => {
156+
mockConfiguration.isHandlerEnabledForSite.returns(false);
157+
158+
const result = await runDisableImportAuditProcessor(message, context);
159+
160+
expect(result.status).to.equal(200);
161+
});
162+
});

0 commit comments

Comments
 (0)