Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/api/genres/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Genre = {
id: string;
name: string;
};

export const genresKeys = {
all: () => ["genres"] as const,
};
Comment on lines +6 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. genreskeys.all uses arrow 📘 Rule violation ⚙ Maintainability

genresKeys.all is implemented as an arrow function, but this rule requires named/exported
functions to use function declarations. Keeping arrow functions for named utilities can undermine
consistent refactor style and enforcement.
Agent Prompt
## Issue description
`genresKeys.all` is a named/exported function implemented as an arrow function inside an exported object. The compliance rule requires function declaration syntax (`function Name(...) {}`) for named/exported functions.

## Issue Context
This module is part of the new `src/api/genres` structure; keep query key factories compliant while preserving the existing `genresKeys.all()` call sites.

## Fix Focus Areas
- src/api/genres/types.ts[6-8]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/components/ui/use-toast";
import { genresKeys } from "./types";

interface CreateGenreParams {
name: string;
Expand Down Expand Up @@ -29,8 +30,7 @@ export function useCreateGenreMutation() {
return data;
},
onSuccess: () => {
// Invalidate genres query if it exists
queryClient.invalidateQueries({ queryKey: ["genres"] });
queryClient.invalidateQueries({ queryKey: genresKeys.all() });

toast({
title: "Success",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { queryOptions, useQuery } from "@tanstack/react-query";
import { supabase } from "@/integrations/supabase/client";
import { Genre, genresKeys } from "./types";

// Query key factory
export const genresKeys = {
all: ["genres"] as const,
};

// Business logic function
async function fetchGenres(): Promise<Array<{ id: string; name: string }>> {
export async function fetchGenres(): Promise<Genre[]> {
const { data, error } = await supabase
.from("music_genres")
.select("id, name")
Expand All @@ -20,15 +15,18 @@ async function fetchGenres(): Promise<Array<{ id: string; name: string }>> {
return data || [];
}

// Hook
export function useGenresQuery() {
return useQuery({
queryKey: genresKeys.all,
export function genresQuery() {
return queryOptions({
queryKey: genresKeys.all(),
queryFn: fetchGenres,
staleTime: 10 * 60 * 1000, // 10 minutes - genres don't change often
staleTime: 10 * 60 * 1000,
});
}

export function useGenresQuery() {
return useQuery(genresQuery());
}

export function useGenres() {
const { data: genres = [], isLoading, error } = useGenresQuery();

Expand Down
4 changes: 2 additions & 2 deletions src/components/GenreBadge.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { describe, expect, it, vi, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import { GenreBadge } from "./GenreBadge";
import * as useGenresModule from "@/hooks/queries/genres/useGenres";
import * as useGenresModule from "@/api/genres/useGenres";

vi.mock("@/hooks/queries/genres/useGenres");
vi.mock("@/api/genres/useGenres");
Comment on lines +4 to +6

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Test mocks usegenres hook 📜 Skill insight ▣ Testability

GenreBadge.test.tsx mocks the internal useGenres hook module, which is an internal collaborator
rather than an external system boundary. This makes the test brittle to refactors (e.g., changing
which hook/component provides genres) while keeping behavior the same.
Agent Prompt
## Issue description
The test mocks an internal module (`@/api/genres/useGenres`) instead of mocking only at a system boundary. This violates the testing compliance requirement and makes the test depend on implementation details.

## Issue Context
`GenreBadge` uses `useGenres()` internally. Instead of mocking that hook, prefer testing through the component’s observable behavior by providing the real hook with a `QueryClientProvider` and seeding React Query data (or mocking the Supabase client / network boundary).

## Fix Focus Areas
- src/components/GenreBadge.test.tsx[4-6]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


describe("GenreBadge", () => {
beforeEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/GenreBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Badge } from "@/components/ui/badge";
import { useGenres } from "@/hooks/queries/genres/useGenres";
import { useGenres } from "@/api/genres/useGenres";

interface GenreBadgeProps {
genreId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react";
import type { SortOption, FilterSortState } from "@/hooks/useUrlState";
import { useGenres } from "@/hooks/queries/genres/useGenres";
import { useGenres } from "@/api/genres/useGenres";
import { SortControls } from "./SortControls";
import { MobileFilters } from "./MobileFilters";
import { DesktopFilters } from "./DesktopFilters";
Expand Down
2 changes: 1 addition & 1 deletion src/pages/admin/AddGenreDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useForm } from "react-hook-form";
import { useCreateGenreMutation } from "@/hooks/queries/genres/useCreateGenreMutation";
import { useCreateGenreMutation } from "@/api/genres/useCreateGenreMutation";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
Expand Down
2 changes: 1 addition & 1 deletion src/pages/admin/ArtistsManagement/AddArtistDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import { Music } from "lucide-react";
import { useAuth } from "@/contexts/AuthContext";
import { useUserPermissionsQuery } from "@/hooks/queries/auth/useUserPermissions";
import { useGenresQuery } from "@/hooks/queries/genres/useGenres";
import { useGenresQuery } from "@/api/genres/useGenres";
import { useCreateArtistMutation } from "@/hooks/queries/artists/useCreateArtist";
import { useUpdateArtistMutation } from "@/hooks/queries/artists/useUpdateArtist";
import { GenreMultiSelect } from "./GenreMultiSelect";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { GenreMultiSelect } from "../GenreMultiSelect";
import { useGenresQuery } from "@/hooks/queries/genres/useGenres";
import { useGenresQuery } from "@/api/genres/useGenres";
import { Check, X } from "lucide-react";

interface GenresCellProps {
Expand Down
Loading