Add test helpers

This commit is contained in:
Zoe Roux 2025-01-10 00:25:47 +01:00
parent 0555fcb9a5
commit e78f28ea71
No known key found for this signature in database
5 changed files with 112 additions and 120 deletions

View File

@ -1,56 +1,20 @@
import { afterAll, beforeAll, describe, expect, it } from "bun:test"; import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import Elysia from "elysia"; import { expectStatus } from "tests/utils";
import { base } from "~/base";
import { movies } from "~/controllers/movies";
import { seedMovie } from "~/controllers/seed/movies"; import { seedMovie } from "~/controllers/seed/movies";
import { db } from "~/db"; import { db } from "~/db";
import { shows } from "~/db/schema"; import { shows } from "~/db/schema";
import { bubble } from "~/models/examples"; import { bubble } from "~/models/examples";
import { dune1984 } from "~/models/examples/dune-1984"; import { dune1984 } from "~/models/examples/dune-1984";
import { dune } from "~/models/examples/dune-2021"; import { dune } from "~/models/examples/dune-2021";
import { getMovies, movieApp } from "./movies-helper";
const app = new Elysia().use(base).use(movies); beforeAll(async () => {
const getMovies = async ({ await db.delete(shows);
langs, for (const movie of [bubble, dune1984, dune]) await seedMovie(movie);
...query });
}: { afterAll(async () => {
filter?: string; await db.delete(shows);
limit?: number; });
after?: string;
sort?: string | string[];
langs?: string;
}) => {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (!Array.isArray(value)) {
params.append(key, value.toString());
continue;
}
for (const v of value) params.append(key, v.toString());
}
const resp = await app.handle(
new Request(`http://localhost/movies?${params}`, {
method: "GET",
headers: langs
? {
"Accept-Language": langs,
}
: {},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
function expectStatus(resp: Response, body: object) {
const matcher = expect({ ...body, status: resp.status });
return {
toBe: (status: number) => {
matcher.toMatchObject({ status: status });
},
};
}
describe("Get all movies", () => { describe("Get all movies", () => {
it("Invalid filter params", async () => { it("Invalid filter params", async () => {
@ -108,7 +72,7 @@ describe("Get all movies", () => {
}); });
expectStatus(resp, body).toBe(200); expectStatus(resp, body).toBe(200);
resp = await app.handle(new Request(body.next)); resp = await movieApp.handle(new Request(body.next));
body = await resp.json(); body = await resp.json();
expectStatus(resp, body).toBe(200); expectStatus(resp, body).toBe(200);
@ -141,23 +105,19 @@ describe("Get all movies", () => {
), ),
}); });
resp = await app.handle(new Request(next)); resp = await movieApp.handle(new Request(next));
body = await resp.json(); body = await resp.json();
expectStatus(resp, body).toBe(200); expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({ expect(body).toMatchObject({
items: [expect.objectContaining({ slug: dune1984.slug })], items: [
expect.objectContaining({
slug: dune1984.slug,
airDate: dune1984.airDate,
}),
],
this: next, this: next,
next: null, next: null,
}); });
}); });
// TODO: sort with an item that has null in it. We want it to always be last (in both asc & desc).
});
beforeAll(async () => {
await db.delete(shows);
for (const movie of [bubble, dune1984, dune]) await seedMovie(movie);
});
afterAll(async () => {
await db.delete(shows);
}); });

View File

