async function runOnUrl(url, options, context) {
  const runner = getRunner(options);
  process.stdout.write(`Running Lighthouse ${options.numberOfRuns} time(s) on ${url}\n`);

  const baseSettings = options.settings || {};
  const settings = context.puppeteer.isActive()
    ? {...baseSettings, port: await context.puppeteer.getBrowserPort()}
    : baseSettings;

  for (let i = 0; i < options.numberOfRuns; i++) {
    process.stdout.write(`Run #${i + 1}...`);
    try {
      const lhr = await runner.runUntilSuccess(url, {
        ...options,
        settings,
      });
      await saveLHR(lhr);
      process.stdout.write('done.\n');

      // PSI caches results for a minute. Ensure each run is unique by waiting 60s between runs.
      if (options.method === 'psi' && i < options.numberOfRuns - 1) {
        await new Promise(r => setTimeout(r, PsiRunner.CACHEBUST_TIMEOUT));
      }
    } catch (err) {
      process.stdout.write('failed!\n');
      throw err;
    }
  }
}
@param {string} url
@param {LHCI.CollectCommand.Options} options
@param {{puppeteer: import('./puppeteer-manager.js')}} context
@return {Promise<void>}