Skip to content

Commit be82400

Browse files
address review comments
1 parent 6d84d84 commit be82400

File tree

7 files changed

+140
-94
lines changed

7 files changed

+140
-94
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ SpaceCat Task Processor is a Node.js service that processes messages from the AW
2727
1. Clone the repository
2828
2. Install dependencies:
2929
```sh
30-
npm ci
30+
npm install
3131
```
3232
3. Configure AWS credentials and environment variables as needed
3333

scripts/watch-and-copy.js

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/tasks/demo-url-processor/handler.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,37 @@ import { say } from '../../utils/slack-utils.js';
1515

1616
const TASK_TYPE = 'demo-url-processor';
1717

18+
/**
19+
* Gets the IMS tenant ID from the organization
20+
* @param {object} organization - The organization object
21+
* @param {object} context - The context object
22+
* @param {object} log - The log object
23+
* @returns {string} The IMS tenant ID
24+
*/
25+
function getImsTenantId(organization, context, log) {
26+
const { name, imsOrgId } = organization;
27+
try {
28+
const imsOrgToTenantMapping = context.env.IMSORG_TO_TENANT;
29+
if (imsOrgToTenantMapping) {
30+
const mapping = JSON.parse(imsOrgToTenantMapping);
31+
if (mapping[imsOrgId]) {
32+
return mapping[imsOrgId];
33+
}
34+
}
35+
} catch (error) {
36+
log.error('Error loading IMSORG_TO_TENANT mapping:', error.message);
37+
}
38+
return name.toLowerCase().replace(/\s+/g, '');
39+
}
40+
1841
/**
1942
* Runs the audit status processor
2043
* @param {object} demoUrlMessage - The demoUrlMessage object
2144
* @param {object} context - The context object
2245
*/
2346
export async function runDemoUrlProcessor(message, context) {
24-
const { log, env } = context;
47+
const { log, env, dataAccess } = context;
48+
const { Organization } = dataAccess;
2549
const { siteId, organizationId, taskContext } = message;
2650
const {
2751
siteUrl, slackContext,
@@ -34,7 +58,15 @@ export async function runDemoUrlProcessor(message, context) {
3458
organizationId,
3559
});
3660

37-
const demoUrl = `${siteUrl}?organizationId=${organizationId}#/@aemrefdemoshared/sites-optimizer/sites/${siteId}/home`;
61+
const organization = await Organization.findById(organizationId);
62+
if (!organization) {
63+
log.error(`Organization not found for organizationId: ${organizationId}`);
64+
await say(env, log, slackContext, `:x: Organization not found for organizationId: ${organizationId}`);
65+
return ok({ message: 'Organization not found' });
66+
}
67+
68+
const imsTenantId = getImsTenantId(organization, context, log);
69+
const demoUrl = `${siteUrl}?organizationId=${organizationId}#/@${imsTenantId}/sites-optimizer/sites/${siteId}/home`;
3870
const slackMessage = `:white_check_mark: Setup complete! Access your demo environment here: ${demoUrl}`;
3971
await say(env, log, slackContext, slackMessage);
4072
log.info(`Setup complete! Access your demo environment here: ${demoUrl}`);

src/tasks/opportunity-status-processor/handler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export async function runOpportunityStatusProcessor(message, context) {
6262

6363
try {
6464
// Get the site and its opportunities
65-
const site = await Site.findByBaseURL(`https://${siteId}.com`);
65+
const site = await Site.findById(siteId);
6666
if (!site) {
6767
log.error(`Site not found for siteId: ${siteId}`);
6868
await say(env, log, slackContext, `:x: Site not found for siteId: ${siteId}`);

test/index.test.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,28 @@ describe('Index Tests', () => {
8383
// Test that the handler can handle broken env gracefully
8484
messageBodyJson.type = 'demo-url-processor';
8585
messageBodyJson.siteId = 'test-site';
86+
messageBodyJson.organizationId = 'test-org';
87+
messageBodyJson.taskContext = {
88+
siteUrl: 'https://example.com',
89+
slackContext: 'test-slack-context',
90+
};
8691
context.invocation.event.Records[0].body = JSON.stringify(messageBodyJson);
87-
// Remove env to test error handling in the handler
88-
context.env = null;
92+
93+
// Provide minimal data access and env
94+
context.dataAccess = {
95+
Organization: {
96+
findById: sandbox.stub().resolves({
97+
name: 'Test Organization',
98+
imsOrgId: 'TEST_ORG_ID@AdobeOrg',
99+
}),
100+
},
101+
};
102+
context.env = {
103+
IMSORG_TO_TENANT: JSON.stringify({
104+
'TEST_ORG_ID@AdobeOrg': 'test-org',
105+
}),
106+
};
107+
89108
const resp = await main(request, context);
90109
expect(resp.status).to.equal(200); // Handler should handle the error gracefully
91110
// Verify the task handler was found
@@ -99,7 +118,6 @@ describe('Index Tests', () => {
99118
expect(context.log.info.calledWith('Found task handler for type: dummy')).to.be.true;
100119
// Print all log.info calls for debugging
101120
// eslint-disable-next-line no-console
102-
console.log('log.info calls:', context.log.info.getCalls().map((call) => call.args[0]));
103121
// Verify the task completion message (using partial match since timing varies)
104122
expect(context.log.info.calledWithMatch(sinon.match('dummy task for site-id completed in'))).to.be.true;
105123
});

test/tasks/demo-url-processor/demo-url-processor.test.js

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ describe('Demo URL Processor', () => {
3737
// Mock context
3838
context = new MockContextBuilder()
3939
.withSandbox(sandbox)
40+
.withDataAccess({
41+
Organization: {
42+
findById: sandbox.stub().resolves({
43+
name: 'Adobe Sites Engineering',
44+
imsOrgId: '8C6043F15F43B6390A49401A@AdobeOrg',
45+
}),
46+
},
47+
})
4048
.build();
4149

4250
// Mock message
@@ -56,22 +64,92 @@ describe('Demo URL Processor', () => {
5664

5765
describe('runDemoUrlProcessor', () => {
5866
it('should process demo URL successfully', async () => {
67+
// Set up the IMSORG_TO_TENANT secret in context
68+
context.env.IMSORG_TO_TENANT = JSON.stringify({
69+
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
70+
});
71+
5972
await runDemoUrlProcessor(message, context);
6073
expect(context.log.info.calledWith('Processing demo url for site:', {
6174
taskType: 'demo-url-processor',
6275
siteId: 'test-site-id',
6376
siteUrl: 'https://example.com',
6477
organizationId: 'test-org-id',
6578
})).to.be.true;
66-
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aemrefdemoshared/sites-optimizer/sites/test-site-id/home';
79+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
6780
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
6881
});
6982

7083
it('should handle missing slackContext in taskContext', async () => {
84+
// Set up the IMSORG_TO_TENANT secret in context
85+
context.env.IMSORG_TO_TENANT = JSON.stringify({
86+
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
87+
});
88+
7189
delete message.taskContext.slackContext;
7290
await runDemoUrlProcessor(message, context);
73-
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aemrefdemoshared/sites-optimizer/sites/test-site-id/home';
91+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
92+
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
93+
});
94+
95+
it('should use IMSORG_TO_TENANT mapping when available', async () => {
96+
// Set up the IMSORG_TO_TENANT secret in context
97+
context.env.IMSORG_TO_TENANT = JSON.stringify({
98+
'8C6043F15F43B6390A49401A@AdobeOrg': 'aem-sites-engineering',
99+
});
100+
101+
await runDemoUrlProcessor(message, context);
102+
103+
// Should use the mapped tenant name instead of the fallback
104+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@aem-sites-engineering/sites-optimizer/sites/test-site-id/home';
105+
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
106+
});
107+
108+
it('should fallback to name-based tenant when IMSORG_TO_TENANT mapping is not available', async () => {
109+
// Don't set IMSORG_TO_TENANT secret
110+
delete context.env.IMSORG_TO_TENANT;
111+
112+
await runDemoUrlProcessor(message, context);
113+
114+
// Should use the fallback name-based tenant (lowercase, no spaces)
115+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
74116
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
75117
});
118+
119+
it('should fallback to name-based tenant when IMSORG_TO_TENANT mapping is invalid JSON', async () => {
120+
// Set invalid JSON in IMSORG_TO_TENANT secret
121+
context.env.IMSORG_TO_TENANT = 'invalid-json';
122+
123+
await runDemoUrlProcessor(message, context);
124+
125+
// Should use the fallback name-based tenant
126+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
127+
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
128+
});
129+
130+
it('should fallback to name-based tenant when IMSORG_TO_TENANT mapping does not contain the imsOrgId', async () => {
131+
// Set IMSORG_TO_TENANT secret with different mapping
132+
context.env.IMSORG_TO_TENANT = JSON.stringify({
133+
'DIFFERENT_ORG_ID@AdobeOrg': 'different-team',
134+
});
135+
136+
await runDemoUrlProcessor(message, context);
137+
138+
// Should use the fallback name-based tenant since the imsOrgId is not in the mapping
139+
const expectedDemoUrl = 'https://example.com?organizationId=test-org-id#/@adobesitesengineering/sites-optimizer/sites/test-site-id/home';
140+
expect(context.log.info.calledWith(`Setup complete! Access your demo environment here: ${expectedDemoUrl}`)).to.be.true;
141+
});
142+
143+
it('should handle organization not found error', async () => {
144+
// Mock Organization.findById to return null
145+
context.dataAccess.Organization.findById.resolves(null);
146+
147+
await runDemoUrlProcessor(message, context);
148+
149+
// Should log error and return early
150+
expect(context.log.error.calledWith('Organization not found for organizationId: test-org-id')).to.be.true;
151+
// Should not log the success message
152+
expect(context.log.info.calledWithMatch(sinon.match('Setup complete!'))).to.be.false;
153+
});
76154
});
77155
});

test/tasks/opportunity-status-processor/opportunity-status-processor.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('Opportunity Status Processor', () => {
4747
.withSandbox(sandbox)
4848
.withDataAccess({
4949
Site: {
50-
findByBaseURL: sandbox.stub().resolves(mockSite),
50+
findById: sandbox.stub().resolves(mockSite),
5151
},
5252
})
5353
.build();
@@ -91,13 +91,13 @@ describe('Opportunity Status Processor', () => {
9191
auditTypes: ['cwv', 'broken-links'],
9292
})).to.be.true;
9393

94-
expect(context.dataAccess.Site.findByBaseURL.calledWith('https://test-site-id.com')).to.be.true;
94+
expect(context.dataAccess.Site.findById.calledWith('test-site-id')).to.be.true;
9595
expect(mockSite.getOpportunities.called).to.be.true;
9696
expect(context.log.info.calledWith('Found 2 opportunities for site test-site-id')).to.be.true;
9797
});
9898

9999
it('should handle site not found error', async () => {
100-
context.dataAccess.Site.findByBaseURL.resolves(null);
100+
context.dataAccess.Site.findById.resolves(null);
101101

102102
await runOpportunityStatusProcessor(message, context);
103103

0 commit comments

Comments
 (0)