import { createUser, db, get, insertCategory, insertDump, insertPlaylist, test, } from "../helpers.ts"; import type { SearchResults } from "../../../shared/search.ts"; import { assertEquals, assertFalse } from "@std/assert"; test("GET /api/search: dumps, users and playlists, privacy-filtered", async () => { const owner = await createUser({ username: "searcher_a" }); const other = await createUser(); db.prepare( `UPDATE users SET description = 'loves banana bread' WHERE id = ?;`, ).run(other.id); insertDump({ userId: owner.id, title: "Banana split" }); insertDump({ userId: owner.id, title: "x", comment: "a banana in the comment", }); insertDump({ userId: owner.id, title: "y", richContent: { type: "generic", url: "u", description: "banana page" }, }); insertDump({ userId: owner.id, title: "Secret banana", isPrivate: true }); insertDump({ userId: owner.id, title: "Apple" }); insertPlaylist({ userId: owner.id, title: "Banana hits" }); insertPlaylist({ userId: owner.id, title: "Private bananas", isPublic: false, }); const anon = (await get("/api/search?q=banana")).data; assertEquals(anon.dumps.total, 3); assertEquals(anon.users.map((u) => u.id), [other.id]); // Profiles only: a search must never hand out hashes or emails. assertFalse("passwordHash" in anon.users[0]); assertFalse("email" in anon.users[0]); assertEquals(anon.playlists.map((p) => p.title), [ "Banana hits", ]); const mine = (await get("/api/search?q=banana", { auth: owner.auth })) .data; assertEquals(mine.dumps.total, 4); assertEquals(mine.playlists.length, 2); const paged = (await get("/api/search?q=banana&limit=2")).data.dumps; assertEquals(paged.items.length, 2); assertEquals(paged.hasMore, true); assertEquals((await get("/api/search?q=%20%20")).data, { dumps: { items: [], total: 0, hasMore: false }, users: [], playlists: [], }); }); test("GET /api/search: category and playlistCategory narrow each list", async () => { const owner = await createUser(); const music = insertCategory({ slug: "music" }); const mixes = insertCategory({ slug: "mixes", kind: "playlist" }); const filed = insertDump({ userId: owner.id, title: "Banana song" }); insertDump({ userId: owner.id, title: "Banana bread" }); const list = insertPlaylist({ userId: owner.id, title: "Banana mix" }); insertPlaylist({ userId: owner.id, title: "Banana bin" }); db.prepare( `INSERT INTO dump_categories (dump_id, category_id) VALUES (?, ?);`, ).run(filed.id, music); db.prepare( `INSERT INTO playlist_categories (playlist_id, category_id) VALUES (?, ?);`, ).run(list.id, mixes); const all = (await get("/api/search?q=banana")).data; assertEquals(all.dumps.total, 2); assertEquals(all.playlists.length, 2); const dumps = (await get( "/api/search?q=banana&category=music", )).data; assertEquals(dumps.dumps.items.map((d) => d.id), [filed.id]); assertEquals(dumps.dumps.total, 1); assertEquals(dumps.playlists.length, 2); const playlists = (await get( "/api/search?q=banana&playlistCategory=mixes", )).data; assertEquals(playlists.dumps.total, 2); assertEquals(playlists.playlists.map((p) => p.id), [list.id]); assertEquals(playlists.playlists[0].categoryIds, [mixes]); // Each names a category of its own kind only. const crossed = (await get( "/api/search?q=banana&category=mixes&playlistCategory=music", )).data; assertEquals(crossed.dumps.total, 0); assertEquals(crossed.playlists, []); });