"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Expectation = exports.ScreenshotManager = exports.slotProxy = exports.register = exports.DriverManager = exports.fetchKeyByFilter = void 0;
/**
 * This module exposes the utility functions for JET-based WebDriver tests.
 */
const selenium_webdriver_1 = require("selenium-webdriver");
const OjFetch_1 = require("./lib/OjFetch");
const Expectation_1 = require("./lib/Expectation");
Object.defineProperty(exports, "Expectation", { enumerable: true, get: function () { return Expectation_1.Expectation; } });
const sm = require("./lib/ScreenshotManager");
exports.ScreenshotManager = sm;
const busy_context_utils_1 = require("./lib/busy-context-utils");
const viewmodel_utils_1 = require("./lib/viewmodel-utils");
const no_require_jet_1 = require("./lib/no-require-jet");
// Export register function before importing elements so that they can
// call it to register themselves
var dataprovider_utils_1 = require("./lib/dataprovider-utils");
Object.defineProperty(exports, "fetchKeyByFilter", { enumerable: true, get: function () { return dataprovider_utils_1.fetchKeyByFilter; } });
var driver_manager_1 = require("./lib/driver-manager");
Object.defineProperty(exports, "DriverManager", { enumerable: true, get: function () { return driver_manager_1.DriverManager; } });
var driver_override_1 = require("./lib/driver-override");
Object.defineProperty(exports, "register", { enumerable: true, get: function () { return driver_override_1.register; } });
var slot_proxy_1 = require("./lib/slot-proxy");
Object.defineProperty(exports, "slotProxy", { enumerable: true, get: function () { return slot_proxy_1.slotProxy; } });
/**
 * Check the running JET UI version against this oraclejet-webdriver package
 * version. It's expected that the JET UI is already fully loaded so that
 * "oj.version" and "oj.revision" will resolve.
 * If a mismatch is found, a console warning will be logged with the mismatched
 * values.
 * @param driver WebDriver instance
 * @private
 */
async function checkVersions(driver) {
    const pjson = require('./package.json');
    const version = pjson.version;
    const rev = pjson.config.revision;
    const jet = await driver.executeScript(`
    return { version: oj.version, revision: oj.revision }
  `);
    if (
    // Check if not local build (running from JET repo)
    rev !== '#@@oj.revision@@#' &&
        // or version mismatch
        (version !== jet.version || rev !== jet.revision)) {
        const mismatch = `version mismatch: oraclejet ${JSON.stringify(jet)}, oraclejet-webdriver {"version": "${version}", "revision": "${rev}"}`;
        console.warn(`
Your oraclejet UI version/revision does not match oraclejet-webdriver
${mismatch}
    `);
        throw Error(mismatch);
    }
}
/**
 * The test utility object for JET component WebElements.  This object contains
 * all of the factory functions needed to create the component WebElements, plus,
 * additional utilities useful for testing JET-based UIs.  This object should be
 * imported into tests with
 * ```javascript
 * import ojwd from "@oracle/oraclejet-webdriver";
 * ```
 */
