Browse Source

ref: sendReq function for unit tests

Sv443 4 months ago
parent
commit
a15b510dbd
5 changed files with 62 additions and 37 deletions
  1. 8 8
      test/album.spec.ts
  2. 33 5
      test/hooks.ts
  3. 5 6
      test/misc.spec.ts
  4. 9 10
      test/search.spec.ts
  5. 7 8
      test/translations.spec.ts

+ 8 - 8
test/album.spec.ts

@@ -1,14 +1,14 @@
-import { baseUrl, defaultFetchOpts } from "./constants";
-import { checkAlbumProps, checkArtistProps } from "./hooks";
+import { baseUrl } from "./constants";
+import { checkAlbumProps, checkArtistProps, sendReq } from "./hooks";
 
 describe("Album routes", () => {
   //#region /album/:id
 
   it("Album details yields correct props", async () => {
-    const res = await fetch(`${baseUrl}/album/7105950`, defaultFetchOpts);
+    const { status, res } = await sendReq(`${baseUrl}/album/7105950`);
     const body = await res.json();
 
-    expect(res.status).toBe(200);
+    expect(status).toBe(200);
 
     expect(body?.error).toEqual(false);
     expect(body?.matches).toEqual(1);
@@ -21,10 +21,10 @@ describe("Album routes", () => {
   //#region inv /album/:id
 
   it("Invalid song ID yields error", async () => {
-    const res = await fetch(`${baseUrl}/album/0`, defaultFetchOpts);
+    const { res, status } = await sendReq(`${baseUrl}/album/0`);
     const body = await res.json();
 
-    expect(res.status).toBe(400);
+    expect(status).toBe(400);
 
     expect(body?.error).toEqual(true);
     expect(body?.matches).toEqual(0);
@@ -34,10 +34,10 @@ describe("Album routes", () => {
   //#region inv /album
 
   it("Album path without ID yields error", async () => {
-    const res = await fetch(`${baseUrl}/album`, defaultFetchOpts);
+    const { res, status } = await sendReq(`${baseUrl}/album`);
     const body = await res.json();
 
-    expect(res.status).toBe(400);
+    expect(status).toBe(400);
 
     expect(body?.error).toEqual(true);
     expect(body?.matches).toEqual(null);

+ 33 - 5
test/hooks.ts

@@ -1,10 +1,17 @@
-export function checkValProps(val: unknown, props: string[]) {
+import { baseUrl, defaultFetchOpts } from "./constants";
+
+//#region validate objects
+
+/** Checks if the given object has the specified properties */
+export function checkObjProps(val: unknown, props: string[]) {
+  expect(typeof val).toBe("object");
   for(const prop of props)
     expect(val).toHaveProperty(prop);
 }
 
+/** Checks if the given song object has the required properties */
 export function checkSongProps(songObj: unknown) {
-  return checkValProps(songObj, [
+  return checkObjProps(songObj, [
     "url", 
     "path", 
     "lyricsState", 
@@ -15,8 +22,9 @@ export function checkSongProps(songObj: unknown) {
   ]);
 }
 
+/** Checks if the given album object has the required properties */
 export function checkAlbumProps(albumObj: unknown) {
-  return checkValProps(albumObj, [
+  return checkObjProps(albumObj, [
     "name",
     "fullTitle",
     "url",
@@ -26,8 +34,9 @@ export function checkAlbumProps(albumObj: unknown) {
   ]);
 }
 
+/** Checks if the given artist object has the required properties */
 export function checkArtistProps(artistObj: unknown) {
-  return checkValProps(artistObj, [
+  return checkObjProps(artistObj, [
     "name",
     "url",
     "image",
@@ -35,8 +44,9 @@ export function checkArtistProps(artistObj: unknown) {
   ]);
 }
 
+/** Checks if the given translation object has the required properties */
 export function checkTranslationProps(translationObj: unknown) {
-  return checkValProps(translationObj, [
+  return checkObjProps(translationObj, [
     "language",
     "id",
     "path",
@@ -44,3 +54,21 @@ export function checkTranslationProps(translationObj: unknown) {
     "url",
   ]);
 }
+
+//#region send requests
+
+/** Sends a request to the specified URL with the given options. Authentication and method "GET" are set by default. */
+export async function sendReq<
+  TAsJson extends boolean,
+>(
+  path: string,
+  opts?: RequestInit & { asJson?: TAsJson },
+): Promise<{
+  res: Response;
+  status: number;
+  headers: Headers;
+}> {
+  const res = await fetch(`${baseUrl}/${path.startsWith("/") ? path.substring(1) : path}`, { ...defaultFetchOpts, ...opts });
+  
+  return { res, status: res.status, headers: res.headers };
+}

+ 5 - 6
test/misc.spec.ts

@@ -1,15 +1,14 @@
-import { baseUrl, defaultFetchOpts } from "./constants";
+import { sendReq } from "./hooks";
 
-describe("Misc", () => {
+describe("Miscellaneous", () => {
   //#region health check
 
   it("Health check", async () => {
-    const res = await fetch(`${baseUrl}/health`, {
-      ...defaultFetchOpts,
+    const { status, headers } = await sendReq("/health", {
       method: "HEAD",
     });
 
-    expect(res.status).toBe(200);
-    expect(res.headers.get("api-info")).not.toBeNull();
+    expect(status).toBe(200);
+    expect(headers.get("api-info")).not.toBeNull();
   });
 });

+ 9 - 10
test/search.spec.ts

@@ -1,16 +1,15 @@
 import { randomBytes } from "crypto";
 import { XMLParser } from "fast-xml-parser";
-import { baseUrl, defaultFetchOpts } from "./constants";
-import { checkSongProps } from "./hooks";
+import { checkSongProps, sendReq } from "./hooks";
 
 describe("Search routes", () => {
   //#region /search/top
 
   it("Top search yields expected props", async () => {
-    const res = await fetch(`${baseUrl}/search/top?q=Lil Nas X - LIGHT AGAIN!`, defaultFetchOpts);
+    const { res, status } = await sendReq("/search/top?q=Lil Nas X - LIGHT AGAIN!");
     const body = await res.json();
 
-    expect(res.status).toBe(200);
+    expect(status).toBe(200);
 
     expect(body?.error).toEqual(false);
     expect(body?.matches).toEqual(1);
@@ -21,10 +20,10 @@ describe("Search routes", () => {
   //#region /search/top xml
 
   it("Top search with format=xml yields valid XML", async () => {
-    const res = await fetch(`${baseUrl}/search/top?format=xml&q=Lil Nas X - LIGHT AGAIN!`, defaultFetchOpts);
+    const { res, status } = await sendReq("/search/top?format=xml&q=Lil Nas X - LIGHT AGAIN!");
     const body = await res.text();
 
-    expect(res.status).toBe(200);
+    expect(status).toBe(200);
 
     const parsed = new XMLParser().parse(body);
 
@@ -39,10 +38,10 @@ describe("Search routes", () => {
   //#region /search
 
   it("Regular search yields <=10 results", async () => {
-    const res = await fetch(`${baseUrl}/search?q=Lil Nas X`, defaultFetchOpts);
+    const { res, status } = await sendReq("/search?q=Lil Nas X");
     const body = await res.json();
 
-    expect(res.status).toBe(200);
+    expect(status).toBe(200);
 
     expect(body?.error).toEqual(false);
     expect(body?.matches).toBeLessThanOrEqual(10);
@@ -60,10 +59,10 @@ describe("Search routes", () => {
 
   it("Invalid search yields error", async () => {
     const randText = randomBytes(32).toString("hex");
-    const res = await fetch(`${baseUrl}/search?q=${randText}`, defaultFetchOpts);
+    const { res, status } = await sendReq(`/search?q=${randText}`);
     const body = await res.json();
 
-    expect(res.status).toBe(400);
+    expect(status).toBe(400);
 
     expect(body?.error).toEqual(true);
     expect(body?.matches).toEqual(0);

+ 7 - 8
test/translations.spec.ts

@@ -1,14 +1,13 @@
-import { baseUrl, defaultFetchOpts } from "./constants";
-import { checkTranslationProps } from "./hooks";
+import { checkTranslationProps, sendReq } from "./hooks";
 
 describe("Translation routes", () => {
   //#region /translations/:id
 
   it("Translation yields correct props", async () => {
-    const res = await fetch(`${baseUrl}/translations/7105950`, defaultFetchOpts);
+    const { res, status } = await sendReq("/translations/7105950");
     const body = await res.json();
 
-    expect(res.status).toBe(200);
+    expect(status).toBe(200);
 
     expect(body?.error).toEqual(false);
     expect(body?.matches).toBeGreaterThan(0);
@@ -21,10 +20,10 @@ describe("Translation routes", () => {
   //#region inv /translations/:id
 
   it("Invalid song ID yields error", async () => {
-    const res = await fetch(`${baseUrl}/translations/0`, defaultFetchOpts);
+    const { res, status } = await sendReq("/translations/0");
     const body = await res.json();
 
-    expect(res.status).toBe(400);
+    expect(status).toBe(400);
 
     expect(body?.error).toEqual(true);
     expect(body?.matches).toEqual(null);
@@ -34,10 +33,10 @@ describe("Translation routes", () => {
   //#region inv /translations
 
   it("Translations path without ID yields error", async () => {
-    const res = await fetch(`${baseUrl}/translations`, defaultFetchOpts);
+    const { res, status } = await sendReq("/translations");
     const body = await res.json();
 
-    expect(res.status).toBe(400);
+    expect(status).toBe(400);
 
     expect(body?.error).toEqual(true);
     expect(body?.matches).toEqual(null);