microsoft / playwright

Playwright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.
https://playwright.dev
Apache License 2.0
65.43k stars 3.56k forks source link

[Feature]: Seamless integration with Lighthouse #31696

Open IevaKoltan opened 1 month ago

IevaKoltan commented 1 month ago

🚀 Feature Request

Hello, I'm working with web performance and wanted to use Playwright and Lighthouse setup for that. However, Playwright integration with Lighthouse isn't straightforward and requires workarounds, such as overriding Playwright fixtures for state management. In the current Playwright+Lighthouse setup, Lighthouse opens a separate browser page, which causes state loss. To circumvent this, you would need to set the state, save it, and override some fixtures so that the new browser/context instance launched by Lighthouse would inherit the state. However, this is quite cumbersome.

In contrast, Puppeteer offers seamless integration, where you can use a Puppeteer script to automation and set the page state, and then Lighthouse can take over that page to run performance tests. Achieving a similar seamless integration with Playwright would significantly enhance its usability.

I have tried making such integration by passing Playwright's page to Lighthouse function which accepts Pupeteers page as parameter and one of the initial obstacles I encountered is that Playwright’s page object lacks the target function, which in turn has the createCDPSession function. I attempted to resolve this by overriding the page fixture (see code below), but then hit another roadblock: Playwright’s CDPSession is missing the id function, which I couldn't work around. In Pupeteer that returns session id but I am not sure where is it used and whether there would be additional roadblocks.

// page fixture override to implement missing functions

  page: async ({ page }, use) => {
    const cdpSession = await page.context().newCDPSession(page)

    await use(
      Object.assign(page, {
        target() {
          return {
            createCDPSession: async () => cdpSession,
          }
        },
      }),
    )
  },

Given these challenges, would you consider implementing the missing methods or otherwise enable Lighthouse to take over the page in Playwright for performance checks without opening a separate window?

Example

Passing Playwright's page to Lighthouse function should work out of the box.

import { test, expect } from '@playwright/test';
import lighthouse from 'lighthouse';

test('example with Lighthouse', async ({ page }) => {
  await page.goto('https://example.com');

  // Perform actions to set up the state

  // Run Lighthouse audit, Lighthouse should take over the page to run checks
  const result = await lighthouse('https://example.com', options, config, page)

  // Do whatever with result
})

Motivation

Seamlessly integrating Playwright with Lighthouse would open new opportunities by adding seamless performance testing to Playwright's existing capabilities in end-to-end, component, and API testing.

dgozman commented 1 month ago

@IevaKoltan There is no way to pass Playwright's page to Lighthouse, and it's unlikely that's going to happen. However, integrating with Lighthouse in some other way is a reasonable feature request, so I'll leave it open for prioritization.

mxschmitt commented 1 month ago

@levaKoltan there is this third-party package which might work for you: https://www.npmjs.com/package/playwright-lighthouse. It seems to accept a Page instance, e.g. from @playwright/test.

IevaKoltan commented 1 month ago

@levaKoltan there is this third-party package which might work for you: https://www.npmjs.com/package/playwright-lighthouse. It seems to accept a Page instance, e.g. from @playwright/test.

It does accept page instance but it's only using for LambdaTest integration. Otherwise, for direct integration with Lighthouse it doesn't pass page or it would run into same problems I did.