Skip to content

Commit d2bd34e

Browse files
feat(selectivity): add ability to save incomplete dumps
1 parent 0d50573 commit d2bd34e

10 files changed

Lines changed: 360 additions & 64 deletions

File tree

src/browser/cdp/selectivity/hash-writer.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class HashWriter {
6161
dependencies.modules?.forEach(dependency => this._addModuleDependency(dependency));
6262
}
6363

64-
async save(readExisting?: boolean): Promise<void> {
64+
async save(): Promise<void> {
6565
const hasStaged = Boolean(
6666
this._stagedFileHashes.size || this._stagedModuleHashes.size || this._stagedPatternHashes.size,
6767
);
@@ -89,13 +89,7 @@ export class HashWriter {
8989
shallowSortObject(dest);
9090
};
9191

92-
const fileContents = readExisting
93-
? await readHashFileContents(this._selectivityHashesPath, this._compresion)
94-
: {
95-
files: {},
96-
modules: {},
97-
patterns: {},
98-
};
92+
const fileContents = await readHashFileContents(this._selectivityHashesPath, this._compresion);
9993

10094
await writeTo(this._stagedFileHashes, fileContents.files);
10195
await writeTo(this._stagedModuleHashes, fileContents.modules);

src/browser/cdp/selectivity/index.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getCollectedTestplaneJsDependencies, getCollectedTestplanePngDependenci
1212
import { getHashReader } from "./hash-reader";
1313
import type { Config } from "../../../config";
1414
import { MasterEvents } from "../../../events";
15-
import { selectivityShouldRead, selectivityShouldWrite } from "./modes";
15+
import { selectivityShouldWrite } from "./modes";
1616
import { debugSelectivity } from "./debug";
1717
import { getUsedDumpsTracker } from "./used-dumps-tracker";
1818
import { DebuggerEvents } from "../domains/debugger";
@@ -21,18 +21,22 @@ import { CDPSessionId } from "../types";
2121
type StopSelectivityFn = (test: Test, shouldWrite: boolean) => Promise<void>;
2222

2323
/**
24-
* Called at the end of successfull testplane run
24+
* Called at the end of testplane run
2525
* Not using "Promise.all" here because all hashes are already calculated and cached at the start
2626
*/
27-
export const updateSelectivityHashes = async (config: Config): Promise<void> => {
27+
export const updateSelectivityHashes = async (config: Config, isRunFailed: boolean): Promise<void> => {
2828
const browserIds = config.getBrowserIds();
2929
const processedRoots = new Set();
3030

3131
for (const browserId of browserIds) {
3232
const browserConfig = config.forBrowser(browserId);
33-
const { enabled, testDependenciesPath, compression, disableSelectivityPatterns } = browserConfig.selectivity;
34-
const shouldReadExistingHashes = selectivityShouldRead(enabled);
35-
const rootKey = `${shouldReadExistingHashes}#${testDependenciesPath}#${compression}`;
33+
const { enabled, testDependenciesPath, compression, disableSelectivityPatterns, saveIncompleteDumpOnFail } =
34+
browserConfig.selectivity;
35+
const rootKey = `${testDependenciesPath}#${compression}`;
36+
37+
if ((isRunFailed || browserConfig.lastFailed.only) && !saveIncompleteDumpOnFail) {
38+
continue;
39+
}
3640

3741
if (!selectivityShouldWrite(enabled) || processedRoots.has(rootKey)) {
3842
continue;
@@ -50,7 +54,7 @@ export const updateSelectivityHashes = async (config: Config): Promise<void> =>
5054
}
5155

5256
try {
53-
await hashWriter.save(shouldReadExistingHashes);
57+
await hashWriter.save();
5458
} catch (cause) {
5559
throw new Error("Selectivity: couldn't save test dependencies hash", { cause });
5660
}
@@ -59,16 +63,21 @@ export const updateSelectivityHashes = async (config: Config): Promise<void> =>
5963
}
6064
};
6165

62-
export const clearUnusedSelectivityDumps = async (config: Config): Promise<void> => {
66+
/**
67+
* Called at the end of testplane run
68+
*/
69+
export const clearUnusedSelectivityDumps = async (config: Config, isRunFailed: boolean): Promise<void> => {
6370
const usedDumpsTracker = getUsedDumpsTracker();
6471
const browserIds = config.getBrowserIds();
6572
const selectivityRoots: string[] = [];
6673

6774
for (const browserId of browserIds) {
6875
const browserConfig = config.forBrowser(browserId);
69-
const { enabled, testDependenciesPath } = browserConfig.selectivity;
76+
const { enabled, testDependenciesPath, saveIncompleteDumpOnFail } = browserConfig.selectivity;
7077

71-
if (selectivityShouldWrite(enabled) && !selectivityRoots.includes(testDependenciesPath)) {
78+
if ((isRunFailed && !saveIncompleteDumpOnFail) || browserConfig.lastFailed.only) {
79+
continue;
80+
} else if (selectivityShouldWrite(enabled) && !selectivityRoots.includes(testDependenciesPath)) {
7281
selectivityRoots.push(testDependenciesPath);
7382
}
7483
}

src/browser/cdp/selectivity/runner.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ const shouldDisableBrowserSelectivity = _.memoize(
2222
return true;
2323
}
2424

25+
if (config.lastFailed.only) {
26+
if (!config.selectivity.saveIncompleteDumpOnFail) {
27+
logger.warn(`Disabling selectivity for ${browserId}: lastFailedOnly mode is enabled`);
28+
} else {
29+
debugSelectivity(`Not skipping tests for ${browserId}: lastFailedOnly mode controls it`);
30+
}
31+
32+
return true;
33+
}
34+
2535
if (!config.selectivity.disableSelectivityPatterns.length) {
2636
return false;
2737
}
@@ -65,9 +75,10 @@ const shouldDisableBrowserSelectivity = _.memoize(
6575
},
6676
config => {
6777
const { enabled, testDependenciesPath, compression, disableSelectivityPatterns } = config.selectivity;
78+
const lastFailed = config.lastFailed.only;
6879

6980
return selectivityShouldRead(enabled)
70-
? testDependenciesPath + "#" + compression + "#" + disableSelectivityPatterns.join("#")
81+
? lastFailed + "#" + testDependenciesPath + "#" + compression + "#" + disableSelectivityPatterns.join("#")
7182
: "";
7283
},
7384
);

src/config/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ module.exports = {
132132
timeTravel: TimeTravelMode.Off,
133133
selectivity: {
134134
enabled: false,
135+
saveIncompleteDumpOnFail: false,
135136
sourceRoot: "",
136137
testDependenciesPath: ".testplane/selectivity",
137138
compression: "gz",

src/config/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ export interface CommonConfig {
419419

420420
selectivity: {
421421
enabled: SelectivityModeValue;
422+
saveIncompleteDumpOnFail: boolean;
422423
sourceRoot: string;
423424
testDependenciesPath: string;
424425
compression: SelectivityCompressionType;

src/test-reader/test-parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export class TestParser extends EventEmitter {
9999
}
100100
} catch {
101101
logger.warn(
102-
`Could not read failed tests data at ${config.lastFailed.input}. Running all tests instead`,
102+
`Could not read failed tests data at ${config.lastFailed.input}.`,
103103
);
104104
}
105105
}

src/testplane.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,10 @@ export class Testplane extends BaseTestplane {
206206
{ shouldDisableSelectivity },
207207
);
208208

209-
if (!shouldDisableSelectivity && !this.isFailed()) {
209+
if (!shouldDisableSelectivity) {
210210
const [updateResult, clearResult] = await Promise.allSettled([
211-
updateSelectivityHashes(this.config),
212-
clearUnusedSelectivityDumps(this.config),
211+
updateSelectivityHashes(this.config, this.isFailed()),
212+
clearUnusedSelectivityDumps(this.config, this.isFailed()),
213213
]);
214214

215215
if (updateResult.status === "rejected") {

test/src/browser/cdp/selectivity/hash-writer.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -214,24 +214,7 @@ describe("CDP/Selectivity/HashWriter", () => {
214214
});
215215
});
216216

217-
it("should not readHashFileContents when readExisting is false", async () => {
218-
const writer = new HashWriter("/test/selectivity", "none");
219-
const dependencies = {
220-
css: ["src/styles.css"],
221-
js: [],
222-
modules: [],
223-
png: [],
224-
};
225-
226-
fileHashProviderMock.calculateForFile.withArgs("src/styles.css").resolves("css-hash");
227-
228-
writer.addTestDependencyHashes(dependencies);
229-
await writer.save(false);
230-
231-
assert.notCalled(readHashFileContentsStub);
232-
});
233-
234-
it("should merge staged hashes with existing file contents when readExisting is true", async () => {
217+
it("should merge staged hashes with existing file contents", async () => {
235218
const existingContents = {
236219
files: { "src/old.css": "old-hash" },
237220
modules: { "node_modules/old-module": "old-module-hash" },
@@ -255,7 +238,7 @@ describe("CDP/Selectivity/HashWriter", () => {
255238
.resolves("module-hash");
256239

257240
writer.addTestDependencyHashes(dependencies);
258-
await writer.save(true);
241+
await writer.save();
259242

260243
assert.calledWith(writeJsonWithCompression, "/test/selectivity/hashes.json", {
261244
files: {

0 commit comments

Comments
 (0)