Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Feat: recursive dom profiler #96

Merged
merged 46 commits into from
Jun 17, 2024
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d9fd443
feat(profiler): run browserstack locally
soundofspace Jun 4, 2024
106364d
fix(profiler): chrome unique datadir
soundofspace Jun 4, 2024
1ebe10f
wip
soundofspace Jun 4, 2024
2ac6f12
wip
soundofspace Jun 4, 2024
2f0cad5
wip
soundofspace Jun 4, 2024
8768681
wip
soundofspace Jun 11, 2024
5916224
wip
soundofspace Jun 12, 2024
be10a07
wip
soundofspace Jun 12, 2024
f1f8ad8
wip
soundofspace Jun 12, 2024
40e3fee
wip
soundofspace Jun 12, 2024
9488b44
copy
soundofspace Jun 12, 2024
a6448c0
async
soundofspace Jun 12, 2024
555afdb
json
soundofspace Jun 13, 2024
5b5c70d
incode async in otherInvocationKey
soundofspace Jun 13, 2024
3ddfd5a
test
soundofspace Jun 13, 2024
589a316
fix wrong space
soundofspace Jun 13, 2024
c27305a
fix broken worker
soundofspace Jun 13, 2024
34952c6
remove extra calls
soundofspace Jun 13, 2024
d5a9c09
wip
soundofspace Jun 13, 2024
0a96a05
wip
soundofspace Jun 13, 2024
86714d3
wip
soundofspace Jun 13, 2024
cd84932
wip
soundofspace Jun 13, 2024
1fb73a4
wip
soundofspace Jun 13, 2024
46b4378
comments
soundofspace Jun 13, 2024
c93dfa6
Trigger CI
soundofspace Jun 13, 2024
cdb1a3d
test
soundofspace Jun 14, 2024
dc58a6c
test
soundofspace Jun 14, 2024
664c69c
test
soundofspace Jun 14, 2024
8b4a199
test
soundofspace Jun 14, 2024
c58a14b
test
soundofspace Jun 14, 2024
bb2954a
test
soundofspace Jun 14, 2024
762c82b
test
soundofspace Jun 14, 2024
fa50917
test
soundofspace Jun 14, 2024
2da0195
test
soundofspace Jun 14, 2024
b08316f
test
soundofspace Jun 17, 2024
4e9ced5
test
soundofspace Jun 17, 2024
a62176a
test
soundofspace Jun 17, 2024
60edf3b
test
soundofspace Jun 17, 2024
454bdbc
Merge remote-tracking branch 'upstream/main' into feat--recursive-dom…
soundofspace Jun 17, 2024
1d59a8e
test
soundofspace Jun 17, 2024
07916df
test
soundofspace Jun 17, 2024
c081cff
test
soundofspace Jun 17, 2024
970dfb8
test
soundofspace Jun 17, 2024
dd286ef
test
soundofspace Jun 17, 2024
2d4f3d7
test
soundofspace Jun 17, 2024
f9351aa
test
soundofspace Jun 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test
soundofspace committed Jun 17, 2024
commit 60edf3bb079eb1d63b58a811739d583e5f3b384d
2 changes: 1 addition & 1 deletion .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ jobs:
run: NODE_OPTIONS=--max-old-space-size=4096 yarn lint

