Skip to content

Commit 2e2de6b

Browse files
committed
feat(client): get/set/delete cookies + domstorage
# Conflicts: # client/package.json # core-interfaces/package.json # core/package.json
1 parent 3bd89e3 commit 2e2de6b

36 files changed

+645
-151
lines changed

.github/workflows/lint-and-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474

7575
- uses: actions/setup-node@v1
7676
with:
77-
node-version: 12
77+
node-version: ${{ matrix.node-version }}
7878
- uses: actions/setup-go@v2
7979
with:
8080
go-version: 1.14

client/index.ts

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
11
// setup must go first
2-
import './lib/SetupAwaitedHandler';
3-
4-
import { ILocationTrigger, LocationStatus } from '@secret-agent/core-interfaces/Location';
5-
import IConfigureOptions from '@secret-agent/core-interfaces/IConfigureOptions';
6-
import { RenderingOption } from '@secret-agent/core-interfaces/ITabOptions';
7-
import os from 'os';
8-
import initializeConstantsAndProperties from 'awaited-dom/base/initializeConstantsAndProperties';
9-
import { IRequestInit } from 'awaited-dom/base/interfaces/official';
10-
import { ISuperElement } from 'awaited-dom/base/interfaces/super';
11-
import { ICookie } from '@secret-agent/core-interfaces/ICookie';
12-
import IDomStorage from '@secret-agent/core-interfaces/IDomStorage';
13-
import ISessionOptions from '@secret-agent/core-interfaces/ISessionOptions';
14-
import IUserProfile from '@secret-agent/core-interfaces/IUserProfile';
15-
import IWaitForResourceOptions from '@secret-agent/core-interfaces/IWaitForResourceOptions';
16-
import IWaitForElementOptions from '@secret-agent/core-interfaces/IWaitForElementOptions';
17-
import StateMachine from 'awaited-dom/base/StateMachine';
18-
import Request from 'awaited-dom/impl/official-klasses/Request';
19-
import { bindFunctions } from '@secret-agent/commons/utils';
20-
import ICreateSessionOptions from '@secret-agent/core-interfaces/ICreateSessionOptions';
21-
import ICreateSecretAgentOptions from './interfaces/ICreateSecretAgentOptions';
22-
import CoreClient from './lib/CoreClient';
2+
import "./lib/SetupAwaitedHandler";
3+
4+
import { ILocationTrigger, LocationStatus } from "@secret-agent/core-interfaces/Location";
5+
import IConfigureOptions from "@secret-agent/core-interfaces/IConfigureOptions";
6+
import { RenderingOption } from "@secret-agent/core-interfaces/ITabOptions";
7+
import os from "os";
8+
import initializeConstantsAndProperties from "awaited-dom/base/initializeConstantsAndProperties";
9+
import { IRequestInit } from "awaited-dom/base/interfaces/official";
10+
import { ISuperElement } from "awaited-dom/base/interfaces/super";
11+
import IDomStorage from "@secret-agent/core-interfaces/IDomStorage";
12+
import ISessionOptions from "@secret-agent/core-interfaces/ISessionOptions";
13+
import IUserProfile from "@secret-agent/core-interfaces/IUserProfile";
14+
import IWaitForResourceOptions from "@secret-agent/core-interfaces/IWaitForResourceOptions";
15+
import IWaitForElementOptions from "@secret-agent/core-interfaces/IWaitForElementOptions";
16+
import StateMachine from "awaited-dom/base/StateMachine";
17+
import Request from "awaited-dom/impl/official-klasses/Request";
18+
import { bindFunctions } from "@secret-agent/commons/utils";
19+
import ICreateSessionOptions from "@secret-agent/core-interfaces/ICreateSessionOptions";
20+
import ICreateSecretAgentOptions from "./interfaces/ICreateSecretAgentOptions";
21+
import CoreClient from "./lib/CoreClient";
2322
import ISecretAgentClass, {
2423
ISecretAgent,
25-
ISecretAgentConfigureOptions, ISecretAgentEvents,
24+
ISecretAgentConfigureOptions,
25+
ISecretAgentEvents,
2626
SecretAgentStatics
2727
} from "./interfaces/ISecretAgent";
28-
import CoreTab from './lib/CoreTab';
29-
import Tab, { createTab, getCoreTab } from './lib/Tab';
30-
import IInteractions, {
31-
Command,
32-
IMousePosition,
33-
ITypeInteraction,
34-
} from './interfaces/IInteractions';
35-
import Interactor from './lib/Interactor';
36-
import IWaitForResourceFilter from './interfaces/IWaitForResourceFilter';
37-
import AwaitedEventTarget from './lib/AwaitedEventTarget';
38-
import ScriptInstance from './lib/ScriptInstance';
28+
import CoreTab from "./lib/CoreTab";
29+
import Tab, { createTab, getCoreTab } from "./lib/Tab";
30+
import IInteractions, { Command, IMousePosition, ITypeInteraction } from "./interfaces/IInteractions";
31+
import Interactor from "./lib/Interactor";
32+
import IWaitForResourceFilter from "./interfaces/IWaitForResourceFilter";
33+
import AwaitedEventTarget from "./lib/AwaitedEventTarget";
34+
import ScriptInstance from "./lib/ScriptInstance";
3935
import Signals = NodeJS.Signals;
4036

