Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 9 additions & 2 deletions src/browser/cdp/selectivity/css-selectivity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { groupBy } from "lodash";
import mm from "micromatch";
import path from "node:path";
import { resolve as urlResolve } from "node:url";
import { CSS_SOURCE_MAP_URL_COMMENT } from "../../../error-snippets/constants";
Expand All @@ -20,17 +21,19 @@ export class CSSSelectivity {
private readonly _cdp: CDP;
private readonly _sessionId: CDPSessionId;
private readonly _sourceRoot: string;
private readonly _ignoreSourceMapUrls: string[];
private _cssOnStyleSheetAddedFn:
| ((params: CssEvents["styleSheetAdded"], cdpSessionId?: CDPSessionId) => void)
| null = null;
private _stylesSourceMap: Record<CDPStyleSheetId, SelectivityAssetState> = {};
private _styleSheetIdToSourceMapUrl: Record<CDPStyleSheetId, string | null> = {};
private _coverageResult: CSSRuleUsage[] = [];

constructor(cdp: CDP, sessionId: CDPSessionId, sourceRoot = "") {
constructor(cdp: CDP, sessionId: CDPSessionId, sourceRoot = "", ignoreSourceMapUrls: string[] = []) {
this._cdp = cdp;
this._sessionId = sessionId;
this._sourceRoot = sourceRoot;
this._ignoreSourceMapUrls = ignoreSourceMapUrls;
}

private _processStyle(
Expand All @@ -41,7 +44,11 @@ export class CSSSelectivity {
return;
}

if (!sourceURL || !sourceMapURL) {
if (
!sourceURL ||
!sourceMapURL ||
(this._ignoreSourceMapUrls.length && mm.isMatch(sourceURL, this._ignoreSourceMapUrls))
) {
this._stylesSourceMap[styleSheetId] ||= null;
return;
}
Expand Down
6 changes: 3 additions & 3 deletions src/browser/cdp/selectivity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const testplaneCoverageBreakScriptName = "__testplane_cdp_coverage_snapshot_paus
const scriptToEvaluateOnNewDocument = `window.addEventListener("beforeunload", function ${testplaneCoverageBreakScriptName}() {debugger;});`;

export const startSelectivity = async (browser: ExistingBrowser): Promise<StopSelectivityFn> => {
const { enabled, compression, sourceRoot, testDependenciesPath, mapDependencyRelativePath } =
const { enabled, compression, sourceRoot, testDependenciesPath, mapDependencyRelativePath, ignoreSourceMapUrls } =
browser.config.selectivity;

if (!selectivityShouldWrite(enabled) || !browser.publicAPI.isChromium) {
Expand Down Expand Up @@ -169,8 +169,8 @@ export const startSelectivity = async (browser: ExistingBrowser): Promise<StopSe

const sessionId = await cdp.target.attachToTarget(cdpTargetId).then(r => r.sessionId);

const cssSelectivity = new CSSSelectivity(cdp, sessionId, sourceRoot);
const jsSelectivity = new JSSelectivity(cdp, sessionId, sourceRoot);
const cssSelectivity = new CSSSelectivity(cdp, sessionId, sourceRoot, ignoreSourceMapUrls);
const jsSelectivity = new JSSelectivity(cdp, sessionId, sourceRoot, ignoreSourceMapUrls);

await Promise.all([
cdp.dom.enable(sessionId).then(() => cdp.css.enable(sessionId)),
Expand Down
10 changes: 7 additions & 3 deletions src/browser/cdp/selectivity/js-selectivity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { groupBy } from "lodash";
import mm from "micromatch";
import { resolve as urlResolve } from "node:url";
import { JS_SOURCE_MAP_URL_COMMENT } from "../../../error-snippets/constants";
import { extractSourceFilesDeps, fetchTextWithBrowserFallback, isCachedOnFs, isDataProtocol } from "./utils";
Expand All @@ -19,6 +20,7 @@ export class JSSelectivity {
private readonly _cdp: CDP;
private readonly _sessionId: CDPSessionId;
private readonly _sourceRoot: string;
private readonly _ignoreSourceMapUrls: string[];
private _debuggerOnScriptParsedFn:
| ((params: DebuggerEvents["scriptParsed"], cdpSessionId?: CDPSessionId) => void)
| null = null;
Expand All @@ -28,10 +30,11 @@ export class JSSelectivity {
private _scriptIdToSourceMapUrl: Record<CDPRuntimeScriptId, string | null> = {};
private _coverageResult: CDPScriptCoverage[] = [];

constructor(cdp: CDP, sessionId: CDPSessionId, sourceRoot = "") {
constructor(cdp: CDP, sessionId: CDPSessionId, sourceRoot = "", ignoreSourceMapUrls: string[] = []) {
this._cdp = cdp;
this._sessionId = sessionId;
this._sourceRoot = sourceRoot;
this._ignoreSourceMapUrls = ignoreSourceMapUrls;
}

private _processScript(
Expand All @@ -44,7 +47,7 @@ export class JSSelectivity {

this._scriptIdToSourceUrl[scriptId] ||= url;

if (!url || !sourceMapURL) {
if (!url || !sourceMapURL || (this._ignoreSourceMapUrls.length && mm.isMatch(url, this._ignoreSourceMapUrls))) {
this._scriptsSource[scriptId] ||= null;
this._scriptsSourceMap[scriptId] ||= null;
return;
Expand Down Expand Up @@ -113,7 +116,8 @@ export class JSSelectivity {
// Was processed with "this._processScript" or anonymous
if (
(Object.hasOwn(this._scriptsSource, scriptId) && Object.hasOwn(this._scriptsSourceMap, scriptId)) ||
!fixedUrl
!fixedUrl ||
(this._ignoreSourceMapUrls.length && mm.isMatch(fixedUrl, this._ignoreSourceMapUrls))
) {
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ module.exports = {
testDependenciesPath: ".testplane/selectivity",
compression: "gz",
disableSelectivityPatterns: [],
ignoreSourceMapUrls: [],
mapDependencyRelativePath: null,
reportPath: "",
},
Expand Down
1 change: 1 addition & 0 deletions src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ export interface CommonConfig {
testDependenciesPath: string;
compression: SelectivityCompressionType;
disableSelectivityPatterns: string[];
ignoreSourceMapUrls: string[];
mapDependencyRelativePath: null | SelectivityMapDependencyRelativePathFn;
reportPath: string;
};
Expand Down
41 changes: 41 additions & 0 deletions test/src/browser/cdp/selectivity/css-selectivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,47 @@ describe("CDP/Selectivity/CSSSelectivity", () => {
});
});

describe("ignoreSourceMapUrls", () => {
it("should skip source map fetching for stylesheets matching ignore patterns", async () => {
const cssSelectivity = new CSSSelectivity(cdpMock as any, sessionId, sourceRoot, [
"https://cdn.example.com/**",
]);

await cssSelectivity.start();

const styleSheetAddedHandler = cdpMock.css.on.getCall(0).args[1];

styleSheetAddedHandler(
{
header: {
...styleSheetEvent.header,
sourceURL: "https://cdn.example.com/styles/theme.css",
sourceMapURL: "theme.css.map",
},
},
sessionId,
);

assert.notCalled(fetchTextWithBrowserFallbackStub);
assert.notCalled(hasCachedSelectivityFileStub);
});

it("should still fetch source maps for stylesheets not matching ignore patterns", async () => {
hasCachedSelectivityFileStub.resolves(false);
const cssSelectivity = new CSSSelectivity(cdpMock as any, sessionId, sourceRoot, [
"https://cdn.example.com/**",
]);

await cssSelectivity.start();

const styleSheetAddedHandler = cdpMock.css.on.getCall(0).args[1];

styleSheetAddedHandler(styleSheetEvent, sessionId);

assert.called(hasCachedSelectivityFileStub);
});
});

describe("start", () => {
it("should set up CDP connections and start rule usage tracking", async () => {
const cssSelectivity = new CSSSelectivity(cdpMock as any, sessionId, sourceRoot);
Expand Down
78 changes: 78 additions & 0 deletions test/src/browser/cdp/selectivity/js-selectivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,84 @@ describe("CDP/Selectivity/JSSelectivity", () => {
});
});

describe("ignoreSourceMapUrls", () => {
it("should skip source map fetching for scripts matching ignore patterns", async () => {
const jsSelectivity = new JSSelectivity(cdpMock as unknown as CDP, sessionId, sourceRoot, [
"https://cdn.example.com/**",
]);

await jsSelectivity.start();

const scriptParsedHandler = cdpMock.debugger.on.getCall(0).args[1];

scriptParsedHandler(
{
scriptId: "script-cdn",
url: "https://cdn.example.com/lib/bundle.js",
sourceMapURL: "bundle.js.map",
},
sessionId,
);

assert.notCalled(cdpMock.debugger.getScriptSource);
assert.notCalled(fetchTextWithBrowserFallbackStub);
});

it("should still fetch source maps for scripts not matching ignore patterns", async () => {
const hasCachedResult = Promise.resolve(false);
hasCachedSelectivityFileStub.returns(hasCachedResult);
const jsSelectivity = new JSSelectivity(cdpMock as unknown as CDP, sessionId, sourceRoot, [
"https://cdn.example.com/**",
]);

await jsSelectivity.start();

const scriptParsedHandler = cdpMock.debugger.on.getCall(0).args[1];

scriptParsedHandler(
{
scriptId: "script-own",
url: "https://my-app.example.com/app.js",
sourceMapURL: "app.js.map",
},
sessionId,
);

await hasCachedResult;

assert.calledOnce(cdpMock.debugger.getScriptSource);
});

it("should skip source map fetching in _ensureScriptsAreLoading for ignored URLs", async () => {
cdpMock.profiler.takePreciseCoverage.resolves({
timestamp: 100500,
result: [
{
scriptId: "script-cdn",
url: "https://cdn.example.com/lib/bundle.js",
functions: [
{
functionName: "foo",
isBlockCoverage: false,
ranges: [{ startOffset: 0, endOffset: 30, count: 1 }],
},
],
},
],
});

const jsSelectivity = new JSSelectivity(cdpMock as unknown as CDP, sessionId, sourceRoot, [
"https://cdn.example.com/**",
]);

await jsSelectivity.start();
await jsSelectivity.takeCoverageSnapshot();

assert.notCalled(cdpMock.debugger.getScriptSource);
assert.notCalled(fetchTextWithBrowserFallbackStub);
});
});

describe("start", () => {
it("should set up CDP connections and start coverage", async () => {
const jsSelectivity = new JSSelectivity(cdpMock as unknown as CDP, sessionId, sourceRoot);
Expand Down