"use strict";
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Object.defineProperty(exports, "__esModule", { value: true });
exports.navigateToLighthouseTab = navigateToLighthouseTab;
exports.waitForResult = waitForResult;
exports.selectCategories = selectCategories;
exports.selectRadioOption = selectRadioOption;
exports.selectMode = selectMode;
exports.selectDevice = selectDevice;
exports.setToolbarCheckboxWithText = setToolbarCheckboxWithText;
exports.setThrottlingMethod = setThrottlingMethod;
exports.clickStartButton = clickStartButton;
exports.isGenerateReportButtonDisabled = isGenerateReportButtonDisabled;
exports.getHelpText = getHelpText;
exports.openStorageView = openStorageView;
exports.clearSiteData = clearSiteData;
exports.waitForStorageUsage = waitForStorageUsage;
exports.waitForTimespanStarted = waitForTimespanStarted;
exports.endTimespan = endTimespan;
exports.getAuditsBreakdown = getAuditsBreakdown;
exports.getTargetViewport = getTargetViewport;
exports.getServiceWorkerCount = getServiceWorkerCount;
exports.registerServiceWorker = registerServiceWorker;
exports.interceptNextFileSave = interceptNextFileSave;
exports.renderHtmlInIframe = renderHtmlInIframe;
const chai_1 = require("chai");
const application_helpers_js_1 = require("./application-helpers.js");
const quick_open_helpers_js_1 = require("./quick_open-helpers.js");
async function navigateToLighthouseTab(path, devToolsPage, inspectedPage) {
    await (0, quick_open_helpers_js_1.openCommandMenu)(devToolsPage);
    await devToolsPage.pasteText('Lighthouse');
    await devToolsPage.pressKey('Enter');
    await devToolsPage.waitFor('.view-container > .lighthouse');
    if (path) {
        await inspectedPage.bringToFront();
        await inspectedPage.goToResource(path);
        await devToolsPage.bringToFront();
    }
    return await devToolsPage.waitFor('.lighthouse-start-view');
}
/**
 * Instead of watching the worker or controller/panel internals, we wait for the Lighthouse renderer
 * to create the new report DOM. And we pull the LHR and artifacts off the lh-root node.
 **/
async function waitForResult(devToolsPage, inspectedPage) {
    // Ensure the target page is in front so the Lighthouse run can finish.
    await inspectedPage.bringToFront();
    await devToolsPage.waitForFunction(() => {
        return devToolsPage.evaluate(`(async () => {
      const Lighthouse = await import('./panels/lighthouse/lighthouse.js');
      return Lighthouse.LighthousePanel.LighthousePanel.instance().reportSelector.hasItems();
    })()`);
    });
    // Bring the DT frontend back in front to render the Lighthouse report.
    await devToolsPage.bringToFront();
    const reportEl = await devToolsPage.waitFor('.lh-root');
    const result = await reportEl.evaluate(elem => {
        // @ts-expect-error we installed this obj on a DOM element
        const lhr = elem._lighthouseResultForTesting;
        // @ts-expect-error we installed this obj on a DOM element
        const artifacts = elem._lighthouseArtifactsForTesting;
        // Delete so any subsequent runs don't accidentally reuse this.
        // @ts-expect-error
        delete elem._lighthouseResultForTesting;
        // @ts-expect-error
        delete elem._lighthouseArtifactsForTesting;
        return { lhr, artifacts };
    });
    return { ...result, reportEl };
}
/**
 * Set the category checkboxes
 * @param selectedCategoryIds One of 'performance'|'accessibility'|'best-practices'|'seo'|'pwa'
 */
