fix: resolve biome lint errors in discovery files
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:
@@ -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" && (
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"];
|
||||||
|
|||||||
@@ -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" });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user