blob: cefedb9fff80f3f3b449398b336e7906c4f13f2c [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';
import {allThreadEntriesInTrace, getAllNetworkRequestsByHost} from '../../testing/TraceHelpers.js';
import {TraceLoader} from '../../testing/TraceLoader.js';
import * as Trace from './trace.js';
describeWithEnvironment('EntityMapper', function() {
it('correctly merges handler data', async function() {
const parsedTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
const fromRenderer = parsedTrace.data.Renderer.entityMappings.eventsByEntity;
const fromNetwork = parsedTrace.data.NetworkRequests.entityMappings.eventsByEntity;
const mapper = new Trace.EntityMapper.EntityMapper(parsedTrace);
const mappings = mapper.mappings();
// [paulirish.com, Google Tag Manager, Google Fonts, Google Analytics, Disqus, Firebase]
assert.deepEqual(mappings.eventsByEntity.size, 6);
// Check that mappings.eventsByEntity includes all the events of RendererHandler.
fromRenderer.entries().forEach(([entity, events]) => {
assert.isTrue(mappings.eventsByEntity.has(entity));
const gotEvents = mappings.eventsByEntity.get(entity) ?? [];
events.forEach(e => {
assert.isTrue(gotEvents.includes(e));
});
});
// Check that mappings.eventsByEntity includes all the events of NetworkRequestsHandler.
fromNetwork.entries().forEach(([entity, events]) => {
assert.isTrue(mappings.eventsByEntity.has(entity));
const gotEvents = mappings.eventsByEntity.get(entity) ?? [];
events.forEach(e => {
assert.isTrue(gotEvents.includes(e));
});
});
// These would be the same object identity, if not for shallowClone
assert.deepEqual(fromRenderer, fromNetwork);
assert.deepEqual(fromRenderer, mappings.eventsByEntity);
});
describe('entityForEvent', () => {
it('correctly contains network req entity mappings', async function() {
const parsedTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
const mapper = new Trace.EntityMapper.EntityMapper(parsedTrace);
// Check entities for network requests.
const reqs = getAllNetworkRequestsByHost(parsedTrace.data.NetworkRequests.byTime, 'www.paulirish.com');
let gotEntity = mapper.entityForEvent(reqs[0]);
assert.deepEqual(gotEntity?.name, 'paulirish.com');
const gstatic = getAllNetworkRequestsByHost(parsedTrace.data.NetworkRequests.byTime, 'fonts.gstatic.com');
gotEntity = mapper.entityForEvent(gstatic[0]);
assert.deepEqual(gotEntity?.name, 'Google Fonts');
});
it('correctly contains main event entity mappings', async function() {
const parsedTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
const mapper = new Trace.EntityMapper.EntityMapper(parsedTrace);
const funcCall = allThreadEntriesInTrace(parsedTrace).find(e => Trace.Types.Events.isFunctionCall(e));
assert.exists(funcCall);
// This function call should map to paulirish.com entity.
const gotEntity = mapper.entityForEvent(funcCall);
assert.deepEqual(gotEntity?.name, 'paulirish.com');
});
});
describe('eventsForEntity', () => {
it('correctly contains network req entity mappings', async function() {
const parsedTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
const mapper = new Trace.EntityMapper.EntityMapper(parsedTrace);
const reqs = getAllNetworkRequestsByHost(parsedTrace.data.NetworkRequests.byTime, 'www.paulirish.com');
const entity = mapper.entityForEvent(reqs[0]);
assert.exists(entity);
assert.deepEqual(entity.name, 'paulirish.com');
// Reqs should all be mapped to the correct entity.
const gotEvents = mapper.eventsForEntity(entity);
reqs.forEach(req => {
assert.isTrue(gotEvents.includes(req));
});
});
});
describe('first party', () => {
it('correctly captures the first party entity', async function() {
const localhostTrace = await TraceLoader.traceEngine(this, 'load-simple.json.gz');
let mapper = new Trace.EntityMapper.EntityMapper(localhostTrace);
let got = mapper.firstPartyEntity();
assert.deepEqual(got?.name, 'localhost');
const paulTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
mapper = new Trace.EntityMapper.EntityMapper(paulTrace);
got = mapper.firstPartyEntity();
assert.deepEqual(got?.name, 'paulirish.com');
const webDevTrace = await TraceLoader.traceEngine(this, 'web-dev.json.gz');
mapper = new Trace.EntityMapper.EntityMapper(webDevTrace);
got = mapper.firstPartyEntity();
assert.deepEqual(got?.name, 'web.dev');
});
it('correctly captures 3p events', async function() {
const paulTrace = await TraceLoader.traceEngine(this, 'lantern/paul/trace.json.gz');
const mapper = new Trace.EntityMapper.EntityMapper(paulTrace);
const got = mapper.firstPartyEntity();
assert.exists(got);
assert.deepEqual(got.name, 'paulirish.com');
const firstPartyEvents = mapper.eventsForEntity(got);
const gotThirdPartyEvents = mapper.thirdPartyEvents();
// If any failure is found in here, the event is categorized as both 1p AND 3p.
gotThirdPartyEvents.forEach(e => {
assert.isNotOk(firstPartyEvents.includes(e));
});
});
});
});