Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/plugins/default-browser-emulator/test/utils.test.ts
1029 views
1
import * as Helpers from '@secret-agent/testing/helpers';
2
import { inspect } from 'util';
3
import Puppet from '@secret-agent/puppet';
4
import injectedSourceUrl from '@secret-agent/interfaces/injectedSourceUrl';
5
import Log from '@secret-agent/commons/Logger';
6
import CorePlugins from '@secret-agent/core/lib/CorePlugins';
7
import { IBoundLog } from '@secret-agent/interfaces/ILog';
8
// @ts-ignore
9
// eslint-disable-next-line import/extensions
10
import { proxyFunction } from '../injected-scripts/_proxyUtils';
11
import { getOverrideScript } from '../lib/DomOverridesBuilder';
12
import BrowserEmulator from '../index';
13
import DomExtractor = require('./DomExtractor');
14
15
const { log } = Log(module);
16
const selectBrowserMeta = BrowserEmulator.selectBrowserMeta();
17
18
let puppet: Puppet;
19
beforeAll(async () => {
20
puppet = new Puppet(selectBrowserMeta.browserEngine);
21
Helpers.onClose(() => puppet.close(), true);
22
await puppet.start();
23
});
24
25
afterAll(Helpers.afterAll);
26
afterEach(Helpers.afterEach);
27
28
const debug = process.env.DEBUG || false;
29
30
test('should be able to override a function', async () => {
31
class TestClass {
32
public doSomeWork(param: string) {
33
return `${param} nope`;
34
}
35
}
36
const holder = {
37
tester: new TestClass(),
38
};
39
const win = {
40
TestClass,
41
holder,
42
};
43
44
// @ts-ignore
45
global.self = this;
46
const hierarchy = JSON.parse(await new DomExtractor('window').run(win, 'win')).window;
47
if (debug) console.log(inspect(hierarchy, false, null, true));
48
expect(win.holder.tester.doSomeWork('we')).toBe('we nope');
49
50
proxyFunction(win.TestClass.prototype, 'doSomeWork', (target, thisArg, args) => {
51
return `${target.apply(thisArg, args)} yep`;
52
});
53
54
const afterHierarchy = JSON.parse(await new DomExtractor('window').run(win, 'win')).window;
55
if (debug) console.log(inspect(afterHierarchy, false, null, true));
56
57
expect(win.holder.tester.doSomeWork('oh')).toBe('oh nope yep');
58
expect(afterHierarchy.TestClass.prototype.doSomeWork._$invocation).toBe('undefined nope yep');
59
// these 2 will now be different in the structure
60
delete hierarchy.TestClass.prototype.doSomeWork._$invocation;
61
delete afterHierarchy.TestClass.prototype.doSomeWork._$invocation;
62
expect(hierarchy).toStrictEqual(afterHierarchy);
63
});
64
65
test('should override a function and clean error stacks', async () => {
66
const httpServer = await Helpers.runHttpServer();
67
const plugins = new CorePlugins({ selectBrowserMeta }, log as IBoundLog);
68
const context = await puppet.newContext(plugins, log);
69
Helpers.onClose(() => context.close());
70
const page = await context.newPage();
71
72
page.on('page-error', console.log);
73
if (debug) {
74
page.on('console', console.log);
75
}
76
await page.addNewDocumentScript(
77
getOverrideScript('navigator.deviceMemory', {
78
memory: '4gb',
79
}).script,
80
false,
81
);
82
await Promise.all([
83
page.navigate(httpServer.url),
84
page.mainFrame.waitOn('frame-lifecycle', ev => ev.name === 'DOMContentLoaded'),
85
]);
86
87
const worksOnce = await page.evaluate(
88
`navigator.permissions.query({ name: 'geolocation' }).then(x => x.state)`,
89
);
90
expect(worksOnce).toBeTruthy();
91
92
const perms = await page.evaluate(`(async () => {
93
try {
94
await navigator.permissions.query()
95
} catch(err) {
96
return err.stack;
97
}
98
})();`);
99
expect(perms).not.toContain(injectedSourceUrl);
100
});
101
102
test('should override Errors properly on https pages', async () => {
103
const httpServer = await Helpers.runHttpsServer((req, res) => {
104
res.end(`<html lang="en"><body><h1>Hi</h1></body></html>`);
105
});
106
const plugins = new CorePlugins({ selectBrowserMeta }, log as IBoundLog);
107
const context = await puppet.newContext(plugins, log);
108
Helpers.onClose(() => context.close());
109
const page = await context.newPage();
110
111
page.on('console', console.log);
112
await page.addNewDocumentScript(getOverrideScript('Error.captureStackTrace').script, false);
113
await page.addNewDocumentScript(getOverrideScript('Error.constructor').script, false);
114
await Promise.all([
115
page.navigate(httpServer.url),
116
page.mainFrame.waitOn('frame-lifecycle', event => event.name === 'load'),
117
]);
118
119
const errorToString = await page.evaluate(`Error.toString()`);
120
expect(errorToString).toBe('function Error() { [native code] }');
121
const errorToStringString = await page.evaluate(`Error.toString.toString()`);
122
expect(errorToStringString).toBe('function toString() { [native code] }');
123
const errorConstructorToString = await page.evaluate(`Error.constructor.toString()`);
124
expect(errorConstructorToString).toBe('function Function() { [native code] }');
125
});
126
127