Skip to content

Commit 44e4934

Browse files
authored
feat: implement scoreTarget for categories
1 parent b2c4000 commit 44e4934

19 files changed

+99
-140
lines changed

packages/ci/src/lib/portal/__snapshots__/transform.unit.test.ts.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ exports[`transformGQLReport > should convert full GraphQL report to valid report
44
{
55
"categories": [
66
{
7-
"isBinary": false,
87
"refs": [
98
{
109
"plugin": "eslint",
@@ -17,7 +16,6 @@ exports[`transformGQLReport > should convert full GraphQL report to valid report
1716
"title": "Code style",
1817
},
1918
{
20-
"isBinary": false,
2119
"refs": [
2220
{
2321
"plugin": "bundle-stats",

packages/ci/src/lib/portal/transform.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ function transformGQLCategory(category: CategoryFragment): CategoryConfig {
6161
return {
6262
slug: category.slug,
6363
title: category.title,
64-
isBinary: category.isBinary,
6564
...(category.description && { description: category.description }),
6665
refs: category.refs.map(
6766
({ target, weight }): CategoryRef => ({
@@ -71,6 +70,9 @@ function transformGQLCategory(category: CategoryFragment): CategoryConfig {
7170
weight,
7271
}),
7372
),
73+
// TODO: Portal API migration - convert isBinary to scoreTarget for backward compatibility
74+
// Remove this conversion when Portal API supports scoreTarget (#713)
75+
...(category.isBinary && { scoreTarget: 1 }),
7476
};
7577
}
7678

packages/core/src/lib/implementation/report-to-gql.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,9 @@ function categoryToGQL(category: CategoryConfig): PortalCategory {
199199
slug: category.slug,
200200
title: category.title,
201201
description: category.description,
202-
isBinary: category.isBinary,
202+
// TODO: Portal API migration - convert scoreTarget to isBinary for backward compatibility
203+
// Remove this conversion when Portal API supports scoreTarget (#713)
204+
isBinary: category.scoreTarget === 1,
203205
refs: category.refs.map(ref => ({
204206
plugin: ref.plugin,
205207
type: categoryRefTypeToGQL(ref.type),

packages/models/docs/models-reference.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,15 @@ _Boolean._
167167

168168
_Object containing the following properties:_
169169

170-
| Property | Description | Type |
171-
| :--------------- | :------------------------------------------------------------------------- | :---------------------------------------------------------------- |
172-
| **`slug`** (\*) | Human-readable unique ID, e.g. "performance" | `string` (_regex: `/^[a-z\d]+(?:-[a-z\d]+)*$/`, max length: 128_) |
173-
| **`refs`** (\*) | | _Array of at least 1 [CategoryRef](#categoryref) items_ |
174-
| **`title`** (\*) | Category Title | `string` (_max length: 256_) |
175-
| `description` | Category description | `string` (_max length: 65536_) |
176-
| `docsUrl` | Category docs URL | `string` (_url_) (_optional_) _or_ `''` |
177-
| `isSkipped` | | `boolean` |
178-
| `isBinary` | Is this a binary category (i.e. only a perfect score considered a "pass")? | `boolean` |
170+
| Property | Description | Type |
171+
| :--------------- | :------------------------------------------- | :---------------------------------------------------------------- |
172+
| **`slug`** (\*) | Human-readable unique ID, e.g. "performance" | `string` (_regex: `/^[a-z\d]+(?:-[a-z\d]+)*$/`, max length: 128_) |
173+
| **`refs`** (\*) | | _Array of at least 1 [CategoryRef](#categoryref) items_ |
174+
| **`title`** (\*) | Category Title | `string` (_max length: 256_) |
175+
| `description` | Category description | `string` (_max length: 65536_) |
176+
| `docsUrl` | Category docs URL | `string` (_url_) (_optional_) _or_ `''` |
177+
| `isSkipped` | | `boolean` |
178+
| `scoreTarget` | Pass/fail score threshold (0-1) | `number` (_≥0, ≤1_) |
179179

180180
_(\*) Required._
181181

packages/models/src/lib/category-config.ts

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from './implementation/checks.js';
66
import {
77
metaSchema,
8+
nonnegativeNumberSchema,
89
scorableSchema,
910
slugSchema,
1011
weightedRefSchema,
@@ -14,18 +15,16 @@ import { formatRef } from './implementation/utils.js';
1415
export const categoryRefSchema = weightedRefSchema(
1516
'Weighted references to audits and/or groups for the category',
1617
'Slug of an audit or group (depending on `type`)',
17-
).merge(
18-
z.object({
19-
type: z
20-
.enum(['audit', 'group'])
21-
.describe(
22-
'Discriminant for reference kind, affects where `slug` is looked up',
23-
),
24-
plugin: slugSchema.describe(
25-
'Plugin slug (plugin should contain referenced audit or group)',
18+
).extend({
19+
type: z
20+
.enum(['audit', 'group'])
21+
.describe(
22+
'Discriminant for reference kind, affects where `slug` is looked up',
2623
),
27-
}),
28-
);
24+
plugin: slugSchema.describe(
25+
'Plugin slug (plugin should contain referenced audit or group)',
26+
),
27+
});
2928
export type CategoryRef = z.infer<typeof categoryRefSchema>;
3029

3130
export const categoryConfigSchema = scorableSchema(
@@ -37,24 +36,20 @@ export const categoryConfigSchema = scorableSchema(
3736
`Category has duplicate references: ${formatSerializedCategoryRefTargets(duplicates)}`,
3837
),
3938
)
40-
.merge(
39+
.extend(
4140
metaSchema({
4241
titleDescription: 'Category Title',
4342
docsUrlDescription: 'Category docs URL',
4443
descriptionDescription: 'Category description',
4544
description: 'Meta info for category',
46-
}),
45+
}).shape,
4746
)
48-
.merge(
49-
z.object({
50-
isBinary: z
51-
.boolean()
52-
.describe(
53-
'Is this a binary category (i.e. only a perfect score considered a "pass")?',
54-
)
55-
.optional(),
56-
}),
57-
);
47+
.extend({
48+
scoreTarget: nonnegativeNumberSchema
49+
.max(1)
50+
.describe('Pass/fail score threshold (0-1)')
51+
.optional(),
52+
});
5853

5954
export type CategoryConfig = z.infer<typeof categoryConfigSchema>;
6055

packages/models/src/lib/category-config.unit.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ describe('categoryConfigSchema', () => {
9292
title: 'Test results',
9393
description: 'This category collects test results.',
9494
docsUrl: 'https://www.cypress.io/',
95-
isBinary: false,
9695
refs: [
9796
{
9897
plugin: 'cypress',

packages/plugin-lighthouse/README.md

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,6 @@ export default {
8686
title: 'SEO',
8787
refs: [lighthouseGroupRef('seo')],
8888
},
89-
{
90-
slug: 'pwa',
91-
title: 'PWA',
92-
isBinary: true,
93-
refs: [lighthouseGroupRef('pwa')],
94-
},
9589
],
9690
};
9791
```
@@ -108,10 +102,10 @@ export default {
108102
// ...
109103
categories: [
110104
{
111-
slug: 'pwa',
112-
title: 'PWA',
113-
isBinary: true,
114-
refs: [lighthouseAuditRef('installable-manifest', 2), lighthouseAuditRef('splash-screen', 1), lighthouseAuditRef('themed-omnibox', 1), lighthouseAuditRef('content-width', 1), lighthouseAuditRef('themed-omnibox', 2), lighthouseAuditRef('viewport', 2), lighthouseAuditRef('maskable-icon', 1), lighthouseAuditRef('pwa-cross-browser', 0), lighthouseAuditRef('pwa-page-transitions', 0), lighthouseAuditRef('pwa-each-page-has-url', 0)],
105+
slug: 'core-web-vitals',
106+
title: 'Core Web Vitals',
107+
scoreTarget: 0.9,
108+
refs: [lighthouseAuditRef('largest-contentful-paint', 3), lighthouseAuditRef('first-input-delay', 2), lighthouseAuditRef('cumulative-layout-shift', 2), lighthouseAuditRef('first-contentful-paint', 1)],
115109
},
116110
],
117111
};

packages/plugin-lighthouse/src/lib/constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export const LIGHTHOUSE_GROUP_SLUGS = [
1616
'accessibility',
1717
'best-practices',
1818
'seo',
19-
'pwa',
2019
] as const;
2120

2221
export const SINGLE_URL_THRESHOLD = 1;

packages/plugin-lighthouse/src/lib/merge-categories.unit.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,6 @@ describe('mergeLighthouseCategories', () => {
327327
title: 'Performance',
328328
description: 'Website performance metrics',
329329
docsUrl: 'https://docs.example.com/performance',
330-
isBinary: true,
331330
refs: [
332331
{
333332
type: 'group',
@@ -336,14 +335,14 @@ describe('mergeLighthouseCategories', () => {
336335
weight: 1,
337336
},
338337
],
338+
scoreTarget: 1,
339339
},
340340
])[0],
341341
).toEqual({
342342
slug: 'performance',
343343
title: 'Performance',
344344
description: 'Website performance metrics',
345345
docsUrl: 'https://docs.example.com/performance',
346-
isBinary: true,
347346
refs: [
348347
{
349348
type: 'group',
@@ -358,6 +357,7 @@ describe('mergeLighthouseCategories', () => {
358357
weight: 1,
359358
},
360359
],
360+
scoreTarget: 1,
361361
});
362362
});
363363
});
@@ -689,7 +689,6 @@ describe('expandAggregatedCategory', () => {
689689
title: 'Performance',
690690
description: 'Website performance metrics',
691691
docsUrl: 'https://docs.example.com',
692-
isBinary: true,
693692
refs: [
694693
{
695694
type: 'group',
@@ -698,6 +697,7 @@ describe('expandAggregatedCategory', () => {
698697
weight: 1,
699698
},
700699
],
700+
scoreTarget: 1,
701701
};
702702
expect(
703703
expandAggregatedCategory(category, { urlCount: 1, weights: { 1: 1 } }),

packages/utils/perf/score-report/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ function minimalReport(opt?: MinimalReportOptions): Report {
154154
slug: `${AUDIT_P1_PREFIX}${idx}`,
155155
weight: 1,
156156
})),
157-
isBinary: false,
158157
},
159158
{
160159
slug: 'c2_',
@@ -165,7 +164,6 @@ function minimalReport(opt?: MinimalReportOptions): Report {
165164
slug: `${AUDIT_P2_PREFIX}${idx}`,
166165
weight: 1,
167166
})),
168-
isBinary: false,
169167
},
170168
],
171169
plugins: [

0 commit comments

Comments
 (0)