chore(ai): CI health fixes (flaky tests)

- Fix flaky test in `tests/hashtag-preferences.test.mjs` by defining missing `fetchCalls` variable.
- Fix `webtorrent` initialization error in `tests/unit/services/r2Service.storage-config.test.mjs` by ensuring `window.crypto` is available and `File` mock extends `Blob`.
- Update `tests/test-helpers/setup-localstorage.mjs` to polyfill `window.crypto` using `globalThis.crypto`.
- Update `scripts/run-unit-tests.mjs` to support test file filtering via command line arguments.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-02-01 02:10:21 +00:00
1 parent cd6e5862d7
commit 3511877ebe
4 files changed
+31 -10

No files matched your search

+21 -6
View File
@@ -11,8 +11,11 @@ const rootDir = path.dirname(fileURLToPath(new URL("../package.json", import.met
const testsDir = path.join(rootDir, "tests");
const testFiles = [];
const setupImport = new URL("../tests/test-helpers/setup-localstorage.mjs", import.meta.url);
const shardArg = process.argv.find((arg) => arg.startsWith("--shard="));
const args = process.argv.slice(2);
const shardArg = args.find((arg) => arg.startsWith("--shard="));
const shardValue = shardArg ? shardArg.split("=")[1] : process.env.UNIT_TEST_SHARD;
const filters = args.filter((arg) => !arg.startsWith("--"));
const timeoutMs = process.env.UNIT_TEST_TIMEOUT_MS
? Number(process.env.UNIT_TEST_TIMEOUT_MS)
: null;
@@ -89,19 +92,31 @@ async function run() {
return;
}
const shard = parseShard(shardValue);
const selectedTests = shard
? testFiles.filter((_, index) => index % shard.total === shard.index - 1)
: testFiles;
let selectedTests = testFiles;
if (filters.length > 0) {
selectedTests = selectedTests.filter((file) =>
filters.some((f) => file.includes(f)),
);
if (selectedTests.length === 0) {
console.log(`No tests matched filters: ${filters.join(", ")}`);
return;
}
console.log(`Filtered to ${selectedTests.length} test(s).`);
}
const shard = parseShard(shardValue);
if (shard) {
selectedTests = selectedTests.filter(
(_, index) => index % shard.total === shard.index - 1,
);
console.log(
`Using shard ${shard.index}/${shard.total} (${selectedTests.length} of ${testFiles.length} files).`,
);
}
if (selectedTests.length === 0) {
console.log("No unit tests found for this shard.");
console.log("No unit tests found for this shard/filter.");
return;
}
+2
View File
@@ -248,6 +248,8 @@ test(
: nostrClient.writeRelays;
const originalWindowNostr = window.nostr;
let fetchCalls = 0;
const event = {
id: "pref-permission",
created_at: 400,
@@ -44,6 +44,10 @@ if (typeof globalThis.window.localStorage === "undefined") {
globalThis.window.localStorage = globalThis.localStorage;
}
if (typeof globalThis.window.crypto === "undefined" && typeof globalThis.crypto !== "undefined") {
globalThis.window.crypto = globalThis.crypto;
}
if (typeof globalThis.structuredClone === "undefined") {
globalThis.structuredClone = (val) => JSON.parse(JSON.stringify(val));
}
@@ -22,6 +22,7 @@ beforeEach(() => {
globalThis.window = {
location: { origin: "" },
crypto: globalThis.crypto,
NostrTools: {
nip19: {
decode: () => ({ type: "npub", data: "pubkey123" }),
@@ -29,11 +30,10 @@ beforeEach(() => {
},
};
globalThis.File = class TestFile {
globalThis.File = class TestFile extends Blob {
constructor(parts, name, options = {}) {
this.parts = parts;
super(parts, options);
this.name = name;
this.type = options.type;
}
};
@@ -109,7 +109,7 @@ describe("R2Service bucket selection", () => {
await service.handleCloudflareUploadSubmit({
npub,
file: { name: "video.mp4", type: "video/mp4" },
file: new globalThis.File([], "video.mp4", { type: "video/mp4" }),
metadata: { title: "Test upload" },
publishVideoNote: mock.fn(async () => true),
});