import { mount } from "@vue/test-utils" import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" import { ref } from "vue" const ghAccessToken = ref(null) const ghUsername = ref(null) const atIsLoggedIn = ref(false) const atHandle = ref(null) const atAvatarUrl = ref(null) vi.mock("@/hooks/useGitHubLogin.hook", () => ({ useGitHubLogin: () => ({ username: ghUsername, accessToken: ghAccessToken }) })) vi.mock("@/hooks/useATProtoLogin.hook", () => ({ useATProtoLogin: () => ({ isLoggedIn: atIsLoggedIn, handle: atHandle, avatarUrl: atAvatarUrl }) })) import UserPill from "./UserPill.vue" describe("UserPill", () => { beforeEach(() => { ghAccessToken.value = null ghUsername.value = null atIsLoggedIn.value = false atHandle.value = null atAvatarUrl.value = null }) afterEach(() => { vi.clearAllMocks() }) it("shows the ghost 'Sign in' pill when nobody is logged in", () => { const wrapper = mount(UserPill) expect(wrapper.text()).toContain("Sign in") expect(wrapper.classes()).toContain("profile-chip--ghost") }) it("shows the GitHub username and initial when logged in via GitHub only", () => { ghAccessToken.value = "tok" ghUsername.value = "alice" const wrapper = mount(UserPill) expect(wrapper.text()).toContain("alice") expect(wrapper.find(".profile-avatar-initial").text()).toBe("A") expect(wrapper.find("img").exists()).toBe(false) expect(wrapper.classes()).not.toContain("profile-chip--ghost") }) it("shows the ATProto handle and avatar when logged in via ATProto", () => { atIsLoggedIn.value = true atHandle.value = "alice.bsky.social" atAvatarUrl.value = "https://cdn.example.com/avatar.jpg" const wrapper = mount(UserPill) expect(wrapper.text()).toContain("alice.bsky.social") const img = wrapper.find("img") expect(img.exists()).toBe(true) expect(img.attributes("src")).toBe("https://cdn.example.com/avatar.jpg") }) it("prefers the ATProto handle over the GitHub username when both are present", () => { ghAccessToken.value = "tok" ghUsername.value = "alice-gh" atIsLoggedIn.value = true atHandle.value = "alice.bsky.social" const wrapper = mount(UserPill) expect(wrapper.text()).toContain("alice.bsky.social") expect(wrapper.text()).not.toContain("alice-gh") }) it("falls back to '?' initial when no name is available but a user is logged in", () => { atIsLoggedIn.value = true atHandle.value = "" const wrapper = mount(UserPill) expect(wrapper.find(".profile-avatar-initial").text()).toBe("?") }) it("emits click when clicked", async () => { const wrapper = mount(UserPill) await wrapper.trigger("click") expect(wrapper.emitted("click")).toHaveLength(1) }) })