Skip to content

Commit 1bec22a

Browse files
committed
fix(core): update attachedstate to nodepointer
feat: getComputedVisibility(node|element)
1 parent 8037c64 commit 1bec22a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1025
-719
lines changed

client/lib/Agent.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import IWaitForElementOptions from '@secret-agent/interfaces/IWaitForElementOpti
1515
import { ILocationTrigger } from '@secret-agent/interfaces/Location';
1616
import Request from 'awaited-dom/impl/official-klasses/Request';
1717
import IWaitForOptions from '@secret-agent/interfaces/IWaitForOptions';
18-
import { IElementIsolate } from 'awaited-dom/base/interfaces/isolate';
18+
import { IElementIsolate, INodeIsolate } from 'awaited-dom/base/interfaces/isolate';
1919
import CSSStyleDeclaration from 'awaited-dom/impl/official-klasses/CSSStyleDeclaration';
2020
import IAgentMeta from '@secret-agent/interfaces/IAgentMeta';
2121
import IScreenshotOptions from '@secret-agent/interfaces/IScreenshotOptions';
22+
import { INodeVisibility } from '@secret-agent/interfaces/INodeVisibility';
2223
import WebsocketResource from './WebsocketResource';
2324
import IWaitForResourceFilter from '../interfaces/IWaitForResourceFilter';
2425
import Resource from './Resource';
@@ -277,12 +278,17 @@ export default class Agent extends AwaitedEventTarget<{ close: void }> {
277278
return this.activeTab.getComputedStyle(element, pseudoElement);
278279
}
279280

281+
public getComputedVisibility(node: INodeIsolate): Promise<INodeVisibility> {
282+
return this.activeTab.getComputedVisibility(node);
283+
}
284+
280285
public getJsValue<T>(path: string): Promise<T> {
281286
return this.activeTab.getJsValue<T>(path);
282287
}
283288

