diff --git a/src/components/Profile/EditProfileModal/EditProfileModal.test.tsx b/src/components/Profile/EditProfileModal/EditProfileModal.test.tsx index 2ebb6d67..6cc73874 100644 --- a/src/components/Profile/EditProfileModal/EditProfileModal.test.tsx +++ b/src/components/Profile/EditProfileModal/EditProfileModal.test.tsx @@ -125,6 +125,12 @@ describe("EditProfileModal", () => { onSave={mockOnSave} />, ); + expect(screen.getByTestId("edit-modal-close-button")).toHaveClass( + "bg-bg-actionbutton", + ); + expect(screen.getByTestId("edit-modal-close-button")).toHaveClass( + "text-text-secondary", + ); fireEvent.click(screen.getByTestId("edit-modal-close-button")); expect(mockOnClose).toHaveBeenCalled(); }); diff --git a/src/components/Profile/EditProfileModal/EditProfileModal.tsx b/src/components/Profile/EditProfileModal/EditProfileModal.tsx index e984b167..105f5e8b 100644 --- a/src/components/Profile/EditProfileModal/EditProfileModal.tsx +++ b/src/components/Profile/EditProfileModal/EditProfileModal.tsx @@ -208,7 +208,7 @@ const EditProfileModal: React.FC = ({ diff --git a/src/components/Profile/ProfileSideBar/ProfileSideBar.test.tsx b/src/components/Profile/ProfileSideBar/ProfileSideBar.test.tsx index 4dab0b07..4b8eb762 100644 --- a/src/components/Profile/ProfileSideBar/ProfileSideBar.test.tsx +++ b/src/components/Profile/ProfileSideBar/ProfileSideBar.test.tsx @@ -264,6 +264,7 @@ describe("ProfileSideBar", () => { ); expect(screen.getByText("travis-scott")).toBeInTheDocument(); expect(screen.getByText("1 FOLLOWING")).toBeInTheDocument(); + expect(screen.getByText("6.0M")).toBeInTheDocument(); expect( screen.getByTestId("follow-button-travis-scott"), ).toBeInTheDocument(); @@ -322,6 +323,10 @@ describe("ProfileSideBar", () => { it("navigates to checkout on Upgrade to Artist Pro click", () => { render(); + expect(screen.getByTestId("upgrade-pro-button")).toHaveClass( + "bg-bg-inverted", + ); + expect(screen.getByTestId("upgrade-pro-button")).toHaveClass("text-bg"); fireEvent.click(screen.getByTestId("upgrade-pro-button")); expect(mockNavigate).toHaveBeenCalledWith("/premium"); }); diff --git a/src/components/Profile/ProfileSideBar/ProfileSideBar.tsx b/src/components/Profile/ProfileSideBar/ProfileSideBar.tsx index ddefbe79..58d7b905 100644 --- a/src/components/Profile/ProfileSideBar/ProfileSideBar.tsx +++ b/src/components/Profile/ProfileSideBar/ProfileSideBar.tsx @@ -270,7 +270,7 @@ const ProfileSideBar: React.FC = ({ diff --git a/src/components/Profile/ProfileSideBar/TrackItem.test.tsx b/src/components/Profile/ProfileSideBar/TrackItem.test.tsx index 611f220d..77541755 100644 --- a/src/components/Profile/ProfileSideBar/TrackItem.test.tsx +++ b/src/components/Profile/ProfileSideBar/TrackItem.test.tsx @@ -27,7 +27,11 @@ vi.mock("@/stores/player.store", () => ({ const mockLikesStore = { isTrackLiked: vi.fn().mockReturnValue(false), + isTrackReposted: vi.fn().mockReturnValue(false), + repostedTrackIds: [], + itemStats: {}, toggleTrack: vi.fn(), + toggleRepost: vi.fn().mockResolvedValue(undefined), }; vi.mock("@/stores/likes.store", () => ({ @@ -148,4 +152,26 @@ describe("TrackItem", () => { fireEvent.click(screen.getByTestId("track-more-download-1")); expect(mockNavigate).toHaveBeenCalledWith("/premium"); }); + + it("shows Unrepost when the track is already reposted", () => { + render(); + const container = screen.getByTestId("track-item-1"); + fireEvent.mouseEnter(container); + fireEvent.click(screen.getByTestId("track-more-button-1")); + expect(screen.getByTestId("track-more-repost-1")).toHaveTextContent( + "Unrepost", + ); + }); + + it("switches back to Repost when unreposted", async () => { + render(); + const container = screen.getByTestId("track-item-1"); + fireEvent.mouseEnter(container); + fireEvent.click(screen.getByTestId("track-more-button-1")); + fireEvent.click(screen.getByTestId("track-more-repost-1")); + expect(mockLikesStore.toggleRepost).toHaveBeenCalled(); + expect(screen.getByTestId("track-more-repost-1")).toHaveTextContent( + "Repost", + ); + }); }); diff --git a/src/components/Profile/ShareModal/ShareModal.test.jsx b/src/components/Profile/ShareModal/ShareModal.test.jsx index c0a4c518..ceeb2994 100644 --- a/src/components/Profile/ShareModal/ShareModal.test.jsx +++ b/src/components/Profile/ShareModal/ShareModal.test.jsx @@ -98,6 +98,14 @@ describe("ShareModal", () => { it("calls onClose when close button is clicked", () => { render(); + expect(screen.getByTestId("share-modal-close")).toHaveClass("top-14"); + expect(screen.getByTestId("share-modal-close")).toHaveClass("right-4"); + expect(screen.getByTestId("share-modal-close")).toHaveClass( + "bg-bg-actionbutton", + ); + expect(screen.getByTestId("share-modal-close")).toHaveClass( + "text-text-secondary", + ); fireEvent.click(screen.getByTestId("share-modal-close")); expect(mockOnClose).toHaveBeenCalled(); }); diff --git a/src/components/Profile/ShareModal/ShareModal.tsx b/src/components/Profile/ShareModal/ShareModal.tsx index 34181731..40850f13 100644 --- a/src/components/Profile/ShareModal/ShareModal.tsx +++ b/src/components/Profile/ShareModal/ShareModal.tsx @@ -114,7 +114,7 @@ const ShareModal: React.FC = ({ url, onClose }) => { diff --git a/src/components/UI/FollowButton.test.tsx b/src/components/UI/FollowButton.test.tsx new file mode 100644 index 00000000..a045578a --- /dev/null +++ b/src/components/UI/FollowButton.test.tsx @@ -0,0 +1,98 @@ +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import React from "react"; +import FollowButton from "@/components/UI/FollowButton"; + +const mockToggleFollow = vi.fn(); +const mockFollowUser = vi.fn(); +const mockUnfollowUser = vi.fn(); +const mockSetUser = vi.fn(); + +vi.mock("@/stores/auth.store", () => ({ + useAuthStore: vi.fn(), +})); + +vi.mock("@/services/user.service", () => ({ + followUser: (...args: unknown[]) => mockFollowUser(...args), + unfollowUser: (...args: unknown[]) => mockUnfollowUser(...args), +})); + +import { useAuthStore } from "@/stores/auth.store"; + +describe("UI FollowButton", () => { + beforeEach(() => { + vi.clearAllMocks(); + mockFollowUser.mockResolvedValue(undefined); + mockUnfollowUser.mockResolvedValue(undefined); + vi.mocked(useAuthStore).mockReturnValue({ + user: { + id: "user-1", + username: "me", + following_ids: [], + }, + toggleFollow: mockToggleFollow, + setUser: mockSetUser, + } as any); + }); + + it("renders Follow when not following", () => { + render(); + + expect(screen.getByTestId("follow-button-travis-scott")).toHaveTextContent( + "Follow", + ); + }); + + it("follows a user when clicked", async () => { + render(); + + fireEvent.click(screen.getByTestId("follow-button-travis-scott")); + + await waitFor(() => { + expect(mockToggleFollow).toHaveBeenCalledWith("travis-scott", [ + "artist-1", + ]); + expect(mockFollowUser).toHaveBeenCalledWith("artist-1"); + }); + }); + + it("unfollows a user when already following", async () => { + vi.mocked(useAuthStore).mockReturnValue({ + user: { + id: "user-1", + username: "me", + following_ids: ["artist-1"], + }, + toggleFollow: mockToggleFollow, + setUser: mockSetUser, + } as any); + + render(); + + expect(screen.getByTestId("follow-button-travis-scott")).toHaveTextContent( + "Following", + ); + + fireEvent.click(screen.getByTestId("follow-button-travis-scott")); + + await waitFor(() => { + expect(mockToggleFollow).toHaveBeenCalledWith("travis-scott", [ + "artist-1", + ]); + expect(mockUnfollowUser).toHaveBeenCalledWith("artist-1"); + }); + }); + + it("shows Blocked when blocked without following", () => { + render( + + Blocked + , + ); + + expect(screen.getByTestId("follow-button-travis-scott")).toHaveTextContent( + "Blocked", + ); + expect(screen.getByTestId("follow-button-travis-scott")).toBeDisabled(); + }); +}); diff --git a/src/components/UI/TrackItem.test.tsx b/src/components/UI/TrackItem.test.tsx new file mode 100644 index 00000000..82bcc4fd --- /dev/null +++ b/src/components/UI/TrackItem.test.tsx @@ -0,0 +1,145 @@ +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import React from "react"; +import TrackItem from "@/components/UI/TrackItem"; + +const mockNavigate = vi.fn(); +const mockToggleTrack = vi.fn(); +const mockToggleRepost = vi.fn().mockResolvedValue(undefined); +const mockToggleDownload = vi.fn(); +const mockSetTrack = vi.fn(); +const mockTogglePlay = vi.fn(); + +vi.mock("react-router-dom", () => ({ + useNavigate: () => mockNavigate, +})); + +vi.mock("@/stores/player.store", () => ({ + usePlayerStore: Object.assign( + vi.fn(() => ({ + currentTrack: null, + isPlaying: false, + setTrack: mockSetTrack, + togglePlay: mockTogglePlay, + })), + { + getState: vi.fn(() => ({ + playContext: vi.fn(), + })), + }, + ), +})); + +const mockLikesState = { + isTrackLiked: vi.fn().mockReturnValue(false), + isTrackReposted: vi.fn().mockReturnValue(false), + repostedTrackIds: [] as string[], + itemStats: {} as Record, + toggleTrack: mockToggleTrack, + toggleRepost: mockToggleRepost, +}; + +vi.mock("@/stores/likes.store", () => ({ + useLikesStore: vi.fn((selector) => { + if (typeof selector === "function") { + return selector(mockLikesState); + } + return mockLikesState; + }), +})); + +vi.mock("@/stores/history.store", () => ({ + useHistoryStore: vi.fn(() => ({ + addTrack: vi.fn(), + })), +})); + +vi.mock("@/stores/auth.store", () => ({ + useAuthStore: vi.fn(() => ({ + user: { id: "user-123", username: "me", isPro: true }, + })), +})); + +vi.mock("@/stores/useDownload", () => ({ + useDownloadStore: vi.fn(() => ({ + isDownloaded: vi.fn().mockReturnValue(false), + toggleDownload: mockToggleDownload, + })), +})); + +vi.mock("@/services/track.service", () => ({ + getRelatedTracks: vi.fn().mockResolvedValue({ tracks: [] }), +})); + +vi.mock("@/pages/[username]/[trackSlug]/components/SharePopup", () => ({ + default: () =>
, +})); + +vi.mock("@/components/playlist/AddToPlaylistModal", () => ({ + default: () =>
, +})); + +vi.mock("@/components/UI/CoverImage", () => ({ + default: (props: any) => , +})); + +const defaultProps = { + id: "track-1", + title: "Butterfly Effect", + artist: "Travis Scott", + artistUsername: "travisscott", + trackSlug: "butterfly-effect", + coverUrl: "https://example.com/cover.jpg", + plays: 1200, + likes: 250, + reposts: 42, + comments: 7, +}; + +describe("UI TrackItem", () => { + beforeEach(() => { + vi.clearAllMocks(); + mockLikesState.isTrackLiked.mockReturnValue(false); + mockLikesState.isTrackReposted.mockReturnValue(false); + mockLikesState.repostedTrackIds = []; + mockLikesState.itemStats = {}; + }); + + it("renders the track metadata", () => { + render(); + + expect(screen.getByText("Butterfly Effect")).toBeInTheDocument(); + expect(screen.getByText("Travis Scott")).toBeInTheDocument(); + }); + + it("shows Unrepost for already reposted tracks and flips back after click", async () => { + render(); + + fireEvent.mouseEnter(screen.getByTestId("track-item-track-1")); + fireEvent.click(screen.getByTestId("track-more-button-track-1")); + + expect(screen.getByTestId("track-more-repost-track-1")).toHaveTextContent( + "Unrepost", + ); + + fireEvent.click(screen.getByTestId("track-more-repost-track-1")); + + await waitFor(() => { + expect(mockToggleRepost).toHaveBeenCalledTimes(1); + expect(screen.getByTestId("track-more-repost-track-1")).toHaveTextContent( + "Repost", + ); + }); + }); + + it("shows Download for pro users in the more menu", () => { + render(); + + fireEvent.mouseEnter(screen.getByTestId("track-item-track-1")); + fireEvent.click(screen.getByTestId("track-more-button-track-1")); + + expect(screen.getByTestId("track-more-download-track-1")).toHaveTextContent( + "Download", + ); + }); +}); diff --git a/src/components/UI/TrackItem.tsx b/src/components/UI/TrackItem.tsx index 1abbb513..8df898b1 100644 --- a/src/components/UI/TrackItem.tsx +++ b/src/components/UI/TrackItem.tsx @@ -1,11 +1,10 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { usePlayerStore } from "@/stores/player.store"; import { useLikesStore } from "@/stores/likes.store"; import { useHistoryStore } from "@/stores/history.store"; import { useAuthStore } from "@/stores/auth.store"; import { useDownloadStore } from "@/stores/useDownload"; -import * as engagementService from "@/services/engagement.service"; import { getRelatedTracks } from "@/services/track.service"; import SharePopup from "@/pages/[username]/[trackSlug]/components/SharePopup"; import AddToPlaylistModal from "@/components/playlist/AddToPlaylistModal"; @@ -66,18 +65,36 @@ const TrackItem: React.FC = ({ const [hovered, setHovered] = useState(false); const [coverHovered, setCoverHovered] = useState(false); const [showMore, setShowMore] = useState(false); - const [reposted, setReposted] = useState(initialReposted); const [shareOpen, setShareOpen] = useState(false); const [playlistModalOpen, setPlaylistModalOpen] = useState(false); const navigate = useNavigate(); const { setTrack, currentTrack, isPlaying, togglePlay } = usePlayerStore(); const isTrackLiked = useLikesStore((s) => s.isTrackLiked); + const storeReposted = useLikesStore((s) => s.isTrackReposted(id)); + const storeHasRepostInfo = useLikesStore((s) => { + const trackStats = s.itemStats[String(id)]; + return ( + s.repostedTrackIds.includes(String(id)) || + trackStats?.isReposted !== undefined + ); + }); const toggleTrack = useLikesStore((s) => s.toggleTrack); + const toggleRepost = useLikesStore((s) => s.toggleRepost); const { addTrack } = useHistoryStore(); const { user } = useAuthStore(); const { isDownloaded, toggleDownload } = useDownloadStore(); const liked = isTrackLiked(id); + const [reposted, setReposted] = useState(() => + storeHasRepostInfo ? storeReposted : initialReposted, + ); + + useEffect(() => { + if (storeHasRepostInfo && reposted !== storeReposted) { + setReposted(storeReposted); + } + }, [storeHasRepostInfo, storeReposted, reposted]); + const finalArtistSlug = artistUsername || (artist ?? "").toLowerCase().replace(/\s+/g, "-"); @@ -118,11 +135,7 @@ const TrackItem: React.FC = ({ const wasReposted = reposted; setReposted(!wasReposted); try { - if (wasReposted) { - await engagementService.removeRepost(id); - } else { - await engagementService.repostTrack(id); - } + await toggleRepost(trackForActions); } catch (err) { console.error("Repost failed", err); setReposted(wasReposted); diff --git a/src/components/UI/card/Card.test.tsx b/src/components/UI/card/Card.test.tsx index 869b895f..95a2ff23 100644 --- a/src/components/UI/card/Card.test.tsx +++ b/src/components/UI/card/Card.test.tsx @@ -3,6 +3,8 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import React from "react"; import TrackCard from "@/components/UI/card/Card"; import type { Track } from "@/types/track"; +import { useAuthStore } from "@/stores/auth.store"; +import { useDownloadStore } from "@/stores/useDownload"; // ─── Mocks ──────────────────────────────────────────────── @@ -37,6 +39,8 @@ const mockLikesStore = { toggleRadioTrack: vi.fn(), }; +const mockToggleDownload = vi.fn(); + vi.mock("@/stores/likes.store", () => ({ useLikesStore: vi.fn(() => mockLikesStore), })); @@ -47,8 +51,16 @@ vi.mock("@/stores/history.store", () => ({ })), })); +vi.mock("@/stores/auth.store", () => ({ + useAuthStore: vi.fn(), +})); + +vi.mock("@/stores/useDownload", () => ({ + useDownloadStore: vi.fn(), +})); + vi.mock("@/components/UI/CardOverlay/CardOverlay", () => ({ - default: ({ isPlaying, onPlay, isLiked, onLike, moreMenuItems }: any) => ( + default: ({ isPlaying, onPlay, isLiked, onLike, downloadMenuItem, moreMenuItems }: any) => (
+ @@ -102,6 +117,11 @@ describe("TrackCard", () => { mockPlayerStore.currentTrack = null; mockPlayerStore.isPlaying = false; mockLikesStore.isTrackLiked.mockReturnValue(false); + vi.mocked(useAuthStore).mockReturnValue({ user: { isPro: true } } as any); + vi.mocked(useDownloadStore).mockReturnValue({ + isDownloaded: vi.fn().mockReturnValue(false), + toggleDownload: mockToggleDownload, + } as any); }); it("renders cover image, title and artist", () => { @@ -166,4 +186,24 @@ describe("TrackCard", () => { expect(screen.getByTestId("add-to-playlist-modal")).toBeInTheDocument(); }); + + it("passes a download action into the overlay for pro users", () => { + render(); + + expect(screen.getByTestId("button-download")).toHaveTextContent("Download"); + fireEvent.click(screen.getByTestId("button-download")); + + expect(mockToggleDownload).toHaveBeenCalledWith(mockTrack, true); + }); + + it("sends non-pro users to premium from the overlay download action", () => { + vi.mocked(useAuthStore).mockReturnValue({ user: { isPro: false } } as any); + + render(); + + expect(screen.getByTestId("button-download")).toHaveTextContent("Download"); + fireEvent.click(screen.getByTestId("button-download")); + + expect(mockNavigate).toHaveBeenCalledWith("/premium"); + }); }); diff --git a/src/components/UI/card/Card.tsx b/src/components/UI/card/Card.tsx index 5b50e8e9..53af5c9f 100644 --- a/src/components/UI/card/Card.tsx +++ b/src/components/UI/card/Card.tsx @@ -3,6 +3,8 @@ import { useState, useCallback } from "react"; import { useNavigate } from "react-router-dom"; import { usePlayerStore } from "@/stores/player.store"; import { useLikesStore } from "@/stores/likes.store"; +import { useAuthStore } from "@/stores/auth.store"; +import { useDownloadStore } from "@/stores/useDownload"; import { getRelatedTracks } from "@/services/track.service"; import AddToPlaylistModal from "@/components/playlist/AddToPlaylistModal"; import CardOverlay, { @@ -117,6 +119,8 @@ const TrackCard = ({ const navigate = useNavigate(); const { setTrack, currentTrack, isPlaying, togglePlay } = usePlayerStore(); const { isTrackLiked, toggleTrack, isRadioTrackLiked, toggleRadioTrack } = useLikesStore(); + const { user } = useAuthStore(); + const { isDownloaded, toggleDownload } = useDownloadStore(); const fetchTracksForModal = useCallback(async () => { const previewTrack = { @@ -141,6 +145,8 @@ const TrackCard = ({ }, [track.id, track.title, track.artistName, track.coverUrl, addToPlaylistTracks]); const liked = radioLikeMode ? isRadioTrackLiked(track.id) : isTrackLiked(track.id); + const isPro = !!user?.isPro; + const downloaded = isDownloaded(track.id); // Check if this card's track is the one currently playing const isThisTrackPlaying = currentTrack?.id === track.id && isPlaying; @@ -151,6 +157,21 @@ const TrackCard = ({ .replace(/-+/g, "-"); const playlistPath = `/discover/personalised/${playlistSlug}:${track.id}`; + const downloadMenuItem = { + label: downloaded ? "Remove Download" : "Download", + iconNode: ( + + ), + onClick: () => { + if (!isPro) { + navigate("/premium"); + return; + } + toggleDownload(track, true); + }, + }; // Handler for play button click (play/pause toggle) const handlePlayClick = (e: React.MouseEvent) => { e.stopPropagation(); @@ -188,6 +209,7 @@ const TrackCard = ({ if (radioLikeMode) toggleRadioTrack(track); else toggleTrack(track); }} + downloadMenuItem={downloadMenuItem} moreMenuItems={[ { label: "Add to playlist", diff --git a/src/pages/[username]/Usernamepage.test.tsx b/src/pages/[username]/Usernamepage.test.tsx index b02955a0..6d9ee668 100644 --- a/src/pages/[username]/Usernamepage.test.tsx +++ b/src/pages/[username]/Usernamepage.test.tsx @@ -26,9 +26,17 @@ vi.mock("react-router-dom", () => ({ })); vi.mock("@/stores/auth.store", () => ({ - useAuthStore: vi.fn(), + useAuthStore: Object.assign(vi.fn(), { + subscribe: vi.fn(), + getState: vi.fn(), + }), })); +const mockAuthStore = { + user: null, + setUser: vi.fn(), +}; + vi.mock("@/services/user.service", () => ({ getMyProfile: (...args: unknown[]) => mockGetMyProfile(...args), getUserById: (...args: unknown[]) => mockGetUserById(...args), @@ -228,13 +236,19 @@ describe("UsernamePage", () => { message: "ok", }); const authStoreMock = useAuthStore as unknown as ReturnType; - authStoreMock.mockReturnValue({ - user: mockCurrentUser, - setUser: vi.fn(), + authStoreMock.mockImplementation((selector?: unknown) => { + const state = { + ...mockAuthStore, + user: mockCurrentUser, + }; + if (typeof selector === "function") { + return (selector as (value: typeof state) => unknown)(state); + } + return state; }); (authStoreMock as unknown as { getState: () => unknown }).getState = () => ({ + ...mockAuthStore, user: mockCurrentUser, - setUser: vi.fn(), }); (useLocation as unknown as ReturnType).mockReturnValue({ pathname: "/me", diff --git a/src/pages/[username]/albums/AlbumsPage.tsx b/src/pages/[username]/albums/AlbumsPage.tsx index b3f0a384..06eb73aa 100644 --- a/src/pages/[username]/albums/AlbumsPage.tsx +++ b/src/pages/[username]/albums/AlbumsPage.tsx @@ -108,7 +108,7 @@ export default function AlbumsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, })); @@ -118,7 +118,7 @@ export default function AlbumsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, isFollowing: u.isFollowing, diff --git a/src/pages/[username]/popular-tracks/PopularTracksPage.tsx b/src/pages/[username]/popular-tracks/PopularTracksPage.tsx index caeb8636..b13e5489 100644 --- a/src/pages/[username]/popular-tracks/PopularTracksPage.tsx +++ b/src/pages/[username]/popular-tracks/PopularTracksPage.tsx @@ -72,7 +72,7 @@ export default function PopularTracksPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, })); @@ -82,7 +82,7 @@ export default function PopularTracksPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, isFollowing: u.isFollowing, diff --git a/src/pages/[username]/reposts/RepostsPage.tsx b/src/pages/[username]/reposts/RepostsPage.tsx index 541df9ec..332158d5 100644 --- a/src/pages/[username]/reposts/RepostsPage.tsx +++ b/src/pages/[username]/reposts/RepostsPage.tsx @@ -79,7 +79,7 @@ export default function RepostsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, })); @@ -89,7 +89,7 @@ export default function RepostsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, isFollowing: u.isFollowing, diff --git a/src/pages/[username]/sets/SetsPage.tsx b/src/pages/[username]/sets/SetsPage.tsx index fdb20867..2fbfa318 100644 --- a/src/pages/[username]/sets/SetsPage.tsx +++ b/src/pages/[username]/sets/SetsPage.tsx @@ -107,7 +107,7 @@ export default function SetsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, })); @@ -117,7 +117,7 @@ export default function SetsPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, isFollowing: u.isFollowing, diff --git a/src/pages/[username]/tracks/TracksPage.tsx b/src/pages/[username]/tracks/TracksPage.tsx index 7c6d8f75..ed67f923 100644 --- a/src/pages/[username]/tracks/TracksPage.tsx +++ b/src/pages/[username]/tracks/TracksPage.tsx @@ -85,7 +85,7 @@ export default function TracksPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, })); @@ -95,7 +95,7 @@ export default function TracksPage() { username: u.username || u.id, displayName: u.display_name, avatar: u.profile_picture ?? "", - followers: 0, + followers: (u as { followers_count?: number }).followers_count ?? 0, tracks: 0, isVerified: u.is_verified, isFollowing: u.isFollowing, diff --git a/src/pages/settings/privacy/PrivacyPage.test.tsx b/src/pages/settings/privacy/PrivacyPage.test.tsx index 232adc6d..2c4d8ffd 100644 --- a/src/pages/settings/privacy/PrivacyPage.test.tsx +++ b/src/pages/settings/privacy/PrivacyPage.test.tsx @@ -81,7 +81,7 @@ describe("PrivacyPage", () => { const toggle = getToggleForText("Show when I'm a First or Top Fan"); - expect(toggle.className).toContain("bg-[var(--color-accent)]"); + expect(toggle.className).toContain("bg-accent"); fireEvent.click(toggle); await waitFor(() => { @@ -91,7 +91,7 @@ describe("PrivacyPage", () => { }); await waitFor(() => { - expect(toggle.className).toContain("bg-[var(--color-accent)]"); + expect(toggle.className).toContain("bg-accent"); }); }); });