@redhat-developer/page-objects
Version:
Page Object API implementation for a VS Code editor used by ExTester framework.
863 lines • 35.6 kB
JavaScript
"use strict";
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License", destination); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindWidget = exports.CodeLens = exports.TextEditor = exports.BreakpointError = void 0;
const __1 = require("../..");
const selenium_webdriver_1 = require("selenium-webdriver");
const url_1 = require("url");
const StatusBar_1 = require("../statusBar/StatusBar");
const Editor_1 = require("./Editor");
const ElementWithContextMenu_1 = require("../ElementWithContextMenu");
const AbstractElement_1 = require("../AbstractElement");
const Breakpoint_1 = require("./Breakpoint");
const compare_versions_1 = require("compare-versions");
class BreakpointError extends Error {
}
exports.BreakpointError = BreakpointError;
/**
* Page object representing the active text editor
*/
class TextEditor extends Editor_1.Editor {
breakPoints = [];
/**
* Find whether the active editor has unsaved changes
* @returns Promise resolving to true/false
*/
async isDirty() {
const tab = await this.enclosingItem.findElement(TextEditor.locators.TextEditor.activeTab);
const klass = await tab.getAttribute('class');
return klass.indexOf('dirty') >= 0;
}
/**
* Saves the active editor
* @returns Promise resolving when ctrl+s is invoked
*/
async save() {
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 's'));
}
/**
* Open the Save as prompt
*
* @returns InputBox serving as a simple file dialog
*/
async saveAs() {
const tab = await this.getTab();
await tab.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, selenium_webdriver_1.Key.SHIFT, 's'));
return await __1.InputBox.create();
}
/**
* Retrieve the Uri of the file opened in the active editor
* @returns Promise resolving to editor's underlying Uri
*/
async getFileUri() {
const ed = await this.findElement(TextEditor.locators.TextEditor.editorContainer);
return await ed.getAttribute(TextEditor.locators.TextEditor.dataUri);
}
/**
* Retrieve the path to the file opened in the active editor
* @returns Promise resolving to editor's underlying file path
*/
async getFilePath() {
return (0, url_1.fileURLToPath)(await this.getFileUri());
}
/**
* Open/Close the content assistant at the current position in the editor by sending the default
* keyboard shortcut signal
* @param open true to open, false to close
* @returns Promise resolving to ContentAssist object when opening, void otherwise
*/
async toggleContentAssist(open) {
let isHidden = true;
try {
const assist = await this.findElement(TextEditor.locators.ContentAssist.constructor);
const klass = await assist.getAttribute('class');
const visibility = await assist.getCssValue('visibility');
isHidden = klass.indexOf('visible') < 0 || visibility === 'hidden';
}
catch (err) {
isHidden = true;
}
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
if (open) {
if (isHidden) {
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(selenium_webdriver_1.Key.CONTROL, selenium_webdriver_1.Key.SPACE));
await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.ContentAssist.constructor), 2000);
}
const assist = await new __1.ContentAssist(this).wait();
await this.getDriver().wait(() => {
return assist.isLoaded();
}, 10000);
return assist;
}
else {
if (!isHidden) {
await inputarea.sendKeys(selenium_webdriver_1.Key.ESCAPE);
}
}
}
/**
* Get all text from the editor
* @returns Promise resolving to editor text
*/
async getText() {
const clipboard = (await import('clipboardy')).default;
let originalClipboard = '';
try {
originalClipboard = clipboard.readSync();
}
catch (error) {
// workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
// do not fail if clipboard is empty
}
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'), selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'c'));
await new Promise((res) => setTimeout(res, 500));
const text = clipboard.readSync();
await inputarea.sendKeys(selenium_webdriver_1.Key.UP);
if (originalClipboard.length > 0) {
clipboard.writeSync(originalClipboard);
}
return text;
}
/**
* Replace the contents of the editor with a given text
* @param text text to type into the editor
* @param formatText format the new text, default false
* @returns Promise resolving once the new text is copied over
*/
async setText(text, formatText = false) {
const clipboard = (await import('clipboardy')).default;
let originalClipboard = '';
try {
originalClipboard = clipboard.readSync();
}
catch (error) {
// workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
// do not fail if clipboard is empty
}
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
clipboard.writeSync(text);
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'), selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'v'));
if (originalClipboard.length > 0) {
clipboard.writeSync(originalClipboard);
}
if (formatText) {
await this.formatDocument();
}
}
/**
* Deletes all text within the editor
* @returns Promise resolving once the text is deleted
*/
async clearText() {
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'a'));
await inputarea.sendKeys(selenium_webdriver_1.Key.BACK_SPACE);
}
/**
* Get text from a given line
* @param line number of the line to retrieve
* @returns Promise resolving to text at the given line number
*/
async getTextAtLine(line) {
const text = await this.getText();
const lines = text.split('\n');
if (line < 1 || line > lines.length) {
throw new Error(`Line number ${line} does not exist`);
}
return lines[line - 1];
}
/**
* Replace the contents of a line with a given text
* @param line number of the line to edit
* @param text text to set at the line
* @returns Promise resolving when the text is typed in
*/
async setTextAtLine(line, text) {
if (line < 1 || line > (await this.getNumberOfLines())) {
throw new Error(`Line number ${line} does not exist`);
}
const lines = (await this.getText()).split('\n');
lines[line - 1] = text;
await this.setText(lines.join('\n'));
}
/**
* Get line number that contains the given text. Not suitable for multi line inputs.
*
* @param text text to search for
* @param occurrence select which occurrence of the search text to look for in case there are multiple in the document, defaults to 1 (the first instance)
*
* @returns Number of the line that contains the start of the given text. -1 if no such text is found.
* If occurrence number is specified, searches until it finds as many instances of the given text.
* Returns the line number that holds the last occurrence found this way.
*/
async getLineOfText(text, occurrence = 1) {
let lineNum = -1;
let found = 0;
const lines = (await this.getText()).split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes(text)) {
found++;
lineNum = i + 1;
if (found >= occurrence) {
break;
}
}
}
return lineNum;
}
/**
* Find and select a given text. Not usable for multi line selection.
*
* @param text text to select
* @param occurrence specify which occurrence of text to select if multiple are present in the document
*/
async selectText(text, occurrence = 1) {
const lineNum = await this.getLineOfText(text, occurrence);
if (lineNum < 1) {
throw new Error(`Text '${text}' not found`);
}
const line = await this.getTextAtLine(lineNum);
const column = line.indexOf(text) + 1;
await this.moveCursor(lineNum, column);
let actions = this.getDriver().actions();
await actions.clear();
actions.keyDown(selenium_webdriver_1.Key.SHIFT);
for (let i = 0; i < text.length; i++) {
actions = actions.sendKeys(selenium_webdriver_1.Key.RIGHT);
}
actions = actions.keyUp(selenium_webdriver_1.Key.SHIFT);
await actions.perform();
await new Promise((res) => setTimeout(res, 500));
}
/**
* Get the text that is currently selected as string
*/
async getSelectedText() {
const clipboard = (await import('clipboardy')).default;
let originalClipboard = '';
try {
originalClipboard = clipboard.readSync();
}
catch (error) {
// workaround issue https://github.com/redhat-developer/vscode-extension-tester/issues/835
// do not fail if clipboard is empty
}
if (process.platform !== 'darwin') {
const selection = await this.getSelection();
if (!selection) {
return '';
}
const menu = await selection.openContextMenu();
await menu.select('Copy');
}
else {
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.sendKeys(selenium_webdriver_1.Key.chord(TextEditor.ctlKey, 'c'));
await new Promise((res) => setTimeout(res, 500));
await inputarea.sendKeys(selenium_webdriver_1.Key.UP);
}
await new Promise((res) => setTimeout(res, 500));
const text = clipboard.readSync();
if (originalClipboard.length > 0) {
clipboard.writeSync(originalClipboard);
}
return text;
}
/**
* Get the selection block as a page object
* @returns Selection page object
*/
async getSelection() {
const selection = await this.findElements(TextEditor.locators.TextEditor.selection);
if (selection.length < 1) {
return undefined;
}
return new Selection(selection[0], this);
}
async openFindWidget() {
const actions = this.getDriver().actions();
await actions.clear();
await actions.keyDown(TextEditor.ctlKey).sendKeys('f').keyUp(TextEditor.ctlKey).perform();
const widget = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(TextEditor.locators.TextEditor.findWidget), 2000);
await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(widget), 2000);
return new FindWidget(widget, this);
}
/**
* Add the given text to the given coordinates
* @param line number of the line to type into
* @param column number of the column to start typing at
* @param text text to add
* @returns Promise resolving when the text is typed in
*/
async typeTextAt(line, column, text) {
await this.moveCursor(line, column);
await this.typeText(text);
}
/**
* Type given text at the current coordinates
* @param text text to type
* @returns promise resolving when the text is typed in
*/
async typeText(text) {
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.sendKeys(text);
}
/**
* Set cursor to given position using command prompt :Ln,Col
* @param line line number to set to
* @param column column number to set to
* @returns Promise resolving when the cursor has reached the given coordinates
*/
async setCursor(line, column, timeout = 2_500) {
const input = await new __1.Workbench().openCommandPrompt();
await input.setText(`:${line},${column}`);
await input.confirm();
await this.waitForCursorPositionAt(line, column, timeout);
}
/**
* Get indentation from the status bar for the currently opened text editor
* @returns \{ string, number \} object which contains label and value of indentation
*/
async getIndentation() {
const indentation = await new StatusBar_1.StatusBar().getCurrentIndentation();
const value = Number(indentation.match(/\d+/g)?.at(0));
const label = indentation.match(/^[a-zA-Z\s]+/g)?.at(0);
return { label, value };
}
/**
* Move the cursor to the given coordinates
* @param line line number to move to
* @param column column number to move to
* @returns Promise resolving when the cursor has reached the given coordinates
*/
async moveCursor(line, column, timeout = 10_000) {
if (line < 1 || line > (await this.getNumberOfLines())) {
throw new Error(`Line number ${line} does not exist`);
}
if (column < 1) {
throw new Error(`Column number ${column} does not exist`);
}
const inputarea = await this.findElement(TextEditor.locators.Editor.inputArea);
await inputarea.getDriver().wait(async () => {
await this.moveCursorToLine(inputarea, line);
return await this.isLine(line);
}, timeout, `Unable to move cursor to line: ${line}`);
await inputarea.getDriver().wait(async () => {
await this.moveCursorToColumn(inputarea, column);
return await this.isColumn(column);
}, timeout, `Unable to move cursor to column: ${column}`);
}
/**
* (private) Move the cursor to the given line coordinate
* @param inputArea WebElement of an editor input area
* @param line line number to move to
* @returns Promise resolving when the cursor has reached the given line coordinate
*/
async moveCursorToLine(inputArea, line) {
const coordinates = await this.getCoordinates();
const lineGap = coordinates[0] - line;
const lineKey = lineGap >= 0 ? selenium_webdriver_1.Key.UP : selenium_webdriver_1.Key.DOWN;
for (let i = 0; i < Math.abs(lineGap); i++) {
if (await this.isLine(line)) {
break;
}
await inputArea.getDriver().actions().clear();
await inputArea.sendKeys(lineKey);
await inputArea.getDriver().sleep(50);
}
}
/**
* (private) Move the cursor to the given column coordinate
* @param inputArea WebElement of an editor input area
* @param column column number to move to
* @returns Promise resolving when the cursor has reached the given column coordinate
*/
async moveCursorToColumn(inputArea, column) {
const coordinates = await this.getCoordinates();
const columnGap = coordinates[1] - column;
const columnKey = columnGap >= 0 ? selenium_webdriver_1.Key.LEFT : selenium_webdriver_1.Key.RIGHT;
for (let i = 0; i < Math.abs(columnGap); i++) {
if (await this.isColumn(column)) {
break;
}
await inputArea.getDriver().actions().clear();
await inputArea.sendKeys(columnKey);
await inputArea.getDriver().sleep(50);
if ((await this.getCoordinates())[0] !== coordinates[0]) {
throw new Error(`Column number ${column} is not accessible on line ${coordinates[0]}`);
}
}
}
/**
* (private) Check if the cursor is already on requested line
* @param line line number to check against current cursor position
* @returns true / false
*/
async isLine(line) {
const actualCoordinates = await this.getCoordinates();
if (actualCoordinates[0] === line) {
return true;
}
return false;
}
/**
* (private) Check if the cursor is already on requested column
* @param column column number to check against current cursor position
* @returns true / false
*/
async isColumn(column) {
const actualCoordinates = await this.getCoordinates();
if (actualCoordinates[1] === column) {
return true;
}
return false;
}
/**
* (private) Dynamic waiting for cursor position movements
* @param line line number to wait
* @param column column number to wait
* @param timeout default timeout
*/
async waitForCursorPositionAt(line, column, timeout = 2_500) {
(await this.waitForCursorPositionAtLine(line, timeout)) && (await this.waitForCursorPositionAtColumn(column, timeout));
}
/**
* (private) Dynamic waiting for cursor position movements at line
* @param line line number to wait
* @param timeout
*/
async waitForCursorPositionAtLine(line, timeout) {
return await this.getDriver().wait(async () => {
return await this.isLine(line);
}, timeout, `Unable to set cursor at line ${line}`, 500);
}
/**
* (private) Dynamic waiting for cursor position movements at column
* @param column column number to wait
* @param timeout
*/
async waitForCursorPositionAtColumn(column, timeout) {
return await this.getDriver().wait(async () => {
return await this.isColumn(column);
}, timeout, `Unable to set cursor at column ${column}`, 500);
}
/**
* Get number of lines in the editor
* @returns Promise resolving to number of lines
*/
async getNumberOfLines() {
const lines = (await this.getText()).split('\n');
return lines.length;
}
/**
* Use the built-in 'Format Document' option to format the text
* @returns Promise resolving when the Format Document command is invoked
*/
async formatDocument() {
const menu = await this.openContextMenu();
try {
await menu.select('Format Document');
}
catch (err) {
console.log('Warn: Format Document not available for selected language');
if (await menu.isDisplayed()) {
await menu.close();
}
}
}
async openContextMenu() {
await this.getDriver().actions().contextClick(this).perform();
const shadowRootHost = await this.enclosingItem.findElements(TextEditor.locators.TextEditor.shadowRootHost);
if (shadowRootHost.length > 0) {
let shadowRoot;
const webdriverCapabilities = await this.getDriver().getCapabilities();
const chromiumVersion = webdriverCapabilities.getBrowserVersion();
if (chromiumVersion && parseInt(chromiumVersion.split('.')[0]) >= 96) {
shadowRoot = await shadowRootHost[0].getShadowRoot();
return new __1.ContextMenu(await shadowRoot.findElement(TextEditor.locators.TextEditor.monacoMenuContainer)).wait();
}
else {
shadowRoot = (await this.getDriver().executeScript('return arguments[0].shadowRoot', shadowRootHost[0]));
return new __1.ContextMenu(shadowRoot).wait();
}
}
return await super.openContextMenu();
}
/**
* Get the cursor's coordinates as an array of two numbers: `[line, column]`
*
* **Caution** line & column coordinates do not start at `0` but at `1`!
*/
async getCoordinates() {
const coords = [];
const statusBar = new StatusBar_1.StatusBar();
const coordinates = (await statusBar.getCurrentPosition()).match(/\d+/g);
for (const c of coordinates) {
coords.push(+c);
}
return [coords[0], coords[1]];
}
/**
* Toggle breakpoint on a given line
*
* @param line target line number
* @returns promise resolving to True when a breakpoint was added, False when removed
*/
async toggleBreakpoint(line) {
const margin = await this.findElement(TextEditor.locators.TextEditor.marginArea);
const lineNum = await margin.findElement(TextEditor.locators.TextEditor.lineNumber(line));
await this.getDriver().actions().move({ origin: lineNum }).perform();
const lineOverlay = await margin.findElement(TextEditor.locators.TextEditor.lineOverlay(line));
const breakpointContainer = (0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0')
? await this.findElement(TextEditor.locators.TextEditor.glyphMarginWidget)
: lineOverlay;
const breakPoint = await breakpointContainer.findElements(TextEditor.locators.TextEditor.breakpoint.generalSelector);
if (breakPoint.length > 0) {
if (this.breakPoints.indexOf(line) !== -1) {
await breakPoint[this.breakPoints.indexOf(line)].click();
await new Promise((res) => setTimeout(res, 200));
this.breakPoints.splice(this.breakPoints.indexOf(line), 1);
return false;
}
}
const noBreak = await breakpointContainer.findElements(TextEditor.locators.TextEditor.debugHint);
if (noBreak.length > 0) {
await noBreak[0].click();
await new Promise((res) => setTimeout(res, 200));
this.breakPoints.push(line);
return true;
}
return false;
}
/**
* Get paused breakpoint if available. Otherwise, return undefined.
* @returns promise which resolves to either Breakpoint page object or undefined
*/
async getPausedBreakpoint() {
const breakpointLocators = Breakpoint_1.Breakpoint.locators.TextEditor.breakpoint;
const breakpointContainer = (0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0')
? await this.findElement(TextEditor.locators.TextEditor.glyphMarginWidget)
: this;
const breakpoints = await breakpointContainer.findElements(breakpointLocators.pauseSelector);
if (breakpoints.length === 0) {
return undefined;
}
if (breakpoints.length > 1) {
throw new BreakpointError(`unexpected number of paused breakpoints: ${breakpoints.length}; expected 1 at most`);
}
// get parent
let lineElement;
if ((0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0')) {
const styleTopAttr = await breakpoints[0].getCssValue('top');
lineElement = await this.findElement(TextEditor.locators.TextEditor.marginArea).findElement(TextEditor.locators.TextEditor.lineElement(styleTopAttr));
}
else {
lineElement = await breakpoints[0].findElement(TextEditor.locators.TextEditor.elementLevelBack);
}
return new Breakpoint_1.Breakpoint(breakpoints[0], lineElement);
}
/**
* Get paused breakpoint on line if available. Otherwise, return undefined.
* @param line number of the line to retrieve
* @returns promise which resolves to either Breakpoint page object or undefined
*/
async getBreakpoint(line) {
const breakpoints = await this.getBreakpoints();
for (const breakpoint of breakpoints) {
if ((await breakpoint.getLineNumber()) === line) {
return breakpoint;
}
}
return undefined;
}
/**
* Get all breakpoints.
* @returns List of Breakpoints.
*/
async getBreakpoints() {
const breakpoints = [];
const breakpointLocators = Breakpoint_1.Breakpoint.locators.TextEditor.breakpoint;
const breakpointContainer = (0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0')
? await this.findElement(TextEditor.locators.TextEditor.glyphMarginWidget)
: this;
const breakpointsSelectors = await breakpointContainer.findElements(breakpointLocators.generalSelector);
for (const breakpointSelector of breakpointsSelectors) {
let lineElement;
if ((0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0')) {
const styleTopAttr = await breakpointSelector.getCssValue('top');
lineElement = await this.findElement(TextEditor.locators.TextEditor.marginArea).findElement(TextEditor.locators.TextEditor.lineElement(styleTopAttr));
}
else {
lineElement = await breakpointSelector.findElement(TextEditor.locators.TextEditor.elementLevelBack);
}
breakpoints.push(new Breakpoint_1.Breakpoint(breakpointSelector, lineElement));
}
return breakpoints;
}
/**
* Get all code lenses within the editor
* @returns list of CodeLens page objects
*/
async getCodeLenses() {
const lenses = [];
const widgets = await this.findElement(TextEditor.locators.TextEditor.contentWidgets);
const items = await widgets.findElements(TextEditor.locators.TextEditor.contentWidgetsElements);
for (const item of items) {
lenses.push(await new CodeLens(item, this).wait());
}
return lenses;
}
/**
* Get a code lens based on title, or zero based index
*
* @param indexOrTitle zero based index (counting from the top of the editor), or partial title of the code lens
* @returns CodeLens object if such a code lens exists, undefined otherwise
*/
async getCodeLens(indexOrTitle) {
const lenses = await this.getCodeLenses();
if (typeof indexOrTitle === 'string') {
for (const lens of lenses) {
const title = await lens.getText();
const match = title.match(indexOrTitle);
if (match && match.length > 0) {
return lens;
}
}
}
else if (lenses[indexOrTitle]) {
return lenses[indexOrTitle];
}
return undefined;
}
}
exports.TextEditor = TextEditor;
/**
* Text selection block
*/
class Selection extends ElementWithContextMenu_1.ElementWithContextMenu {
constructor(el, editor) {
super(el, editor);
}
async openContextMenu() {
const ed = this.getEnclosingElement();
await this.getDriver().actions().contextClick(this).perform();
const shadowRootHost = await ed.getEnclosingElement().findElements(TextEditor.locators.TextEditor.shadowRootHost);
if (shadowRootHost.length > 0) {
let shadowRoot;
const webdriverCapabilities = await this.getDriver().getCapabilities();
const chromiumVersion = webdriverCapabilities.getBrowserVersion();
if (chromiumVersion && parseInt(chromiumVersion.split('.')[0]) >= 96) {
shadowRoot = await shadowRootHost[0].getShadowRoot();
return new __1.ContextMenu(await shadowRoot.findElement(TextEditor.locators.TextEditor.monacoMenuContainer)).wait();
}
else {
shadowRoot = (await this.getDriver().executeScript('return arguments[0].shadowRoot', shadowRootHost[0]));
return new __1.ContextMenu(shadowRoot).wait();
}
}
return await super.openContextMenu();
}
}
/**
* Page object for Code Lens inside a text editor
*/
class CodeLens extends AbstractElement_1.AbstractElement {
/**
* Get tooltip of the code lens
* @returns tooltip as string
*/
async getTooltip() {
return await this.getAttribute('title');
}
}
exports.CodeLens = CodeLens;
/**
* Text Editor's Find Widget
*/
class FindWidget extends AbstractElement_1.AbstractElement {
constructor(element, editor) {
super(element, editor);
}
/**
* Toggle between find and replace mode
* @param replace true for replace, false for find
*/
async toggleReplace(replace) {
const btn = await this.findElement(FindWidget.locators.FindWidget.toggleReplace);
const klass = await btn.getAttribute('class');
if ((replace && klass.includes('collapsed')) || (!replace && !klass.includes('collapsed'))) {
await btn.sendKeys(selenium_webdriver_1.Key.SPACE);
const repl = await this.getDriver().wait(selenium_webdriver_1.until.elementLocated(FindWidget.locators.FindWidget.replacePart), 2000);
if (replace) {
await this.getDriver().wait(selenium_webdriver_1.until.elementIsVisible(repl), 2000);
}
else {
await this.getDriver().wait(selenium_webdriver_1.until.elementIsNotVisible(repl), 2000);
}
}
}
/**
* Set text in the search box
* @param text text to fill in
*/
async setSearchText(text) {
const findPart = await this.findElement(FindWidget.locators.FindWidget.findPart);
await this.setText(text, findPart);
}
/**
* Get text from Find input box
* @returns value of find input as string
*/
async getSearchText() {
const findPart = await this.findElement(FindWidget.locators.FindWidget.findPart);
return await this.getInputText(findPart);
}
/**
* Set text in the replace box. Will toggle replace mode on if called in find mode.
* @param text text to fill in
*/
async setReplaceText(text) {
await this.toggleReplace(true);
const replacePart = await this.findElement(FindWidget.locators.FindWidget.replacePart);
await this.setText(text, replacePart);
}
/**
* Get text from Replace input box
* @returns value of replace input as string
*/
async getReplaceText() {
const replacePart = await this.findElement(FindWidget.locators.FindWidget.replacePart);
return await this.getInputText(replacePart);
}
/**
* Click 'Next match'
*/
async nextMatch() {
await this.clickButton(FindWidget.locators.FindWidget.nextMatch, 'find');
}
/**
* Click 'Previous match'
*/
async previousMatch() {
await this.clickButton(FindWidget.locators.FindWidget.previousMatch, 'find');
}
/**
* Click 'Replace'. Only works in replace mode.
*/
async replace() {
await this.clickButton('Replace', 'replace');
}
/**
* Click 'Replace All'. Only works in replace mode.
*/
async replaceAll() {
await this.clickButton('Replace All', 'replace');
}
/**
* Close the widget.
*/
async close() {
const part = (0, compare_versions_1.satisfies)(TextEditor.versionInfo.version, '>=1.80.0') ? 'close' : 'find';
await this.clickButton('Close', part);
}
/**
* Get the number of results as an ordered pair of numbers
* @returns pair in form of [current result index, total number of results]
*/
async getResultCount() {
const count = await this.findElement(FindWidget.locators.FindWidget.matchCount);
const text = await count.getText();
if (text.includes('No results')) {
return [0, 0];
}
const numbers = text.split(' of ');
return [+numbers[0], +numbers[1]];
}
/**
* Toggle the search to match case
* @param toggle true to turn on, false to turn off
*/
async toggleMatchCase(toggle) {
await this.toggleControl('Match Case', 'find', toggle);
}
/**
* Toggle the search to match whole words
* @param toggle true to turn on, false to turn off
*/
async toggleMatchWholeWord(toggle) {
await this.toggleControl('Match Whole Word', 'find', toggle);
}
/**
* Toggle the search to use regular expressions
* @param toggle true to turn on, false to turn off
*/
async toggleUseRegularExpression(toggle) {
await this.toggleControl('Use Regular Expression', 'find', toggle);
}
/**
* Toggle the replace to preserve case
* @param toggle true to turn on, false to turn off
*/
async togglePreserveCase(toggle) {
await this.toggleControl('Preserve Case', 'replace', toggle);
}
async toggleControl(title, part, toggle) {
let element;
if (part === 'find') {
element = await this.findElement(FindWidget.locators.FindWidget.findPart);
}
if (part === 'replace') {
element = await this.findElement(FindWidget.locators.FindWidget.replacePart);
await this.toggleReplace(true);
}
const control = await element.findElement(FindWidget.locators.FindWidget.checkbox(title));
const checked = await control.getAttribute('aria-checked');
if ((toggle && checked !== 'true') || (!toggle && checked === 'true')) {
await control.click();
}
}
async clickButton(title, part) {
let element;
if (part === 'find') {
element = await this.findElement(FindWidget.locators.FindWidget.findPart);
}
if (part === 'replace') {
element = await this.findElement(FindWidget.locators.FindWidget.replacePart);
await this.toggleReplace(true);
}
if (part === 'close') {
element = this;
}
const btn = await element.findElement(FindWidget.locators.FindWidget.button(title));
await btn.click();
await this.getDriver().sleep(100);
}
async setText(text, composite) {
const input = await composite.findElement(FindWidget.locators.FindWidget.input);
await input.clear();
await input.sendKeys(text);
}
async getInputText(composite) {
const input = await composite.findElement(FindWidget.locators.FindWidget.content);
return await input.getAttribute('innerHTML');
}
}
exports.FindWidget = FindWidget;
//# sourceMappingURL=TextEditor.js.map