Skip to content

Commit

Permalink
feat(plugin-lighthouse): add lighthouse plugin (#593)
Browse files Browse the repository at this point in the history
  • Loading branch information
BioPhoton authored Apr 10, 2024
1 parent b2ec27e commit ac5a0e2
Show file tree
Hide file tree
Showing 31 changed files with 4,904 additions and 6,095 deletions.
1 change: 1 addition & 0 deletions .github/workflows/code-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- plugin-eslint
- plugin-coverage
- plugin-js-packages
- plugin-lighthouse
scope: [unit, integration]
name: Update code coverage
runs-on: ubuntu-latest
Expand Down
42 changes: 32 additions & 10 deletions code-pushup.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import 'dotenv/config';
import { z } from 'zod';
import {
// LIGHTHOUSE_OUTPUT_FILE_DEFAULT,
fileSizePlugin,
fileSizeRecommendedRefs, // lighthouseCorePerfGroupRefs,
// lighthousePlugin,
fileSizeRecommendedRefs,
packageJsonDocumentationGroupRef,
packageJsonPerformanceGroupRef,
packageJsonPlugin,
Expand All @@ -16,6 +14,10 @@ import eslintPlugin, {
eslintConfigFromNxProjects,
} from './dist/packages/plugin-eslint';
import jsPackagesPlugin from './dist/packages/plugin-js-packages';
import {
lighthouseGroupRef,
lighthousePlugin,
} from './dist/packages/plugin-lighthouse';
import type { CoreConfig } from './packages/models/src';

// load upload configuration from environment
Expand Down Expand Up @@ -75,15 +77,36 @@ const config: CoreConfig = {
type: 'module',
}),

// see https://github.com/code-pushup/cli/issues/538
// await lighthousePlugin({
// url: 'https://staging.code-pushup.dev/login',
// outputPath: join('.code-pushup', LIGHTHOUSE_OUTPUT_FILE_DEFAULT),
// headless: true,
// }),
await lighthousePlugin('https://codepushup.dev/'),
],

categories: [
{
slug: 'performance',
title: 'Performance',
refs: [lighthouseGroupRef('performance')],
},
{
slug: 'a11y',
title: 'Accessibility',
refs: [lighthouseGroupRef('accessibility')],
},
{
slug: 'best-practices',
title: 'Best Practices',
refs: [lighthouseGroupRef('best-practices')],
},
{
slug: 'seo',
title: 'SEO',
refs: [lighthouseGroupRef('seo')],
},
{
slug: 'pwa',
title: 'PWA',
isBinary: true,
refs: [lighthouseGroupRef('pwa')],
},
{
slug: 'bug-prevention',
title: 'Bug prevention',
Expand Down Expand Up @@ -145,7 +168,6 @@ const config: CoreConfig = {
...fileSizeRecommendedRefs,
packageJsonPerformanceGroupRef,
packageJsonDocumentationGroupRef,
// ...lighthouseCorePerfGroupRefs,
],
},
],
Expand Down
158 changes: 158 additions & 0 deletions e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1696,3 +1696,161 @@ exports[`CLI collect > should run ESLint plugin and create report.json 1`] = `
],
}
`;

