Skip to content

Commit

Permalink
feat(core): click verification modes
Browse files Browse the repository at this point in the history
  • Loading branch information
blakebyrnes committed Jan 3, 2022
1 parent 6ff62f4 commit bbfffde
Show file tree
Hide file tree
Showing 27 changed files with 1,342 additions and 887 deletions.
50 changes: 28 additions & 22 deletions client/interfaces/IInteractions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ISuperElement, ISuperNode } from "awaited-dom/base/interfaces/super";
import { IMousePositionXY } from "@ulixee/hero-interfaces/IInteractions";
import { IKeyboardKeyCode } from "@ulixee/hero-interfaces/IKeyboardLayoutUS";
import { IKeyboardKeyCode } from '@ulixee/hero-interfaces/IKeyboardLayoutUS';
import {
IElementInteractVerification,
IMousePositionXY,
} from '@ulixee/hero-interfaces/IInteractions';
import { ISuperElement, ISuperNode } from 'awaited-dom/base/interfaces/super';

export type IInteraction = ICommand | ICommandDetailed;
type IInteractions = IInteraction[];
Expand Down Expand Up @@ -44,24 +47,24 @@ export enum Command {
export type ICommand = keyof typeof Command;

export interface ICommandDetailed {
[Command.scroll]?: IMousePosition;
[Command.move]?: IMousePosition;
[Command.click]?: IMousePosition;
[Command.clickLeft]?: IMousePosition;
[Command.clickMiddle]?: IMousePosition;
[Command.clickRight]?: IMousePosition;
[Command.doubleclick]?: IMousePosition;
[Command.doubleclickLeft]?: IMousePosition;
[Command.doubleclickMiddle]?: IMousePosition;
[Command.doubleclickRight]?: IMousePosition;
[Command.clickUp]?: IMousePosition;
[Command.clickUpLeft]?: IMousePosition;
[Command.clickUpMiddle]?: IMousePosition;
[Command.clickUpRight]?: IMousePosition;
[Command.clickDown]?: IMousePosition;
[Command.clickDownLeft]?: IMousePosition;
[Command.clickDownMiddle]?: IMousePosition;
[Command.clickDownRight]?: IMousePosition;
[Command.scroll]?: IMousePositionXY | ISuperElement;
[Command.move]?: IMousePositionXY | ISuperElement;
[Command.click]?: IMousePositionXY | ISuperElement | ISuperElementWithVerification;
[Command.clickLeft]?: IMousePositionXY | ISuperElement;
[Command.clickMiddle]?: IMousePositionXY | ISuperElement;
[Command.clickRight]?: IMousePositionXY | ISuperElement;
[Command.doubleclick]?: IMousePositionXY | ISuperElement | ISuperElementWithVerification;
[Command.doubleclickLeft]?: IMousePositionXY | ISuperElement;
[Command.doubleclickMiddle]?: IMousePositionXY | ISuperElement;
[Command.doubleclickRight]?: IMousePositionXY | ISuperElement;
[Command.clickUp]?: IMousePositionXY | ISuperElement;
[Command.clickUpLeft]?: IMousePositionXY | ISuperElement;
[Command.clickUpMiddle]?: IMousePositionXY | ISuperElement;
[Command.clickUpRight]?: IMousePositionXY | ISuperElement;
[Command.clickDown]?: IMousePositionXY | ISuperElement;
[Command.clickDownLeft]?: IMousePositionXY | ISuperElement;
[Command.clickDownMiddle]?: IMousePositionXY | ISuperElement;
[Command.clickDownRight]?: IMousePositionXY | ISuperElement;

[Command.type]?: ITypeInteraction;
[Command.keyPress]?: IKeyboardKeyCode;
Expand All @@ -75,4 +78,7 @@ export interface ICommandDetailed {

export type ITypeInteraction = string | IKeyboardKeyCode;

export type IMousePosition = IMousePositionXY | ISuperElement;
export type ISuperElementWithVerification = {
element: ISuperElement;
verification: IElementInteractVerification;
};
39 changes: 29 additions & 10 deletions client/lib/DomExtender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@ import { ITypeInteraction } from '../interfaces/IInteractions';
import Interactor from './Interactor';
import { INodeVisibility } from '@ulixee/hero-interfaces/INodeVisibility';
import CoreFrameEnvironment from './CoreFrameEnvironment';
import { createInstanceWithNodePointer } from './SetupAwaitedHandler';
import AwaitedPath from 'awaited-dom/base/AwaitedPath';
import IAwaitedOptions from '../interfaces/IAwaitedOptions';
import INodePointer from 'awaited-dom/base/INodePointer';
import { IElementInteractVerification } from '@ulixee/hero-interfaces/IInteractions';

const { getState } = StateMachine<ISuperElement, ISuperElementProperties>();
const awaitedPathState = StateMachine<
any,
{ awaitedPath: AwaitedPath; awaitedOptions: IAwaitedOptions; nodePointer?: INodePointer }
>();

interface IBaseExtend {
$click: () => Promise<void>;
$click: (verification?: IElementInteractVerification) => Promise<void>;
$type: (...typeInteractions: ITypeInteraction[]) => Promise<void>;
$waitForVisible: () => Promise<void>;
$waitForVisible: (timeoutMs?: number) => Promise<ISuperElement>;
$getComputedVisibility: () => Promise<INodeVisibility>;
}

Expand All @@ -38,11 +47,11 @@ for (const Item of [SuperElement, SuperNode, SuperHTMLElement, Element, Node, HT
enumerable: false,
configurable: false,
writable: false,
async value(): Promise<void> {
async value(verification: IElementInteractVerification = 'elementAtPath'): Promise<void> {
const { awaitedOptions } = getState(this);
const coreFrame: CoreFrameEnvironment = await awaitedOptions?.coreFrame;
await Interactor.run(coreFrame, [{ click: this }]);
}
await Interactor.run(coreFrame, [{ click: { element: this, verification } }]);
},
});

void Object.defineProperty(Item.prototype, '$type', {
Expand All @@ -57,18 +66,28 @@ for (const Item of [SuperElement, SuperNode, SuperHTMLElement, Element, Node, HT
coreFrame,
typeInteractions.map(t => ({ type: t })),
);
}
},
});

void Object.defineProperty(Item.prototype, '$waitForVisible', {
enumerable: false,
configurable: false,
writable: false,
async value(): Promise<void> {
async value(timeoutMs?: number): Promise<ISuperElement> {
const { awaitedPath, awaitedOptions } = getState(this);
const coreFrame: CoreFrameEnvironment = await awaitedOptions?.coreFrame;
await coreFrame.waitForElement(awaitedPath.toJSON(), { waitForVisible: true });
}
const nodePointer = await coreFrame.waitForElement(awaitedPath.toJSON(), {
waitForVisible: true,
timeoutMs,
});
if (!nodePointer) return null;
return createInstanceWithNodePointer(
awaitedPathState,
awaitedPath,
awaitedOptions,
nodePointer,
);
},
});

void Object.defineProperty(Item.prototype, '$getComputedVisibility', {
Expand All @@ -79,6 +98,6 @@ for (const Item of [SuperElement, SuperNode, SuperHTMLElement, Element, Node, HT
const { awaitedOptions } = getState(this);
const coreFrame: CoreFrameEnvironment = await awaitedOptions?.coreFrame;
await coreFrame.getComputedVisibility(this);
}
},
});
}
13 changes: 8 additions & 5 deletions client/lib/FrameEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ import Hero, { IState as IHeroState } from './Hero';
import { createInstanceWithNodePointer, getAwaitedPathAsMethodArg } from './SetupAwaitedHandler';
import CoreFrameEnvironment from './CoreFrameEnvironment';
import Tab, { IState as ITabState } from './Tab';
import { IMousePosition } from '../interfaces/IInteractions';
import Resource, { createResource } from './Resource';
import IMagicSelectorOptions from '@ulixee/hero-interfaces/IMagicSelectorOptions';
import { runMagicSelector, runMagicSelectorAll } from '@ulixee/hero-interfaces/jsPathFnNames';
import {
runMagicSelectorFnName,
runMagicSelectorAllFnName,
} from '@ulixee/hero-interfaces/jsPathFnNames';
import { IMousePositionXY } from '@ulixee/hero-interfaces/IInteractions';

const { getState, setState } = StateMachine<FrameEnvironment, IState>();
const { getState: getTabState } = StateMachine<Tab, ITabState>();
Expand Down Expand Up @@ -215,13 +218,13 @@ export default class FrameEnvironment {
}

public magicSelector(selectorOrOptions?: string | IMagicSelectorOptions): ISuperNode {
const awaitedPath = new AwaitedPath(null, [runMagicSelector, selectorOrOptions]);
const awaitedPath = new AwaitedPath(null, [runMagicSelectorFnName, selectorOrOptions]);
const awaitedOptions: IAwaitedOptions = { coreFrame: getState(this).coreFrame };
return createSuperNode(awaitedPath, awaitedOptions);
}

public magicSelectorAll(selectorOrOptions?: string | IMagicSelectorOptions): ISuperNodeList {
const awaitedPath = new AwaitedPath(null, [runMagicSelectorAll, selectorOrOptions]);
const awaitedPath = new AwaitedPath(null, [runMagicSelectorAllFnName, selectorOrOptions]);
const awaitedOptions: IAwaitedOptions = { coreFrame: getState(this).coreFrame };
return createSuperNodeList(awaitedPath, awaitedOptions);
}
Expand Down Expand Up @@ -287,7 +290,7 @@ export function getCoreFrameEnvironment(
}

export function getCoreFrameEnvironmentForPosition(
mousePosition: IMousePosition,
mousePosition: IMousePositionXY | ISuperElement,
): Promise<CoreFrameEnvironment> {
const state = awaitedPathState.getState(mousePosition);
if (!state) return;
Expand Down
22 changes: 18 additions & 4 deletions client/lib/Hero.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ import requirePlugins from '@ulixee/hero-plugin-utils/lib/utils/requirePlugins';
import filterPlugins from '@ulixee/hero-plugin-utils/lib/utils/filterPlugins';
import extractPlugins from '@ulixee/hero-plugin-utils/lib/utils/extractPlugins';
import { IPluginClass } from '@ulixee/hero-interfaces/IPlugin';
import {
IElementInteractVerification,
IMousePositionXY,
isMousePositionXY,
} from '@ulixee/hero-interfaces/IInteractions';
import WebsocketResource from './WebsocketResource';
import IWaitForResourceFilter from '../interfaces/IWaitForResourceFilter';
import Resource from './Resource';
import Interactor from './Interactor';
import IInteractions, {
Command,
IMousePosition,
IInteraction,
ITypeInteraction,
} from '../interfaces/IInteractions';
import Tab, { createTab, getCoreTab } from './Tab';
Expand Down Expand Up @@ -265,10 +270,19 @@ export default class Hero extends AwaitedEventTarget<{

// INTERACT METHODS

public async click(mousePosition: IMousePosition): Promise<void> {
public async click(
mousePosition: IMousePositionXY | ISuperElement,
clickVerification: IElementInteractVerification = 'elementAtPath',
): Promise<void> {
let coreFrame = await getCoreFrameEnvironmentForPosition(mousePosition);
coreFrame ??= await getCoreFrameEnvironment(this.activeTab.mainFrameEnvironment);
await Interactor.run(coreFrame, [{ click: mousePosition }]);
let interaction: IInteraction = { click: mousePosition };
if (!isMousePositionXY(mousePosition)) {
interaction = {
click: { element: mousePosition as ISuperElement, verification: clickVerification },
};
}
await Interactor.run(coreFrame, [interaction]);
}

public async getFrameEnvironment(
Expand All @@ -284,7 +298,7 @@ export default class Hero extends AwaitedEventTarget<{
await Interactor.run(coreFrame, interactions);
}

public async scrollTo(mousePosition: IMousePosition): Promise<void> {
public async scrollTo(mousePosition: IMousePositionXY | ISuperElement): Promise<void> {
let coreFrame = await getCoreFrameEnvironmentForPosition(mousePosition);
coreFrame ??= await getCoreFrameEnvironment(this.activeTab.mainFrameEnvironment);
await Interactor.run(coreFrame, [{ [Command.scroll]: mousePosition }]);
Expand Down
Loading

0 comments on commit bbfffde

Please sign in to comment.