import { __awaiter, __generator } from "tslib";
import { androidAttributeToEnumName, attributeToEnumName, BASE_TESTPAGE, BOOT_APP_TIMEOUT, E2E_MODE_SWITCH, E2E_TEST_SECTION, ROOT_VIEW, TESTPAGE_BUTTONS_SCROLLVIEWER, TESTPAGE_CONTENT_SCROLLVIEWER, } from './consts';
var DUMMY_CHAR = '';
// The E2ETEST_PLATFORM environment variable should be set in the beforeSession hook in the wdio.conf file for the respective platform
var PLATFORM = process.env['E2ETEST_PLATFORM'];
export var COMPONENT_SCROLL_COORDINATES = { x: -0, y: -100 }; // These are the offsets. Y is negative because we want the touch to move up (and thus it scrolls down)
var rootView = null;
/* Win32/UWP-Specific Selector. We use this to get elements on the test page */
export function By(identifier) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!(PLATFORM === 'windows')) return [3 /*break*/, 2];
                    return [4 /*yield*/, $('~' + identifier)];
                case 1: 
                // For some reason, the rootView node is never put into the element tree on the UWP tester. Remove this when fixed.
                return [2 /*return*/, _a.sent()];
                case 2: return [4 /*yield*/, QueryWithChaining(identifier)];
                case 3: return [2 /*return*/, _a.sent()];
            }
        });
    });
}
function QueryWithChaining(identifier) {
    return __awaiter(this, void 0, void 0, function () {
        var selector, queryResult;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    if (!(rootView === null)) return [3 /*break*/, 2];
                    return [4 /*yield*/, $('~' + ROOT_VIEW)];
                case 1:
                    // Most of the elements we're searching for will be children of this rootView node.
                    rootView = _a.sent();
                    _a.label = 2;
                case 2:
                    selector = '~' + identifier;
                    return [4 /*yield*/, rootView.$(selector)];
                case 3:
                    queryResult = _a.sent();
                    if (!queryResult.error) return [3 /*break*/, 5];
                    return [4 /*yield*/, $(selector)];
                case 4:
                    // In some cases, such as opened ContextualMenu items, the element nodes are not children of the rootView node, meaning we need to start our search from the top of the tree.
                    queryResult = _a.sent();
                    _a.label = 5;
                case 5: return [2 /*return*/, queryResult];
            }
        });
    });
}
/****************************** IMPORTANT! PLEASE READ! **************************************************
 * Every component's page object extends this. We can assume each test page will interact with at least
 * two UI elements, so we'll add integration for two UI elements in this file (See *Getters* section below).
 * Every additional UI element that a test page wants to interact with should be handled in that respective
 * component's page object.
 *********************************************************************************************************/
