UNPKG

playwright-fluent

Version:
1,876 lines • 74.3 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cast = exports.PlaywrightFluent = exports.defaultTracingOptions = exports.defaultAssertOptions = exports.userHomeDirectory = exports.userDownloadsDirectory = exports.uniqueFilename = exports.noWaitNoThrowOptions = exports.harHeadersToHttpHeaders = exports.getHarResponseFor = exports.getHarResponseContentAs = exports.getHarDataFrom = exports.defaultWaitUntilOptions = exports.sizeOf = exports.allKnownDevices = exports.validateMock = exports.mockPostWithEmptyResponseAndStatus = exports.mockGetWithUnauthorizedResponse = exports.mockGetWithJsonResponseDependingOnQueryString = exports.mockGetWithJsonResponse = exports.mockGetWithJavascriptResponse = exports.mockGetWithForbiddenResponse = exports.mockGetWithEmptyResponseAndStatus = exports.getOutdatedMocks = exports.getMissingMocks = exports.generateCodeForMissingMock = exports.defaultMocksOptions = void 0;
const tslib_1 = require("tslib");
const action = tslib_1.__importStar(require("../actions"));
const actions_1 = require("../actions");
const assertion = tslib_1.__importStar(require("../assertions"));
const devices_1 = require("../devices");
const selector_api_1 = require("../selector-api");
const utils_1 = require("../utils");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const isCI = require('is-ci');
var actions_2 = require("../actions");
Object.defineProperty(exports, "defaultMocksOptions", { enumerable: true, get: function () { return actions_2.defaultMocksOptions; } });
Object.defineProperty(exports, "generateCodeForMissingMock", { enumerable: true, get: function () { return actions_2.generateCodeForMissingMock; } });
Object.defineProperty(exports, "getMissingMocks", { enumerable: true, get: function () { return actions_2.getMissingMocks; } });
Object.defineProperty(exports, "getOutdatedMocks", { enumerable: true, get: function () { return actions_2.getOutdatedMocks; } });
Object.defineProperty(exports, "mockGetWithEmptyResponseAndStatus", { enumerable: true, get: function () { return actions_2.mockGetWithEmptyResponseAndStatus; } });
Object.defineProperty(exports, "mockGetWithForbiddenResponse", { enumerable: true, get: function () { return actions_2.mockGetWithForbiddenResponse; } });
Object.defineProperty(exports, "mockGetWithJavascriptResponse", { enumerable: true, get: function () { return actions_2.mockGetWithJavascriptResponse; } });
Object.defineProperty(exports, "mockGetWithJsonResponse", { enumerable: true, get: function () { return actions_2.mockGetWithJsonResponse; } });
Object.defineProperty(exports, "mockGetWithJsonResponseDependingOnQueryString", { enumerable: true, get: function () { return actions_2.mockGetWithJsonResponseDependingOnQueryString; } });
Object.defineProperty(exports, "mockGetWithUnauthorizedResponse", { enumerable: true, get: function () { return actions_2.mockGetWithUnauthorizedResponse; } });
Object.defineProperty(exports, "mockPostWithEmptyResponseAndStatus", { enumerable: true, get: function () { return actions_2.mockPostWithEmptyResponseAndStatus; } });
Object.defineProperty(exports, "validateMock", { enumerable: true, get: function () { return actions_2.validateMock; } });
var devices_2 = require("../devices");
Object.defineProperty(exports, "allKnownDevices", { enumerable: true, get: function () { return devices_2.allKnownDevices; } });
Object.defineProperty(exports, "sizeOf", { enumerable: true, get: function () { return devices_2.sizeOf; } });
var utils_2 = require("../utils");
Object.defineProperty(exports, "defaultWaitUntilOptions", { enumerable: true, get: function () { return utils_2.defaultWaitUntilOptions; } });
Object.defineProperty(exports, "getHarDataFrom", { enumerable: true, get: function () { return utils_2.getHarDataFrom; } });
Object.defineProperty(exports, "getHarResponseContentAs", { enumerable: true, get: function () { return utils_2.getHarResponseContentAs; } });
Object.defineProperty(exports, "getHarResponseFor", { enumerable: true, get: function () { return utils_2.getHarResponseFor; } });
Object.defineProperty(exports, "harHeadersToHttpHeaders", { enumerable: true, get: function () { return utils_2.harHeadersToHttpHeaders; } });
Object.defineProperty(exports, "noWaitNoThrowOptions", { enumerable: true, get: function () { return utils_2.noWaitNoThrowOptions; } });
Object.defineProperty(exports, "uniqueFilename", { enumerable: true, get: function () { return utils_2.uniqueFilename; } });
Object.defineProperty(exports, "userDownloadsDirectory", { enumerable: true, get: function () { return utils_2.userDownloadsDirectory; } });
Object.defineProperty(exports, "userHomeDirectory", { enumerable: true, get: function () { return utils_2.userHomeDirectory; } });
exports.defaultAssertOptions = {
    stabilityInMilliseconds: 300,
    timeoutInMilliseconds: 30000,
    verbose: false,
};
exports.defaultTracingOptions = {
    screenshots: true,
    snapshots: true,
};
class PlaywrightFluent {
    async then(onfulfilled, onrejected) {
        // prettier-ignore
        return await this.executeActions()
            .then(onfulfilled)
            .catch(onrejected);
    }
    lastError() {
        return this._lastError;
    }
    async executeActions() {
        try {
            this._lastError = undefined;
            // eslint-disable-next-line no-constant-condition
            while (true) {
                if (this.actions.length === 0) {
                    break;
                }
                const action = this.actions.shift();
                action && (await action());
            }
        }
        catch (error) {
            this._lastError = error;
            this.actions = [];
            throw error;
        }
        finally {
            this.actions = [];
        }
    }
    constructor(browser, pageOrFrame) {
        this._isDialogOpened = false;
        this._isDialogClosed = true;
        this._hasBeenRedirectedToAnotherTab = false;
        this._context = {};
        this.actions = [];
        this.launchOptions = actions_1.defaultLaunchOptions;
        this.defaultWaitOptions = {
            ...utils_1.defaultWaitUntilOptions,
        };
        this.defaultAssertOptions = {
            ...exports.defaultAssertOptions,
        };
        this.contextOptions = { viewport: null, acceptDownloads: true };
        this.emulatedDevice = undefined;
        this.customWindowSize = undefined;
        this.customWindowSizeOptions = devices_1.defaultWindowSizeOptions;
        this.showMousePosition = false;
        this.handleDialogs = false;
        this.handleTracing = false;
        this.tracingOptions = exports.defaultTracingOptions;
        this.sentRequests = [];
        this.failedRequests = [];
        this.pageErrors = [];
        this._mocksContext = {};
        this._allMocks = [];
        if (browser && pageOrFrame) {
            this.browser = browser;
            this.page = (0, utils_1.toPage)(pageOrFrame);
            this.frame = (0, utils_1.toFrame)(pageOrFrame);
        }
    }
    currentBrowser() {
        return this.browser;
    }
    isDialogOpened() {
        return this._isDialogOpened;
    }
    isDialogClosed() {
        return this._isDialogClosed;
    }
    currentDialog() {
        return this.dialog;
    }
    currentPage() {
        return this.page;
    }
    currentFrame() {
        return this.frame;
    }
    /**
     * When execution context is a frame it will returns the current playwright Frame object,
     * otherwise it returns the current playwright Page object
     *
     * @returns {(Page | Frame | undefined)}
     * @memberof PlaywrightFluent
     */
    currentPageOrFrame() {
        if (this.frame) {
            return this.frame;
        }
        return this.page;
    }
    previousPage() {
        return this._previousPage;
    }
    hasBeenRedirectedToAnotherTab() {
        return this._hasBeenRedirectedToAnotherTab;
    }
    /**
     * Private context object you can use to store data shared between any steps at runtime
     *
     * @readonly
     * @type {unknown}
     * @memberof PlaywrightFluent
     */
    get context() {
        return this._context;
    }
    /**
     * Private typed context object you can use to store data shared between any steps at runtime
     *
     * @readonly
     * @type {unknown}
     * @memberof PlaywrightFluent
     */
    contextAs() {
        return this._context;
    }
    buildAssertOptionsFrom(options) {
        const fullOptions = {
            ...this.defaultAssertOptions,
            ...options,
        };
        return fullOptions;
    }
    async enableTracingOnBrowserContext() {
        var _a, _b;
        if (!this.handleTracing) {
            return;
        }
        await ((_b = (_a = this.browserContext) === null || _a === void 0 ? void 0 : _a.tracing) === null || _b === void 0 ? void 0 : _b.start(this.tracingOptions));
    }
    async launchBrowser(name) {
        const contextOptions = { ...this.contextOptions };
        if (this.emulatedDevice) {
            contextOptions.viewport = this.emulatedDevice.viewport;
            contextOptions.userAgent = this.emulatedDevice.userAgent;
            contextOptions.hasTouch = this.emulatedDevice.hasTouch;
            contextOptions.isMobile = name !== 'firefox' && this.emulatedDevice.isMobile;
            contextOptions.screen = this.emulatedDevice.screen;
            this.launchOptions.args = this.launchOptions.args || [];
            this.launchOptions.args.push(...(0, devices_1.getBrowserArgsForDevice)(this.emulatedDevice).andBrowser(name));
        }
        if (this.customWindowSize) {
            this.launchOptions.args = this.launchOptions.args || [];
            this.launchOptions.args.push(...(0, devices_1.getBrowserArgsForWindowSize)(this.customWindowSize, this.customWindowSizeOptions).andBrowser(name));
        }
        if (this.handleTracing && this.tracingOptions && this.tracingOptions.tracesDir) {
            this.launchOptions.tracesDir = this.tracingOptions.tracesDir;
        }
        this.browser = await action.launchBrowser(name, this.launchOptions);
        this.browserContext = await this.browser.newContext(contextOptions);
        await this.enableTracingOnBrowserContext();
        this.browserContext.on('page', async (p) => {
            this._previousPage = this.page;
            this.page = p;
            this._hasBeenRedirectedToAnotherTab = true;
            try {
                await p.waitForLoadState();
                // eslint-disable-next-line no-empty
            }
            catch (error) { }
        });
        this.page = await this.browserContext.newPage();
        if (this.showMousePosition) {
            await action.showMousePosition(this.page);
        }
        if (this.handleDialogs) {
            await action.recordPageDialogs(this.page, (dialog) => {
                this.dialog = dialog;
                this._isDialogOpened = true;
                this._isDialogClosed = false;
            });
        }
    }
    async gotoPreviousTab() {
        if (!this._previousPage) {
            return;
        }
        await this._previousPage.bringToFront();
        const from = this._previousPage;
        this._previousPage = this.page;
        this.page = from;
        this._hasBeenRedirectedToAnotherTab = true;
    }
    withDefaultWaitOptions(options) {
        const updatedOptions = {
            ...this.defaultWaitOptions,
            ...options,
        };
        this.defaultWaitOptions = updatedOptions;
        return this;
    }
    withDefaultAssertOptions(options) {
        const updatedOptions = {
            ...this.defaultAssertOptions,
            ...options,
        };
        this.defaultAssertOptions = updatedOptions;
        return this;
    }
    withOptions(options) {
        const updatedOptions = {
            ...this.launchOptions,
            ...options,
        };
        this.launchOptions = updatedOptions;
        return this;
    }
    withWindowSize(size, options) {
        const windowSizeOptions = {
            ...devices_1.defaultWindowSizeOptions,
            ...options,
        };
        this.customWindowSize = size;
        this.customWindowSizeOptions = windowSizeOptions;
        return this;
    }
    withViewport(viewport, options) {
        const viewportOptions = {
            ...devices_1.defaultViewportOptions,
            ...options,
        };
        if (viewportOptions.ciOnly && !isCI) {
            return this;
        }
        this.contextOptions.viewport = viewport;
        return this;
    }
    withBrowser(name) {
        const action = () => this.launchBrowser(name);
        this.actions.push(action);
        return this;
    }
    withGeolocation(location) {
        this.contextOptions.geolocation = location;
        return this;
    }
    withTimezone(timezoneId) {
        this.contextOptions.timezoneId = timezoneId;
        return this;
    }
    withExtraHttpHeaders(headers) {
        this.contextOptions.extraHTTPHeaders = headers;
        return this;
    }
    ignoreHttpsErrors() {
        this.contextOptions.ignoreHTTPSErrors = true;
        return this;
    }
    withPermissions(...permissions) {
        this.contextOptions.permissions = permissions;
        return this;
    }
    withStorageState(storageStateFile) {
        this.contextOptions.storageState = storageStateFile;
        return this;
    }
    /**
     * Show mouse position with a non intrusive cursor
     *
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    withCursor() {
        this.showMousePosition = true;
        return this;
    }
    /**
     * Subscribe to page Dialogs events, so that you can act and assert on opened dialogs.
     *
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    WithDialogs() {
        this.handleDialogs = true;
        return this;
    }
    /**
     * Enable tracing API.
     * Playwright should be installed with a version >= 1.12.0
     *
     * @param {Partial<TracingOptions>} [options]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     * @example
     *  const p = new PlaywrightFluent();
     *  const tracePath = path.join(__dirname, 'trace1.zip');
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .withTracing()
     *    .startTracing({title: 'my first trace'})
     *    .navigateTo(url)
     *    ...
     *    .stopTracingAndSaveTrace({path: tracePath})
     *    .close();
     *
     */
    withTracing(options) {
        this.handleTracing = true;
        this.tracingOptions = {
            ...this.tracingOptions,
            ...options,
        };
        return this;
    }
    async startTracingChunk(options) {
        var _a, _b;
        await ((_b = (_a = this.browserContext) === null || _a === void 0 ? void 0 : _a.tracing) === null || _b === void 0 ? void 0 : _b.startChunk(options));
    }
    async stopTracingChunk(options) {
        var _a, _b;
        await ((_b = (_a = this.browserContext) === null || _a === void 0 ? void 0 : _a.tracing) === null || _b === void 0 ? void 0 : _b.stopChunk(options));
    }
    /**
     * Start a new trace chunk.
     * You must first enable tracing by calling the .withTrace() method.
     *
     * @param {Partial<StartTracingOptions>} [options]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     * @example
     *  const p = new PlaywrightFluent();
     *  const tracePath = path.join(__dirname, 'trace1.zip');
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .withTracing()
     *    .startTracing({title: 'my first trace'})
     *    .navigateTo(url)
     *    ...
     *    .stopTracingAndSaveTrace({path: tracePath})
     *    .close();
     *
     */
    startTracing(options) {
        const startOptions = {
            ...options,
        };
        if (!this.handleTracing) {
            throw new Error('Cannot start Tracing because Tracing is not enabled. Maybe you forgot to call the withTrace(options)');
        }
        const action = () => this.startTracingChunk(startOptions);
        this.actions.push(action);
        return this;
    }
    /**
     * Stop the trace chunk and store the trace file to the specified path.
     *
     * @param {Partial<StopTracingOptions>} [options]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     * @example
     *  const p = new PlaywrightFluent();
     *  const tracePath = path.join(__dirname, 'trace1.zip');
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .withTracing()
     *    .startTracing({title: 'my first trace'})
     *    .navigateTo(url)
     *    ...
     *    .stopTracingAndSaveTrace({path: tracePath})
     *    .close();
     */
    stopTracingAndSaveTrace(options) {
        const stopOptions = {
            ...options,
        };
        if (!this.handleTracing) {
            throw new Error('Cannot stop Tracing and save trace file because Tracing is not enabled. Maybe you forgot to call the withTrace(options)');
        }
        const action = () => this.stopTracingChunk(stopOptions);
        this.actions.push(action);
        return this;
    }
    /**
     * Enables HAR recording for all pages.
     * Network activity will be saved into options.path file.
     * If not specified, the HAR is not recorded.
     * Make sure to await browserContext.close() for the HAR to be saved.
     *
     * @param {HarOptions} options
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     * @example
     *  const p = new PlaywrightFluent();
     *  const harFilepath = `${path.join(__dirname, uniqueFilename({ prefix: 'har-', extension: '.json' }))}`;
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .recordNetworkActivity({ path: harFilepath })
     *    ...
     *    .close();
     *
     *  const harData = p.getRecordedNetworkActivity();
     *
     */
    recordNetworkActivity(options) {
        this.contextOptions.recordHar = options;
        return this;
    }
    /**
     * Enables video recording into the options.dir directory.
     * If not specified videos are not recorded.
     * Make sure to await browserContext.close() for videos to be saved.
     *
     * @param {RecordVideoOptions} options
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     *
     * @example
     *  const p = new PlaywrightFluent();
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withWindowSize(sizeOf._1024x768)
     *    .clearVideoFilesOlderThan(__dirname, 60)
     *    .recordVideo({ dir: __dirname, size: sizeOf._1024x768 })
     *    .navigateTo(url)
     *    ...
     *    .close();
     *
     *  const videoPath = await p.getRecordedVideoPath();
     */
    recordVideo(options) {
        this.contextOptions.recordVideo = options;
        return this;
    }
    async getRecordedVideoPath() {
        var _a, _b;
        const videoPath = await ((_b = (_a = this.page) === null || _a === void 0 ? void 0 : _a.video()) === null || _b === void 0 ? void 0 : _b.path());
        return videoPath;
    }
    async clearVideoFiles(dir, durationInSeconds) {
        const files = (0, utils_1.getFilesOlderThanInDirectory)(dir, durationInSeconds, (path) => {
            return path.endsWith('.webm');
        });
        files.forEach((file) => {
            // eslint-disable-next-line no-console
            console.warn(`File '${file}' is about to be deleted`);
            (0, utils_1.deleteFile)(file);
        });
    }
    /**
     * Remove video files generated by previous tests run
     *
     * @param {string} dir
     * @param {number} durationInSeconds
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    clearVideoFilesOlderThan(dir, durationInSeconds) {
        const action = () => this.clearVideoFiles(dir, durationInSeconds);
        this.actions.push(action);
        return this;
    }
    /**
     * Get HAR data as json data.
     * Call this method only after the browser is closed.
     * @param {string} [filepath] optional
     * @returns {HarData}
     * @memberof PlaywrightFluent
     */
    getRecordedNetworkActivity(filepath) {
        var _a;
        const harFilePath = filepath || ((_a = this.contextOptions.recordHar) === null || _a === void 0 ? void 0 : _a.path);
        return (0, utils_1.getHarDataFrom)(harFilePath);
    }
    async closeBrowser(options) {
        await action.closeBrowser(this.currentBrowser(), options);
    }
    close(options) {
        const closeOptions = {
            ...actions_1.defaultCloseOptions,
            ...options,
        };
        const action = () => this.closeBrowser(closeOptions);
        this.actions.push(action);
        return this;
    }
    switchToPreviousTab() {
        const action = () => this.gotoPreviousTab();
        this.actions.push(action);
        return this;
    }
    getRecordedRequestsTo(url) {
        return [...this.sentRequests.filter((req) => req.url().includes(url))];
    }
    getLastRecordedRequestTo(url) {
        return this.sentRequests.filter((req) => req.url().includes(url)).pop();
    }
    clearRecordedRequestsTo(url) {
        this.sentRequests = [...this.sentRequests.filter((req) => !req.url().includes(url))];
    }
    async recordRequestsToUrl(partialUrl, ignorePredicate) {
        await action.recordRequestsTo(partialUrl, ignorePredicate, this.currentPage(), (request) => this.sentRequests.push(request));
    }
    /**
     * Will track and record requests whose url contains the input url.
     * Usefull when you need to check what the front sends to the back and/or what the back sends to the front.
     * Each recorded request is a standard `playwright` request object that contains both the request and the response.
     *
     * @param {string} partialUrl This parameter should be seen as a partial url (it is not a regex and not a glob pattern).
     * @param {(request: Request) => boolean} [ignorePredicate=() => false] optional predicate to provide if you want to ignore specific requests
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     * @example
     *  const p = new PlaywrightFluent();
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .recordRequestsTo('/api/v1/user', (request) => request.method() === 'OPTIONS')
     *    .recordRequestsTo('/api/v1/books')
     *    .navigateTo(url);
     */
    recordRequestsTo(partialUrl, ignorePredicate = () => false) {
        const action = () => this.recordRequestsToUrl(partialUrl, ignorePredicate);
        this.actions.push(action);
        return this;
    }
    async recordDownloadsToDirectory(directory) {
        await action.recordDownloadsTo(directory, this.currentPage());
    }
    /**
     * Save all downloads in directory.
     *
     * @param {string} directory
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     *
     * @example
     *  const p = new PlaywrightFluent();
     *  const expectedDownloadedFilepath = path.join(userDownloadsDirectory, 'download.zip');
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .recordDownloadsTo(userDownloadsDirectory)
     *    .navigateTo(url)
     *    .click('a#download-package')
     *    .waitUntil(async () => fileExists(expectedDownloadedFilepath));
     */
    recordDownloadsTo(directory) {
        const action = () => this.recordDownloadsToDirectory(directory);
        this.actions.push(action);
        return this;
    }
    async delayRequestsToUrl(partialUrl, delayInSeconds) {
        await action.delayRequestsTo(partialUrl, delayInSeconds, this.currentPage());
    }
    delayRequestsTo(partialUrl, delayInSeconds) {
        const action = () => this.delayRequestsToUrl(partialUrl, delayInSeconds);
        this.actions.push(action);
        return this;
    }
    async onRequestToRespondWith(partialUrl, options, response) {
        await action.onRequestToRespondWith(partialUrl, options, response, this.currentPage());
    }
    async onRequestToRespondFromHar(partialUrl, harFiles, options) {
        await action.onRequestToRespondFromHar(partialUrl, harFiles, this.currentPage(), options);
    }
    onRequestTo(partialUrl, options = {}) {
        return {
            respondWith: (response) => {
                const action = () => this.onRequestToRespondWith(partialUrl, options, response);
                this.actions.push(action);
                return this;
            },
            respondFromHar: (harFiles, options) => {
                const harOptions = {
                    ...actions_1.defaultHarRequestResponseOptions,
                    ...options,
                };
                const action = () => this.onRequestToRespondFromHar(partialUrl, harFiles, harOptions);
                this.actions.push(action);
                return this;
            },
        };
    }
    getFailedRequests() {
        return [...this.failedRequests];
    }
    clearFailedRequests() {
        this.failedRequests = [];
    }
    async recordAllFailedRequests() {
        await action.recordFailedRequests(this.currentPage(), (request) => this.failedRequests.push(request));
    }
    recordFailedRequests() {
        const action = () => this.recordAllFailedRequests();
        this.actions.push(action);
        return this;
    }
    getPageErrors() {
        return [...this.pageErrors];
    }
    clearPageErrors() {
        this.pageErrors = [];
    }
    async recordUncaughtExceptions() {
        await action.recordPageErrors(this.currentPage(), (err) => this.pageErrors.push(err));
    }
    recordPageErrors() {
        const action = () => this.recordUncaughtExceptions();
        this.actions.push(action);
        return this;
    }
    async saveStorageStateToFile(targetFile) {
        var _a;
        await ((_a = this.browserContext) === null || _a === void 0 ? void 0 : _a.storageState({ path: targetFile }));
    }
    /**
     * Will save the storage state in a local file
     *
     * @param {string} targetFile : The file path to save the storage state to. If path is a relative path, then it is resolved relative to current working directory
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    saveStorageStateTo(targetFile) {
        const action = () => this.saveStorageStateToFile(targetFile);
        this.actions.push(action);
        return this;
    }
    /**
     * Get current Playwright Storage State
     *
     * @returns {(Promise<StorageState | undefined>)}
     * @memberof PlaywrightFluent
     */
    async currentStorageState() {
        var _a;
        return await ((_a = this.browserContext) === null || _a === void 0 ? void 0 : _a.storageState());
    }
    async pauseExecution() {
        await action.pause(this.currentPage());
    }
    pause() {
        const action = () => this.pauseExecution();
        this.actions.push(action);
        return this;
    }
    async waitForDialogToOpen(options) {
        await action.waitForDialog(() => this.dialog, this.currentPage(), options);
    }
    /**
     * Wait for a dialog to open.
     *
     * @param {Partial<WaitUntilOptions>} [options={}]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    waitForDialog(options = {}) {
        const waitUntilOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const action = () => this.waitForDialogToOpen(waitUntilOptions);
        this.actions.push(action);
        return this;
    }
    async cancelCurrentDialog() {
        await action.cancelDialog(this.dialog, this.currentPage(), () => {
            this.dialog = undefined;
            this._isDialogClosed = true;
            this._isDialogOpened = false;
        });
    }
    cancelDialog() {
        const action = () => this.cancelCurrentDialog();
        this.actions.push(action);
        return this;
    }
    async acceptCurrentDialog() {
        await action.acceptDialog(this.dialog, undefined, this.currentPage(), () => {
            this.dialog = undefined;
            this._isDialogClosed = true;
            this._isDialogOpened = false;
        });
    }
    acceptDialog() {
        const action = () => this.acceptCurrentDialog();
        this.actions.push(action);
        return this;
    }
    async typeTextInCurrentDialogAndSubmit(text) {
        await action.acceptDialog(this.dialog, text, this.currentPage(), () => {
            this.dialog = undefined;
            this._isDialogClosed = true;
            this._isDialogOpened = false;
        });
    }
    typeTextInDialogAndSubmit(text) {
        const action = () => this.typeTextInCurrentDialogAndSubmit(text);
        this.actions.push(action);
        return this;
    }
    /**
     * context shared between all mocks.
     *
     * @readonly
     * @type {unknown}
     * @memberof PlaywrightFluent
     */
    get mocksContext() {
        return this._mocksContext;
    }
    /**
     * typed context shared between all mocks.
     *
     * @template T
     * @returns {T}
     * @memberof PlaywrightFluent
     */
    mocksContextAs() {
        return this._mocksContext;
    }
    async registerMocks(options) {
        await action.withMocks(() => this._allMocks, () => this._mocksContext, options, this.currentPage());
    }
    /**
     * Provide a set of mocks in order to automatically handle request interceptions
     * This method can be called multiple times with different set of mocks:
     * in this case all mocks are concatenated in a single internal array.
     *
     * * @template T
     * @param {() => Partial<FluentMock<T>[]} mocks
     * @param {Partial<WithMocksOptions>} [options=defaultMocksOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    withMocks(mocks, options = actions_1.defaultMocksOptions) {
        mocks.forEach(actions_1.validateMock);
        if (this._allMocks.length === 0) {
            const action = () => this.registerMocks(options);
            this.actions.push(action);
        }
        this._allMocks = this._allMocks.concat(mocks);
        return this;
    }
    removeMocksWithDisplayName(displayName) {
        this._allMocks = this._allMocks.filter((mock) => mock.displayName !== displayName);
        return this;
    }
    hasMockWithDisplayName(displayName) {
        return this._allMocks.some((mock) => mock.displayName === displayName);
    }
    /**
     * Get all mocks with the given displayName
     *
     * @param {(string | undefined)} displayName
     * @return {*}  {(Partial<FluentMock>[] | undefined)}
     * @memberof PlaywrightFluent
     */
    getAllMocksWithDisplayName(displayName) {
        return this._allMocks.filter((mock) => mock.displayName === displayName);
    }
    /**
     * Get the last mock with the given displayName
     *
     * @param {(string | undefined)} displayName
     * @return {*}  {(Partial<FluentMock> | undefined)}
     * @memberof PlaywrightFluent
     */
    getLastMockWithDisplayName(displayName) {
        return [...this._allMocks.filter((mock) => mock.displayName === displayName)].pop();
    }
    async gotoUrl(url, options) {
        await action.navigateTo(url, options, this.currentPageOrFrame());
    }
    navigateTo(url, options) {
        const navigationOptions = {
            ...actions_1.defaultNavigationOptions,
            ...options,
        };
        const action = () => this.gotoUrl(url, navigationOptions);
        this.actions.push(action);
        return this;
    }
    async hoverOnSelector(selector, options) {
        await action.hoverOnSelector(selector, this.currentPageOrFrame(), options);
    }
    async hoverOnSelectorObject(selector, options) {
        await action.hoverOnSelectorObject(selector, this.currentPageOrFrame(), options);
    }
    hover(selector, options) {
        const hoverOptions = {
            ...actions_1.defaultHoverOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.hoverOnSelector(selector, hoverOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.hoverOnSelectorObject(selector, hoverOptions);
            this.actions.push(action);
            return this;
        }
    }
    async switchFromSelectorToIframe(selector, options) {
        this.frame = await action.switchFromSelectorToIframe(selector, () => this.currentPageOrFrame(), {
            ...options,
            injectCursor: this.showMousePosition,
        });
    }
    async switchFromSelectorObjectToIframe(selector, options) {
        this.frame = await action.switchFromSelectorObjectToIframe(selector, () => this.currentPageOrFrame(), {
            ...options,
            injectCursor: this.showMousePosition,
        });
    }
    /**
     * Will switch inside the iframe targeted by the specified selector
     *
     * @param {(string | SelectorFluent)} selector
     * @param {Partial<SwitchToIframeOptions>} [options]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     *
     * @example
     *  const p = new PlaywrightFluent();
     *  const selector = 'iframe';
     *  const inputInIframe = '#input-inside-iframe';
     *  const inputInMainPage = '#input-in-main-page';
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: false })
     *    .withCursor()
     *    .navigateTo(url)
     *    .hover(selector)
     *    .switchToIframe(selector)
     *    .click(inputInIframe)
     *    .typeText('hey I am in the iframe')
     *    .switchBackToPage()
     *    .click(inputInMainPage)
     *    .typeText('hey I am back in the page!');
     */
    switchToIframe(selector, options) {
        const switchToIframeOptions = {
            ...actions_1.defaultSwitchToIframeOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.switchFromSelectorToIframe(selector, switchToIframeOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.switchFromSelectorObjectToIframe(selector, switchToIframeOptions);
            this.actions.push(action);
            return this;
        }
    }
    async switchBackFromIframeToCurrentPage() {
        this.frame = undefined;
    }
    /**
     * Will switch from the current Iframe back to the current page.
     *
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    switchBackToPage() {
        const action = () => this.switchBackFromIframeToCurrentPage();
        this.actions.push(action);
        return this;
    }
    async clickOnSelector(selector, options) {
        await action.clickOnSelector(selector, this.currentPageOrFrame(), options);
    }
    async clickOnSelectorObject(selector, options) {
        await action.clickOnSelectorObject(selector, this.currentPageOrFrame(), options);
    }
    click(selector, options) {
        const clickOptions = {
            ...actions_1.defaultClickOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.clickOnSelector(selector, clickOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.clickOnSelectorObject(selector, clickOptions);
            this.actions.push(action);
            return this;
        }
    }
    async doubleClickOnSelector(selector, options) {
        await action.doubleClickOnSelector(selector, this.currentPageOrFrame(), options);
    }
    async doubleClickOnSelectorObject(selector, options) {
        await action.doubleClickOnSelectorObject(selector, this.currentPageOrFrame(), options);
    }
    doubleClick(selector, options) {
        const doubleClickOptions = {
            ...actions_1.defaultDoubleClickOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.doubleClickOnSelector(selector, doubleClickOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.doubleClickOnSelectorObject(selector, doubleClickOptions);
            this.actions.push(action);
            return this;
        }
    }
    async clickAtPositionOnPage(position, options) {
        await action.clickAtPosition(position, this.currentPage(), options);
    }
    clickAtPosition(position, options) {
        const clickOptions = {
            ...actions_1.defaultClickOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const action = () => this.clickAtPositionOnPage(position, clickOptions);
        this.actions.push(action);
        return this;
    }
    async checkSelector(selector, options) {
        await action.checkSelector(selector, this.currentPageOrFrame(), options);
    }
    async checkSelectorObject(selector, options) {
        await action.checkSelectorObject(selector, this.currentPageOrFrame(), options);
    }
    check(selector, options) {
        const checkOptions = {
            ...actions_1.defaultCheckOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.checkSelector(selector, checkOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.checkSelectorObject(selector, checkOptions);
            this.actions.push(action);
            return this;
        }
    }
    async uncheckSelector(selector, options) {
        await action.uncheckSelector(selector, this.currentPageOrFrame(), options);
    }
    async uncheckSelectorObject(selector, options) {
        await action.uncheckSelectorObject(selector, this.currentPageOrFrame(), options);
    }
    uncheck(selector, options) {
        const checkOptions = {
            ...actions_1.defaultCheckOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.uncheckSelector(selector, checkOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.uncheckSelectorObject(selector, checkOptions);
            this.actions.push(action);
            return this;
        }
    }
    async selectOptionsInSelector(selector, labels, options) {
        await action.selectOptionsInSelector(selector, labels, this.currentPageOrFrame(), options);
    }
    async selectOptionsInFocusedSelector(labels, options) {
        await action.selectOptionsInFocused(labels, this.currentPageOrFrame(), options);
    }
    async selectOptionsInSelectorObject(selector, labels, options) {
        await action.selectOptionsInSelectorObject(selector, labels, this.currentPageOrFrame(), options);
    }
    select(...labels) {
        return {
            in: (selector, options) => {
                const selectOptions = {
                    ...actions_1.defaultSelectOptions,
                    ...this.defaultWaitOptions,
                    ...options,
                };
                if (typeof selector === 'string') {
                    const action = () => this.selectOptionsInSelector(selector, labels, selectOptions);
                    this.actions.push(action);
                    return this;
                }
                {
                    const action = () => this.selectOptionsInSelectorObject(selector, labels, selectOptions);
                    this.actions.push(action);
                    return this;
                }
            },
            inFocused: (options) => {
                const selectOptions = {
                    ...actions_1.defaultSelectOptions,
                    ...this.defaultWaitOptions,
                    ...options,
                };
                const action = () => this.selectOptionsInFocusedSelector(labels, selectOptions);
                this.actions.push(action);
                return this;
            },
        };
    }
    async selectOptionsByValueInFocusedSelector(values, options) {
        await action.selectOptionsByValueInFocused(values, this.currentPageOrFrame(), options);
    }
    async selectOptionsByValueInSelector(selector, values, options) {
        await action.selectOptionsByValueInSelector(selector, values, this.currentPageOrFrame(), options);
    }
    async selectOptionsByValueInSelectorObject(selector, values, options) {
        await action.selectOptionsByValueInSelectorObject(selector, values, this.currentPageOrFrame(), options);
    }
    selectByValue(...values) {
        return {
            in: (selector, options) => {
                const selectOptions = {
                    ...actions_1.defaultSelectOptions,
                    ...this.defaultWaitOptions,
                    ...options,
                };
                if (typeof selector === 'string') {
                    const action = () => this.selectOptionsByValueInSelector(selector, values, selectOptions);
                    this.actions.push(action);
                    return this;
                }
                {
                    const action = () => this.selectOptionsByValueInSelectorObject(selector, values, selectOptions);
                    this.actions.push(action);
                    return this;
                }
            },
            inFocused: (options) => {
                const selectOptions = {
                    ...actions_1.defaultSelectOptions,
                    ...this.defaultWaitOptions,
                    ...options,
                };
                const action = () => this.selectOptionsByValueInFocusedSelector(values, selectOptions);
                this.actions.push(action);
                return this;
            },
        };
    }
    /**
     * Emulate device
     *
     * @param {DeviceName} deviceName
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    emulateDevice(deviceName) {
        const device = (0, devices_1.getDevice)(deviceName);
        if (!device) {
            throw new Error(`device '${deviceName}' is unknown. It must be one of : [${devices_1.allKnownDevices
                .map((d) => d.name)
                .join(';')}] `);
        }
        this.emulatedDevice = device;
        return this;
    }
    async typeTextInFocusedElement(text, options) {
        await action.typeText(text, this.currentPageOrFrame(), options);
    }
    /**
     * Type text in the element that has current focus.
     *
     * @param {string} text
     * @param {Partial<TypeTextOptions>} [options=defaultTypeTextOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    typeText(text, options) {
        const typeTextOptions = {
            ...actions_1.defaultTypeTextOptions,
            ...options,
        };
        const action = () => this.typeTextInFocusedElement(text, typeTextOptions);
        this.actions.push(action);
        return this;
    }
    async clearTextInFocusedElement(options) {
        await action.clearText(this.currentPageOrFrame(), options);
    }
    /**
     * Clear text in the element that has current focus.
     *
     * @param {Partial<ClearTextOptions>} [options=defaultClearTextOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    clearText(options) {
        const clearTextOptions = {
            ...actions_1.defaultClearTextOptions,
            ...options,
        };
        const action = () => this.clearTextInFocusedElement(clearTextOptions);
        this.actions.push(action);
        return this;
    }
    /**
     * Alias for clearText.
     *
     * @param {Partial<ClearTextOptions>} [options=defaultClearTextOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    clear(options) {
        return this.clearText(options);
    }
    async invokeMethodOnSelector(methodName, selector, options) {
        await action.invokeMethodOnSelector(methodName, selector, this.currentPageOrFrame(), options);
    }
    async invokeMethodOnSelectorObject(methodName, selector, options) {
        await action.invokeMethodOnSelectorObject(methodName, selector, options);
    }
    /**
     * Be able to invoke a native method on a selector.
     * Use this action only in edge cases
     * where the selector itself is hidden because of its transprency,
     * or because it has null dimension,
     * and the normal click does not work neither on this selector nor on it's parent.
     *
     * @param {MethodName} methodName
     * @param {(string | SelectorFluent)} selector
     * @param {Partial<InvokeOptions>} [options]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    invokeMethod(methodName, selector, options) {
        const invokeOptions = {
            ...actions_1.defaultInvokeOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        if (typeof selector === 'string') {
            const action = () => this.invokeMethodOnSelector(methodName, selector, invokeOptions);
            this.actions.push(action);
            return this;
        }
        {
            const action = () => this.invokeMethodOnSelectorObject(methodName, selector, invokeOptions);
            this.actions.push(action);
            return this;
        }
    }
    async pasteTextInFocusedElement(text, options) {
        await action.pasteText(text, this.currentPageOrFrame(), options);
    }
    /**
     * Paste text in the element that has current focus.
     *
     * @param {string} text
     * @param {Partial<PasteTextOptions>} [options=defaultPasteTextOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    pasteText(text, options) {
        const pasteTextOptions = {
            ...actions_1.defaultPasteTextOptions,
            ...options,
        };
        const action = () => this.pasteTextInFocusedElement(text, pasteTextOptions);
        this.actions.push(action);
        return this;
    }
    async pressOnKey(key, options) {
        await action.pressKey(key, this.currentPageOrFrame(), options);
    }
    pressKey(key, options) {
        const pressKeyOptions = {
            ...actions_1.defaultKeyboardPressOptions,
            ...options,
        };
        const action = () => this.pressOnKey(key, pressKeyOptions);
        this.actions.push(action);
        return this;
    }
    async holdKey(key) {
        await action.holdDownKey(key, this.currentPageOrFrame());
    }
    holdDownKey(key) {
        const action = () => this.holdKey(key);
        this.actions.push(action);
        return this;
    }
    async releaseHoldKey(key) {
        await action.releaseKey(key, this.currentPageOrFrame());
    }
    releaseKey(key) {
        const action = () => this.releaseHoldKey(key);
        this.actions.push(action);
        return this;
    }
    wait(durationInMilliseconds) {
        this.actions.push(async () => await (0, utils_1.sleep)(durationInMilliseconds));
        return this;
    }
    async takeFullPageScreenshotAsBase64(options) {
        const screenshotOptions = {
            ...actions_1.defaultFullPageScreenshotOptions,
            ...options,
        };
        const result = await action.takeFullPageScreenshotAsBase64(this.currentPage(), screenshotOptions);
        return result;
    }
    registerStory(story, param) {
        if (typeof story !== 'function') {
            throw new Error('Story should be a function');
        }
        if (param === undefined) {
            this.actions.push(async () => await story(this));
            return this;
        }
        this.actions.push(async () => await story(this, param));
        return this;
    }
    runStory(story, param) {
        return this.registerStory(story, param);
    }
    attemptsTo(story, param) {
        return this.registerStory(story, param);
    }
    and(story, param) {
        return this.registerStory(story, param);
    }
    do(story, param) {
        return this.registerStory(story, param);
    }
    verifyIf(story, param) {
        return this.registerStory(story, param);
    }
    /**
     * Wait until predicate becomes true,
     * and always return true during 300 ms.
     * The waiting mechanism can be modified by setting options
     *
     * @param {() => Promise<boolean>} predicate
     * @param {Partial<WaitUntilOptions>} [options=defaultWaitUntilOptions]
     * @param {(string | (() => Promise<string>))} errorMessage
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    waitUntil(predicate, options = {}, errorMessage) {
        const waitUntilOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const defaultErrorMessage = `Predicate still resolved to false after ${waitUntilOptions.timeoutInMilliseconds} ms.`;
        const errorMessageOrDefault = errorMessage || defaultErrorMessage;
        this.actions.push(async () => {
            await (0, utils_1.waitUntil)(predicate, errorMessageOrDefault, waitUntilOptions);
        });
        return this;
    }
    /**
     * Waits until the function getValue() returns the same result during 300 ms.
     * The waiting mechanism can be modified by setting options
     *
     * @param {(() => Promise<string | boolean | number | null | undefined>)} getValue
     * @param {Partial<WaitUntilOptions>} [options=defaultWaitUntilOptions]
     * @returns {PlaywrightFluent}
     * @memberof PlaywrightFluent
     */
    waitForStabilityOf(getValue, options) {
        const waitUntilOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        this.actions.push(async () => {
            const defaultErrorMessage = `Value function could not have a stable result after ${waitUntilOptions.timeoutInMilliseconds} ms. Use verbose option to get more details.`;
            await (0, utils_1.waitForStabilityOf)(getValue, defaultErrorMessage, waitUntilOptions);
        });
        return this;
    }
    /**
     * Get current url.
     *
     * If the underlying browser tab has been closed, or the browser context has been closed, or the browser has been closed, it will return the error message provided by Playwright.
     * @returns {Promise<string>}
     */
    async getCurrentUrl() {
        return await action.getCurrentUrl(this.currentPageOrFrame());
    }
    async getCurrentWindowState() {
        return await action.getWindowState(this.currentPageOrFrame());
    }
    async getInnerTextOf(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const result = await action.getInnerTextOfSelector(selector, this.currentPageOrFrame(), waitOptions);
        return result;
    }
    async getSelectedText() {
        const page = this.currentPageOrFrame();
        if (!page) {
            return '';
        }
        /* istanbul ignore next */
        const selectedText = await page.evaluate(() => (document.getSelection() || '').toString());
        return selectedText;
    }
    /**
     * Get the today date inside the browser
     *
     * @param {(DateFormat | DateTimeFormatOptions)} [format] see more details for DateTimeFormatOptions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#examples
     * @returns {Promise<string>}
     * @memberof PlaywrightFluent
     *
     * @example
     * const p = new PlaywrightFluent();
     *  await p
     *    .withBrowser('chromium')
     *    .withOptions({ headless: true })
     *    .withCursor()
     *    .withTimezone('Asia/Tokyo')
     *    .navigateTo(url);
     *
     *  const today = await p.getToday('yyyy-mm-dd');
     *  const todayInCustomFormat = await p.getToday({
     *    locale: 'en',
     *    intlOptions: { year: 'numeric', month: 'short', day: 'numeric' },
     * })
     */
    async getToday(format) {
        const page = this.currentPageOrFrame();
        return await action.getToday(page, format);
    }
    async getValueOf(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const result = await action.getValueOfSelector(selector, this.currentPageOrFrame(), waitOptions);
        return result;
    }
    async getAllOptionsOf(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const result = await action.getAllOptionsOfSelector(selector, this.currentPageOrFrame(), waitOptions);
        return result;
    }
    async getSelectedOptionOf(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const selectOptions = await action.getAllOptionsOfSelector(selector, this.currentPageOrFrame(), waitOptions);
        const selectedOption = selectOptions.find((option) => option.selected);
        return selectedOption;
    }
    async getAllSelectedOptionsOf(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultWaitOptions,
            ...options,
        };
        const selectOptions = await action.getAllOptionsOfSelector(selector, this.currentPageOrFrame(), waitOptions);
        const selectedOptions = selectOptions.filter((option) => option.selected);
        return selectedOptions;
    }
    /**
     * Create a Selector object to be able to target a DOM element
     * that is embedded in a complex dom hierarchy or dom array
     *
     * @param {string} selector
     * @returns {SelectorFluent}
     * @memberof PlaywrightFluent
     */
    selector(selector) {
        return new selector_api_1.SelectorFluent(selector, this);
    }
    async hasFocus(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.hasFocus(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorHasFocus(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasFocus(selector, this.currentPageOrFrame(), fullOptions);
    }
    async hasText(selector, text, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.hasText(selector, text, this.currentPageOrFrame(), waitOptions);
    }
    async hasValue(selector, value, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.hasValue(selector, value, this.currentPageOrFrame(), waitOptions);
    }
    async hasExactValue(selector, value, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.hasExactValue(selector, value, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorHasText(selector, text, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasText(selector, text, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorHasExactValue(selector, value, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasExactValue(selector, value, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorHasValue(selector, value, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasValue(selector, value, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorHasClass(selector, className, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasClass(selector, className, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorDoesNotHaveClass(selector, className, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorDoesNotHaveClass(selector, className, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorHasPlaceholder(selector, text, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasPlaceholder(selector, text, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorHasAttributeWithValue(selector, attributeName, attributeValue, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorHasAttributeWithValue(selector, attributeName, attributeValue, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorExists(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorDoesExist(selector, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorDoesNotExist(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorDoesNotExist(selector, this.currentPageOrFrame(), fullOptions);
    }
    async exists(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.doesExist(selector, this.currentPageOrFrame(), waitOptions);
    }
    async doesNotExist(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.doesNotExist(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorIsVisible(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsVisible(selector, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorIsVisibleInViewport(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsVisibleInViewport(selector, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorIsNotVisible(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsNotVisible(selector, this.currentPageOrFrame(), fullOptions);
    }
    async expectThatSelectorIsNotVisibleInViewport(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsNotVisibleInViewport(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isNotVisible(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isNotVisible(selector, this.currentPageOrFrame(), waitOptions);
    }
    async isNotVisibleInViewport(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isNotVisibleInViewport(selector, this.currentPageOrFrame(), waitOptions);
    }
    async isVisible(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isVisible(selector, this.currentPageOrFrame(), waitOptions);
    }
    async isVisibleInViewport(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isVisibleInViewport(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorIsChecked(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsChecked(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isChecked(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isChecked(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorIsUnchecked(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsUnchecked(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isUnchecked(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isUnchecked(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorIsEnabled(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsEnabled(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isEnabled(selector, options) {
        const waitOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isEnabled(selector, this.currentPageOrFrame(), waitOptions);
    }
    async expectThatSelectorIsDisabled(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsDisabled(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isDisabled(selector, options) {
        const assertOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isDisabled(selector, this.currentPageOrFrame(), assertOptions);
    }
    async expectThatSelectorIsReadOnly(selector, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatSelectorIsReadOnly(selector, this.currentPageOrFrame(), fullOptions);
    }
    async isReadOnly(selector, options) {
        const assertOptions = {
            ...utils_1.defaultWaitUntilOptions,
            ...this.defaultAssertOptions,
            ...options,
        };
        return await assertion.isReadOnly(selector, this.currentPageOrFrame(), assertOptions);
    }
    async expectThatAsyncFuncHasResult(func, value, options) {
        const assertOptions = {
            ...this.defaultAssertOptions,
            ...options,
        };
        await assertion.expectThatAsyncFuncHasResult(func, value, assertOptions);
    }
    expectThatAsyncFunc(func) {
        return {
            resolvesTo: (value, options) => {
                this.actions.push(() => this.expectThatAsyncFuncHasResult(func, value, options));
                return this;
            },
        };
    }
    expectThatSelector(selector) {
        return {
            doesNotHaveClass: (className, options) => {
                this.actions.push(() => this.expectThatSelectorDoesNotHaveClass(selector, className, options));
                return this;
            },
            doesNotExist: (options) => {
                this.actions.push(() => this.expectThatSelectorDoesNotExist(selector, options));
                return this;
            },
            exists: (options) => {
                this.actions.push(() => this.expectThatSelectorExists(selector, options));
                return this;
            },
            hasAttributeWithValue: (attributeName, attributeValue, options) => {
                this.actions.push(() => this.expectThatSelectorHasAttributeWithValue(selector, attributeName, attributeValue, options));
                return this;
            },
            hasClass: (className, options) => {
                this.actions.push(() => this.expectThatSelectorHasClass(selector, className, options));
                return this;
            },
            hasExactValue: (value, options) => {
                this.actions.push(() => this.expectThatSelectorHasExactValue(selector, value, options));
                return this;
            },
            hasFocus: (options) => {
                this.actions.push(() => this.expectThatSelectorHasFocus(selector, options));
                return this;
            },
            hasPlaceholder: (text, options) => {
                this.actions.push(() => this.expectThatSelectorHasPlaceholder(selector, text, options));
                return this;
            },
            hasText: (text, options) => {
                this.actions.push(() => this.expectThatSelectorHasText(selector, text, options));
                return this;
            },
            hasValue: (value, options) => {
                this.actions.push(() => this.expectThatSelectorHasValue(selector, value, options));
                return this;
            },
            isChecked: (options) => {
                this.actions.push(() => this.expectThatSelectorIsChecked(selector, options));
                return this;
            },
            isUnchecked: (options) => {
                this.actions.push(() => this.expectThatSelectorIsUnchecked(selector, options));
                return this;
            },
            isDisabled: (options) => {
                this.actions.push(() => this.expectThatSelectorIsDisabled(selector, options));
                return this;
            },
            isEnabled: (options) => {
                this.actions.push(() => this.expectThatSelectorIsEnabled(selector, options));
                return this;
            },
            isReadOnly: (options) => {
                this.actions.push(() => this.expectThatSelectorIsReadOnly(selector, options));
                return this;
            },
            isVisible: (options) => {
                this.actions.push(() => this.expectThatSelectorIsVisible(selector, options));
                return this;
            },
            isNotVisible: (options) => {
                this.actions.push(() => this.expectThatSelectorIsNotVisible(selector, options));
                return this;
            },
            isVisibleInViewport: (options) => {
                this.actions.push(() => this.expectThatSelectorIsVisibleInViewport(selector, options));
                return this;
            },
            isNotVisibleInViewport: (options) => {
                this.actions.push(() => this.expectThatSelectorIsNotVisibleInViewport(selector, options));
                return this;
            },
        };
    }
    /**
     * Alias for expectThatSelector()
     *
     * @param {(string | SelectorFluent)} selector
     * @returns {ExpectAssertion}
     * @memberof PlaywrightFluent
     */
    expectThat(selector) {
        return {
            doesNotHaveClass: (className, options) => {
                this.actions.push(() => this.expectThatSelectorDoesNotHaveClass(selector, className, options));
                return this;
            },
            doesNotExist: (options) => {
                this.actions.push(() => this.expectThatSelectorDoesNotExist(selector, options));
                return this;
            },
            exists: (options) => {
                this.actions.push(() => this.expectThatSelectorExists(selector, options));
                return this;
            },
            hasAttributeWithValue: (attributeName, attributeValue, options) => {
                this.actions.push(() => this.expectThatSelectorHasAttributeWithValue(selector, attributeName, attributeValue, options));
                return this;
            },
            hasClass: (className, options) => {
                this.actions.push(() => this.expectThatSelectorHasClass(selector, className, options));
                return this;
            },
            hasExactValue: (value, options) => {
                this.actions.push(() => this.expectThatSelectorHasExactValue(selector, value, options));
                return this;
            },
            hasFocus: (options) => {
                this.actions.push(() => this.expectThatSelectorHasFocus(selector, options));
                return this;
            },
            hasPlaceholder: (text, options) => {
                this.actions.push(() => this.expectThatSelectorHasPlaceholder(selector, text, options));
                return this;
            },
            hasText: (text, options) => {
                this.actions.push(() => this.expectThatSelectorHasText(selector, text, options));
                return this;
            },
            hasValue: (value, options) => {
                this.actions.push(() => this.expectThatSelectorHasValue(selector, value, options));
                return this;
            },
            isChecked: (options) => {
                this.actions.push(() => this.expectThatSelectorIsChecked(selector, options));
                return this;
            },
            isUnchecked: (options) => {
                this.actions.push(() => this.expectThatSelectorIsUnchecked(selector, options));
                return this;
            },
            isDisabled: (options) => {
                this.actions.push(() => this.expectThatSelectorIsDisabled(selector, options));
                return this;
            },
            isEnabled: (options) => {
                this.actions.push(() => this.expectThatSelectorIsEnabled(selector, options));
                return this;
            },
            isReadOnly: (options) => {
                this.actions.push(() => this.expectThatSelectorIsReadOnly(selector, options));
                return this;
            },
            isVisible: (options) => {
                this.actions.push(() => this.expectThatSelectorIsVisible(selector, options));
                return this;
            },
            isNotVisible: (options) => {
                this.actions.push(() => this.expectThatSelectorIsNotVisible(selector, options));
                return this;
            },
            isVisibleInViewport: (options) => {
                this.actions.push(() => this.expectThatSelectorIsVisibleInViewport(selector, options));
                return this;
            },
            isNotVisibleInViewport: (options) => {
                this.actions.push(() => this.expectThatSelectorIsNotVisibleInViewport(selector, options));
                return this;
            },
        };
    }
    async expectThatDialogIsOfType(dialogType, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatDialogIsOfType(() => this.dialog, dialogType, fullOptions);
    }
    async expectThatDialogHasMessage(message, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatDialogHasMessage(() => this.dialog, message, fullOptions);
    }
    async expectThatDialogHasValue(value, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatDialogHasValue(() => this.dialog, value, fullOptions);
    }
    async expectThatDialogHasExactValue(value, options) {
        const fullOptions = this.buildAssertOptionsFrom(options);
        await assertion.expectThatDialogHasExactValue(() => this.dialog, value, fullOptions);
    }
    expectThatDialog() {
        return {
            hasMessage: (message, options) => {
                this.actions.push(() => this.expectThatDialogHasMessage(message, options));
                return this;
            },
            hasValue: (value, options) => {
                this.actions.push(() => this.expectThatDialogHasValue(value, options));
                return this;
            },
            hasExactValue: (value, options) => {
                this.actions.push(() => this.expectThatDialogHasExactValue(value, options));
                return this;
            },
            isOfType: (dialogType, options) => {
                this.actions.push(() => this.expectThatDialogIsOfType(dialogType, options));
                return this;
            },
        };
    }
}
exports.PlaywrightFluent = PlaywrightFluent;
/**
 * cast input object as a PlaywrightFluent instance
 * usefull when such instance is store in an untyped context
 * @param p : an untyped PlaywrightFluent instance
 */
const cast = (p) => {
    return p;
};
exports.cast = cast;