|
|
@ -1,6 +1,7 @@ |
|
|
import { describe, expect, test } from "bun:test"; |
|
|
import { describe, expect, test } from "bun:test"; |
|
|
import { |
|
|
import { |
|
|
buildMarkdownExportFileName, |
|
|
buildMarkdownExportFileName, |
|
|
|
|
|
downloadMarkdownFile, |
|
|
normalizeMarkdownImageUrls, |
|
|
normalizeMarkdownImageUrls, |
|
|
} from "./markdown-export"; |
|
|
} from "./markdown-export"; |
|
|
|
|
|
|
|
|
@ -55,3 +56,126 @@ describe("buildMarkdownExportFileName", () => { |
|
|
expect(result).toBe("post-42.md"); |
|
|
expect(result).toBe("post-42.md"); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
describe("downloadMarkdownFile", () => { |
|
|
|
|
|
test("does not throw when window/document are unavailable", () => { |
|
|
|
|
|
const windowDescriptor = Object.getOwnPropertyDescriptor(globalThis, "window"); |
|
|
|
|
|
const documentDescriptor = Object.getOwnPropertyDescriptor(globalThis, "document"); |
|
|
|
|
|
|
|
|
|
|
|
Object.defineProperty(globalThis, "window", { |
|
|
|
|
|
value: undefined, |
|
|
|
|
|
configurable: true, |
|
|
|
|
|
writable: true, |
|
|
|
|
|
}); |
|
|
|
|
|
Object.defineProperty(globalThis, "document", { |
|
|
|
|
|
value: undefined, |
|
|
|
|
|
configurable: true, |
|
|
|
|
|
writable: true, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
expect(() => downloadMarkdownFile("post.md", "# hello")).not.toThrow(); |
|
|
|
|
|
} finally { |
|
|
|
|
|
if (windowDescriptor) { |
|
|
|
|
|
Object.defineProperty(globalThis, "window", windowDescriptor); |
|
|
|
|
|
} else { |
|
|
|
|
|
Reflect.deleteProperty(globalThis, "window"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (documentDescriptor) { |
|
|
|
|
|
Object.defineProperty(globalThis, "document", documentDescriptor); |
|
|
|
|
|
} else { |
|
|
|
|
|
Reflect.deleteProperty(globalThis, "document"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
test("creates object URL, clicks anchor, and revokes URL in browser flow", () => { |
|
|
|
|
|
const windowDescriptor = Object.getOwnPropertyDescriptor(globalThis, "window"); |
|
|
|
|
|
const documentDescriptor = Object.getOwnPropertyDescriptor(globalThis, "document"); |
|
|
|
|
|
const urlDescriptor = Object.getOwnPropertyDescriptor(globalThis, "URL"); |
|
|
|
|
|
|
|
|
|
|
|
let createElementArg = ""; |
|
|
|
|
|
let appendedNode: unknown; |
|
|
|
|
|
let clicked = false; |
|
|
|
|
|
let removed = false; |
|
|
|
|
|
let revokedArg = ""; |
|
|
|
|
|
const blobUrl = "blob:test-url"; |
|
|
|
|
|
|
|
|
|
|
|
const anchor = { |
|
|
|
|
|
href: "", |
|
|
|
|
|
download: "", |
|
|
|
|
|
style: { display: "" }, |
|
|
|
|
|
click: () => { |
|
|
|
|
|
clicked = true; |
|
|
|
|
|
}, |
|
|
|
|
|
remove: () => { |
|
|
|
|
|
removed = true; |
|
|
|
|
|
}, |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Object.defineProperty(globalThis, "window", { |
|
|
|
|
|
value: {}, |
|
|
|
|
|
configurable: true, |
|
|
|
|
|
writable: true, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
Object.defineProperty(globalThis, "document", { |
|
|
|
|
|
value: { |
|
|
|
|
|
createElement: (tag: string) => { |
|
|
|
|
|
createElementArg = tag; |
|
|
|
|
|
return anchor; |
|
|
|
|
|
}, |
|
|
|
|
|
body: { |
|
|
|
|
|
appendChild: (node: unknown) => { |
|
|
|
|
|
appendedNode = node; |
|
|
|
|
|
}, |
|
|
|
|
|
}, |
|
|
|
|
|
}, |
|
|
|
|
|
configurable: true, |
|
|
|
|
|
writable: true, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
Object.defineProperty(globalThis, "URL", { |
|
|
|
|
|
value: { |
|
|
|
|
|
createObjectURL: (_blob: Blob) => blobUrl, |
|
|
|
|
|
revokeObjectURL: (url: string) => { |
|
|
|
|
|
revokedArg = url; |
|
|
|
|
|
}, |
|
|
|
|
|
}, |
|
|
|
|
|
configurable: true, |
|
|
|
|
|
writable: true, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
downloadMarkdownFile("hello.md", "# hello"); |
|
|
|
|
|
|
|
|
|
|
|
expect(createElementArg).toBe("a"); |
|
|
|
|
|
expect(appendedNode).toBe(anchor); |
|
|
|
|
|
expect(anchor.href).toBe(blobUrl); |
|
|
|
|
|
expect(anchor.download).toBe("hello.md"); |
|
|
|
|
|
expect(anchor.style.display).toBe("none"); |
|
|
|
|
|
expect(clicked).toBe(true); |
|
|
|
|
|
expect(removed).toBe(true); |
|
|
|
|
|
expect(revokedArg).toBe(blobUrl); |
|
|
|
|
|
} finally { |
|
|
|
|
|
if (windowDescriptor) { |
|
|
|
|
|
Object.defineProperty(globalThis, "window", windowDescriptor); |
|
|
|
|
|
} else { |
|
|
|
|
|
Reflect.deleteProperty(globalThis, "window"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (documentDescriptor) { |
|
|
|
|
|
Object.defineProperty(globalThis, "document", documentDescriptor); |
|
|
|
|
|
} else { |
|
|
|
|
|
Reflect.deleteProperty(globalThis, "document"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (urlDescriptor) { |
|
|
|
|
|
Object.defineProperty(globalThis, "URL", urlDescriptor); |
|
|
|
|
|
} else { |
|
|
|
|
|
Reflect.deleteProperty(globalThis, "URL"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|