Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/full-client/test/interact.test.ts
1028 views
1
import Core from '@secret-agent/core';
2
import CoreServer from '@secret-agent/core/server';
3
import { Helpers } from '@secret-agent/testing';
4
import { KeyboardKeys } from '@secret-agent/interfaces/IKeyboardLayoutUS';
5
import { Command } from '@secret-agent/client/interfaces/IInteractions';
6
import { ITestKoaServer } from '@secret-agent/testing/helpers';
7
import HumanEmulator from '@secret-agent/plugin-utils/lib/HumanEmulator';
8
import { Handler, LocationStatus } from '../index';
9
10
let koaServer: ITestKoaServer;
11
let handler: Handler;
12
beforeAll(async () => {
13
const coreServer = new CoreServer();
14
await coreServer.listen({ port: 0 });
15
Core.use(
16
class BasicHumanEmulator extends HumanEmulator {
17
static id = 'basic';
18
},
19
);
20
handler = new Handler({ host: await coreServer.address });
21
Helpers.onClose(() => {
22
handler.close();
23
coreServer.close();
24
}, true);
25
koaServer = await Helpers.runKoaServer(true);
26
});
27
afterAll(Helpers.afterAll);
28
afterEach(Helpers.afterEach);
29
30
describe('basic Interact tests', () => {
31
it('should be able to go to a second page', async () => {
32
const text = "hello, is it me you're looking for?";
33
const onPost = jest.fn().mockImplementation(body => {
34
expect(body).toBe(text);
35
});
36
const httpServer = await Helpers.runHttpServer({ onPost });
37
const url = httpServer.url;
38
39
const agent = await handler.createAgent();
40
Helpers.needsClosing.push(agent);
41
42
await agent.goto(`${url}page1`);
43
await agent.document.querySelector('#input').focus();
44
await agent.waitForMillis(50);
45
await agent.interact({ type: text });
46
await agent.waitForMillis(20);
47
await agent.click(agent.document.querySelector('#submit-button'));
48
await agent.waitForLocation('change');
49
const html = await agent.document.documentElement.outerHTML;
50
expect(html).toBe(`<html><head></head><body>${text}</body></html>`);
51
expect(onPost).toHaveBeenCalledTimes(1);
52
53
await agent.close();
54
await httpServer.close();
55
}, 30e3);
56
57
it('should clean up cookies between runs', async () => {
58
const agent1 = await handler.createAgent();
59
let setCookieValue = 'ulixee=test1';
60
const httpServer = await Helpers.runHttpServer({
61
addToResponse: response => {
62
response.setHeader('Set-Cookie', setCookieValue);
63
},
64
});
65
const url = httpServer.url;
66
67
Helpers.needsClosing.push(agent1);
68
{
69
await agent1.goto(url);
70
71
const cookie = await agent1.activeTab.cookieStorage.getItem('ulixee');
72
expect(cookie.value).toBe('test1');
73
}
74
75
{
76
setCookieValue = 'ulixee2=test2';
77
await agent1.goto(url);
78
79
const cookieStorage = await agent1.activeTab.cookieStorage;
80
expect(await cookieStorage.length).toBe(2);
81
const cookie1 = await cookieStorage.getItem('ulixee');
82
expect(cookie1.value).toBe('test1');
83
const cookie2 = await cookieStorage.getItem('ulixee2');
84
expect(cookie2.value).toBe('test2');
85
}
86
87
{
88
setCookieValue = 'ulixee3=test3';
89
// should be able to get a second agent out of the pool
90
const agent2 = await handler.createAgent();
91
Helpers.needsClosing.push(agent2);
92
await agent2.goto(url);
93
94
const cookieStorage = await agent2.activeTab.cookieStorage;
95
expect(await cookieStorage.length).toBe(1);
96
const cookie = await cookieStorage.getItem('ulixee3');
97
expect(cookie.value).toBe('test3');
98
99
await agent2.close();
100
}
101
102
await agent1.close();
103
}, 20e3);
104
105
it('should be able to combine a waitForElementVisible and a click', async () => {
106
koaServer.get('/waitTest', ctx => {
107
ctx.body = `
108
<body>
109
<a href="/finish">Click Me</a>
110
<script>
111
setTimeout(() => {
112
document.querySelector('a').classList.add('ready');
113
}, 200);
114
</script>
115
</body>
116
`;
117
});
118
koaServer.get('/finish', ctx => (ctx.body = `Finished!`));
119
const agent = await handler.createAgent();
120
Helpers.needsClosing.push(agent);
121
await agent.goto(`${koaServer.baseUrl}/waitTest`);
122
await agent.waitForPaintingStable();
123
const readyLink = agent.document.querySelector('a.ready');
124
await agent.interact({ click: readyLink, waitForElementVisible: readyLink });
125
await agent.waitForLocation('change');
126
const finalUrl = await agent.url;
127
expect(finalUrl).toBe(`${koaServer.baseUrl}/finish`);
128
129
await agent.close();
130
});
131
132
it('should be able to type various combinations of characters', async () => {
133
koaServer.get('/keys', ctx => {
134
ctx.body = `
135
<body>
136
<h1>Text Area</h1>
137
<textarea></textarea>
138
</body>
139
`;
140
});
141
const agent = await handler.createAgent();
142
Helpers.needsClosing.push(agent);
143
await agent.goto(`${koaServer.baseUrl}/keys`);
144
await agent.waitForPaintingStable();
145
const textarea = agent.document.querySelector('textarea');
146
await agent.click(textarea);
147
await agent.type('Test!');
148
expect(await textarea.value).toBe('Test!');
149
await agent.type(KeyboardKeys.Backspace);
150
expect(await textarea.value).toBe('Test');
151
152
await agent.interact(
153
{ [Command.keyDown]: KeyboardKeys.Shift },
154
{ [Command.keyPress]: KeyboardKeys.ArrowLeft },
155
{ [Command.keyPress]: KeyboardKeys.ArrowLeft },
156
{ [Command.keyPress]: KeyboardKeys.ArrowLeft },
157
{ [Command.keyUp]: KeyboardKeys.Shift },
158
{ [Command.keyPress]: KeyboardKeys.Delete },
159
);
160
161
expect(await textarea.value).toBe('T');
162
await agent.close();
163
});
164
165
it('should be able to click on the same element twice', async () => {
166
koaServer.get('/twice', ctx => {
167
ctx.body = `
168
<body>
169
<div id="spot">Twice spot</div>
170
</body>
171
`;
172
});
173
const agent = await handler.createAgent({
174
humanEmulatorId: 'basic',
175
});
176
Helpers.needsClosing.push(agent);
177
await agent.goto(`${koaServer.baseUrl}/twice`);
178
await agent.activeTab.waitForLoad(LocationStatus.DomContentLoaded);
179
const logo = agent.document.querySelector('#spot');
180
await expect(agent.interact({ click: logo })).resolves.toBeUndefined();
181
await agent.waitForMillis(100);
182
await expect(agent.interact({ click: logo })).resolves.toBeUndefined();
183
await agent.close();
184
});
185
186
it('can accept empty commands', async () => {
187
koaServer.get('/empty-click', ctx => {
188
ctx.body = `
189
<body>
190
<div style="margin-top: 200px">
191
<a href="#none" onclick="clickit()">Empty clicker</a>
192
</div>
193
<script>
194
let lastClicked = '';
195
function clickit() {
196
lastClicked = 'clickedit';
197
}
198
</script>
199
</body>
200
`;
201
});
202
const agent = await handler.createAgent({ humanEmulatorId: 'basic' });
203
Helpers.needsClosing.push(agent);
204
await agent.goto(`${koaServer.baseUrl}/empty-click`);
205
await agent.activeTab.waitForLoad(LocationStatus.PaintingStable);
206
await agent.interact(
207
{
208
[Command.move]: agent.document.querySelector('a'),
209
},
210
'click',
211
);
212
213
expect(await agent.activeTab.getJsValue('lastClicked')).toBe('clickedit');
214
});
215
216
it('should be able to click an element in an iframe', async () => {
217
koaServer.get('/interact-frame', ctx => {
218
ctx.body = `
219
<body>
220
<h1>Iframe Page</h1>
221
<br/><br/>
222
<iframe src="/innerFrame" id="frame1" style="height:300px"></iframe>
223
</body>
224
`;
225
});
226
koaServer.get('/innerFrame', ctx => {
227
ctx.body = `<body>
228
<div style="margin-top: 200px">
229
<a href="#none" onclick="clickit()">Empty clicker</a>
230
</div>
231
<script>
232
let lastClicked = '';
233
function clickit() {
234
lastClicked = 'clickedit';
235
}
236
</script>
237
238
</body>`;
239
});
240
241
const agent = await handler.createAgent();
242
Helpers.needsClosing.push(agent);
243
await agent.goto(`${koaServer.baseUrl}/interact-frame`);
244
await agent.waitForPaintingStable();
245
246
const frameElement = agent.document.querySelector('#frame1');
247
await agent.waitForElement(frameElement);
248
const frameEnv = await agent.activeTab.getFrameEnvironment(frameElement);
249
await frameEnv.waitForLoad(LocationStatus.AllContentLoaded);
250
251
await agent.click(frameEnv.document.querySelector('a'));
252
expect(await frameEnv.getJsValue('lastClicked')).toBe('clickedit');
253
254
await agent.close();
255
});
256
});
257
258