exports[`CLI collect > should run Lighthouse plugin that runs lighthouse CLI and creates report.json 1`] = `
{
"categories": [
{
"refs": [
{
"plugin": "lighthouse",
"slug": "performance",
"type": "group",
"weight": 1,
},
],
"slug": "performance",
"title": "Performance",
},
{
"refs": [
{
"plugin": "lighthouse",
"slug": "accessibility",
"type": "group",
"weight": 1,
},
],
"slug": "a11y",
"title": "Accessibility",
},
{
"refs": [
{
"plugin": "lighthouse",
"slug": "best-practices",
"type": "group",
"weight": 1,
},
],
"slug": "best-practices",
"title": "Best Practices",
},
{
"refs": [
{
"plugin": "lighthouse",
"slug": "seo",
"type": "group",
"weight": 1,
},
],
"slug": "seo",
"title": "SEO",
},
{
"isBinary": true,
"refs": [
{
"plugin": "lighthouse",
"slug": "pwa",
"type": "group",
"weight": 1,
},
],
"slug": "pwa",
"title": "PWA",
},
],
"packageName": "@code-pushup/core",
"plugins": [
{
"audits": [
{
"description": "Largest Contentful Paint marks the time at which the largest text or image is painted. [Learn more about the Largest Contentful Paint metric](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint/)",
"slug": "largest-contentful-paint",
"title": "Largest Contentful Paint",
},
{
"description": "Service worker is the technology that enables your app to use many Progressive Web App features, such as offline, add to homescreen, and push notifications. With proper service worker and manifest implementations, browsers can proactively prompt users to add your app to their homescreen, which can lead to higher engagement. [Learn more about manifest installability requirements](https://developer.chrome.com/docs/lighthouse/pwa/installable-manifest/).",
"slug": "installable-manifest",
"title": "Web app manifest and service worker meet the installability requirements",
},
{
"description": "Deprecated APIs will eventually be removed from the browser. [Learn more about deprecated APIs](https://developer.chrome.com/docs/lighthouse/best-practices/deprecations/).",
"slug": "deprecations",
"title": "Avoids deprecated APIs",
},
{
"description": "Each ARIA \`role\` supports a specific subset of \`aria-*\` attributes. Mismatching these invalidates the \`aria-*\` attributes. [Learn how to match ARIA attributes to their roles](https://dequeuniversity.com/rules/axe/4.8/aria-allowed-attr).",
"slug": "aria-allowed-attr",
"title": "\`[aria-*]\` attributes match their roles",
},
{
"description": "hreflang links tell search engines what version of a page they should list in search results for a given language or region. [Learn more about \`hreflang\`](https://developer.chrome.com/docs/lighthouse/seo/hreflang/).",
"slug": "hreflang",
"title": "Document has a valid \`hreflang\`",
},
],
"groups": [
{
"refs": [
{
"slug": "largest-contentful-paint",
"weight": 25,
},
],
"slug": "performance",
"title": "Performance",
},
{
"description": "These checks highlight opportunities to [improve the accessibility of your web app](https://developer.chrome.com/docs/lighthouse/accessibility/). Automatic detection can only detect a subset of issues and does not guarantee the accessibility of your web app, so [manual testing](https://web.dev/articles/how-to-review) is also encouraged.",
"refs": [
{
"slug": "aria-allowed-attr",
"weight": 10,
},
],
"slug": "accessibility",
"title": "Accessibility",
},
{
"refs": [
{
"slug": "deprecations",
"weight": 5,
},
],
"slug": "best-practices",
"title": "Best Practices",
},
{
"description": "These checks ensure that your page is following basic search engine optimization advice. There are many additional factors Lighthouse does not score here that may affect your search ranking, including performance on [Core Web Vitals](https://web.dev/explore/vitals). [Learn more about Google Search Essentials](https://support.google.com/webmasters/answer/35769).",
"refs": [
{
"slug": "hreflang",
"weight": 1,
},
],
"slug": "seo",
"title": "SEO",
},
{
"description": "These checks validate the aspects of a Progressive Web App. [Learn what makes a good Progressive Web App](https://web.dev/articles/pwa-checklist).",
"refs": [
{
"slug": "installable-manifest",
"weight": 2,
},
],
"slug": "pwa",
"title": "PWA",
},
],
"icon": "lighthouse",
"slug": "lighthouse",
"title": "Lighthouse",
},
],
}
`;
54 changes: 46 additions & 8 deletions e2e/cli-e2e/tests/collect.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { PluginReport, Report, reportSchema } from '@code-pushup/models';
import {
AuditReport,
PluginReport,
Report,
reportSchema,
} from '@code-pushup/models';
import { cleanTestFolder } from '@code-pushup/test-setup';
import { executeProcess, readJsonFile, readTextFile } from '@code-pushup/utils';