const ojwd = {
    /**
     * Flag to indicate if testing environment is running a JET application without
     * RequireJS, such as WebPack. This property can only be set once.
     * Defaults to false.
     */
    noRequireJet: false,
    /**
     * Opens a JET page and wait for the UI to be ready for testing. This method
     * should be used in place of WebDriver.get() to open a page for test. It will
     * wait on the page's BusyContext to clear before continuing on.
     * Note that this method should only be used to open a JET page, one which uses
     * RequireJS. Attempting to open a non-JET page will result in the script
     * timing out waiting for RequireJS to become available.
     *
     * @param driver The WebDriver instance
     * @param url The URL to open
     */
    async get(driver, url) {
        await driver.get(url);
        const timeouts = await driver.manage().getTimeouts();
        try {
            await driver.wait((0, busy_context_utils_1.pageReady)(), timeouts.pageLoad);
            await checkVersions(driver);
        }
        catch (ex) {
            if (ex instanceof selenium_webdriver_1.error.TimeoutError || ex instanceof selenium_webdriver_1.error.ScriptTimeoutError) {
                const openStates = await (0, busy_context_utils_1.getBusyStates)(driver);
                ex.message += ` - open busy states: ${openStates}`;
            }
            throw ex;
        }
    },
    /**
     * @deprecated
     * Wait until the JET page indicates that it's loaded and ready.  This function
     * returns a Condition that can be used with WebDriver.wait().
     * ```javascript
     * await driver.wait(ojwd.pageReady())
     * ```
     * This function is deprecated. All WebElements interacting with JET pages
     * should automatically block until the BusyContext is cleared before performing
     * their actions. Therefore, explicitly waiting for the page to be ready should
     * not be needed.
     */
    pageReady() {
        console.warn('pageReady() is deprecated and will be removed in the next release. ' +
            'Use ojwd.get() to open and wait for the page to be ready for testing');
        return (0, busy_context_utils_1.pageReady)();
    },
    /**
     * Invoke fetch in the browser to permit interaction with REST services.
     * Browsers must support fetch api.
     *
     * The fetch parameters mirror the MDN fetch api
     * https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters
     *
     * Note the return value is not the typical Response object, to accommodate webdriver marshalling.
     *
     * @param {WebDriver} driver A WebDriver-like object
     * @param {MarshalableRequestInfo} input String containing the direct URL of the resource you want to fetch.
     * @param {MarshalableResponseInfo} responseInfo Indicates the desired structure of the response body, text or json
     * @param {MarshalableRequestInit} init Optional
     *  An options object containing any custom settings that you want to apply to the request.
     * @param {string} init.method: The request method, e.g., GET, POST. Note that the Origin header is not set on Fetch requests with a method of HEAD or GET (this behavior was corrected in Firefox 65 — seebug 1508661).
     * @param {MarshalableHeaders} init.headers: Any headers you want to add to your request, contained within a MarshalableHeaders object
     * @param {MarshalableBody} init.body: Any body that you want to add to your request, json or text, in a MarshalableBody object
     * @param {string} init.mode: The mode you want to use for the request, e.g., cors, no-cors, or same-origin.
     * @param {string} init.credentials: The request credentials you want to use for the request: omit, same-origin, or include. To automatically send cookies for the current domain, this option must be provided. Starting with Chrome 50, this property also takes a FederatedCredential instance or a PasswordCredential instance.
     * @return {Promise<MarshaledResponse>} A Promise resolving to a MarshaledResponse object
     *
     * ###### Example of READ and UPDATE operations
     * ```javascript
     *     let dept:any;
     *     try {
     *       let res:MarshaledResponse = await ojwd.fetch(driver,restServer + 'Departments/?DepartmentId=20',
     *          { "responseBodyAs": "json" } );
     *       assert(res.status == 200,"Status code should be 200, was " + res.status);
     *       assert(res.body.kind == "json","Body kind should be 'json', was " + res.body.kind);
     *       assert(res.body.body[0].DepartmentName == "Marketing","Dept 20 should be named 'Marketing' not " + res.body.body[0].DepartmentName);
     *       dept = res.body.body[0];
     *
     *       dept.DepartmentName = "Product Marketing";
     *       res = await ojwd.fetch(driver,restServer + 'Departments/30', { "responseBodyAs": "json" }, {
     *         method: 'put',
     *         headers: { "Content-Type": "application/json" },
     *         body: {"kind":"json", "body": JSON.stringify(dept)}
     *       });
     *       assert(res.status == 200,"Status code should be 200, was " + res.status + " body = " + JSON.stringify(res.body,null,2));
     *     } catch(err) {
     *       assert(false, "fetch failed : " + err);
     *     }
     * ```
     *
     * ###### Example of CREATE and DELETE operations
     * ```javascript
     *     try {
     *       let res:MarshaledResponse = await ojwd.fetch(driver,restServer + 'Departments/',
     *          { "responseBodyAs": "json" },
     *          { method: 'post',
     *          headers: { "Content-Type": "application/json"},
     *          body: { "kind": "json", "body": JSON.stringify(newdept)} });
     *        assert(res.status == 201,"Status code should be 201, was " + res.status);
     *
     *        res = await ojwd.fetch(driver,restServer + 'Departments/190',
     *          { "responseBodyAs": "text" },
     *          { method: 'delete' });
     *        assert(res.status == 200,"Status code should be 200, was " + res.status);
     *       } catch(err) {
     *        assert(false, "fetch failed : " + err);
     *       }
     * ```
     *
     * ###### Example of Checking for row deleted operation
     * ```javascript
     *       try {
     *         let res:MarshaledResponse = await ojwd.fetch(driver,restServer + 'Departments/400',
     *           { "responseBodyAs": "json" });
     *         assert(res.status == 404,"Status code should be 404, was " + res.status);
     *       } catch(err) {
     *         assert(false, "fetch failed : " + err);
     *       }
     * ```
     *
     * ###### Example of MarshaledResponse object for READ fetch
     * ```javascript
     * {
     *  "body": {
     *    "body": [
     *     {
     *        "DepartmentId": 20,
     *        "DepartmentName": "Marketing",
     *        "LocationId": null,
     *         "ManagerId": null
     *      }
     *    ],
     *     "kind": "json"
     *   },
     *   "headers": {
     *    "cache-control": "no-cache",
     *     "content-type": "application/json; charset=utf-8",
     *     "expires": "-1",
     *     "pragma": "no-cache"
     *   },
     *   "ok": true,
     *   "redirected": false,
     *   "status": 200,
     *   "statusText": "OK",
     *   "type": "cors",
     *   "url": "http://localhost:3000/Departments/?DepartmentId=20"
     *   }
     * ```
     *
     */
    async fetch(driver, requestInfo, responseInfo, init) {
        let ojFetch = new OjFetch_1.OjFetch();
        return ojFetch.fetch(driver, requestInfo, responseInfo, init);
    },
    /**
     * This is a convenience function to allow either WebDriver or WebElement to
     * be passed as the driver and the search to be performed using that object.
     * @param driver A WebDriver-like object, either WebDriver itself or a
     * WebElement. The target element will be searched using this driver.
     * @param by The locator by which to find the element
     * @deprecated Since 11.0.0 This method is equivalient to calling
     * driver.findElement(by)
     */
    async waitAndFindElement(driver, by) {
        // findElement will wait on busy context before executing
        return driver.findElement(by);
    },
    assertViewModelValue: viewmodel_utils_1.assertViewModelValue
};
Object.defineProperties(ojwd, {
    /*
     * Add a guard to only set the noRequireJet flag once
     */
    noRequireJet: {
        set: function (v) {
            if ((0, no_require_jet_1.isNoRequireJet)() === undefined) {
                (0, no_require_jet_1.setNoRequireJet)(v);
            }
            else {
                throw Error('noRequireJet cannot be set more than once');
            }
        },
        get: no_require_jet_1.isNoRequireJet,
        enumerable: false,
        configurable: false
    }
});
exports.default = ojwd;
//# sourceMappingURL=index.js.map