Path: blob/main/plugins/default-browser-emulator/test/utils.test.ts
1029 views
import * as Helpers from '@secret-agent/testing/helpers';1import { inspect } from 'util';2import Puppet from '@secret-agent/puppet';3import injectedSourceUrl from '@secret-agent/interfaces/injectedSourceUrl';4import Log from '@secret-agent/commons/Logger';5import CorePlugins from '@secret-agent/core/lib/CorePlugins';6import { IBoundLog } from '@secret-agent/interfaces/ILog';7// @ts-ignore8// eslint-disable-next-line import/extensions9import { proxyFunction } from '../injected-scripts/_proxyUtils';10import { getOverrideScript } from '../lib/DomOverridesBuilder';11import BrowserEmulator from '../index';12import DomExtractor = require('./DomExtractor');1314const { log } = Log(module);15const selectBrowserMeta = BrowserEmulator.selectBrowserMeta();1617let puppet: Puppet;18beforeAll(async () => {19puppet = new Puppet(selectBrowserMeta.browserEngine);20Helpers.onClose(() => puppet.close(), true);21await puppet.start();22});2324afterAll(Helpers.afterAll);25afterEach(Helpers.afterEach);2627const debug = process.env.DEBUG || false;2829test('should be able to override a function', async () => {30class TestClass {31public doSomeWork(param: string) {32return `${param} nope`;33}34}35const holder = {36tester: new TestClass(),37};38const win = {39TestClass,40holder,41};4243// @ts-ignore44global.self = this;45const hierarchy = JSON.parse(await new DomExtractor('window').run(win, 'win')).window;46if (debug) console.log(inspect(hierarchy, false, null, true));47expect(win.holder.tester.doSomeWork('we')).toBe('we nope');4849proxyFunction(win.TestClass.prototype, 'doSomeWork', (target, thisArg, args) => {50return `${target.apply(thisArg, args)} yep`;51});5253const afterHierarchy = JSON.parse(await new DomExtractor('window').run(win, 'win')).window;54if (debug) console.log(inspect(afterHierarchy, false, null, true));5556expect(win.holder.tester.doSomeWork('oh')).toBe('oh nope yep');57expect(afterHierarchy.TestClass.prototype.doSomeWork._$invocation).toBe('undefined nope yep');58// these 2 will now be different in the structure59delete hierarchy.TestClass.prototype.doSomeWork._$invocation;60delete afterHierarchy.TestClass.prototype.doSomeWork._$invocation;61expect(hierarchy).toStrictEqual(afterHierarchy);62});6364test('should override a function and clean error stacks', async () => {65const httpServer = await Helpers.runHttpServer();66const plugins = new CorePlugins({ selectBrowserMeta }, log as IBoundLog);67const context = await puppet.newContext(plugins, log);68Helpers.onClose(() => context.close());69const page = await context.newPage();7071page.on('page-error', console.log);72if (debug) {73page.on('console', console.log);74}75await page.addNewDocumentScript(76getOverrideScript('navigator.deviceMemory', {77memory: '4gb',78}).script,79false,80);81await Promise.all([82page.navigate(httpServer.url),83page.mainFrame.waitOn('frame-lifecycle', ev => ev.name === 'DOMContentLoaded'),84]);8586const worksOnce = await page.evaluate(87`navigator.permissions.query({ name: 'geolocation' }).then(x => x.state)`,88);89expect(worksOnce).toBeTruthy();9091const perms = await page.evaluate(`(async () => {92try {93await navigator.permissions.query()94} catch(err) {95return err.stack;96}97})();`);98expect(perms).not.toContain(injectedSourceUrl);99});100101test('should override Errors properly on https pages', async () => {102const httpServer = await Helpers.runHttpsServer((req, res) => {103res.end(`<html lang="en"><body><h1>Hi</h1></body></html>`);104});105const plugins = new CorePlugins({ selectBrowserMeta }, log as IBoundLog);106const context = await puppet.newContext(plugins, log);107Helpers.onClose(() => context.close());108const page = await context.newPage();109110page.on('console', console.log);111await page.addNewDocumentScript(getOverrideScript('Error.captureStackTrace').script, false);112await page.addNewDocumentScript(getOverrideScript('Error.constructor').script, false);113await Promise.all([114page.navigate(httpServer.url),115page.mainFrame.waitOn('frame-lifecycle', event => event.name === 'load'),116]);117118const errorToString = await page.evaluate(`Error.toString()`);119expect(errorToString).toBe('function Error() { [native code] }');120const errorToStringString = await page.evaluate(`Error.toString.toString()`);121expect(errorToStringString).toBe('function toString() { [native code] }');122const errorConstructorToString = await page.evaluate(`Error.constructor.toString()`);123expect(errorConstructorToString).toBe('function Function() { [native code] }');124});125126127