mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-08 22:02:54 +00:00
tests(11): make uploadModal-reset zombie-callback test deterministic (correct mock boundary)
The "guard against zombie callbacks" subtest passed its asserts but leaked async
activity after the test ended (node:test flags that as failure). Root cause: it
mocked modal.generateTorrentMetadata / resolveUploadIdentifier, but
handleVideoSelection drives the upload through this.mediaUploader.uploadVideo —
a DIFFERENT object with its own helpers — so the mediaUploader still ran real
createTorrentMetadata()/hashing on a synthetic {name:"video.mp4"} file ("invalid
input type" async) and captureVideoMetadata() ran URL.createObjectURL(file)
("must be an instance of Blob"). Not intermittent — a consistent wrong-boundary mock.
Fix: mock at the real DI boundary — modal.mediaUploader.uploadVideo = () =>
delayedUpload (controllable pending promise) — and stub captureVideoMetadata.
Hermetic, deterministic (3/3 exit 0, # pass 3). Mutation-verified: breaking the
videoUploadId zombie guard makes the test fail. Production code untouched. See
TEST_INTEGRITY.md.
NOTE: the runner is fail-fast, so the full suite surfaces pre-existing failures one
at a time. tests/unit/hashChangeHandler.test.mjs is next (consistent AssertionError
on "loads default view if hash is empty" — likely the same stale-default bug the
sibling tests/app/hash-change-handler.test.mjs already had when TRENDING became the
logged-out default). Enumerating full scope next.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
a326d04330
commit
567a12c758
3 files changed
+68
-16
No files matched your search
@@ -151,17 +151,9 @@ describe("UploadModal Reset Logic", () => {
|
||||
let resolveUpload;
|
||||
const delayedUpload = new Promise(r => { resolveUpload = r; });
|
||||
|
||||
const slowR2Service = {
|
||||
prepareUpload: async () => ({
|
||||
settings: {},
|
||||
bucketEntry: { bucket: 'test', publicBaseUrl: 'https://test.com' }
|
||||
}),
|
||||
uploadFile: () => delayedUpload // Return promise that waits
|
||||
};
|
||||
|
||||
const modal = new UploadModal({
|
||||
storageService: mockStorageService,
|
||||
r2Service: slowR2Service,
|
||||
r2Service: mockR2Service,
|
||||
getCurrentPubkey: () => "pk1",
|
||||
removeTrackingScripts: () => {},
|
||||
setGlobalModalState: () => {},
|
||||
@@ -175,9 +167,19 @@ describe("UploadModal Reset Logic", () => {
|
||||
modal.activeProvider = "cloudflare_r2";
|
||||
modal.activeCredentials = { accountId: 'acc', accessKeyId: 'key', secretAccessKey: 'sec' };
|
||||
|
||||
// Mock generateTorrentMetadata BEFORE calling handleVideoSelection
|
||||
modal.generateTorrentMetadata = async () => ({ hasValidInfoHash: false });
|
||||
modal.resolveUploadIdentifier = async () => "mock-identifier";
|
||||
// handleVideoSelection() drives the upload through this.mediaUploader.uploadVideo
|
||||
// — NOT the modal's own generate/resolve helpers — so mock at THAT boundary.
|
||||
// Returning the controllable pending promise lets us reset mid-upload and then
|
||||
// release a "zombie" completion. This isolates the unit under test (the modal's
|
||||
// videoUploadId versioning guard) from real webtorrent/S3, which is what the
|
||||
// test intends. Previously the test mocked modal.generateTorrentMetadata /
|
||||
// resolveUploadIdentifier (the wrong object), so the mediaUploader still ran
|
||||
// real createTorrentMetadata()/hashing on a synthetic file — throwing "invalid
|
||||
// input type" as async activity after the test ended.
|
||||
modal.mediaUploader.uploadVideo = () => delayedUpload;
|
||||
// captureVideoMetadata() does URL.createObjectURL(file), which needs a real
|
||||
// Blob; stub it so the synthetic file below doesn't throw an async Blob error.
|
||||
modal.captureVideoMetadata = async () => {};
|
||||
|
||||
// Start upload
|
||||
const file = { name: "video.mp4" };
|
||||
|
||||
Reference in new issue
Block a user