284-
public isElementVisible(element: IElementIsolate): Promise<boolean> {
285-
return this.activeTab.isElementVisible(element);
289+
// @deprecated 2021-04-30: Replaced with getComputedVisibility
290+
public async isElementVisible(element: IElementIsolate): Promise<boolean> {
291+
return await this.getComputedVisibility(element as any).then(x => x.isVisible);
286292
}
287293

288294
public takeScreenshot(options?: IScreenshotOptions): Promise<Buffer> {

client/lib/CoreFrameEnvironment.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { ICookie } from '@secret-agent/interfaces/ICookie';
66
import IWaitForElementOptions from '@secret-agent/interfaces/IWaitForElementOptions';
77
import IExecJsPathResult from '@secret-agent/interfaces/IExecJsPathResult';
88
import { IRequestInit } from 'awaited-dom/base/interfaces/official';
9-
import IAttachedState from 'awaited-dom/base/IAttachedState';
9+
import INodePointer from 'awaited-dom/base/INodePointer';
1010
import ISetCookieOptions from '@secret-agent/interfaces/ISetCookieOptions';
1111
import IWaitForOptions from '@secret-agent/interfaces/IWaitForOptions';
1212
import IFrameMeta from '@secret-agent/interfaces/IFrameMeta';
13+
import { INodeVisibility } from '@secret-agent/interfaces/INodeVisibility';
1314
import CoreCommandQueue from './CoreCommandQueue';
1415

1516
export default class CoreFrameEnvironment {
@@ -48,11 +49,11 @@ export default class CoreFrameEnvironment {
4849
return await this.commandQueue.run('FrameEnvironment.getJsValue', expression);
4950
}
5051

51-
public async fetch(request: string | number, init?: IRequestInit): Promise<IAttachedState> {
52+
public async fetch(request: string | number, init?: IRequestInit): Promise<INodePointer> {
5253
return await this.commandQueue.run('FrameEnvironment.fetch', request, init);
5354
}
5455

55-
public async createRequest(input: string | number, init?: IRequestInit): Promise<IAttachedState> {
56+
public async createRequest(input: string | number, init?: IRequestInit): Promise<INodePointer> {
5657
return await this.commandQueue.run('FrameEnvironment.createRequest', input, init);
5758
}
5859

@@ -80,8 +81,8 @@ export default class CoreFrameEnvironment {
8081
return await this.commandQueue.run('FrameEnvironment.removeCookie', name);
8182
}
8283

83-
public async isElementVisible(jsPath: IJsPath): Promise<boolean> {
84-
return await this.commandQueue.run('FrameEnvironment.isElementVisible', jsPath);
84+
public async getComputedVisibility(jsPath: IJsPath): Promise<INodeVisibility> {
85+
return await this.commandQueue.run('FrameEnvironment.getComputedVisibility', jsPath);
8586
}
8687

8788
public async waitForElement(jsPath: IJsPath, opts: IWaitForElementOptions): Promise<void> {

client/lib/FrameEnvironment.ts

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import { ILocationTrigger, LocationStatus } from '@secret-agent/interfaces/Locat
1717
import IWaitForElementOptions from '@secret-agent/interfaces/IWaitForElementOptions';
1818
import Response from 'awaited-dom/impl/official-klasses/Response';
1919
import IWaitForOptions from '@secret-agent/interfaces/IWaitForOptions';
20-
import { IElementIsolate } from 'awaited-dom/base/interfaces/isolate';
20+
import { IElementIsolate, INodeIsolate } from 'awaited-dom/base/interfaces/isolate';
21+
import { INodeVisibility } from '@secret-agent/interfaces/INodeVisibility';
2122
import IAwaitedOptions from '../interfaces/IAwaitedOptions';
2223
import RequestGenerator, { getRequestIdOrUrl } from './Request';
2324
import CookieStorage, { createCookieStorage } from './CookieStorage';
@@ -89,19 +90,19 @@ export default class FrameEnvironment {
8990
}
9091

9192
public get document(): SuperDocument {
92-
const awaitedPath = new AwaitedPath('document');
93+
const awaitedPath = new AwaitedPath(null, 'document');
9394
const awaitedOptions = { ...getState(this) };
9495
return createSuperDocument<IAwaitedOptions>(awaitedPath, awaitedOptions) as SuperDocument;
9596
}
9697

9798
public get localStorage(): Storage {
98-
const awaitedPath = new AwaitedPath('localStorage');
99+
const awaitedPath = new AwaitedPath(null, 'localStorage');
99100
const awaitedOptions = { ...getState(this) };
100101
return createStorage<IAwaitedOptions>(awaitedPath, awaitedOptions) as Storage;
101102
}
102103

103104
public get sessionStorage(): Storage {
104-
const awaitedPath = new AwaitedPath('sessionStorage');
105+
const awaitedPath = new AwaitedPath(null, 'sessionStorage');
105106
const awaitedOptions = { ...getState(this) };
106107
return createStorage<IAwaitedOptions>(awaitedPath, awaitedOptions) as Storage;
107108
}
@@ -115,9 +116,9 @@ export default class FrameEnvironment {
115116
public async fetch(request: Request | string, init?: IRequestInit): Promise<Response> {
116117
const requestInput = await getRequestIdOrUrl(request);
117118
const coreFrame = await getCoreFrameEnvironment(this);
118-
const attachedState = await coreFrame.fetch(requestInput, init);
119+
const nodePointer = await coreFrame.fetch(requestInput, init);
119120

120-
const awaitedPath = new AwaitedPath().withAttachedId(attachedState.id);
121+
const awaitedPath = new AwaitedPath(null).withNodeId(null, nodePointer.id);
121122
return createResponse(awaitedPath, { ...getState(this) });
122123
}
123124

@@ -128,7 +129,7 @@ export default class FrameEnvironment {
128129

129130
public getComputedStyle(element: IElementIsolate, pseudoElement?: string): CSSStyleDeclaration {
130131
const { awaitedPath: elementAwaitedPath } = awaitedPathState.getState(element);
131-
const awaitedPath = new AwaitedPath('window', [
132+
const awaitedPath = new AwaitedPath(null, 'window', [
132133
'getComputedStyle',
133134
getAwaitedPathAsMethodArg(elementAwaitedPath),
134135
pseudoElement,
@@ -140,15 +141,21 @@ export default class FrameEnvironment {
140141
) as CSSStyleDeclaration;
141142
}
142143

143-
public async getJsValue<T>(path: string): Promise<T> {
144+
public async getComputedVisibility(node: INodeIsolate): Promise<INodeVisibility> {
145+
if (!node) return { isVisible: false, nodeExists: false };
146+
const { awaitedPath } = awaitedPathState.getState(node);
144147
const coreFrame = await getCoreFrameEnvironment(this);
145-
return coreFrame.getJsValue<T>(path);
148+
return coreFrame.getComputedVisibility(awaitedPath.toJSON());
146149
}
147150

151+
// @deprecated 2021-04-30: Replaced with getComputedVisibility
148152
public async isElementVisible(element: IElementIsolate): Promise<boolean> {
149-
const { awaitedPath } = awaitedPathState.getState(element);
153+
return await this.getComputedVisibility(element as any).then(x => x.isVisible);
154+
}
155+
156+
public async getJsValue<T>(path: string): Promise<T> {
150157
const coreFrame = await getCoreFrameEnvironment(this);
151-
return coreFrame.isElementVisible(awaitedPath.toJSON());
158+
return coreFrame.getJsValue<T>(path);
152159
}
153160

154161
public async waitForPaintingStable(options?: IWaitForOptions): Promise<void> {
@@ -165,6 +172,7 @@ export default class FrameEnvironment {
165172
element: ISuperElement,
166173
options?: IWaitForElementOptions,
167174
): Promise<void> {
175+
if (!element) throw new Error('Element being waited for is null');
168176
const { awaitedPath } = awaitedPathState.getState(element);
169177
const coreFrame = await getCoreFrameEnvironment(this);
170178
await coreFrame.waitForElement(awaitedPath.toJSON(), options);

client/lib/Request.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import FetchRequest from 'awaited-dom/impl/official-klasses/Request';
22
import AwaitedPath from 'awaited-dom/base/AwaitedPath';
33
import StateMachine from 'awaited-dom/base/StateMachine';
44
import { IRequestInfo, IRequestInit } from 'awaited-dom/base/interfaces/official';
5-
import IAttachedState from 'awaited-dom/base/IAttachedState';
5+
import INodePointer from 'awaited-dom/base/INodePointer';
66
import CoreFrameEnvironment from './CoreFrameEnvironment';
77

88
interface IState {
99
awaitedPath: AwaitedPath;
10-
attachedState: IAttachedState;
10+
nodePointer: INodePointer;
1111
remoteInitializerPromise: Promise<void>;
1212
coreFrame: Promise<CoreFrameEnvironment>;
1313
}
@@ -37,10 +37,10 @@ async function createRemoteInitializer(
3737
): Promise<void> {
3838
const requestInput = await getRequestIdOrUrl(input);
3939
const coreFrame = await coreFramePromise;
40-
const attachedState = await coreFrame.createRequest(requestInput, init);
41-
const awaitedPath = new AwaitedPath().withAttachedId(attachedState.id);
40+
const nodePointer = await coreFrame.createRequest(requestInput, init);
41+
const awaitedPath = new AwaitedPath(null).withNodeId(null, nodePointer.id);
4242
setState(instance, {
43-
attachedState,
43+
nodePointer,
4444
awaitedPath,
4545
});
4646
}

client/lib/SetupAwaitedHandler.ts

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
import AwaitedHandler, { NotImplementedError } from 'awaited-dom/base/AwaitedHandler';
22
import AwaitedPath, { IJsPath } from 'awaited-dom/base/AwaitedPath';
33
import Constructable from 'awaited-dom/base/Constructable';
4-
import IAttachedState from 'awaited-dom/base/IAttachedState';
4+
import INodePointer from 'awaited-dom/base/INodePointer';
55
import IExecJsPathResult from '@secret-agent/interfaces/IExecJsPathResult';
6-
import getAttachedStateFnName from '@secret-agent/interfaces/getAttachedStateFnName';
6+
import getNodePointerFnName from '@secret-agent/interfaces/getNodePointerFnName';
77
import IAwaitedOptions from '../interfaces/IAwaitedOptions';
88
import CoreFrameEnvironment from './CoreFrameEnvironment';
99

10-
// Sets up AwaitedHandler initializer hooks. See Noderdom/AwaitedDOM
11-
AwaitedHandler.delegate = {
10+
export const delegate = {
1211
getProperty,
1312
setProperty,
1413
construct,
1514
runMethod,
1615
runStatic,
17-
loadState,
16+
createNodePointer,
1817
};
1918

20-
export async function getProperty<T, TClass>(
19+
// Sets up AwaitedHandler initializer hooks. See Noderdom/AwaitedDOM
20+
AwaitedHandler.delegate = delegate;
21+
22+
async function getProperty<T, TClass>(
2123
self: AwaitedHandler<TClass>,
2224
instance: TClass,
2325
name: string,
2426
): Promise<T> {
25-
const state = self.getState(instance);
26-
await awaitRemoteInitializer(state);
27-
const awaitedPath = state.awaitedPath as AwaitedPath;
28-
const { coreFrame } = state.awaitedOptions as IAwaitedOptions;
29-
const awaitedCoreFrame = await coreFrame;
30-
const finalPath = awaitedPath.addProperty(name).toJSON();
31-
const result = await execJsPath<TClass, T>(self, awaitedCoreFrame, instance, finalPath);
27+
const { awaitedPath, coreFrame } = await getAwaitedState(self, instance);
28+
29+
const finalPath = awaitedPath.addProperty(instance as any, name);
30+
31+
const result = await execJsPath<TClass, T>(self, coreFrame, instance, finalPath.toJSON());
3232

3333
return cleanResult(self, instance, result);
3434
}
3535

36-
export async function setProperty<T, TClass>(
36+
async function setProperty<T, TClass>(
3737
self: AwaitedHandler<TClass>,
3838
instance: TClass,
3939
name: string,
@@ -43,50 +43,57 @@ export async function setProperty<T, TClass>(
4343
self.setState(instance, { [name]: value });
4444
}
4545

46-
export async function runMethod<T, TClass>(
46+
async function runMethod<T, TClass>(
4747
self: AwaitedHandler<TClass>,
4848
instance: TClass,
4949
name: string,
5050
args: any[],
5151
): Promise<T> {
52-
await awaitRemoteInitializer(instance);
53-
const state = self.getState(instance);
54-
const awaitedPath = state.awaitedPath as AwaitedPath;
55-
const { coreFrame } = state.awaitedOptions as IAwaitedOptions;
56-
const awaitedCoreFrame = await coreFrame;
57-
const finalPath = awaitedPath.addMethod(name, ...args).toJSON();
58-
const result = await execJsPath<TClass, T>(self, awaitedCoreFrame, instance, finalPath);
52+
const { awaitedPath, coreFrame } = await getAwaitedState(self, instance);
53+
const finalPath = awaitedPath.addMethod(instance as any, name, ...args);
54+
55+
const result = await execJsPath<TClass, T>(self, coreFrame, instance, finalPath.toJSON());
5956
return cleanResult(self, instance, result);
6057
}
6158

62-
export async function loadState<TClass>(
59+
async function createNodePointer<TClass>(
6360
self: AwaitedHandler<TClass>,
6461
instance: TClass,
65-
properties?: string[],
66-
): Promise<IAttachedState> {
67-
await awaitRemoteInitializer(instance);
68-
const state = self.getState(instance);
69-
const awaitedPath = state.awaitedPath as AwaitedPath;
70-
const { coreFrame } = state.awaitedOptions as IAwaitedOptions;
71-
const awaitedCoreFrame = await coreFrame;
72-
const finalPath = awaitedPath.addMethod(getAttachedStateFnName, properties).toJSON();
73-
const result = await execJsPath<TClass, null>(self, awaitedCoreFrame, instance, finalPath);
62+
): Promise<INodePointer> {
63+
const { awaitedPath, coreFrame } = await getAwaitedState(self, instance);
64+
const finalPath = awaitedPath.addMethod(instance as any, getNodePointerFnName).toJSON();
65+
const result = await execJsPath<TClass, null>(self, coreFrame, instance, finalPath);
7466

75-
return result?.attachedState as IAttachedState;
67+
return result?.nodePointer;
7668
}
7769

78-
export function runStatic<T, TClass>(
70+
function runStatic<T, TClass>(
7971
self: AwaitedHandler<TClass>,
8072
_klass: Constructable<TClass>,
8173
name: string,
8274
): T {
8375
throw new NotImplementedError(`${self.className}.${name} static method not implemented`);
8476
}
8577

86-
export function construct<TClass>(self: AwaitedHandler<TClass>): TClass {
78+
function construct<TClass>(self: AwaitedHandler<TClass>): TClass {
8779
throw new NotImplementedError(`${self.className} constructor not implemented`);
8880
}
8981

82+
async function getAwaitedState<TClass>(
83+
self: AwaitedHandler<TClass>,
84+
instance: TClass,
85+
): Promise<{
86+
awaitedPath: AwaitedPath;
87+
coreFrame: CoreFrameEnvironment;
88+
}> {
89+
await awaitRemoteInitializer(instance);
90+
const state = self.getState(instance);
91+
const awaitedPath = state.awaitedPath as AwaitedPath;
92+
const { coreFrame } = state.awaitedOptions as IAwaitedOptions;
93+
const awaitedCoreFrame = await coreFrame;
94+
return { awaitedPath, coreFrame: awaitedCoreFrame };
95+
}
96+
9097
export function getAwaitedPathAsMethodArg(awaitedPath: AwaitedPath): string {
9198
return `$$jsPath=${JSON.stringify(awaitedPath.toJSON())}`;
9299
}
@@ -121,12 +128,12 @@ function cleanResult<T, TClass>(
121128
result: IExecJsPathResult<T>,
122129
): T {
123130
if (!result) return null;
124-
if (!result?.attachedState) return result?.value;
125131

126-
self.setState(instance, {
127-
attachedState: result.attachedState,
128-
});
129-
delete result.attachedState;
132+
if (result.nodePointer) {
133+
self.setState(instance, {
134+
nodePointer: result.nodePointer,
135+
});
136+
}
130137

131138
return result.value;
132139
}

client/lib/Tab.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import IWaitForResourceOptions from '@secret-agent/interfaces/IWaitForResourceOp
1111
import IWaitForElementOptions from '@secret-agent/interfaces/IWaitForElementOptions';
1212
import Response from 'awaited-dom/impl/official-klasses/Response';
1313
import IWaitForOptions from '@secret-agent/interfaces/IWaitForOptions';
14-
import { IElementIsolate } from 'awaited-dom/base/interfaces/isolate';
14+
import { IElementIsolate, INodeIsolate } from 'awaited-dom/base/interfaces/isolate';
1515
import IScreenshotOptions from '@secret-agent/interfaces/IScreenshotOptions';
1616
import AwaitedPath from 'awaited-dom/base/AwaitedPath';
17+
import { INodeVisibility } from '@secret-agent/interfaces/INodeVisibility';
1718
import CoreTab from './CoreTab';
1819
import Resource, { createResource } from './Resource';
1920
import IWaitForResourceFilter from '../interfaces/IWaitForResourceFilter';
@@ -160,8 +161,13 @@ export default class Tab extends AwaitedEventTarget<IEventType> {
160161
return await this.mainFrameEnvironment.getJsValue(path);
161162
}
162163

164+
// @deprecated 2021-04-30: Replaced with getComputedVisibility
163165
public async isElementVisible(element: IElementIsolate): Promise<boolean> {
164-
return await this.mainFrameEnvironment.isElementVisible(element);
166+
return await this.getComputedVisibility(element as any).then(x => x.isVisible);
167+
}
168+
169+
public async getComputedVisibility(node: INodeIsolate): Promise<INodeVisibility> {
170+
return await this.mainFrameEnvironment.getComputedVisibility(node);
165171
}
166172

167173
public async takeScreenshot(options?: IScreenshotOptions): Promise<Buffer> {

client/lib/WebsocketResource.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function createWebsocketResource(
7979
const resource = new WebsocketResource();
8080
const request = createResourceRequest(coreTab, resourceMeta.id);
8181
const response = createResourceResponse(coreTab, resourceMeta.id);
82-
const awaitedPath = new AwaitedPath('resources', String(resourceMeta.id));
82+
const awaitedPath = new AwaitedPath(null, 'resources', String(resourceMeta.id));
8383
setState(resource, { coreTab, resource: resourceMeta, request, response, awaitedPath });
8484
return resource;
8585
}

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"@secret-agent/commons": "1.4.1-alpha.4",
1111
"@secret-agent/interfaces": "1.4.1-alpha.4",
1212
"@secret-agent/replay": "1.4.1-alpha.4",
13-
"awaited-dom": "1.1.12",
13+
"awaited-dom": "1.2.1",
1414
"uuid": "^8.3.2",
1515
"ws": "^7.4.4"
1616
},

0 commit comments

Comments
 (0)