- name: Run tests
run: yarn jest --testTimeout=180000 --maxWorkers=1
run: yarn jest --testTimeout=60000 --maxWorkers=1
working-directory: ./build
env:
ULX_DATA_DIR: .data-test
29 changes: 16 additions & 13 deletions agent/main/test/mitm.test.ts
Original file line number Diff line number Diff line change
@@ -32,13 +32,17 @@ beforeEach(async () => {
afterAll(Helpers.afterAll);
afterEach(Helpers.afterEach);

function mitmCalls(thisTest: number, opts?: { noGoto?: boolean; noFavicon?: boolean }): number {
// goto and favicon
let calls = 2;
if (opts?.noFavicon) calls -= 1;
if (opts?.noGoto) calls -= 1;

return thisTest + calls;
function mitmCalls(expectedCalls: number): number {
// Takes care of removing favicon from call mitm calls if needed.
// During testing favicon migth or migth not be called depending on
// speed of setup. To prevent flaky tests we ignore this.
const hasCalledFavicon = mocks.MitmRequestContext.create.mock.results.some(
result => result.value.url.href.includes('favicon'),
);
if (hasCalledFavicon) {
return expectedCalls + 1;
}
return expectedCalls;
}

test('should send a Host header to secure http1 Chrome requests', async () => {
@@ -99,7 +103,7 @@ xhr.send('<person><name>DLF</name></person>');
await expect(corsPromise).resolves.toBeTruthy();
await expect(postPromise).resolves.toBeTruthy();

expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(2));
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(3));
const results = mocks.MitmRequestContext.create.mock.results.filter(
result => !result.value.url.href.includes('favicon'),
);
@@ -144,7 +148,7 @@ myWorker.postMessage('send');
await page.goto(`${koa.baseUrl}/testWorker`);
await page.mainFrame.waitForLoad({ loadStatus: 'PaintingStable' });
await expect(serviceXhr).resolves.toBe('FromWorker');
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(2));
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(3));
});

test('should proxy requests from shared workers', async () => {
@@ -191,7 +195,7 @@ sharedWorker.port.addEventListener('message', message => {
await page.goto(`${server.baseUrl}/testSharedWorker`);
await page.mainFrame.waitForLoad({ loadStatus: 'PaintingStable' });
await expect(xhrResolvable.promise).resolves.toBe('FromSharedWorker');
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(2));
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(3));
});

test('should not see proxy headers in a service worker', async () => {
@@ -295,7 +299,7 @@ window.addEventListener('load', function() {
await expect(originalHeaders['proxy-authorization']).not.toBeTruthy();
await expect(headersFromWorker['proxy-authorization']).not.toBeTruthy();
await expect(originalHeaders['user-agent']).toBe(headersFromWorker['user-agent']);
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(3));
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(4));
});

test('should proxy iframe requests', async () => {
@@ -326,8 +330,7 @@ This is the main body
});
await page.goto(`${koa.baseUrl}/iframe-test`);
await page.waitForLoad(LocationStatus.AllContentLoaded);
// TODO why doesn't this load favicon?
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(3, { noFavicon: true }));
expect(mocks.MitmRequestContext.create).toHaveBeenCalledTimes(mitmCalls(4));
const urls = mocks.MitmRequestContext.create.mock.results.map(x => x.value.url.href);
expect(urls).toEqual([
expect.stringMatching(/http:\/\/localhost:\d+\/iframe-test/),

Unchanged files with check annotations Beta

command: InteractionCommand.click,
mousePosition: ['window', 'document', ['querySelector', 'a']],
},
]);

Check failure on line 505 in agent/main/test/navigation.test.ts

GitHub Actions / Test node-20, windows-latest, latest

basic Navigation tests withoutMitm › can wait for another page

thrown: "Exceeded timeout of 60000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at ../agent/main/test/navigation.test.ts:505:3 at Array.forEach (<anonymous>) at Object.<anonymous> (../agent/main/test/navigation.test.ts:46:3)
resolvePendingTriggerSpy.mockClear();
const perfObserver = new PerformanceObserver(() => {
window.location.href = '/popup-done';
});
perfObserver.observe({ type: 'largest-contentful-paint', buffered: true });

Check failure on line 541 in agent/main/test/navigation.test.ts

GitHub Actions / Test node-18, windows-latest, latest

basic Navigation tests withoutMitm › should not trigger location change for first navigation of new pages

