Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/puppet/test/Worker.test.ts
1030 views
1
import Log from '@secret-agent/commons/Logger';
2
import IPuppetContext from '@secret-agent/interfaces/IPuppetContext';
3
import CorePlugins from '@secret-agent/core/lib/CorePlugins';
4
import { IBoundLog } from '@secret-agent/interfaces/ILog';
5
import Core from '@secret-agent/core';
6
import { TestServer } from './server';
7
import { createTestPage, ITestPage } from './TestPage';
8
import Puppet from '../index';
9
import CustomBrowserEmulator from './_CustomBrowserEmulator';
10
11
const { log } = Log(module);
12
const browserEmulatorId = CustomBrowserEmulator.id;
13
14
describe('Worker test', () => {
15
let server: TestServer;
16
let httpsServer: TestServer;
17
let page: ITestPage;
18
let puppet: Puppet;
19
let context: IPuppetContext;
20
21
beforeAll(async () => {
22
Core.use(CustomBrowserEmulator);
23
const { browserEngine } = CustomBrowserEmulator.selectBrowserMeta();
24
server = await TestServer.create(0);
25
httpsServer = await TestServer.createHTTPS(0);
26
puppet = new Puppet(browserEngine);
27
await puppet.start();
28
const plugins = new CorePlugins({ browserEmulatorId }, log as IBoundLog);
29
context = await puppet.newContext(plugins, log);
30
});
31
32
afterEach(async () => {
33
await page.close();
34
});
35
36
beforeEach(async () => {
37
page = createTestPage(await context.newPage());
38
server.reset();
39
httpsServer.reset();
40
});
41
42
afterAll(async () => {
43
await server.stop();
44
await httpsServer.stop();
45
await context.close();
46
await puppet.close();
47
});
48
49
it('Page.workers', async () => {
50
await Promise.all([page.waitOn('worker'), page.goto(`${server.baseUrl}/worker/worker.html`)]);
51
const worker = page.workers[0];
52
expect(worker.url).toContain('worker.js');
53
54
// don't have a way to determine if the worker is loaded yet
55
for (let i = 0; i < 10; i += 1) {
56
const isReady = await worker.evaluate<boolean>('!!self.workerFunction');
57
if (isReady) break;
58
await new Promise(setImmediate);
59
}
60
expect(await worker.evaluate(`self.workerFunction()`)).toBe('worker function result');
61
await page.goto(server.emptyPage);
62
expect(page.workers.length).toBe(0);
63
});
64
65
it('should report console logs', async () => {
66
const [message] = await Promise.all<{ message: string }>([
67
page.waitOn('console'),
68
page.evaluate(`(() => {
69
new Worker(
70
URL.createObjectURL(new Blob(['console.log(1)'], { type: 'application/javascript' })),
71
);
72
})()`),
73
]);
74
expect(message.message).toBe('1');
75
});
76
77
it('should evaluate', async () => {
78
const workerCreatedPromise = page.waitOn('worker');
79
await page.evaluate(`(() => {
80
new Worker(
81
URL.createObjectURL(new Blob(['console.log(1)'], { type: 'application/javascript' })),
82
);
83
})()`);
84
const { worker } = await workerCreatedPromise;
85
expect(await worker.evaluate('1+1')).toBe(2);
86
});
87
88
it('should report errors', async () => {
89
const errorPromise = new Promise<{ error: Error }>(resolve => page.on('page-error', resolve));
90
await page.evaluate(
91
`(() => {
92
const blobFn = \`setTimeout(() => {
93
// Do a console.log just to check that we do not confuse it with an error.
94
console.log('hey');
95
throw new Error('this is my error');
96
})\`;
97
new Worker(
98
URL.createObjectURL(new Blob([blobFn], { type: 'application/javascript' })),
99
);
100
})()`,
101
);
102
const { error } = await errorPromise;
103
expect(error.stack).toContain('this is my error');
104
});
105
106
it('should clear upon navigation', async () => {
107
await page.goto(server.emptyPage);
108
const workerCreatedPromise = page.waitOn('worker');
109
await page.evaluate(`(() => {
110
new Worker(
111
URL.createObjectURL(new Blob(['console.log(1)'], { type: 'application/javascript' })),
112
);
113
})()`);
114
const { worker } = await workerCreatedPromise;
115
expect(page.workers.length).toBe(1);
116
let destroyed = false;
117
worker.once('close', () => (destroyed = true));
118
await page.goto(`${server.baseUrl}/one-style.html`);
119
expect(destroyed).toBe(true);
120
expect(page.workers.length).toBe(0);
121
});
122
123
it('should clear upon cross-process navigation', async () => {
124
await page.goto(server.emptyPage);
125
const workerCreatedPromise = page.waitOn('worker');
126
await page.evaluate(`(() => {
127
new Worker(
128
URL.createObjectURL(new Blob(['console.log(1)'], { type: 'application/javascript' })),
129
);
130
})()`);
131
const { worker } = await workerCreatedPromise;
132
expect(page.workers.length).toBe(1);
133
let destroyed = false;
134
worker.once('close', () => (destroyed = true));
135
await page.goto(`${server.crossProcessBaseUrl}/empty.html`);
136
expect(destroyed).toBe(true);
137
expect(page.workers.length).toBe(0);
138
});
139
140
it('should report network activity', async () => {
141
const [workerEvent] = await Promise.all([
142
page.waitOn('worker'),
143
page.goto(`${server.baseUrl}/worker/worker.html`),
144
]);
145
const url = `${server.baseUrl}/one-style.css`;
146
const requestPromise = page.waitOn(
147
'resource-will-be-requested',
148
x => x.resource.url.href === url,
149
);
150
await workerEvent.worker.evaluate(`(async () => {
151
await fetch("${url}")
152
.then(response => response.text())
153
.then(console.log);
154
})();`);
155
const request = await requestPromise;
156
expect(request.resource.url.href).toBe(url);
157
});
158
159
it('should report network activity on worker creation', async () => {
160
// Chromium needs waitForDebugger enabled for this one.
161
await page.goto(server.emptyPage);
162
const url = `${server.baseUrl}/one-style.css`;
163
const requestPromise = page.waitOn('resource-will-be-requested', x =>
164
x.resource.url.href.includes('one-style.css'),
165
);
166
167
await page.evaluate(`(() => {
168
new Worker(
169
URL.createObjectURL(
170
new Blob(
171
[
172
\`fetch("${url}").then(response => response.text()).then(console.log);\`
173
],
174
{ type: 'application/javascript' },
175
),
176
),
177
);
178
})();`);
179
const request = await requestPromise;
180
expect(request.resource.url.href).toBe(url);
181
});
182
});
183
184