@ -1,39 +1,21 @@
import { afterAll, beforeAll, describe, expect, it } from "bun:test"; import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import Elysia from "elysia";
import { base } from "~/base";
import { movies } from "~/controllers/movies";
import { seedMovie } from "~/controllers/seed/movies"; import { seedMovie } from "~/controllers/seed/movies";
import { db } from "~/db"; import { db } from "~/db";
import { shows } from "~/db/schema"; import { shows } from "~/db/schema";
import { bubble } from "~/models/examples"; import { bubble } from "~/models/examples";
import { getMovie } from "./movies-helper";
const app = new Elysia().use(base).use(movies); import { expectStatus } from "tests/utils";
const getMovie = async (id: string, langs?: string) => {
const resp = await app.handle(
new Request(`http://localhost/movies/${id}`, {
method: "GET",
headers: langs
? {
"Accept-Language": langs,
}
: {},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
let bubbleId = ""; let bubbleId = "";
function expectStatus(resp: Response, body: object) { beforeAll(async () => {
const matcher = expect({ ...body, status: resp.status }); const ret = await seedMovie(bubble);
return { bubbleId = ret.id;
toBe: (status: number) => { });
matcher.toMatchObject({ status: status }); afterAll(async () => {
}, await db.delete(shows).where(eq(shows.slug, bubble.slug));
}; });
}
describe("Get movie", () => { describe("Get movie", () => {
it("Retrive by slug", async () => { it("Retrive by slug", async () => {
@ -94,11 +76,3 @@ describe("Get movie", () => {
expect(resp.headers.get("Content-Language")).toBe("en"); expect(resp.headers.get("Content-Language")).toBe("en");
}); });
}); });
beforeAll(async () => {
const ret = await seedMovie(bubble);
bubbleId = ret.id;
});
afterAll(async () => {
await db.delete(shows).where(eq(shows.slug, bubble.slug));
});

View File

@ -0,0 +1,61 @@
import Elysia from "elysia";
import { buildUrl } from "tests/utils";
import { base } from "~/base";
import { movies } from "~/controllers/movies";
import { seed } from "~/controllers/seed";
import type { SeedMovie } from "~/models/movie";
export const movieApp = new Elysia().use(base).use(movies).use(seed);
export const getMovie = async (id: string, langs?: string) => {
const resp = await movieApp.handle(
new Request(`http://localhost/movies/${id}`, {
method: "GET",
headers: langs
? {
"Accept-Language": langs,
}
: {},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
export const getMovies = async ({
langs,
...query
}: {
filter?: string;
limit?: number;
after?: string;
sort?: string | string[];
langs?: string;
}) => {
const resp = await movieApp.handle(
new Request(buildUrl("movies", query), {
method: "GET",
headers: langs
? {
"Accept-Language": langs,
}
: {},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
export const createMovie = async (movie: SeedMovie) => {
const resp = await movieApp.handle(
new Request("http://localhost/movies", {
method: "POST",
body: JSON.stringify(movie),
headers: {
"Content-Type": "application/json",
},
}),
);
const body = await resp.json();
return [resp, body] as const;
};

View File

@ -1,37 +1,11 @@
import { afterAll, beforeAll, describe, expect, it, test } from "bun:test"; import { afterAll, beforeAll, describe, expect, it, test } from "bun:test";
import { eq, inArray } from "drizzle-orm"; import { eq, inArray } from "drizzle-orm";
import Elysia from "elysia"; import { expectStatus } from "tests/utils";
import { base } from "~/base";
import { seed } from "~/controllers/seed";
import { db } from "~/db"; import { db } from "~/db";
import { shows, showTranslations, videos } from "~/db/schema"; import { shows, showTranslations, videos } from "~/db/schema";
import { bubble } from "~/models/examples"; import { bubble } from "~/models/examples";
import { dune, duneVideo } from "~/models/examples/dune-2021"; import { dune, duneVideo } from "~/models/examples/dune-2021";
import type { SeedMovie } from "~/models/movie"; import { createMovie } from "./movies-helper";
const app = new Elysia().use(base).use(seed);
const createMovie = async (movie: SeedMovie) => {
const resp = await app.handle(
new Request("http://localhost/movies", {
method: "POST",
body: JSON.stringify(movie),
headers: {
"Content-Type": "application/json",
},
}),
);
const body = await resp.json();
return [resp, body] as const;
};
function expectStatus(resp: Response, body: object) {
const matcher = expect({ ...body, status: resp.status });
return {
toBe: (status: number) => {
matcher.toMatchObject({ status: status });
},
};
}
describe("Movie seeding", () => { describe("Movie seeding", () => {
it("Can create a movie", async () => { it("Can create a movie", async () => {

23
api/tests/utils.ts Normal file
View File

@ -0,0 +1,23 @@
import { expect } from "bun:test";
import Elysia from "elysia";
export function expectStatus(resp: Response, body: object) {
const matcher = expect({ ...body, status: resp.status });
return {
toBe: (status: number) => {
matcher.toMatchObject({ status: status });
},
};
}
export const buildUrl = (route: string, query: Record<string, any>) => {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (!Array.isArray(value)) {
params.append(key, value.toString());
continue;
}
for (const v of value) params.append(key, v.toString());
}
return `http://localhost/${route}?${params}`;
};