fix: resolve biome lint errors in discovery files
All checks were successful
CI / ci (push) Successful in 1m8s
CI / e2e (push) Has been skipped
CI / deploy (push) Successful in 14s

Remove unused functions and imports from route tests, fix array index key
warnings in skeleton components, apply biome formatting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 15:15:58 +02:00
parent c98995288b
commit 6e3ce4a31f
4 changed files with 74 additions and 53 deletions

View File

@@ -143,12 +143,14 @@ function TrendingCategoriesSection() {
</div> </div>
{isLoading ? ( {isLoading ? (
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
{Array.from({ length: 8 }).map((_, i) => ( {Array.from({ length: 8 }, (_, i) => `cat-skeleton-${i}`).map(
<div (key) => (
key={i} <div
className="h-8 w-24 bg-gray-100 rounded-full animate-pulse" key={key}
/> className="h-8 w-24 bg-gray-100 rounded-full animate-pulse"
))} />
),
)}
</div> </div>
) : ( ) : (
<div className="flex flex-wrap gap-2"> <div className="flex flex-wrap gap-2">
@@ -172,9 +174,9 @@ function SectionSkeleton({ count, aspect }: { count: number; aspect: string }) {
<div <div
className={`grid ${aspect === "none" ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3" : "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4"} gap-4`} className={`grid ${aspect === "none" ? "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3" : "grid-cols-2 sm:grid-cols-3 lg:grid-cols-4"} gap-4`}
> >
{Array.from({ length: count }).map((_, i) => ( {Array.from({ length: count }, (_, i) => `skeleton-${i}`).map((key) => (
<div <div
key={i} key={key}
className="bg-white rounded-xl border border-gray-100 overflow-hidden animate-pulse" className="bg-white rounded-xl border border-gray-100 overflow-hidden animate-pulse"
> >
{aspect !== "none" && ( {aspect !== "none" && (

View File

@@ -1,6 +1,6 @@
import { and, count, desc, eq, isNotNull, lt, sql } from "drizzle-orm"; import { and, count, desc, eq, isNotNull, lt, sql } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts"; import { db as prodDb } from "../../db/index.ts";
import { globalItems, setups, setupItems, users } from "../../db/schema.ts"; import { globalItems, setupItems, setups, users } from "../../db/schema.ts";
type Db = typeof prodDb; type Db = typeof prodDb;
@@ -44,10 +44,7 @@ export async function getPopularSetups(
.leftJoin(users, eq(users.id, setups.userId)) .leftJoin(users, eq(users.id, setups.userId))
.where(eq(setups.isPublic, true)) .where(eq(setups.isPublic, true))
.groupBy(setups.id, setups.name, setups.createdAt, users.displayName) .groupBy(setups.id, setups.name, setups.createdAt, users.displayName)
.orderBy( .orderBy(desc(sql<number>`COUNT(${setupItems.id})`), desc(setups.id))
desc(sql<number>`COUNT(${setupItems.id})`),
desc(setups.id),
)
.limit(fetchLimit); .limit(fetchLimit);
// Apply cursor filter in JS (composite cursor: itemCount_id) // Apply cursor filter in JS (composite cursor: itemCount_id)

View File

@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it } from "bun:test"; import { beforeEach, describe, expect, it } from "bun:test";
import { Hono } from "hono"; import { Hono } from "hono";
import { globalItems, items, setups, setupItems } from "../../src/db/schema.ts"; import { globalItems, setups } from "../../src/db/schema.ts";
import { discoveryRoutes } from "../../src/server/routes/discovery.ts"; import { discoveryRoutes } from "../../src/server/routes/discovery.ts";
import { createTestDb } from "../helpers/db.ts"; import { createTestDb } from "../helpers/db.ts";
@@ -45,26 +45,6 @@ async function insertPublicSetup(
return row; return row;
} }
async function insertItem(
db: TestDb["db"],
userId: number,
name: string,
): Promise<number> {
const [row] = await db
.insert(items)
.values({ name, categoryId: 1, userId })
.returning();
return row.id;
}
async function addItemToSetup(
db: TestDb["db"],
setupId: number,
itemId: number,
) {
await db.insert(setupItems).values({ setupId, itemId });
}
describe("Discovery Routes", () => { describe("Discovery Routes", () => {
let app: Hono; let app: Hono;
let db: TestDb["db"]; let db: TestDb["db"];

View File

@@ -3,8 +3,8 @@ import { eq } from "drizzle-orm";
import { import {
globalItems, globalItems,
items, items,
setups,
setupItems, setupItems,
setups,
users, users,
} from "../../src/db/schema.ts"; } from "../../src/db/schema.ts";
import { import {
@@ -31,11 +31,7 @@ async function insertGlobalItem(
return row; return row;
} }
async function insertItem( async function insertItem(db: TestDb["db"], userId: number, categoryId = 1) {
db: TestDb["db"],
userId: number,
categoryId = 1,
) {
const [row] = await db const [row] = await db
.insert(items) .insert(items)
.values({ name: "Test Item", categoryId, userId }) .values({ name: "Test Item", categoryId, userId })
@@ -115,7 +111,11 @@ describe("Discovery Service", () => {
const item2 = await insertItem(db, userId); const item2 = await insertItem(db, userId);
const item3 = await insertItem(db, userId); const item3 = await insertItem(db, userId);
await insertPublicSetup(db, userId, "Setup A", [item1.id, item2.id, item3.id]); await insertPublicSetup(db, userId, "Setup A", [
item1.id,
item2.id,
item3.id,
]);
await insertPublicSetup(db, userId, "Setup B", [item1.id, item2.id]); await insertPublicSetup(db, userId, "Setup B", [item1.id, item2.id]);
await insertPublicSetup(db, userId, "Setup C", [item1.id]); await insertPublicSetup(db, userId, "Setup C", [item1.id]);
@@ -129,7 +129,11 @@ describe("Discovery Service", () => {
const item2 = await insertItem(db, userId); const item2 = await insertItem(db, userId);
const item3 = await insertItem(db, userId); const item3 = await insertItem(db, userId);
await insertPublicSetup(db, userId, "Setup A", [item1.id, item2.id, item3.id]); await insertPublicSetup(db, userId, "Setup A", [
item1.id,
item2.id,
item3.id,
]);
await insertPublicSetup(db, userId, "Setup B", [item1.id, item2.id]); await insertPublicSetup(db, userId, "Setup B", [item1.id, item2.id]);
await insertPublicSetup(db, userId, "Setup C", [item1.id]); await insertPublicSetup(db, userId, "Setup C", [item1.id]);
@@ -144,7 +148,8 @@ describe("Discovery Service", () => {
it("includes creatorName from users.displayName", async () => { it("includes creatorName from users.displayName", async () => {
// Update user display name // Update user display name
await db.update(users) await db
.update(users)
.set({ displayName: "Jean-Luc" }) .set({ displayName: "Jean-Luc" })
.where(eq(users.id, userId)); .where(eq(users.id, userId));
@@ -160,11 +165,20 @@ describe("Discovery Service", () => {
describe("getRecentGlobalItems", () => { describe("getRecentGlobalItems", () => {
it("returns items ordered by createdAt descending", async () => { it("returns items ordered by createdAt descending", async () => {
// Insert items with slight delay to get different timestamps // Insert items with slight delay to get different timestamps
const item1 = await insertGlobalItem(db, { brand: "BrandA", model: "Model1" }); const item1 = await insertGlobalItem(db, {
brand: "BrandA",
model: "Model1",
});
await new Promise((r) => setTimeout(r, 5)); await new Promise((r) => setTimeout(r, 5));
const item2 = await insertGlobalItem(db, { brand: "BrandB", model: "Model2" }); const item2 = await insertGlobalItem(db, {
brand: "BrandB",
model: "Model2",
});
await new Promise((r) => setTimeout(r, 5)); await new Promise((r) => setTimeout(r, 5));
const item3 = await insertGlobalItem(db, { brand: "BrandC", model: "Model3" }); const item3 = await insertGlobalItem(db, {
brand: "BrandC",
model: "Model3",
});
const result = await getRecentGlobalItems(db); const result = await getRecentGlobalItems(db);
expect(result.items).toHaveLength(3); expect(result.items).toHaveLength(3);
@@ -208,12 +222,36 @@ describe("Discovery Service", () => {
describe("getTrendingCategories", () => { describe("getTrendingCategories", () => {
it("returns categories ordered by item count descending", async () => { it("returns categories ordered by item count descending", async () => {
// 3 items in Tents, 1 in Bags, 2 in Stoves // 3 items in Tents, 1 in Bags, 2 in Stoves
await insertGlobalItem(db, { brand: "BrandA", model: "Tent1", category: "Tents" }); await insertGlobalItem(db, {
await insertGlobalItem(db, { brand: "BrandB", model: "Tent2", category: "Tents" }); brand: "BrandA",
await insertGlobalItem(db, { brand: "BrandC", model: "Tent3", category: "Tents" }); model: "Tent1",
await insertGlobalItem(db, { brand: "BrandD", model: "Bag1", category: "Bags" }); category: "Tents",
await insertGlobalItem(db, { brand: "BrandE", model: "Stove1", category: "Stoves" }); });
await insertGlobalItem(db, { brand: "BrandF", model: "Stove2", category: "Stoves" }); await insertGlobalItem(db, {
brand: "BrandB",
model: "Tent2",
category: "Tents",
});
await insertGlobalItem(db, {
brand: "BrandC",
model: "Tent3",
category: "Tents",
});
await insertGlobalItem(db, {
brand: "BrandD",
model: "Bag1",
category: "Bags",
});
await insertGlobalItem(db, {
brand: "BrandE",
model: "Stove1",
category: "Stoves",
});
await insertGlobalItem(db, {
brand: "BrandF",
model: "Stove2",
category: "Stoves",
});
const result = await getTrendingCategories(db); const result = await getTrendingCategories(db);
expect(result).toHaveLength(3); expect(result).toHaveLength(3);
@@ -226,7 +264,11 @@ describe("Discovery Service", () => {
}); });
it("excludes items with null category", async () => { it("excludes items with null category", async () => {
await insertGlobalItem(db, { brand: "BrandA", model: "Tent1", category: "Tents" }); await insertGlobalItem(db, {
brand: "BrandA",
model: "Tent1",
category: "Tents",
});
// No category — should be excluded // No category — should be excluded
await insertGlobalItem(db, { brand: "BrandB", model: "NoCategory" }); await insertGlobalItem(db, { brand: "BrandB", model: "NoCategory" });