var BasePage = /** @class */ (function () {
    function BasePage() {
        // Default timeout to wait until page is displayed (25s)
        this.waitForUiEvent = 25000;
        if (PLATFORM) {
            this.platform = PLATFORM;
        }
    }
    /******************************************************************/
    /**************** UI Element Interaction Methods ******************/
    /******************************************************************/
    /**
     * For any given page object, this method automates:
     *  - Navigating to the page by clicking its component button
     *  - Waiting for the component page to load
     *  - Optionally expanding its E2E sections IF a boolean flag is passed.
     *
     * This also contains error checking through its waiters, removing the extra `expect()` calls during test setup.
     *
     * @param {boolean} showE2ESection Some components' E2E tests check only if the test page loads correctly or not. Others
     * (majority), perform UI manipulation tests on UI components on the test page. In these scenarios, these UI components have their
     * own section on the test page (by default, it's hidden so partners don't see it). If this parameter is true, this method opens up
     * that testing section.
     */
    BasePage.prototype.navigateToPageAndLoadTests = function (showE2ESection) {
        if (showE2ESection === void 0) { showE2ESection = false; }
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.platform === 'android' || this.platform === 'ios')) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.mobileScrollToComponentButton()];
                    case 1:
                        _a.sent();
                        _a.label = 2;
                    case 2: return [4 /*yield*/, this._pageButton];
                    case 3: return [4 /*yield*/, (_a.sent()).click()];
                    case 4:
                        _a.sent();
                        // Wait for page to load
                        return [4 /*yield*/, this.waitForCondition(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, this.isPageLoaded()];
                                    case 1: return [2 /*return*/, _a.sent()];
                                }
                            }); }); }, this.ERRORMESSAGE_PAGELOAD, this.waitForUiEvent, 1500)];
                    case 5:
                        // Wait for page to load
                        _a.sent();
                        if (!showE2ESection) return [3 /*break*/, 7];
                        return [4 /*yield*/, this.enableE2ETesterMode()];
                    case 6:
                        _a.sent();
                        _a.label = 7;
                    case 7: return [2 /*return*/];
                }
            });
        });
    };
    BasePage.prototype.enableE2ETesterMode = function () {
        return __awaiter(this, void 0, void 0, function () {
            var e2eSwitch, _a;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this._e2eSwitch];
                    case 1:
                        e2eSwitch = _b.sent();
                        _a = this.platform;
                        switch (_a) {
                            case 'android': return [3 /*break*/, 2];
                        }
                        return [3 /*break*/, 7];
                    case 2: return [4 /*yield*/, e2eSwitch.getAttribute("checked" /* AndroidAttribute.Checked */)];
                    case 3:
                        if (!((_b.sent()) === 'false')) return [3 /*break*/, 6];
                        return [4 /*yield*/, e2eSwitch.click()];
                    case 4:
                        _b.sent();
                        return [4 /*yield*/, this.waitForCondition(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, e2eSwitch.getAttribute("checked" /* AndroidAttribute.Checked */)];
                                    case 1: return [2 /*return*/, (_a.sent()) === 'true'];
                                }
                            }); }); }, 'Clicked the E2E Mode Switch, but it failed to toggle.')];
                    case 5:
                        _b.sent();
                        _b.label = 6;
                    case 6: return [3 /*break*/, 11];
                    case 7: return [4 /*yield*/, e2eSwitch.isSelected()];
                    case 8:
                        if (!!(_b.sent())) return [3 /*break*/, 11];
                        return [4 /*yield*/, e2eSwitch.click()];
                    case 9:
                        _b.sent();
                        return [4 /*yield*/, this.waitForCondition(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                                return [2 /*return*/, e2eSwitch.isSelected()];
                            }); }); }, 'Clicked the E2E Mode Switch, but it failed to toggle.')];
                    case 10:
                        _b.sent();
                        _b.label = 11;
                    case 11: return [4 /*yield*/, this.waitForCondition(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0: return [4 /*yield*/, this._e2eSection];
                                case 1: return [4 /*yield*/, (_a.sent()).isDisplayed()];
                                case 2: return [2 /*return*/, _a.sent()];
                            }
                        }); }); }, 'Pressed E2E Mode Switch, but E2E Test Sections failed to display before the timeout.')];
                    case 12:
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Checks to see if an element attribute is strictly equal to an expected value the user passes in.
     * The advantage to this over testing using .isEqual in a spec is that this throws a detailed error if
     * the expected and actual values don't match. This should be called for attribute tests in specs. */
    BasePage.prototype.compareAttribute = function (element, attribute, expectedValue) {
        return __awaiter(this, void 0, void 0, function () {
            var el, actualValue, _a, _b, _c, _d;
            return __generator(this, function (_e) {
                switch (_e.label) {
                    case 0: return [4 /*yield*/, element];
                    case 1:
                        el = _e.sent();
                        return [4 /*yield*/, el.getAttribute(attribute)];
                    case 2:
                        actualValue = _e.sent();
                        if (!(expectedValue !== actualValue)) return [3 /*break*/, 6];
                        _a = this.platform;
                        switch (_a) {
                            case 'android': return [3 /*break*/, 3];
                        }
                        return [3 /*break*/, 4];
                    case 3: throw new Error("On ".concat(this._pageName, ", expected attribute ").concat(androidAttributeToEnumName[attribute], " value to be ").concat(expectedValue, " but got ").concat(actualValue));
                    case 4:
                        _b = Error.bind;
                        _d = (_c = "On ".concat(this._pageName, ", a test component with a testID = '")).concat;
                        return [4 /*yield*/, el.getAttribute("AutomationId" /* Attribute.TestID */)];
                    case 5: throw new (_b.apply(Error, [void 0, _d.apply(_c, [_e.sent(), "' should have attribute, "]).concat(attributeToEnumName[attribute], " (which maps to windows attribute '").concat(attribute, "' property on the element), equal to '").concat(expectedValue, "'. Instead, ").concat(attributeToEnumName[attribute], " is equal to '").concat(actualValue, "'.")]))();
                    case 6: return [2 /*return*/, true];
                }
            });
        });
    };
    /* Returns true if the test page has loaded. To determine if it's loaded, each test page has a specific UI element we attempt to locate.
     * If this UI element is located, we know the page as loaded correctly. The UI element we look for is a Text component that contains
     * the title of the page (this._testPage returns that UI element)  */
    BasePage.prototype.isPageLoaded = function () {
        return __awaiter(this, void 0, void 0, function () {
            var onPage, _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this._testPage];
                    case 1: return [4 /*yield*/, (_b.sent()).isDisplayed()];
                    case 2:
                        _a = (_b.sent());
                        if (_a) return [3 /*break*/, 5];
                        return [4 /*yield*/, this._primaryComponent];
                    case 3: return [4 /*yield*/, (_b.sent()).isDisplayed()];
                    case 4:
                        _a = (_b.sent());
                        _b.label = 5;
                    case 5:
                        onPage = _a;
                        return [2 /*return*/, onPage];
                }
            });
        });
    };
    /* Returns true if the test page's button is displayed (the button that navigates to each test page) */
    BasePage.prototype.isButtonInView = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._pageButton];
                    case 1: return [4 /*yield*/, (_a.sent()).isDisplayed()];
                    case 2: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    /** Given a WebdriverIO element promise, send a click input to the element. Use this across all PageObject methods and test specs. */
    BasePage.prototype.click = function (element) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, element];
                    case 1: return [4 /*yield*/, (_a.sent()).click()];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /** Given a WebdriverIO element promise, send the passed in list of keys as keyboard inputs. Use this across all PageObject methods and test specs.
     *
     * Common examples:
     * - Press enter on a button control: ButtonPageObject.sendKeys(ButtonPageObject.button, [KEY_ENTER])
     * - Shift tab to the previous element: FocusZonePageObject.sendKeys(FocusZonePageObject.beforeButton, [KEY_SHIFT, KEY_TAB])
     * - Escape out of a menu: MenuPageObject.sendKeys(MenuPageObject.item1, [KEY_ESCAPE])
     */
    BasePage.prototype.sendKeys = function (element, keys) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, element];
                    case 1: return [4 /*yield*/, (_a.sent()).addValue(keys)];
                    case 2:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /** Short-hand method for PageObjects to get an element attribute during testing, with attribute being type-enforced. */
    BasePage.prototype.getElementAttribute = function (element, attribute) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, element.getAttribute(attribute)];
                    case 1: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    /* Scrolls until the desired test page's button is displayed. We use the scroll viewer UI element as the point to start scrolling.
     * We use a negative number as the Y-coordinate because that enables us to scroll downwards */
    BasePage.prototype.mobileScrollToComponentButton = function () {
        return __awaiter(this, void 0, void 0, function () {
            var errorMsg, _a;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0: return [4 /*yield*/, this._pageButton];
                    case 1: return [4 /*yield*/, (_b.sent()).isDisplayed()];
                    case 2:
                        if (_b.sent()) {
                            return [2 /*return*/];
                        }
                        errorMsg = 'Could not scroll to the ' + this._pageName + "'s Button. Please see Pipeline artifacts for more debugging information.";
                        _a = this.platform;
                        switch (_a) {
                            case 'ios': return [3 /*break*/, 3];
                            case 'android': return [3 /*break*/, 5];
                        }
                        return [3 /*break*/, 5];
                    case 3: return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () {
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, driver.execute('mobile: scroll', { direction: 'down' })];
                                    case 1:
                                        _a.sent();
                                        return [4 /*yield*/, this._pageButton];
                                    case 2: return [4 /*yield*/, (_a.sent()).isDisplayed()];
                                    case 3: return [2 /*return*/, _a.sent()];
                                }
                            });
                        }); }, {
                            timeout: this.waitForUiEvent,
                            timeoutMsg: errorMsg,
                        })];
                    case 4:
                        _b.sent();
                        return [3 /*break*/, 7];
                    case 5: 
                    /* 'mobile: scroll' which is used for iOS, does not support direction option on Android.
                     * Instead, we use the UiScrollable class to scroll down to the desired view based on its 'description' (accessibilityLabel).
                     * The first selector tells which container to scroll in, and the other selector tells which component to scroll to. */
                    return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () {
                            var buttonElementSelector, pageButton;
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0:
                                        buttonElementSelector = "new UiScrollable(new UiSelector().description(\"".concat(TESTPAGE_BUTTONS_SCROLLVIEWER, "\").scrollable(true)).setMaxSearchSwipes(10).setAsVerticalList().scrollIntoView(new UiSelector().description(\"").concat(this._pageButtonName, "\"))");
                                        return [4 /*yield*/, $("android=".concat(buttonElementSelector))];
                                    case 1:
                                        pageButton = _a.sent();
                                        return [4 /*yield*/, pageButton.isDisplayed()];
                                    case 2: return [2 /*return*/, _a.sent()];
                                }
                            });
                        }); }, {
                            timeout: this.waitForUiEvent,
                            timeoutMsg: errorMsg,
                        })];
                    case 6:
                        /* 'mobile: scroll' which is used for iOS, does not support direction option on Android.
                         * Instead, we use the UiScrollable class to scroll down to the desired view based on its 'description' (accessibilityLabel).
                         * The first selector tells which container to scroll in, and the other selector tells which component to scroll to. */
                        _b.sent();
                        return [3 /*break*/, 7];
                    case 7: return [2 /*return*/];
                }
            });
        });
    };
    /** Waits for the tester app to load by checking if the startup page loads. If the app doesn't load before the timeout, it causes the test to fail. */
    BasePage.prototype.waitForInitialPageToDisplay = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.waitForCondition(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0: return [4 /*yield*/, this.isInitialPageDisplayed()];
                                case 1: return [2 /*return*/, _a.sent()];
                            }
                        }); }); }, this.ERRORMESSAGE_APPLOAD, BOOT_APP_TIMEOUT)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    BasePage.prototype.isInitialPageDisplayed = function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._initialPage];
                    case 1: return [4 /*yield*/, (_a.sent()).isDisplayed()];
                    case 2: return [2 /*return*/, _a.sent()];
                }
            });
        });
    };
    /* Scrolls to the specified or primary UI test element until it is displayed. */
    BasePage.prototype.scrollToTestElement = function (component) {
        return __awaiter(this, void 0, void 0, function () {
            var ComponentToScrollTo, _a, FocusButton, scrollDownKeys;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!(component !== null && component !== void 0)) return [3 /*break*/, 1];
                        _a = component;
                        return [3 /*break*/, 3];
                    case 1: return [4 /*yield*/, this._primaryComponent];
                    case 2:
                        _a = (_b.sent());
                        _b.label = 3;
                    case 3:
                        ComponentToScrollTo = _a;
                        return [4 /*yield*/, ComponentToScrollTo.isDisplayed()];
                    case 4:
                        if (_b.sent()) {
                            return [2 /*return*/];
                        }
                        return [4 /*yield*/, By('Focus_Button')];
                    case 5:
                        FocusButton = _b.sent();
                        scrollDownKeys = ["\uE00F" /* Keys.PAGE_DOWN */];
                        return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () {
                                return __generator(this, function (_a) {
                                    switch (_a.label) {
                                        case 0: return [4 /*yield*/, FocusButton.addValue(scrollDownKeys)];
                                        case 1:
                                            _a.sent();
                                            scrollDownKeys.push("\uE00F" /* Keys.PAGE_DOWN */);
                                            return [4 /*yield*/, ComponentToScrollTo.isDisplayed()];
                                        case 2: return [2 /*return*/, _a.sent()];
                                    }
                                });
                            }); }, {
                                timeout: 30000,
                                timeoutMsg: 'Could not scroll to the ' +
                                    this._pageName +
                                    "'s main test element. Please see Pipeline artifacts for more debugging information.",
                            })];
                    case 6:
                        _b.sent();
                        // We have this extra scroll here to ensure the whole component is visible.
                        return [4 /*yield*/, FocusButton.addValue(scrollDownKeys)];
                    case 7:
                        // We have this extra scroll here to ensure the whole component is visible.
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /* Scrolls to the specified or primary UI test element until it is displayed. */
    BasePage.prototype.mobileScrollToTestElement = function (componentIdentifier) {
        return __awaiter(this, void 0, void 0, function () {
            var componentToScrollTo, errorMsg, _a;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        componentToScrollTo = componentIdentifier !== null && componentIdentifier !== void 0 ? componentIdentifier : this._primaryComponentName;
                        return [4 /*yield*/, By(componentToScrollTo)];
                    case 1: return [4 /*yield*/, (_b.sent()).isDisplayed()];
                    case 2:
                        if (_b.sent()) {
                            return [2 /*return*/];
                        }
                        errorMsg = 'Could not scroll to the ' + componentToScrollTo + '. Please see Pipeline artifacts for more debugging information.';
                        _a = this.platform;
                        switch (_a) {
                            case 'ios': return [3 /*break*/, 3];
                            case 'android': return [3 /*break*/, 5];
                        }
                        return [3 /*break*/, 7];
                    case 3: return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () {
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0: return [4 /*yield*/, driver.execute('mobile: scroll', { direction: 'down' })];
                                    case 1:
                                        _a.sent();
                                        return [4 /*yield*/, By(componentToScrollTo)];
                                    case 2: return [4 /*yield*/, (_a.sent()).isDisplayed()];
                                    case 3: return [2 /*return*/, _a.sent()];
                                }
                            });
                        }); }, {
                            timeout: this.waitForUiEvent,
                            timeoutMsg: errorMsg,
                        })];
                    case 4:
                        _b.sent();
                        return [3 /*break*/, 7];
                    case 5: 
                    /* 'mobile: scroll' which is used for iOS, does not support direction option on Android.
                     * Instead, we use the UiScrollable class to scroll down to the desired view based on its 'description' (accessibilityLabel).
                     * The first selector tells which container to scroll in, and the other selector tells which component to scroll to. */
                    return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () {
                            var componentSelector, component;
                            return __generator(this, function (_a) {
                                switch (_a.label) {
                                    case 0:
                                        componentSelector = "new UiScrollable(new UiSelector().description(\"".concat(TESTPAGE_CONTENT_SCROLLVIEWER, "\").scrollable(true)).setMaxSearchSwipes(10).scrollIntoView(new UiSelector().description(\"").concat(componentIdentifier, "\"))");
                                        return [4 /*yield*/, $("android=".concat(componentSelector))];
                                    case 1:
                                        component = _a.sent();
                                        return [4 /*yield*/, component.isDisplayed()];
                                    case 2: return [2 /*return*/, _a.sent()];
                                }
                            });
                        }); }, {
                            timeout: this.waitForUiEvent,
                            timeoutMsg: errorMsg,
                        })];
                    case 6:
                        /* 'mobile: scroll' which is used for iOS, does not support direction option on Android.
                         * Instead, we use the UiScrollable class to scroll down to the desired view based on its 'description' (accessibilityLabel).
                         * The first selector tells which container to scroll in, and the other selector tells which component to scroll to. */
                        _b.sent();
                        return [3 /*break*/, 7];
                    case 7: return [2 /*return*/];
                }
            });
        });
    };
    /* A method that allows the caller to pass in a condition. A wrapper for waitUntil(). Once testing becomes more extensive,
     * this will allow cleaner code within all the Page Objects. */
    BasePage.prototype.waitForCondition = function (condition, errorMsg, timeout, interval) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, browser.waitUntil(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0: return [4 /*yield*/, condition()];
                                case 1: return [2 /*return*/, _a.sent()];
                            }
                        }); }); }, {
                            timeout: timeout !== null && timeout !== void 0 ? timeout : this.waitForUiEvent,
                            timeoutMsg: errorMsg !== null && errorMsg !== void 0 ? errorMsg : 'Error. Please see /errorShots and logs for more information.',
                            interval: interval !== null && interval !== void 0 ? interval : 1000,
                        })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    /* FUNCTIONALITY: Determines if an Assert has fired. True if yes; false otherwise
     *
     * WHY/HOW: Unfortunately, some Asserts don't take focus away from the test app. Because of this, the test execution is able
     * to continue without realizing an assert as popped up (unless the assert is a crashing one).
     *
     * In order to detect an assert, this function gets the number of window handles currently open within the test app.
     * Only one instance SHOULD be open at a time (the app itself). If another instance of the app is open, we know an assert dialogue
     * has popped up. With this information, we know to fail the test.
     *
     * Additionally, you might think it's logical to simply place this in the afterEach() hook so it's called after every test (rather than duplicating this call in every test).
     * Unfortunately, afterEach() is designed for setup/teardown - not for determining if a test should fail or not.
     * */
    BasePage.prototype.didAssertPopup = function () {
        return __awaiter(this, void 0, void 0, function () {
            var windowHandles;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(PLATFORM === 'android')) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.isPageLoaded()];
                    case 1: return [2 /*return*/, !(_a.sent())];
                    case 2: return [4 /*yield*/, browser.getWindowHandles()];
                    case 3:
                        windowHandles = _a.sent();
                        return [2 /*return*/, windowHandles.length > 1];
                }
            });
        });
    };
    Object.defineProperty(BasePage.prototype, "_testPage", {
        /*****************************************/
        /**************** Getters ****************/
        /*****************************************/
        /*  IMPORTANT:
         *  Each PageObject class that extends this class is expected to override these values.
         *  This is necessary because each page will have different IDs for their respective UI elements.
         *  DUMMY_CHAR is just a placeholder.
         */
        // Returns: UI Element
        // The Text component on each test page containing the title of that page. We can use this to determine if a test page has loaded correctly.
        get: function () {
            return By(this._pageName);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_primaryComponent", {
        // Returns: UI Element
        // The primary UI element used for testing on the given test page.
        get: function () {
            return By(this._primaryComponentName);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_secondaryComponent", {
        // Returns: UI Element
        // The secondary UI element used for testing on the given test page. Often times, we'll want to set a
        // prop on one component, and not set it on another to verify certain behaviors. This is why we have this secondary component.
        get: function () {
            return By(this._secondaryComponentName);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_pageButton", {
        // Returns: UI Element
        // The button that navigates you to the component's test page.
        get: function () {
            return By(this._pageButtonName);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_primaryComponentName", {
        // Returns: String
        // Returns the identifier of the primary UI element used for testing on the given test page.
        get: function () {
            console.warn('Please verify whether or not your page object should implement _primaryComponentName.');
            return DUMMY_CHAR;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_secondaryComponentName", {
        // Returns: String
        // Returns the identifier of the secondary UI element used for testing on the given test page. Often times, we'll want to set a
        // prop on one component, and not set it on another to verify certain behaviors. This is why we have this secondary component.
        get: function () {
            console.warn('Please verify whether or not your page object should implement _secondaryComponentName.');
            return DUMMY_CHAR;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_testPageButtonScrollViewer", {
        // The scrollviewer containing the list of buttons to navigate to each test page
        get: function () {
            return By(TESTPAGE_BUTTONS_SCROLLVIEWER);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_initialPage", {
        // The title element of the initial test page shown when starting the app.
        get: function () {
            return By(BASE_TESTPAGE);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "ERRORMESSAGE_SUFFIX", {
        /****************** Error Messages ******************/
        get: function () {
            return 'Please review logs and error screenshots for more information.';
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "ERRORMESSAGE_APPLOAD", {
        get: function () {
            return 'The FluentTester app did not load correctly. ' + this.ERRORMESSAGE_SUFFIX;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "ERRORMESSAGE_PAGELOAD", {
        get: function () {
            return 'The ' + this._pageName + ' test page did not load correctly. ' + this.ERRORMESSAGE_SUFFIX;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "ERRORMESSAGE_ASSERT", {
        get: function () {
            return 'An assert popped up. ' + this.ERRORMESSAGE_SUFFIX;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_e2eSwitch", {
        get: function () {
            return By(E2E_MODE_SWITCH);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(BasePage.prototype, "_e2eSection", {
        get: function () {
            return By(E2E_TEST_SECTION);
        },
        enumerable: false,
        configurable: true
    });
    return BasePage;
}());
export { BasePage };
//# sourceMappingURL=BasePage.js.map