thrown: "Exceeded timeout of 60000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." at ../agent/main/test/navigation.test.ts:541:3 at Array.forEach (<anonymous>) at Object.<anonymous> (../agent/main/test/navigation.test.ts:46:3)
</script>
</body>`;
});
});
const { page } = await createAgent(enableMitm);
const resource = await page.goto(startingUrl);
await expect(page.waitForLoad(LocationStatus.PaintingStable)).resolves.toBeTruthy();

Check failure on line 631 in agent/main/test/navigation.test.ts

GitHub Actions / Test node-20, macos-13, latest

basic Navigation tests with Mitm › handles a new page that redirects

expect(received).toHaveLength(expected) Expected length: 5 Received length: 4 Received array: [{"browserRequestId": "3C0B02B43CC2F2AF162D71D954191B51", "documentNavigationId": null, "finalUrl": "http://localhost:49482/popup-redirect2", "frameId": 2, "id": 2, "initiatedTime": 1718615657417, "loaderId": "3C0B02B43CC2F2AF162D71D954191B51", "navigationReason": "newFrame", "requestedUrl": "http://localhost:49482/popup-redirect", "resourceIdResolvable": {"isResolved": false, "resolved": undefined}, "startCommandId": 3, "statusChanges": Map {"HttpRequested" => 1718615657418, "HttpRedirected" => 1718615657419}, "tabId": 2}, {"browserRequestId": "3C0B02B43CC2F2AF162D71D954191B51", "documentNavigationId": null, "finalUrl": "http://localhost:49482/popup-redirect3", "frameId": 2, "id": 3, "initiatedTime": 1718615657419, "loaderId": "3C0B02B43CC2F2AF162D71D954191B51", "navigationReason": "newFrame", "requestedUrl": "http://localhost:49482/popup-redirect2", "resourceId": 86, "resourceIdResolvable": {"isResolved": true, "resolved": 86}, "startCommandId": 3, "statusChanges": Map {"HttpRequested" => 1718615657419, "HttpRedirected" => 1718615657420}, "tabId": 2}, {"browserRequestId": "3C0B02B43CC2F2AF162D71D954191B51", "documentNavigationId": null, "finalUrl": "http://localhost:49482/popup-redirect3", "frameId": 2, "id": 4, "initiatedTime": 1718615657420, "loaderId": "3C0B02B43CC2F2AF162D71D954191B51", "navigationReason": "newFrame", "requestedUrl": "http://localhost:49482/popup-redirect3", "resourceId": 86, "resourceIdResolvable": {"isResolved": true, "resolved": 86}, "startCommandId": 3, "statusChanges": Map {"HttpRequested" => 1718615657421, "HttpResponded" => 1718615657406.773, "DomContentLoaded" => 1718615657426.0308, "AllContentLoaded" => 1718615657426.9941, "JavascriptReady" => 1718615657507, "ContentPaint" => 1718615657507}, "tabId": 2}, {"browserRequestId": "FECCBD1E39D6C4BBC9DCC474084932A8", "documentNavigationId": null, "finalUrl": "http://localhost:49482/popup-done", "frameId": 2, "id": 5, "initiatedTime": 1718615657518, "loaderId": "FECCBD1E39D6C4BBC9DCC474084932A8", "navigationReason": "scriptInitiated", "requestedUrl": "http://localhost:49482/popup-done", "resourceId": 87, "resourceIdResolvable": {"isResolved": true, "resolved": 87}, "startCommandId": 5, "statusChanges": Map {"HttpRequested" => 1718615657518, "HttpResponded" => 1718615657559.286, "DomContentLoaded" => 1718615657568.1948}, "tabId": 2}] at Object.<anonymous> (../agent/main/test/navigation.test.ts:631:21)
expect(resource.request.url).toBe(`${koaServer.baseUrl}/post-stable-redirect`);
expect(resource.isRedirect).toBe(false);
});
sendInitiator?: object,
): Promise<ProtocolMapping.Commands[T]['returnType']> {
if (!this.isConnected()) {
throw new CanceledPromiseError(`Cancel Pending Promise (${method}): Target closed.`);

Check failure on line 71 in agent/main/lib/DevtoolsSession.ts

GitHub Actions / Test node-20.x, ubuntu-latest, chrome-115-0

it should be able to remove properties

CanceledPromiseError: Cancel Pending Promise (Target.createTarget): Target closed. at DevtoolsSession.send (../agent/main/lib/DevtoolsSession.ts:71:13) at BrowserContext.sendWithBrowserDevtoolsSession (../agent/main/lib/BrowserContext.ts:449:41) at BrowserContext.newPage (../agent/main/lib/BrowserContext.ts:134:37) at createPage (../plugins/default-browser-emulator/test/polyfills.test.ts:287:30) at Object.<anonymous> (../plugins/default-browser-emulator/test/polyfills.test.ts:134:22)

Check failure on line 71 in agent/main/lib/DevtoolsSession.ts

GitHub Actions / Test node-20.x, ubuntu-latest, chrome-115-0

it should be able to change properties

CanceledPromiseError: Cancel Pending Promise (Target.createTarget): Target closed. at DevtoolsSession.send (../agent/main/lib/DevtoolsSession.ts:71:13) at BrowserContext.sendWithBrowserDevtoolsSession (../agent/main/lib/BrowserContext.ts:449:41) at BrowserContext.newPage (../agent/main/lib/BrowserContext.ts:134:37) at createPage (../plugins/default-browser-emulator/test/polyfills.test.ts:287:30) at Object.<anonymous> (../plugins/default-browser-emulator/test/polyfills.test.ts:155:22)

Check failure on line 71 in agent/main/lib/DevtoolsSession.ts

GitHub Actions / Test node-20.x, ubuntu-latest, chrome-115-0

it should be able to change property order

CanceledPromiseError: Cancel Pending Promise (Target.createTarget): Target closed. at DevtoolsSession.send (../agent/main/lib/DevtoolsSession.ts:71:13) at BrowserContext.sendWithBrowserDevtoolsSession (../agent/main/lib/BrowserContext.ts:449:41) at BrowserContext.newPage (../agent/main/lib/BrowserContext.ts:134:37) at createPage (../plugins/default-browser-emulator/test/polyfills.test.ts:287:30) at Object.<anonymous> (../plugins/default-browser-emulator/test/polyfills.test.ts:193:22)

Check failure on line 71 in agent/main/lib/DevtoolsSession.ts

GitHub Actions / Test node-20.x, ubuntu-latest, chrome-115-0

it should be able to change window property order

CanceledPromiseError: Cancel Pending Promise (Target.createTarget): Target closed. at DevtoolsSession.send (../agent/main/lib/DevtoolsSession.ts:71:13) at BrowserContext.sendWithBrowserDevtoolsSession (../agent/main/lib/BrowserContext.ts:449:41) at BrowserContext.newPage (../agent/main/lib/BrowserContext.ts:134:37) at createPage (../plugins/default-browser-emulator/test/polyfills.test.ts:287:30) at Object.<anonymous> (../plugins/default-browser-emulator/test/polyfills.test.ts:238:22)
}
const id = this.connection.nextId;
onClosed(): void {
for (const { resolvable, method } of this.pendingMessages.values()) {
const error = new CanceledPromiseError(`Cancel Pending Promise (${method}): Target closed.`);

Check failure on line 142 in agent/main/lib/DevtoolsSession.ts

GitHub Actions / Test node-20.x, ubuntu-latest, chrome-115-0

it should be able to add polyfills

CanceledPromiseError: Cancel Pending Promise (Runtime.evaluate): Target closed. at DevtoolsSession.onClosed (../agent/main/lib/DevtoolsSession.ts:142:21) at Connection.onClosed (../agent/main/lib/Connection.ts:93:15) at PipeTransport.onReadClosed (../agent/main/lib/PipeTransport.ts:85:42) ------DEVTOOLS------------------------------------ ------DEVTOOLS_SESSION_ID=7EC0CB1C9188049A8766EBEB3251AC65 at new Resolvable (../../shared/commons/lib/Resolvable.ts:19:18) at createPromise (../../shared/commons/lib/utils.ts:140:10) at DevtoolsSession.send (../agent/main/lib/DevtoolsSession.ts:82:37) at Frame.evaluate (../agent/main/lib/Frame.ts:285:84) at async Object.<anonymous> (../plugins/default-browser-emulator/test/polyfills.test.ts:110:16)
error.stack += `\n${'------DEVTOOLS'.padEnd(
50,
'-',