1 Commits
Author SHA1 Message Date
clawbot d5d7908ff6 Test the live-photo hash check's error paths (closes #117)
check / check (push) Successful in 16s
Three downloadFile tests cover a live photo whose ZIP names an unknown
compression method, one whose ZIP has no image entry and one with no
video entry. Each checks that nothing is stored and the error names the
file ID; the unreadable ZIP is also checked not to be retried. Each test
fails when its check in livePhotoHasher is removed.

Model: opus-5-5
2026-09-23 04:51:31 +00:00
2 changed files with 43 additions and 0 deletions
+5
View File
@@ -18,6 +18,11 @@ Tag v1.0.0.
# Completed Steps # Completed Steps
- 2026-09-23: Tested the live-photo hash check's error paths (issue 117). Tests
download a live photo whose ZIP names an unknown compression method, one whose
ZIP has no image entry and one with no video entry, and check that nothing is
stored and the error names the file ID; the unreadable one is not retried.
- 2026-09-23: `quak logout` ends the session on the server (issue 108). It calls - 2026-09-23: `quak logout` ends the session on the server (issue 108). It calls
`POST /users/logout` through the new `Client.logoutOnServer()`, then deletes `POST /users/logout` through the new `Client.logoutOnServer()`, then deletes
`session.json` even when that call fails, says so and exits 1. It prints the `session.json` even when that call fails, says so and exits 1. It prints the
+38
View File
@@ -1747,4 +1747,42 @@ describe("downloadFile content hash", () => {
expect(readdirSync(t.dir)).toEqual([]); expect(readdirSync(t.dir)).toEqual([]);
}); });
it("rejects a live photo that is not a readable ZIP and does not retry", async () => {
// Bytes 8-9 of a ZIP entry's local header name its compression
// method; 99 is one no reader knows, so the entry cannot be read.
const zip = livePhotoZip.slice();
zip[8] = 99;
zip[9] = 0;
const t = setup(zip, { fileType: "livePhoto", hash: livePhotoHash });
await expect(t.run()).rejects.toThrow(
/file 999: live photo is not a readable ZIP/,
);
expect(readdirSync(t.dir)).toEqual([]);
expect(t.requests()).toBe(1);
});
it("rejects a live photo ZIP with no image entry", async () => {
const zip = zipSync({ "video.mov": patternBytes(900, 82) });
const t = setup(zip, { fileType: "livePhoto", hash: livePhotoHash });
await expect(t.run()).rejects.toThrow(
/file 999: live photo ZIP does not hold both an image and a video/,
);
expect(readdirSync(t.dir)).toEqual([]);
});
it("rejects a live photo ZIP with no video entry", async () => {
const zip = zipSync({ "image.heic": patternBytes(500, 81) });
const t = setup(zip, { fileType: "livePhoto", hash: livePhotoHash });
await expect(t.run()).rejects.toThrow(
/file 999: live photo ZIP does not hold both an image and a video/,
);
expect(readdirSync(t.dir)).toEqual([]);
});
}); });