Expand All @@ -9,17 +14,35 @@ describe('CLI collect', () => {
const exampleAuditTitle = 'Disallow unused variables';

/* eslint-disable @typescript-eslint/no-unused-vars */
const omitVariableData = ({
const omitVariableAuditData = ({
score,
value,
displayValue,
...auditReport
}: AuditReport) => auditReport;
const omitVariablePluginData = ({
date,
duration,
version,
audits,
...pluginReport
}: PluginReport) =>
({
...pluginReport,
audits: audits.map(
pluginReport.slug === 'lighthouse' ? omitVariableAuditData : p => p,
) as AuditReport[],
} as PluginReport);
const omitVariableReportData = ({
commit,
date,
duration,
version,
...report
}: Omit<Report, 'commit'> | PluginReport) => report;
const omitVariableReportData = ({ commit, ...report }: Report) =>
omitVariableData({
...report,
plugins: report.plugins.map(omitVariableData) as PluginReport[],
});
}: Report) => ({
...report,
plugins: report.plugins.map(omitVariablePluginData),
});
/* eslint-enable @typescript-eslint/no-unused-vars */

beforeEach(async () => {
Expand Down Expand Up @@ -95,6 +118,21 @@ describe('CLI collect', () => {
expect(omitVariableReportData(report as Report)).toMatchSnapshot();
});

it('should run Lighthouse plugin that runs lighthouse CLI and creates report.json', async () => {
const { code, stderr } = await executeProcess({
command: 'code-pushup',
args: ['collect', '--no-progress', '--onlyPlugins=lighthouse'],
cwd: 'examples/react-todos-app',
});

expect(code).toBe(0);
expect(stderr).toBe('');

const report = await readJsonFile('tmp/e2e/react-todos-app/report.json');
expect(() => reportSchema.parse(report)).not.toThrow();
expect(omitVariableReportData(report as Report)).toMatchSnapshot();
});

it('should create report.md', async () => {
const { code, stderr } = await executeProcess({
command: 'code-pushup',
Expand Down
45 changes: 44 additions & 1 deletion examples/react-todos-app/code-pushup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import coveragePlugin from '../../dist/packages/plugin-coverage';
import eslintPlugin from '../../dist/packages/plugin-eslint';
import lighthousePlugin, {
lighthouseAuditRef,
lighthouseGroupRef,
} from '../../dist/packages/plugin-lighthouse';

const eslintAuditRef = (slug, weight) => ({
type: 'audit',
Expand All @@ -24,9 +28,48 @@ export default {
eslintrc: '.eslintrc.js',
patterns: ['src/**/*.js', 'src/**/*.jsx'],
}),
await lighthousePlugin('https://codepushup.dev/', {
onlyAudits: [
// performance category
'largest-contentful-paint',
// a11y category
'aria-allowed-attr',
// best-practices category
'deprecations',
// seo category
'hreflang',
// pwa category
'installable-manifest',
],
}),
],
categories: [
// TODO: add performance category once Lighthouse plugin implemented, include eslintAuditRef('react-jsx-key', 0)
{
slug: 'performance',
title: 'Performance',
refs: [lighthouseGroupRef('performance')],
},
{
slug: 'a11y',
title: 'Accessibility',
refs: [lighthouseGroupRef('accessibility')],
},
{
slug: 'best-practices',
title: 'Best Practices',
refs: [lighthouseGroupRef('best-practices')],
},
{
slug: 'seo',
title: 'SEO',
refs: [lighthouseGroupRef('seo')],
},
{
slug: 'pwa',
title: 'PWA',
isBinary: true,
refs: [lighthouseGroupRef('pwa')],
},
{
slug: 'code-coverage',
title: 'Code coverage',
Expand Down
Loading

0 comments on commit ac5a0e2

Please sign in to comment.