Skip to content
Merged
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
85 changes: 82 additions & 3 deletions lib/artist/__tests__/updateArtistSocials.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { describe, it, expect, vi, beforeEach } from "vitest";

import { updateArtistSocials } from "../updateArtistSocials";

const mockSelectAccountSocials = vi.fn();
const mockDeleteAccountSocial = vi.fn();
const mockInsertAccountSocial = vi.fn();
Expand All @@ -26,8 +28,6 @@ vi.mock("@/lib/supabase/socials/insertSocials", () => ({
insertSocials: (...args: unknown[]) => mockInsertSocials(...args),
}));

import { updateArtistSocials } from "../updateArtistSocials";

describe("updateArtistSocials", () => {
const artistId = "artist-123";

Expand Down Expand Up @@ -155,7 +155,11 @@ describe("updateArtistSocials", () => {
return Promise.resolve([]);
});
mockInsertSocials.mockResolvedValue([
{ id: "new-youtube-social", username: "artistchannel", profile_url: "youtube.com/@artistchannel" },
{
id: "new-youtube-social",
username: "artistchannel",
profile_url: "youtube.com/@artistchannel",
},
]);

// Update both YouTube AND Spotify (same Spotify URL as existing)
Expand All @@ -171,4 +175,79 @@ describe("updateArtistSocials", () => {
// Should also insert YouTube
expect(mockInsertAccountSocial).toHaveBeenCalledWith(artistId, "new-youtube-social");
});

it("adds both Instagram and Spotify when neither exists", async () => {
// BUG: When passing both Instagram and Spotify URLs for a new artist,
// only one social is being added
mockSelectAccountSocials.mockResolvedValue([]);
mockSelectSocials.mockResolvedValue([]);

// Mock insertSocials to return different IDs for each call
let insertCallCount = 0;
mockInsertSocials.mockImplementation(socials => {
insertCallCount++;
const social = socials[0];
if (social.profile_url.includes("instagram")) {
return Promise.resolve([
{
id: "new-instagram-social",
username: "goosebytheway",
profile_url: social.profile_url,
},
]);
} else if (social.profile_url.includes("spotify")) {
return Promise.resolve([
{ id: "new-spotify-social", username: "artist", profile_url: social.profile_url },
]);
}
return Promise.resolve([]);
});

// Add both Instagram AND Spotify for a new artist
await updateArtistSocials(artistId, {
INSTAGRAM: "https://www.instagram.com/goosebytheway/",
SPOTIFY: "https://open.spotify.com/artist/7Lbpx0EuKekUdtfDuNStfh",
});

// Should NOT delete anything since no existing socials
expect(mockDeleteAccountSocial).not.toHaveBeenCalled();

// Should create social records for BOTH platforms
expect(mockInsertSocials).toHaveBeenCalledTimes(2);

// Should create account_social relationships for BOTH platforms
expect(mockInsertAccountSocial).toHaveBeenCalledTimes(2);
expect(mockInsertAccountSocial).toHaveBeenCalledWith(artistId, "new-instagram-social");
expect(mockInsertAccountSocial).toHaveBeenCalledWith(artistId, "new-spotify-social");
});

it("finds existing Instagram social when www prefix is used in URL", async () => {
// BUG: When URL has www. prefix but database has URL without www.,
// the lookup fails and creates a duplicate or fails to link
const existingInstagramInDb = {
id: "existing-instagram-social",
username: "goosebytheway",
profile_url: "instagram.com/goosebytheway", // Note: no www.
};

mockSelectAccountSocials.mockResolvedValue([]);
// Simulate database having the URL without www.
mockSelectSocials.mockImplementation(({ profile_url }) => {
// The normalized URL should match even with www. stripped
if (profile_url === "instagram.com/goosebytheway") {
return Promise.resolve([existingInstagramInDb]);
}
return Promise.resolve([]);
});

// Input URL has www. prefix
await updateArtistSocials(artistId, {
INSTAGRAM: "https://www.instagram.com/goosebytheway/",
});

// Should find existing social and NOT create new one
expect(mockInsertSocials).not.toHaveBeenCalled();
// Should link to existing social
expect(mockInsertAccountSocial).toHaveBeenCalledWith(artistId, "existing-instagram-social");
});
});
20 changes: 15 additions & 5 deletions lib/socials/__tests__/normalizeProfileUrl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ describe("normalizeProfileUrl", () => {
});

it("returns URL unchanged if no protocol", () => {
expect(normalizeProfileUrl("open.spotify.com/artist/123")).toBe(
"open.spotify.com/artist/123",
);
expect(normalizeProfileUrl("open.spotify.com/artist/123")).toBe("open.spotify.com/artist/123");
});

it("handles empty string", () => {
Expand All @@ -28,8 +26,20 @@ describe("normalizeProfileUrl", () => {
});

it("removes trailing slash", () => {
expect(normalizeProfileUrl("https://instagram.com/user/")).toBe(
"instagram.com/user",
expect(normalizeProfileUrl("https://instagram.com/user/")).toBe("instagram.com/user");
});

it("removes www. prefix from URL", () => {
expect(normalizeProfileUrl("https://www.instagram.com/user")).toBe("instagram.com/user");
});

it("removes www. prefix along with protocol and trailing slash", () => {
expect(normalizeProfileUrl("https://www.instagram.com/goosebytheway/")).toBe(
"instagram.com/goosebytheway",
);
});

it("handles URL with www. but without protocol", () => {
expect(normalizeProfileUrl("www.twitter.com/user")).toBe("twitter.com/user");
});
});
5 changes: 3 additions & 2 deletions lib/socials/normalizeProfileUrl.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/**
* Normalizes a profile URL by removing the protocol and trailing slash.
* Normalizes a profile URL by removing the protocol, www. prefix, and trailing slash.
* This ensures consistent URL format for database queries and storage.
*
* @param url - The profile URL to normalize
* @returns The normalized URL without protocol or trailing slash
* @returns The normalized URL without protocol, www., or trailing slash
*/
export function normalizeProfileUrl(url: string | null | undefined): string {
if (!url) return "";

return url
.replace(/^https?:\/\//, "")
.replace(/^www\./, "")
.replace(/\/$/, "");
}