| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- import { assertEquals } from "@std/assert";
- import { find, insert } from "utils/db.ts";
- import { getCryptoString } from "utils/server.ts";
- let testCounter = 0;
- function getTestDbPath() {
- testCounter++;
- return `data/test_api_post_${testCounter}_${Date.now()}.db`;
- }
- function cleanup(dbPath: string) {
- try {
- Deno.removeSync(dbPath);
- } catch {
- // File may not exist
- }
- }
- function makeCtx(method: string, body?: object, cookie?: string) {
- const headers: Record<string, string> = { "Content-Type": "application/json" };
- if (cookie) headers["Cookie"] = cookie;
- const initMethod = method === "GET" && body ? "POST" : method;
- const req = new Request("http://localhost", {
- method: initMethod,
- headers,
- body: body ? JSON.stringify(body) : undefined,
- });
- if (method === "GET" && body) {
- Object.defineProperty(req, "method", { value: "GET" });
- }
- return { req };
- }
- async function seedUserAndToken(email: string, password: string) {
- const hashedPw = await getCryptoString(password, "MD5");
- const user = insert("User", {
- name: email.split("@")[0],
- email,
- password: hashedPw,
- });
- const userId = user[0]["id"] as string | number;
- const token = await getCryptoString("post-token-" + userId + Date.now(), "MD5");
- insert("Token", { token, user_id: userId });
- return { userId, token };
- }
- Deno.test("API post - create a new post", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { token } = await seedUserAndToken("postcreate@example.com", "password");
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("POST", {
- title: "My First Post",
- content: "# Hello World",
- }, `pd-user-token=${token}`);
- const res = await handler.POST!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, true);
- assertEquals(typeof body.data, "string");
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - create without token returns error", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("POST", {
- title: "Unauthorized Post",
- content: "Should fail",
- });
- const res = await handler.POST!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, false);
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - get own post", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { userId, token } = await seedUserAndToken("postget@example.com", "password");
- insert("Post", {
- id: "test-post-1",
- title: "Test Post",
- content: "Some content",
- user_id: userId,
- shared: 0,
- });
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("GET", { id: "test-post-1" }, `pd-user-token=${token}`);
- const res = await handler.GET!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, true);
- assertEquals(body.data.title, "Test Post");
- assertEquals(body.data.content, "Some content");
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - get shared post without token", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { userId } = await seedUserAndToken("postshared@example.com", "password");
- insert("Post", {
- id: "shared-post-1",
- title: "Shared Post",
- content: "Public content",
- user_id: userId,
- shared: 1,
- });
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("GET", { id: "shared-post-1" });
- const res = await handler.GET!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, true);
- assertEquals(body.data.title, "Shared Post");
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - get non-shared post without token returns error", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { userId } = await seedUserAndToken("postprivate@example.com", "password");
- insert("Post", {
- id: "private-post-1",
- title: "Private Post",
- content: "Secret content",
- user_id: userId,
- shared: 0,
- });
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("GET", { id: "private-post-1" });
- const res = await handler.GET!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, false);
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - update post title", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { userId, token } = await seedUserAndToken("postupdate@example.com", "password");
- insert("Post", {
- id: "update-post-1",
- title: "Old Title",
- content: "Content",
- user_id: userId,
- shared: 0,
- });
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("PUT", {
- id: "update-post-1",
- title: "New Title",
- }, `pd-user-token=${token}`);
- const res = await handler.PUT!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, true);
- const post = find("Post", { id: "update-post-1" }, ["title"]);
- assertEquals(post[0]["title"], "New Title");
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - update without token returns error", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("PUT", {
- id: "some-post",
- title: "Hacked Title",
- });
- const res = await handler.PUT!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, false);
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - delete own post", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { userId, token } = await seedUserAndToken("postdelete@example.com", "password");
- insert("Post", {
- id: "delete-post-1",
- title: "Delete Me",
- content: "Bye",
- user_id: userId,
- shared: 0,
- });
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("DELETE", {
- id: "delete-post-1",
- }, `pd-user-token=${token}`);
- const res = await handler.DELETE!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, true);
- const post = find("Post", { id: "delete-post-1" }, ["id"]);
- assertEquals(post.length, 0);
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
- Deno.test("API post - delete without token returns error", async () => {
- const dbPath = getTestDbPath();
- Deno.env.set("POSTDOWN_DB_PATH", dbPath);
- try {
- const { handler } = await import("../../routes/api/post.tsx");
- const ctx = makeCtx("DELETE", { id: "some-post" });
- const res = await handler.DELETE!(ctx as any);
- const body = await res.json();
- assertEquals(body.success, false);
- } finally {
- Deno.env.delete("POSTDOWN_DB_PATH");
- cleanup(dbPath);
- }
- });
|