target / goalert

Open source on-call scheduling, automated escalations, and notifications so you never miss a critical alert
https://goalert.me
Apache License 2.0
2.21k stars 237 forks source link

Improve frontend code coverage visibility for React components, focusing on gaps #3005

Open mastercactapus opened 1 year ago

mastercactapus commented 1 year ago

What problem would you like to solve? Please describe: We are missing visibility into what aspects of the frontend, particularly in our React components, are actually tested. This is especially important for the scheduling UI components, which are among the most complex parts of our application.

Describe the solution you'd like: An overview of the UI code coverage, focusing on identifying gaps in testing, regardless of the type of test (unit, compliance/smoke, integration/end-to-end). The solution should include the percentage of overall code coverage and highlight areas that need additional testing.

Describe alternatives you've considered: Manually walking through tests and guessing the coverage, but this approach is time-consuming and prone to inaccuracies.

Additional context: We are in the process of migrating from Cypress to Playwright for end-to-end tests. Ideally, the solution should prioritize Playwright and may exclude Cypress coverage if it helps incentivize the migration. The main goal is to identify gaps in testing and improve the overall code coverage in our React components.

Forfold commented 1 year ago

We could pretty easily use Cypress if we bundled our code with Babel instead of esbuild, as there is a plugin built using the coverage tool already, but I wasn't able to find anything for esbuild. There may be a workaround to get the Babel plugin to work with esbuild but I'm not familiar with the plugin architecture.

The plugin: https://github.com/istanbuljs/babel-plugin-istanbul


With playwright, we can measure code coverage with Istanbul as well, but it must be done per test, e.g.:

const { chromium } = require('playwright');
const v8toIstanbul = require('v8-to-istanbul');

(async() => {
  const browser = await chromium.launch()
  const page = await browser.newPage()
  await page.coverage.startJSCoverage()
  await page.goto('https://chromium.org')
  const coverage = await page.coverage.stopJSCoverage()
  for (const entry of coverage) {
    const converter = v8toIstanbul('', 0, { source: entry.source })
    await converter.load()
    converter.applyCoverage(entry.functions)
    console.log(JSON.stringify(converter.toIstanbul()))
  }
  await browser.close()
}()

and then we would have to merge each test coverage file together manually, with something like nyc, which is a cli tool made for Istanbul.js