4137
const DefaultOptions = {
@@ -64,7 +60,6 @@ export function SecretAgentClientGenerator(
6460
'activeTab',
6561
'sessionName',
6662
'url',
67-
'cookies',
6863
'lastCommandId',
6964
'Request',
7065
];
@@ -125,10 +120,6 @@ export function SecretAgentClientGenerator(
125120
return getState(this).activeTab;
126121
}
127122

128-
public get cookies(): Promise<ICookie[]> {
129-
return getCoreTab(this.activeTab).then(x => x.getAllCookies());
130-
}
131-
132123
public get document() {
133124
return this.activeTab.document;
134125
}

client/interfaces/ISecretAgent.ts

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
import IConfigureOptions from '@secret-agent/core-interfaces/IConfigureOptions';
2-
import { IRenderingOption } from '@secret-agent/core-interfaces/ITabOptions';
3-
import IUserProfile from '@secret-agent/core-interfaces/IUserProfile';
4-
import SuperDocument from 'awaited-dom/impl/super-klasses/SuperDocument';
5-
import { ILocationTrigger } from '@secret-agent/core-interfaces/Location';
6-
import ISessionOptions from '@secret-agent/core-interfaces/ISessionOptions';
7-
import { ISuperElement } from 'awaited-dom/base/interfaces/super';
8-
import IWaitForResourceOptions from '@secret-agent/core-interfaces/IWaitForResourceOptions';
9-
import Response from 'awaited-dom/impl/official-klasses/Response';
10-
import { IRequestInit } from 'awaited-dom/base/interfaces/official';
11-
import Request from 'awaited-dom/impl/official-klasses/Request';
12-
import { ICookie } from '@secret-agent/core-interfaces/ICookie';
13-
import IWaitForElementOptions from '@secret-agent/core-interfaces/IWaitForElementOptions';
14-
import Resource from '../lib/Resource';
15-
import IInteractions, { IMousePosition, ITypeInteraction } from './IInteractions';
16-
import IWaitForResourceFilter from './IWaitForResourceFilter';
17-
import ICreateSecretAgentOptions from './ICreateSecretAgentOptions';
18-
import Tab from '../lib/Tab';
19-
import IAwaitedEventTarget from './IAwaitedEventTarget';
1+
import IConfigureOptions from "@secret-agent/core-interfaces/IConfigureOptions";
2+
import { IRenderingOption } from "@secret-agent/core-interfaces/ITabOptions";
3+
import IUserProfile from "@secret-agent/core-interfaces/IUserProfile";
4+
import SuperDocument from "awaited-dom/impl/super-klasses/SuperDocument";
5+
import { ILocationTrigger } from "@secret-agent/core-interfaces/Location";
6+
import ISessionOptions from "@secret-agent/core-interfaces/ISessionOptions";
7+
import { ISuperElement } from "awaited-dom/base/interfaces/super";
8+
import IWaitForResourceOptions from "@secret-agent/core-interfaces/IWaitForResourceOptions";
9+
import Response from "awaited-dom/impl/official-klasses/Response";
10+
import { IRequestInit } from "awaited-dom/base/interfaces/official";
11+
import Request from "awaited-dom/impl/official-klasses/Request";
12+
import IWaitForElementOptions from "@secret-agent/core-interfaces/IWaitForElementOptions";
13+
import Resource from "../lib/Resource";
14+
import IInteractions, { IMousePosition, ITypeInteraction } from "./IInteractions";
15+
import IWaitForResourceFilter from "./IWaitForResourceFilter";
16+
import ICreateSecretAgentOptions from "./ICreateSecretAgentOptions";
17+
import Tab from "../lib/Tab";
18+
import IAwaitedEventTarget from "./IAwaitedEventTarget";
2019

2120
export interface ISecretAgentConfigureOptions extends IConfigureOptions {
2221
defaultRenderingOptions: IRenderingOption[];
@@ -39,7 +38,6 @@ export interface ISecretAgent extends IAwaitedEventTarget<ISecretAgentEvents> {
3938
activeTab: Tab;
4039
sessionName: Promise<string>;
4140
url: Promise<string>;
42-
cookies: Promise<ICookie[]>;
4341
lastCommandId: Promise<number>;
4442

4543
click(mousePosition: IMousePosition): Promise<void>;

client/lib/CookieStorage.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import initializeConstantsAndProperties from 'awaited-dom/base/initializeConstantsAndProperties';
2+
import StateMachine from 'awaited-dom/base/StateMachine';
3+
import ISetCookieOptions from '@secret-agent/core-interfaces/ISetCookieOptions';
4+
import CoreTab from './CoreTab';
5+
6+
const { getState, setState } = StateMachine<CookieStorage, IState>();
7+
8+
interface IState {
9+
coreTab: Promise<CoreTab>;
10+
}
11+
12+
export default class CookieStorage {
13+
constructor() {
14+
initializeConstantsAndProperties(this, [], []);
15+
}
16+
17+
public get length() {
18+
return this.getItems().then(x => x.length);
19+
}
20+
21+
public async getItems() {
22+
const coreTab = await getState(this).coreTab;
23+
return await coreTab.getCookies();
24+
}
25+
26+
public async key(index: number) {
27+
const cookies = await this.getItems();
28+
return Object.keys(cookies)[index];
29+
}
30+
31+
public async clear() {
32+
const coreTab = await getState(this).coreTab;
33+
const cookies = await this.getItems();
34+
for (const cookie of cookies) {
35+
await coreTab.removeCookie(cookie.name);
36+
}
37+
}
38+
39+
public async getItem(key: string) {
40+
const cookies = await this.getItems();
41+
return cookies.find(x => x.name === key);
42+
}
43+
44+
public async setItem(key: string, value: string, options?: ISetCookieOptions) {
45+
const coreTab = await getState(this).coreTab;
46+
return coreTab.setCookie(key, value, options);
47+
}
48+
49+
public async removeItem(name: string) {
50+
const coreTab = await getState(this).coreTab;
51+
return coreTab.removeCookie(name);
52+
}
53+
}
54+
55+
export function createCookieStorage(coreTab: Promise<CoreTab>) {
56+
const cookieStorage = new CookieStorage();
57+
setState(cookieStorage, { coreTab });
58+
return cookieStorage;
59+
}

client/lib/CoreTab.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import IUserProfile from '@secret-agent/core-interfaces/IUserProfile';
1111
import IExecJsPathResult from '@secret-agent/core/interfaces/IExecJsPathResult';
1212
import { IRequestInit } from 'awaited-dom/base/interfaces/official';
1313
import IAttachedState from 'awaited-dom/base/IAttachedState';
14+
import ISetCookieOptions from '@secret-agent/core-interfaces/ISetCookieOptions';
1415
import CoreClient from './CoreClient';
1516
import CoreCommandQueue from './CoreCommandQueue';
1617
import CoreEventHeap from './CoreEventHeap';
@@ -98,12 +99,20 @@ export default class CoreTab {
9899
return await this.commandQueue.run('exportUserProfile');
99100
}
100101

101-
public async getPageCookies(): Promise<ICookie[]> {
102-
return await this.commandQueue.run('getPageCookies');
102+
public async getCookies(): Promise<ICookie[]> {
103+
return await this.commandQueue.run('getTabCookies');
103104
}
104105

105-
public async getAllCookies(): Promise<ICookie[]> {
106-
return await this.commandQueue.run('getUserCookies');
106+
public async setCookie(
107+
name: string,
108+
value: string,
109+
options?: ISetCookieOptions,
110+
): Promise<boolean> {
111+
return await this.commandQueue.run('setTabCookie', name, value, options);
112+
}
113+
114+
public async removeCookie(name: string): Promise<boolean> {
115+
return await this.commandQueue.run('removeTabCookie', name);
107116
}
108117

109118
public async isElementVisible(jsPath: IJsPath): Promise<boolean> {

client/lib/Tab.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import initializeConstantsAndProperties from 'awaited-dom/base/initializeConstantsAndProperties';
22
import StateMachine from 'awaited-dom/base/StateMachine';
3-
import { ICookie } from '@secret-agent/core-interfaces/ICookie';
43
import { ISuperElement } from 'awaited-dom/base/interfaces/super';
54
import AwaitedPath from 'awaited-dom/base/AwaitedPath';
65
import { IRequestInit } from 'awaited-dom/base/interfaces/official';
76
import SuperDocument from 'awaited-dom/impl/super-klasses/SuperDocument';
8-
import { createResponse, createSuperDocument } from 'awaited-dom/impl/create';
7+
import Storage from 'awaited-dom/impl/official-klasses/Storage';
8+
import { createResponse, createStorage, createSuperDocument } from 'awaited-dom/impl/create';
99
import Request from 'awaited-dom/impl/official-klasses/Request';
1010
import { ILocationTrigger, LocationStatus } from '@secret-agent/core-interfaces/Location';
1111
import IWaitForResourceOptions from '@secret-agent/core-interfaces/IWaitForResourceOptions';
@@ -18,6 +18,7 @@ import IAwaitedOptions from '../interfaces/IAwaitedOptions';
1818
import RequestGenerator, { getRequestIdOrUrl } from './Request';
1919
import AwaitedEventTarget from './AwaitedEventTarget';
2020
import { ISecretAgent } from '../interfaces/ISecretAgent';
21+
import CookieStorage, { createCookieStorage } from './CookieStorage';
2122

2223
const { getState, setState } = StateMachine<Tab, IState>();
2324
const agentState = StateMachine<ISecretAgent, { activeTab: Tab; tabs: Tab[] }>();
@@ -36,7 +37,9 @@ const propertyKeys: (keyof Tab)[] = [
3637
'lastCommandId',
3738
'tabId',
3839
'url',
39-
'cookies',
40+
'cookieStorage',
41+
'localStorage',
42+
'sessionStorage',
4043
'document',
4144
'Request',
4245
];
@@ -63,8 +66,8 @@ export default class Tab extends AwaitedEventTarget<IEventType, IState> {
6366
return getCoreTab(this).then(x => x.getUrl());
6467
}
6568

66-
public get cookies(): Promise<ICookie[]> {
67-
return getCoreTab(this).then(x => x.getPageCookies());
69+
public get cookieStorage(): CookieStorage {
70+
return createCookieStorage(getCoreTab(this));
6871
}
6972

7073
public get document(): SuperDocument {
@@ -73,6 +76,18 @@ export default class Tab extends AwaitedEventTarget<IEventType, IState> {
7376
return createSuperDocument<IAwaitedOptions>(awaitedPath, awaitedOptions) as SuperDocument;
7477
}
7578

79+
public get localStorage(): Storage {
80+
const awaitedPath = new AwaitedPath('localStorage');
81+
const awaitedOptions = { ...getState(this) };
82+
return createStorage<IAwaitedOptions>(awaitedPath, awaitedOptions) as Storage;
83+
}
84+
85+
public get sessionStorage(): Storage {
86+
const awaitedPath = new AwaitedPath('sessionStorage');
87+
const awaitedOptions = { ...getState(this) };
88+
return createStorage<IAwaitedOptions>(awaitedPath, awaitedOptions) as Storage;
89+
}
90+
7691
public get Request(): typeof Request {
7792
return RequestGenerator(getCoreTab(this));
7893
}

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"@secret-agent/core": "1.1.0-alpha.0",
88
"@secret-agent/core-interfaces": "1.1.0-alpha.0",
99
"@secret-agent/replay": "1.1.0-alpha.0",
10-
"awaited-dom": "^1.1.5",
10+
"awaited-dom": "^1.1.6",
1111
"uuid": "^8.1.0"
1212
},
1313
"devDependencies": {

client/test/basic.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SecretAgentClientGenerator } from '../index';
1+
import { SecretAgentClientGenerator } from "../index";
22

33
describe('basic SecretAgent tests', () => {
44
it('starts, configures, and shuts down', async () => {
@@ -32,7 +32,7 @@ describe('basic SecretAgent tests', () => {
3232
}
3333
});
3434

35-
const agent = await new SecretAgent();
35+
await new SecretAgent();
3636
await SecretAgent.shutdown();
3737

3838
const outgoingCommands = (coreClient.pipeOutgoingCommand as any).mock.calls;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { ICookie } from './ICookie';
2+
3+
export default interface ISetCookieOptions
4+
extends Pick<ICookie, 'httpOnly' | 'secure' | 'sameSite'> {
5+
expires?: Date | number;
6+
}

core-interfaces/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Core interfaces used by SecretAgent",
55
"dependencies": {
66
"@secret-agent/commons": "1.1.0-alpha.0",
7-
"awaited-dom": "^1.1.5"
7+
"awaited-dom": "^1.1.6"
88
},
99
"devDependencies": {
1010
"@secret-agent/injected-scripts": "1.1.0-alpha.0",

0 commit comments

Comments
 (0)