Files
remanso/src/hooks/useImageUpload.hook.spec.ts
Julien Calixte bb3a4a4dad
All checks were successful
CI / verify (push) Successful in 59s
test: cover post-merge gaps in utils, services, and hooks
Adds specs for the files added or modified in the recent merge that
weren't yet covered: oauthReturnPath, withATProtoImages, link,
displayLanguage, and the useGitHubContent / useImageUpload /
useNoteFreshness hooks. Locks in the new pullLatest contract
({raw, failureStatus}) and the fetchLatestSha branch semantics
(ok/unauthorized/offline).
2026-06-06 23:36:17 +02:00

165 lines
4.5 KiB
TypeScript

import { createPinia, setActivePinia } from "pinia"
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
const uploadBinaryFile = vi.fn()
const registerUploadedFile = vi.fn()
vi.mock("@/hooks/useGitHubContent.hook", () => ({
useGitHubContent: () => ({ uploadBinaryFile })
}))
vi.mock("@/modules/repo/store/userRepo.store", () => ({
useUserRepoStore: () => ({
files: [{ path: "alice/notes/already-here.png", sha: "x" }],
registerUploadedFile
})
}))
vi.mock("@/utils/notif", () => ({
errorMessage: vi.fn()
}))
import { errorMessage } from "@/utils/notif"
import { useImageUpload } from "./useImageUpload.hook"
const makeFile = (name: string, body = "fake-image-bytes") =>
new File([body], name, { type: "image/png" })
describe("useImageUpload", () => {
beforeEach(() => {
setActivePinia(createPinia())
uploadBinaryFile.mockReset()
registerUploadedFile.mockReset()
vi.mocked(errorMessage).mockReset()
})
afterEach(() => {
vi.restoreAllMocks()
})
it("returns null and shows an error when notePath is missing", async () => {
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: undefined
})
expect(await uploadImage(makeFile("img.png"))).toBeNull()
expect(errorMessage).toHaveBeenCalledWith("❌ Image upload failed")
expect(uploadBinaryFile).not.toHaveBeenCalled()
})
it("uploads to the note's directory using the note basename and the file extension", async () => {
uploadBinaryFile.mockResolvedValue({ sha: "new-sha", conflict: false })
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "alice/notes/my-note.md"
})
const result = await uploadImage(makeFile("photo.PNG"))
expect(result).toEqual({ filename: "my-note.png" })
expect(uploadBinaryFile).toHaveBeenCalledWith(
expect.objectContaining({
path: "alice/notes/my-note.png"
})
)
})
it("deduplicates filenames against existing files in the store", async () => {
uploadBinaryFile.mockResolvedValue({ sha: "new-sha", conflict: false })
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "alice/notes/already-here.md"
})
const result = await uploadImage(makeFile("photo.png"))
expect(result?.filename).toBe("already-here-2.png")
})
it("returns null on conflict and does NOT register the file", async () => {
uploadBinaryFile.mockResolvedValue({ sha: null, conflict: true })
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "x/note.md"
})
expect(await uploadImage(makeFile("img.png"))).toBeNull()
expect(registerUploadedFile).not.toHaveBeenCalled()
})
it("registers the uploaded file in the store on success", async () => {
uploadBinaryFile.mockResolvedValue({ sha: "abc", conflict: false })
const file = makeFile("img.png", "data")
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "x/note.md"
})
await uploadImage(file)
expect(registerUploadedFile).toHaveBeenCalledWith({
path: "x/note.png",
sha: "abc",
type: "blob",
size: file.size
})
})
it("falls back to .png when the file name has no extension", async () => {
uploadBinaryFile.mockResolvedValue({ sha: "abc", conflict: false })
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "x/note.md"
})
await uploadImage(makeFile("noextension"))
expect(uploadBinaryFile).toHaveBeenCalledWith(
expect.objectContaining({ path: "x/note.png" })
)
})
it("uses the root path when the note is at the repo root", async () => {
uploadBinaryFile.mockResolvedValue({ sha: "abc", conflict: false })
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "root.md"
})
await uploadImage(makeFile("img.png"))
expect(uploadBinaryFile).toHaveBeenCalledWith(
expect.objectContaining({ path: "root.png" })
)
})
it("returns null and notifies on unexpected errors", async () => {
vi.spyOn(console, "warn").mockImplementation(() => {})
uploadBinaryFile.mockRejectedValue(new Error("boom"))
const { uploadImage } = useImageUpload({
user: "alice",
repo: "notes",
notePath: "x/note.md"
})
expect(await uploadImage(makeFile("img.png"))).toBeNull()
expect(errorMessage).toHaveBeenCalledWith("❌ Image upload failed")
})
})