Skip to content

Commit a12759e

Browse files
committed
fix: switch auto-fix URL grouping to whitelist approach
Previously, new opportunity types defaulted to URL-grouped behavior, which silently dropped suggestions without URL data. Now types must explicitly opt-in to URL grouping, making ungrouped the safe default.
1 parent dba6115 commit a12759e

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

src/controllers/suggestions.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,21 @@ function SuggestionsController(ctx, sqs, env) {
5151
throw new Error('Data access required');
5252
}
5353

54-
const AUTOFIX_UNGROUPED_OPPTY_TYPES = [
55-
'broken-backlinks',
56-
'form-accessibility',
57-
'product-metatags',
58-
'security-permissions-redundant',
54+
/**
55+
* Opportunity types that use URL-based suggestion grouping for auto-fix.
56+
* Suggestions are grouped by URL and sent as separate auto-fix messages per URL.
57+
* Add here only when URL grouping is needed.
58+
*/
59+
const URL_GROUPED_OPPORTUNITY_TYPES = [
60+
'alt-text',
61+
'broken-internal-links',
62+
'high-organic-low-ctr',
63+
'meta-tags',
5964
];
6065

6166
const DEFAULT_PAGE_SIZE = 100;
6267

63-
const shouldGroupSuggestionsForAutofix = (type) => !AUTOFIX_UNGROUPED_OPPTY_TYPES.includes(type);
68+
const shouldGroupSuggestionsForAutofix = (type) => URL_GROUPED_OPPORTUNITY_TYPES.includes(type);
6469

6570
/**
6671
* Checks if a suggestion is a domain-wide auto generated suggestion

test/controllers/suggestions.test.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,65 @@ describe('Suggestions Controller', () => {
23982398
expect(mockSqs.sendMessage).to.have.been.calledOnce;
23992399
});
24002400

2401+
it('defaults to ungrouped behavior for unknown opportunity types', async () => {
2402+
// New opportunity types should default to ungrouped behavior
2403+
opportunity.getType = sandbox.stub().returns('some-new-opportunity-type');
2404+
// Enable the auto-fix handler for this test
2405+
mockConfiguration.findLatest.resolves({
2406+
isHandlerEnabledForSite: sandbox.stub().withArgs('some-new-opportunity-type-auto-fix', site).returns(true),
2407+
});
2408+
2409+
const newTypeSuggs = [
2410+
{
2411+
id: SUGGESTION_IDS[0],
2412+
opportunityId: OPPORTUNITY_ID,
2413+
type: 'CONTENT_UPDATE',
2414+
rank: 1,
2415+
status: 'NEW',
2416+
data: {
2417+
url: 'https://www.example.com/page1',
2418+
content: 'Some content',
2419+
},
2420+
updatedAt: new Date(),
2421+
},
2422+
{
2423+
id: SUGGESTION_IDS[1],
2424+
opportunityId: OPPORTUNITY_ID,
2425+
type: 'CONTENT_UPDATE',
2426+
rank: 2,
2427+
status: 'NEW',
2428+
data: {
2429+
url: 'https://www.example.com/page2',
2430+
content: 'Other content',
2431+
},
2432+
updatedAt: new Date(),
2433+
},
2434+
];
2435+
2436+
mockSuggestion.allByOpportunityId.resolves(
2437+
[mockSuggestionEntity(newTypeSuggs[0]), mockSuggestionEntity(newTypeSuggs[1])],
2438+
);
2439+
mockSuggestion.bulkUpdateStatus.resolves([
2440+
mockSuggestionEntity({ ...newTypeSuggs[0], status: 'IN_PROGRESS' }),
2441+
mockSuggestionEntity({ ...newTypeSuggs[1], status: 'IN_PROGRESS' }),
2442+
]);
2443+
2444+
const response = await suggestionsControllerWithMock.autofixSuggestions({
2445+
params: {
2446+
siteId: SITE_ID,
2447+
opportunityId: OPPORTUNITY_ID,
2448+
},
2449+
data: { suggestionIds: [SUGGESTION_IDS[0], SUGGESTION_IDS[1]] },
2450+
...context,
2451+
});
2452+
2453+
expect(response.status).to.equal(207);
2454+
const bulkPatchResponse = await response.json();
2455+
expect(bulkPatchResponse.metadata).to.have.property('success', 2);
2456+
// Unknown types should NOT be grouped by URL, so single SQS call with all suggestions
2457+
expect(mockSqs.sendMessage).to.have.been.calledOnce;
2458+
});
2459+
24012460
it('triggers autofixSuggestion with customData for non-grouped type', async () => {
24022461
opportunity.getType = sandbox.stub().returns('product-metatags');
24032462
mockSuggestion.allByOpportunityId.resolves(
@@ -2436,7 +2495,7 @@ describe('Suggestions Controller', () => {
24362495
expect(sqsCallArgs[1].customData).to.deep.equal(customData);
24372496
});
24382497

2439-
it('triggers autofixSuggestion without customData for grouped type', async () => {
2498+
it('triggers autofixSuggestion without customData for non-grouped type', async () => {
24402499
opportunity.getType = sandbox.stub().returns('form-accessibility');
24412500
mockSuggestion.allByOpportunityId.resolves(
24422501
[mockSuggestionEntity(formAccessibilitySuggs[0])],

0 commit comments

Comments
 (0)