Skip to content

Commit

Permalink
Merge pull request #221 from Scc33/formatLighthouse
Browse files Browse the repository at this point in the history
Format lighthouse and comment on PRs
  • Loading branch information
Scc33 authored May 13, 2024
2 parents 6ef8896 + 6262423 commit 146c05d
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 3 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ jobs:
# Finally we run svelte-check for some last minute svelte sanity
- name: Run svelte-check
run: bun run svelte-check
- name: Jest Coverage Comment
# This comments the current Jest Coverage Report containing JUnit XML reports
# and a Code Coverage Summary
uses: MishaKav/jest-coverage-comment@434e6d2d37116d23d812809b61d499639842fa3b # v1.0.26
with:
title: "Unit Test Coverage Report"
junitxml-path: ./test-results.xml
junitxml-title: Unit Test Report

test:
# Runs on execution of build
Expand Down Expand Up @@ -88,3 +96,30 @@ jobs:
# Run Lighthouse Playwright tests
- name: Run Playwright tests
run: bun run test:lighthouse
- name: Read JSON and set output
id: json-reader
run: |
categories=$(jq -c '.categories' ./lighthouse-reports/lighthouse.json)
echo "::set-output name=json::$categories"
- name: Format Lighthouse Score
# Transform the audit results into a single, friendlier output
id: format-lighthouse-score
uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1
env:
# using env as input to our script
# see https://github.com/actions/github-script#use-env-as-input
LIGHTHOUSE_RESULT: ${{ steps.json-reader.outputs.json }}
with:
# Run as a separate file so we do not have to inline all of our formatting logic.
# See https://github.com/actions/github-script#run-a-separate-file for more info.
script: |
const { formatLighthouseResults } = await import('${{github.workspace}}/scripts/lighthouse/index.js')
await formatLighthouseResults({core})
- name: Add Comment to PR
# Replace the previous message with our formatted lighthouse results
uses: thollander/actions-comment-pull-request@d61db783da9abefc3437960d0cce08552c7c004f # v2.4.2
with:
# Reference the previously created comment
comment_tag: "lighthouse-audit"
message: |
${{ steps.format-lighthouse-score.outputs.comment }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ playwright-report/index.html
yarn-error.log
lighthouse-report
.vscode/settings.json
/test-results
test-results.xml
/lighthouse-reports
3 changes: 2 additions & 1 deletion playwright.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export default defineConfig({
{
name: "lighthouse",
testMatch: "lighthouse.test.js",
use: { baseURL: "http://localhost:4173" }
use: { baseURL: "http://localhost:4173" },
outputDir: "lighthouse-reports"
},

/* Test against desktop viewports. */
Expand Down
37 changes: 37 additions & 0 deletions scripts/lighthouse/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable jsdoc/require-param */
"use strict";

const stoplight = (res) => (res >= 90 ? "🟢" : res >= 75 ? "🟠" : "🔴");
const normalizeScore = (res) => Math.round(res * 100);
const formatScore = (res) => {
const normalizedScore = normalizeScore(res);
return `${stoplight(normalizedScore)} ${normalizedScore}`;
};

/**
* `core` is in scope from https://github.com/actions/github-script
*/
export const formatLighthouseResults = ({ core }) => {
// this will be the shape of https://github.com/treosh/lighthouse-ci-action#manifest
const resultsJson = JSON.parse(process.env.LIGHTHOUSE_RESULT);

// start creating our markdown table
const header =
"# Lighthouse Results\n" +
"| Performance | Accessibility | Best Practices | SEO |\n" +
"| - | - | - | - |\n";

// make each formatted score from our lighthouse properties
const performanceScore = formatScore(resultsJson.performance.score);
const accessibilityScore = formatScore(resultsJson.accessibility.score);
const bestPracticesScore = formatScore(resultsJson["best-practices"].score);
const seoScore = formatScore(resultsJson.seo.score);

const results = `| ${performanceScore} | ${accessibilityScore} | ${bestPracticesScore} | ${seoScore} |`;

// join the header and the rows together
const finalResults = header + results;

// return our output to the github action
core.setOutput("comment", finalResults);
};
56 changes: 56 additions & 0 deletions scripts/lighthouse/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { formatLighthouseResults } from "./index";

describe("formatLighthouseResults", () => {
const MOCK_LIGHTHOUSE_RESULT = `{
"performance": {
"title": "Performance",
"id": "performance",
"score": 0.65
},
"accessibility": {
"title": "Accessibility",
"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.",
"score": 0.75
},
"best-practices": {
"id": "best-practices",
"score": 1
},
"seo": {
"title": "SEO",
"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).",
"id": "seo",
"score": 1
}
}`;

let mockCore, originalEnv;

beforeEach(() => {
mockCore = { setOutput: vi.fn() };
originalEnv = process.env;
process.env = {
...process.env,
LIGHTHOUSE_RESULT: MOCK_LIGHTHOUSE_RESULT
};
});

afterEach(() => {
process.env = originalEnv;
});

it("formats stoplight colors correctly", () => {
formatLighthouseResults({ core: mockCore });

const expectations = [
expect.stringContaining("🟢 100"),
expect.stringContaining("🟠 75"),
expect.stringContaining("🔴 65")
];

expectations.forEach((expectation) => {
expect(mockCore.setOutput).toBeCalledWith("comment", expectation);
});
});
});
9 changes: 9 additions & 0 deletions tests/lighthouse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ test.describe("audit", () => {
"best-practices": 100,
seo: 100
},
reports: {
formats: {
json: true, //defaults to false
html: false, //defaults to false
csv: false //defaults to false
},
name: "lighthouse", //defaults to `lighthouse-${new Date().getTime()}`
directory: "lighthouse-reports" //defaults to `${process.cwd()}/lighthouse`
},
port: 9222
});

Expand Down
6 changes: 4 additions & 2 deletions vitest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ export default defineConfig({
globals: true,
environment: "jsdom",
setupFiles: "./vitest-setup.js",
include: ["src/**/*.test.*"],
include: ["src/**/*.test.*", "scripts/**/*.test.*"],
outputFile: "test-results.xml",
reporters: ["default", "junit"],
coverage: {
include: ["src/components/**/*.svelte"],
include: ["src/components/**/*.svelte", "scripts/**/*.js"],
thresholds: {
statements: 100,
branches: 100,
Expand Down

1 comment on commit 146c05d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit Test Coverage Report

Unit Test Report

Tests Skipped Failures Errors Time
16 0 💤 0 ❌ 0 🔥 3.161s ⏱️

Please sign in to comment.