diff --git a/app/pages/profile/[identity]/index.vue b/app/pages/profile/[identity]/index.vue index 61ca0f69eb..4d63fd6ba8 100644 --- a/app/pages/profile/[identity]/index.vue +++ b/app/pages/profile/[identity]/index.vue @@ -25,7 +25,7 @@ if (!profile.value || profileError.value?.statusCode === 404) { }) } -const { user, pending: userPending } = useAtproto() +const { user } = useAtproto() const isEditing = ref(false) const displayNameInput = ref() const descriptionInput = ref() @@ -86,8 +86,8 @@ const showInviteSection = computed(() => { profile.value.recordExists === false && status.value === 'success' && !likes.value?.records?.length && - !userPending.value && - user.value?.handle !== profile.value.handle + user.value && + user.value.handle !== profile.value.handle ) }) diff --git a/test/nuxt/components/Package/Likes.spec.ts b/test/nuxt/components/Package/Likes.spec.ts index 4dd367f9b6..4ae4648a37 100644 --- a/test/nuxt/components/Package/Likes.spec.ts +++ b/test/nuxt/components/Package/Likes.spec.ts @@ -1,26 +1,23 @@ import type { VueWrapper } from '@vue/test-utils' import { mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { ref } from 'vue' import Likes from '~/components/Package/Likes.vue' +import { useAtproto } from '~/composables/atproto/useAtproto' -const { mockUseAtproto } = vi.hoisted(() => ({ - mockUseAtproto: vi.fn(), -})) - -vi.mock('~/composables/atproto/useAtproto', () => ({ - useAtproto: mockUseAtproto, -})) +function createAtprotoUser(handle: string) { + return { + did: `did:plc:${handle}`, + handle, + pds: 'https://bsky.social', + } +} describe('PackageLikes', () => { let wrapper: VueWrapper | undefined beforeEach(() => { - mockUseAtproto.mockReturnValue({ - user: ref(null), - pending: ref(false), - logout: vi.fn(), - }) + const { user } = useAtproto() + user.value = null }) afterEach(() => { @@ -75,26 +72,25 @@ describe('PackageLikes', () => { it('keeps the top liked badge when a like response omits the rank', async () => { let likeRequests = 0 - - mockUseAtproto.mockReturnValue({ - user: ref({ handle: 'tester.test' }), - pending: ref(false), - logout: vi.fn(), - }) + const { user } = useAtproto() + user.value = createAtprotoUser('tester.test') registerEndpoint('/api/social/likes/svelte', () => ({ totalLikes: 42, userHasLiked: false, topLikedRank: 3, })) - registerEndpoint('/api/social/like', () => { - likeRequests++ - - return { - totalLikes: 43, - userHasLiked: true, - topLikedRank: null, - } + registerEndpoint('/api/social/like', { + method: 'POST', + handler: () => { + likeRequests++ + + return { + totalLikes: 43, + userHasLiked: true, + topLikedRank: null, + } + }, }) wrapper = await mountSuspended(Likes, { diff --git a/test/nuxt/components/ProfileInviteSection.spec.ts b/test/nuxt/components/ProfileInviteSection.spec.ts index 6b5a897ce7..d27a00fd46 100644 --- a/test/nuxt/components/ProfileInviteSection.spec.ts +++ b/test/nuxt/components/ProfileInviteSection.spec.ts @@ -1,16 +1,23 @@ import { mockNuxtImport, mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime' import { describe, expect, it, vi, beforeEach } from 'vitest' +import { useAtproto } from '~/composables/atproto/useAtproto' -const { mockUseAtproto, mockUseProfileLikes } = vi.hoisted(() => ({ - mockUseAtproto: vi.fn(), +const { mockUseProfileLikes } = vi.hoisted(() => ({ mockUseProfileLikes: vi.fn(), })) -mockNuxtImport('useAtproto', () => mockUseAtproto) mockNuxtImport('useProfileLikes', () => mockUseProfileLikes) import ProfilePage from '~/pages/profile/[identity]/index.vue' +function createAtprotoUser(handle: string) { + return { + did: `did:plc:${handle}`, + handle, + pds: 'https://bsky.social', + } +} + registerEndpoint('/api/social/profile/test-handle', () => ({ displayName: 'Test User', description: '', @@ -21,16 +28,14 @@ registerEndpoint('/api/social/profile/test-handle', () => ({ describe('Profile invite section', () => { beforeEach(() => { - mockUseAtproto.mockReset() + const { user } = useAtproto() + user.value = null mockUseProfileLikes.mockReset() }) it('does not show invite section while auth is still loading', async () => { - mockUseAtproto.mockReturnValue({ - user: ref(null), - pending: ref(true), - logout: vi.fn(), - }) + const { user } = useAtproto() + user.value = undefined mockUseProfileLikes.mockReturnValue({ data: ref({ records: [] }), @@ -45,11 +50,8 @@ describe('Profile invite section', () => { }) it('shows invite section after auth resolves for non-owner', async () => { - mockUseAtproto.mockReturnValue({ - user: ref({ handle: 'other-user' }), - pending: ref(false), - logout: vi.fn(), - }) + const { user } = useAtproto() + user.value = createAtprotoUser('other-user') mockUseProfileLikes.mockReturnValue({ data: ref({ records: [] }), @@ -64,11 +66,8 @@ describe('Profile invite section', () => { }) it('does not show invite section for profile owner', async () => { - mockUseAtproto.mockReturnValue({ - user: ref({ handle: 'test-handle' }), - pending: ref(false), - logout: vi.fn(), - }) + const { user } = useAtproto() + user.value = createAtprotoUser('test-handle') mockUseProfileLikes.mockReturnValue({ data: ref({ records: [] }), diff --git a/test/nuxt/composables/use-command-palette-commands.spec.ts b/test/nuxt/composables/use-command-palette-commands.spec.ts index ae56784db3..5c365cabbb 100644 --- a/test/nuxt/composables/use-command-palette-commands.spec.ts +++ b/test/nuxt/composables/use-command-palette-commands.spec.ts @@ -1,7 +1,8 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { computed, defineComponent, h, ref, watchEffect, type Ref } from 'vue' import type { RouteLocationRaw } from 'vue-router' -import { mockNuxtImport, mountSuspended } from '@nuxt/test-utils/runtime' +import { mockNuxtImport, mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime' +import { useAtproto } from '~/composables/atproto/useAtproto' import { downloadPackageTarball } from '~/utils/package-download' import type { CommandPaletteCommand, @@ -23,9 +24,15 @@ const mockConnectorState = ref<{ npmUser: null, }) -const mockAtprotoHandle = ref(null) const mockDisconnectNpm = vi.fn() -const mockLogout = vi.fn(async () => {}) + +function createAtprotoUser(handle: string) { + return { + did: `did:plc:${handle}`, + handle, + pds: 'https://bsky.social', + } +} mockNuxtImport('useConnector', () => { return () => ({ @@ -35,13 +42,6 @@ mockNuxtImport('useConnector', () => { }) }) -mockNuxtImport('useAtproto', () => { - return () => ({ - user: computed(() => (mockAtprotoHandle.value ? { handle: mockAtprotoHandle.value } : null)), - logout: mockLogout, - }) -}) - async function captureCommandPalette(options?: { route?: string query?: string @@ -62,7 +62,8 @@ async function captureCommandPalette(options?: { connected: !!options?.npmUser, npmUser: options?.npmUser ?? null, } - mockAtprotoHandle.value = options?.atprotoHandle ?? null + const { user } = useAtproto() + user.value = options?.atprotoHandle ? createAtprotoUser(options.atprotoHandle) : null const WrapperComponent = defineComponent({ setup() { @@ -122,7 +123,8 @@ afterEach(() => { connected: false, npmUser: null, } - mockAtprotoHandle.value = null + const { user } = useAtproto() + user.value = null vi.clearAllMocks() }) @@ -312,6 +314,12 @@ describe('useCommandPaletteCommands', () => { }) it('adds atproto account commands and disconnect support when a profile is connected', async () => { + const deleteSession = vi.fn(() => null) + registerEndpoint('/api/auth/session', { + method: 'DELETE', + handler: deleteSession, + }) + const { wrapper, flatCommands } = await captureCommandPalette({ route: '/profile/alice.bsky.social', atprotoHandle: 'alice.bsky.social', @@ -324,7 +332,7 @@ describe('useCommandPaletteCommands', () => { await flatCommands.value.find(command => command.id === 'atproto-disconnect')?.action?.() - expect(mockLogout).toHaveBeenCalledTimes(1) + expect(deleteSession).toHaveBeenCalledTimes(1) expect(commandPalette.isOpen.value).toBe(false) wrapper.unmount()