Skip to content

Commit

Permalink
feat(protractor): support for parentElement.closestTo(childElement) API
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-molak committed Jul 17, 2023
1 parent ee1b3c4 commit ec21e18
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
Expand Up @@ -20,6 +20,10 @@ export class ProtractorPageElement extends PageElement<ElementFinder> {
return new ProtractorPageElement(this.locator.of(parent.locator));
}

closestTo(child: ProtractorPageElement): ProtractorPageElement {
return new ProtractorPageElement(this.locator.closestTo(child.locator));
}

async clearValue(): Promise<void> {
// eslint-disable-next-line unicorn/consistent-function-scoping
function times(length: number, key: string) {
Expand Down
@@ -1,12 +1,15 @@
import { LogicError } from '@serenity-js/core';
import type { PageElement, RootLocator, Selector } from '@serenity-js/web';
import { Locator } from '@serenity-js/web';
import type * as protractor from 'protractor';
import { ByCss, Locator } from '@serenity-js/web';
import * as protractor from 'protractor';

import { unpromisedWebElement } from '../../unpromisedWebElement';
import type { ProtractorErrorHandler } from '../ProtractorErrorHandler';
import { ProtractorPageElement } from '../ProtractorPageElement';
import type { ProtractorRootLocator } from './ProtractorRootLocator';
import { ProtractorSelectors } from './ProtractorSelectors';
import { WebElement } from 'selenium-webdriver';
import { promised } from '../../promised';

/**
* Protractor-specific implementation of {@apilink Locator}.
Expand Down Expand Up @@ -46,7 +49,7 @@ export class ProtractorLocator extends Locator<protractor.ElementFinder, protrac
}
}

private async resolveNativeElement(): Promise<protractor.ElementFinder> {
protected async resolveNativeElement(): Promise<protractor.ElementFinder> {
const parent = await this.parent.nativeElement();
const result = await unpromisedWebElement(parent.element(this.nativeSelector()));

Expand All @@ -65,7 +68,11 @@ export class ProtractorLocator extends Locator<protractor.ElementFinder, protrac
return new ProtractorLocator(parent, this.selector, this.errorHandler);
}

locate(child: ProtractorLocator): Locator<protractor.ElementFinder, any> {
closestTo(child: ProtractorLocator): Locator<protractor.ElementFinder, protractor.Locator> {
return new ProtractorParentElementLocator(this.parent, this.selector, child, this.errorHandler);
}

locate(child: ProtractorLocator): Locator<protractor.ElementFinder, protractor.Locator> {
return new ProtractorLocator(this, child.selector, this.errorHandler);
}

Expand Down Expand Up @@ -102,11 +109,39 @@ export class ProtractorExistingElementLocator extends ProtractorLocator {
super(parent, selector, errorHandler);
}

async nativeElement(): Promise<protractor.ElementFinder> {
override async nativeElement(): Promise<protractor.ElementFinder> {
return this.existingNativeElement;
}

async allNativeElements(): Promise<Array<protractor.ElementFinder>> {
override async allNativeElements(): Promise<Array<protractor.ElementFinder>> {
return [ this.existingNativeElement ];
}
}

class ProtractorParentElementLocator extends ProtractorLocator {
constructor(
parent: RootLocator<protractor.ElementFinder>,
selector: Selector,
private readonly child: ProtractorLocator,
errorHandler: ProtractorErrorHandler
) {
super(parent, selector, errorHandler);
}

protected async resolveNativeElement(): Promise<protractor.ElementFinder> {
const cssSelector = this.asCssSelector(this.selector);
const child = await this.child.nativeElement();

const webElement: WebElement = await child.getWebElement();

return await promised(webElement.getDriver().executeScript(
`return arguments[0].closest(arguments[1])`,
webElement,
cssSelector.value,
));
}

override async allNativeElements(): Promise<Array<protractor.ElementFinder>> {
return [ await this.nativeElement() ];
}
}

0 comments on commit ec21e18

Please sign in to comment.