You can find the Cypress tests shown in this blog post in the repo bahmutov/cypress-lighthouse-example .
Let's see how fast my blog https://glebbahmutov.com/blog/ loads in the browser. I will use Cypress to visit the site and use a plugin @cypress-audit/lighthouse to report the performance metrics.
In the tests repository, install Cypress and the plugin
Following the plugin's README, I have added its initialization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import '@cypress-audit/lighthouse/commands' const { lighthouse, prepareAudit } = require ('@cypress-audit/lighthouse' )module .exports = (on, config ) => { on ('before:browser:launch' , (browser = {}, launchOptions ) => { prepareAudit (launchOptions) }) on ('task' , { lighthouse : lighthouse (), }) }
The test The moment of truth. My test should visit the site and run the Lighthouse.
cypress/integration/spec.js 1 2 3 4 5 6 it ('loads fast enough' , () => { cy.visit ('/' ) cy.lighthouse () })
Tip: I am using the special "reference types" comment to load the TypeScript definitions that come with the Lighthouse plugin to load the definition for its custom command cy.lighthouse
Open Cypress Test Runner with npx cypress open
and pick the Chrome browser to run the tests.
Launch the spec file. Ughh, we definitely did not hit 100 across each category.
By default, Lighthouse audits in the mobile mode and requires each score to equal 100. Let's change the thresholds to match our situation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 it ('loads fast enough' , () => { cy.visit ('/' ) cy.lighthouse ( { performance : 60 , accessibility : 90 , 'best-practices' : 80 , seo : 80 , }, { formFactor : 'desktop' , screenEmulation : { mobile : false , disable : false , width : Cypress .config ('viewportWidth' ), height : Cypress .config ('viewportHeight' ), deviceScaleRatio : 1 , }, }, ) })
Now it is passing!
A word of caution: Cypress by intercepting and forwarding all network requests and observing the page affects the performance measurements.
Customize the report You can insert your own summary to the Lighthouse report before returning from the plugins file to the spec. Here is the custom code
cypress/plugins/index.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 const { lighthouse, prepareAudit } = require ('@cypress-audit/lighthouse' )module .exports = (on, config ) => { on ('before:browser:launch' , (browser = {}, launchOptions ) => { prepareAudit (launchOptions) }) on ('task' , { async lighthouse (allOptions ) { let txt const lighthouseTask = lighthouse ((lighthouseReport ) => { let lighthouseScoreText = '' let lighthouseResult = lighthouseReport?.lhr ?.categories let lighthousePerformance = 'Performance: ' + lighthouseResult?.performance ?.score + '\n' let lighthouseAccessibility = 'Accessibility: ' + lighthouseResult?.accessibility ?.score + '\n' let lighthouseBestPractices = 'Best Practices: ' + lighthouseResult?.['best-practices' ]?.score + '\n' let lighthouseSEO = 'SEO: ' + lighthouseResult?.seo ?.score + '\n' lighthouseScoreText = lighthousePerformance + lighthouseAccessibility + lighthouseBestPractices + lighthouseSEO console .log (lighthouseScoreText) txt = lighthouseScoreText }) const report = await lighthouseTask (allOptions) report.txt = txt return report }, }) }
In the spec file we want to log the txt
property to the Command Log. Unfortunately, the default cy.lighthouse()
command provided by the plugin ignores all properties returned by the cy.task('lighthouse')
command, except for the errors
. Thus we can call that task ourselves, rather than going through the plugin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 it.only ('shows the text report returned by from the plugins task' , () => { cy.visit ('/' ) const thresholds = { performance : 50 , accessibility : 90 , 'best-practices' : 80 , seo : 80 , } const opts = { formFactor : 'desktop' , screenEmulation : { mobile : false , disable : false , width : Cypress .config ('viewportWidth' ), height : Cypress .config ('viewportHeight' ), deviceScaleRatio : 1 , }, } cy.url () .then ((url ) => { cy.task ('lighthouse' , { url, thresholds, opts, }) }) .then ((report ) => { const { errors, results, txt } = report cy.log (report.txt ) }) })
We now see the performance summary in the terminal
1 2 3 4 Performance: 0.62 Accessibility: 0.92 Best Practices: 0.87 SEO: 0.8
We can see the same message text in the Cypress Command Log
See also