async function selectCategories(selectedCategoryIds, devToolsPage) {
    const startViewHandle = await devToolsPage.waitFor('.lighthouse-start-view');
    const checkboxHandles = await startViewHandle.$$('devtools-checkbox');
    for (const checkboxHandle of checkboxHandles) {
        await checkboxHandle.evaluate((dtCheckboxElem, selectedCategoryIds) => {
            const elem = dtCheckboxElem;
            const categoryId = elem.getAttribute('data-lh-category') || '';
            elem.checked = selectedCategoryIds.includes(categoryId);
            elem.dispatchEvent(new Event('change')); // Need change event to update the backing setting.
        }, selectedCategoryIds);
    }
}
async function selectRadioOption(value, optionName, devToolsPage) {
    const startViewHandle = await devToolsPage.waitFor('.lighthouse-start-view');
    await startViewHandle.$eval(`input[value="${value}"][name="${optionName}"]`, radioElem => {
        radioElem.checked = true;
        radioElem
            .dispatchEvent(new Event('change')); // Need change event to update the backing setting.
    });
}
async function selectMode(mode, devToolsPage) {
    await selectRadioOption(mode, 'lighthouse.mode', devToolsPage);
}
async function selectDevice(device, devToolsPage) {
    await selectRadioOption(device, 'lighthouse.device-type', devToolsPage);
}
async function setToolbarCheckboxWithText(enabled, textContext, devToolsPage) {
    const toolbarHandle = await devToolsPage.waitFor('.lighthouse-settings-pane .lighthouse-settings-toolbar');
    const label = await devToolsPage.waitForElementWithTextContent(textContext, toolbarHandle);
    await label.evaluate((label, enabled) => {
        const rootNode = label.getRootNode();
        const checkboxId = label.getAttribute('for');
        const checkboxElem = rootNode.getElementById(checkboxId);
        checkboxElem.checked = enabled;
        checkboxElem.dispatchEvent(new Event('change')); // Need change event to update the backing setting.
    }, enabled);
}
async function setThrottlingMethod(throttlingMethod, devToolsPage) {
    const toolbarHandle = await devToolsPage.waitFor('.lighthouse-settings-pane .lighthouse-settings-toolbar');
    await toolbarHandle.evaluate((toolbar, throttlingMethod) => {
        const selectElem = toolbar.querySelector('select');
        const optionElem = selectElem.querySelector(`option[value="${throttlingMethod}"]`);
        optionElem.selected = true;
        selectElem.dispatchEvent(new Event('change')); // Need change event to update the backing setting.
    }, throttlingMethod);
}
async function clickStartButton(devToolsPage) {
    await devToolsPage.click('.lighthouse-start-view devtools-button');
}
async function isGenerateReportButtonDisabled(devToolsPage) {
    const buttonContainer = await devToolsPage.waitFor('.lighthouse-start-button-container');
    const button = await devToolsPage.waitFor('button', buttonContainer);
    return await button.evaluate(element => element.hasAttribute('disabled'));
}
async function getHelpText(devToolsPage) {
    const helpTextHandle = await devToolsPage.waitFor('.lighthouse-start-view .lighthouse-help-text');
    return await helpTextHandle.evaluate(helpTextEl => helpTextEl.textContent);
}
async function openStorageView(devToolsPage) {
    await devToolsPage.click('#tab-resources');
    await devToolsPage.waitFor('.storage-group-list-item');
    await devToolsPage.click('[aria-label="Storage"]');
}
async function clearSiteData(devToolsPage, inspectedPage) {
    await inspectedPage.goToResource('empty.html');
    await openStorageView(devToolsPage);
    await devToolsPage.waitForFunction(async () => {
        await devToolsPage.click('#storage-view-clear-button');
        return (await (0, application_helpers_js_1.getQuotaUsage)(devToolsPage)) === 0;
    });
}
async function waitForStorageUsage(p, devToolsPage) {
    await openStorageView(devToolsPage);
    await (0, application_helpers_js_1.waitForQuotaUsage)(p, devToolsPage);
    await devToolsPage.click('#tab-lighthouse');
}
async function waitForTimespanStarted(devToolsPage) {
    await devToolsPage.waitForElementWithTextContent('Timespan started');
}
async function endTimespan(devToolsPage) {
    const endTimespanBtn = await devToolsPage.waitForElementWithTextContent('End timespan');
    await endTimespanBtn.click();
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getAuditsBreakdown(lhr, flakyAudits = []) {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const auditResults = Object.values(lhr.audits);
    const irrelevantDisplayModes = new Set(['notApplicable', 'manual']);
    const applicableAudits = auditResults.filter(audit => !irrelevantDisplayModes.has(audit.scoreDisplayMode));
    const informativeAudits = applicableAudits.filter(audit => audit.scoreDisplayMode === 'informative');
    const erroredAudits = applicableAudits.filter(audit => audit.score === null && audit && !informativeAudits.includes(audit));
    // 0.5 is the minimum score before we consider an audit "failed"
    // https://github.com/GoogleChrome/lighthouse/blob/d956ec929d2b67028279f5e40d7e9a515a0b7404/report/renderer/util.js#L27
    const failedAudits = applicableAudits.filter(audit => audit.score !== null && audit.score < 0.5 && !flakyAudits.includes(audit.id));
    return { auditResults, erroredAudits, failedAudits };
}
async function getTargetViewport(inspectedPage) {
    return await inspectedPage.evaluate(() => ({
        innerHeight: window.innerHeight,
        innerWidth: window.innerWidth,
        outerWidth: window.outerWidth,
        outerHeight: window.outerHeight,
        devicePixelRatio: window.devicePixelRatio,
    }));
}
async function getServiceWorkerCount(inspectedPage) {
    return await inspectedPage.evaluate(async () => {
        return (await navigator.serviceWorker.getRegistrations()).length;
    });
}
async function registerServiceWorker(inspectedPage) {
    await inspectedPage.evaluate(async () => {
        // @ts-expect-error Custom function added to global scope.
        await window.registerServiceWorker();
    });
    chai_1.assert.strictEqual(await getServiceWorkerCount(inspectedPage), 1);
}
async function interceptNextFileSave(devToolsPage) {
    await devToolsPage.evaluate(() => {
        const original = InspectorFrontendHost.save;
        const nextFilePromise = new Promise(resolve => {
            InspectorFrontendHost.save = (_, content) => {
                resolve(content);
            };
        });
        void nextFilePromise.finally(() => {
            InspectorFrontendHost.save = original;
        });
        // @ts-expect-error
        window.__nextFile = nextFilePromise;
    });
    // @ts-expect-error
    return () => devToolsPage.evaluate(() => window.__nextFile);
}
async function renderHtmlInIframe(html, inspectedPage) {
    return (await inspectedPage.page.evaluateHandle(async (html) => {
        const iframe = document.createElement('iframe');
        iframe.srcdoc = html;
        document.documentElement.append(iframe);
        await new Promise(resolve => iframe.addEventListener('load', resolve));
        return iframe.contentDocument;
    }, html)).asElement();
}
//# sourceMappingURL=lighthouse-helpers.js.map