Skip to content

Commit e0565f7

Browse files
Kanishkaclaude
andcommitted
feat(data-access): update suggestion data schemas for alt-text, cwv, a11y, and internal-links
- Add hasAltAttribute boolean to ALT_TEXT recommendation items - Make CWV url and issues fields optional (groups lack url, issues added via update flow) - Add patchContent and isCodeChangeAvailable to COLOR_CONTRAST and A11Y_ASSISTIVE schemas - Relax BROKEN_INTERNAL_LINKS URL validation to accept malformed URLs as-is Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 29c7744 commit e0565f7

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

packages/spacecat-shared-data-access/src/models/suggestion/suggestion.data-schemas.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ export const DATA_SCHEMAS = {
8585
).required(),
8686
jiraLink: Joi.string().uri().allow(null).optional(),
8787
aggregationKey: Joi.string().optional(),
88+
patchContent: Joi.string().optional(),
89+
isCodeChangeAvailable: Joi.boolean().optional(),
8890
}).unknown(true),
8991
projections: {
9092
minimal: {
@@ -113,6 +115,8 @@ export const DATA_SCHEMAS = {
113115
).required(),
114116
jiraLink: Joi.string().uri().allow(null).optional(),
115117
aggregationKey: Joi.string().optional(),
118+
patchContent: Joi.string().optional(),
119+
isCodeChangeAvailable: Joi.boolean().optional(),
116120
}).unknown(true),
117121
projections: {
118122
minimal: {
@@ -126,7 +130,7 @@ export const DATA_SCHEMAS = {
126130
[OPPORTUNITY_TYPES.CWV]: {
127131
schema: Joi.object({
128132
type: Joi.string().required(),
129-
url: Joi.string().uri().required(),
133+
url: Joi.string().uri().optional(),
130134
pageviews: Joi.number().optional(),
131135
organic: Joi.number().optional(),
132136
metrics: Joi.array().items(
@@ -144,7 +148,7 @@ export const DATA_SCHEMAS = {
144148
organic: Joi.number().optional(),
145149
}).unknown(true),
146150
).required(),
147-
issues: Joi.array().items(Joi.object()).required(),
151+
issues: Joi.array().items(Joi.object()).optional(),
148152
jiraLink: Joi.string().uri().allow(null).optional(),
149153
aggregationKey: Joi.string().allow(null).optional(),
150154
}).unknown(true),
@@ -163,6 +167,7 @@ export const DATA_SCHEMAS = {
163167
Joi.object({
164168
isAppropriate: Joi.boolean().optional(),
165169
isDecorative: Joi.boolean().optional(),
170+
hasAltAttribute: Joi.boolean().optional(),
166171
xpath: Joi.string().optional(),
167172
altText: Joi.string().optional(),
168173
imageUrl: Joi.string().uri().optional(),
@@ -374,12 +379,14 @@ export const DATA_SCHEMAS = {
374379
[OPPORTUNITY_TYPES.BROKEN_INTERNAL_LINKS]: {
375380
schema: Joi.object({
376381
// Support both naming conventions (snake_case and camelCase)
377-
url_from: Joi.string().uri().optional(),
378-
urlFrom: Joi.string().uri().optional(),
379-
url_to: Joi.string().uri().optional(),
380-
urlTo: Joi.string().uri().optional(),
382+
// URL fields use Joi.string() instead of Joi.string().uri() because
383+
// internal-links sometimes keeps URL values as-is, including malformed URLs
384+
url_from: Joi.string().optional(),
385+
urlFrom: Joi.string().optional(),
386+
url_to: Joi.string().optional(),
387+
urlTo: Joi.string().optional(),
381388
title: Joi.string().optional(),
382-
urlsSuggested: Joi.array().items(Joi.string().uri()).optional(),
389+
urlsSuggested: Joi.array().items(Joi.string()).optional(),
383390
aiRationale: Joi.string().optional(),
384391
trafficDomain: Joi.number().optional(),
385392
priority: Joi.string().optional(),

packages/spacecat-shared-data-access/test/unit/models/suggestion/suggestion.model.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,17 +259,17 @@ describe('SuggestionModel', () => {
259259
expect(() => Suggestion.validateData(suggestionData, 'cwv')).to.not.throw();
260260
});
261261

262-
it('fails when issues is missing (schema requires issues array)', () => {
262+
it('passes when issues is missing (issues is optional for update flow)', () => {
263263
const suggestionData = {
264264
type: 'url',
265265
url: 'https://www.example.com/page',
266266
pageviews: 11620,
267267
metrics: [{ deviceType: 'mobile', lcp: 2701 }],
268268
};
269-
expect(() => Suggestion.validateData(suggestionData, 'cwv')).to.throw();
269+
expect(() => Suggestion.validateData(suggestionData, 'cwv')).to.not.throw();
270270
});
271271

272-
it('fails when group-type has pattern but no url (schema requires url)', () => {
272+
it('passes when group-type has pattern but no url (url is optional for groups)', () => {
273273
const suggestionData = {
274274
type: 'group',
275275
name: 'Some pages',
@@ -282,7 +282,7 @@ describe('SuggestionModel', () => {
282282
],
283283
issues: [],
284284
};
285-
expect(() => Suggestion.validateData(suggestionData, 'cwv')).to.throw();
285+
expect(() => Suggestion.validateData(suggestionData, 'cwv')).to.not.throw();
286286
});
287287
});
288288
});

0 commit comments

Comments
 (0)