mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-26 18:23:47 +02:00
add test
This commit is contained in:
78
src/views/Sidebar/__tests__/Sidebar.test.js
Normal file
78
src/views/Sidebar/__tests__/Sidebar.test.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
openSearch: vi.fn(),
|
||||
markAllAsSeen: vi.fn(),
|
||||
refreshFriends: vi.fn(),
|
||||
hasUnseen: { value: true },
|
||||
centerOpen: { value: false }
|
||||
}));
|
||||
|
||||
vi.mock('pinia', async (i) => ({ ...(await i()), storeToRefs: (s) => s }));
|
||||
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (k) => k }) }));
|
||||
vi.mock('@vueuse/core', async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
useMagicKeys: () => ({}),
|
||||
whenever: vi.fn()
|
||||
};
|
||||
});
|
||||
vi.mock('../../../stores', () => ({
|
||||
useFriendStore: () => ({ friends: ref(new Map()), isRefreshFriendsLoading: ref(false), onlineFriendCount: ref(0) }),
|
||||
useGroupStore: () => ({ groupInstances: ref([]) }),
|
||||
useNotificationStore: () => ({ isNotificationCenterOpen: mocks.centerOpen, hasUnseenNotifications: mocks.hasUnseen, markAllAsSeen: (...a) => mocks.markAllAsSeen(...a) }),
|
||||
useAppearanceSettingsStore: () => ({ sidebarSortMethod1: ref(''), sidebarSortMethod2: ref(''), sidebarSortMethod3: ref(''), isSidebarGroupByInstance: ref(false), isHideFriendsInSameInstance: ref(false), isSidebarDivideByFriendGroup: ref(false), sidebarFavoriteGroups: ref([]), setSidebarSortMethod1: vi.fn(), setSidebarSortMethod2: vi.fn(), setSidebarSortMethod3: vi.fn(), setIsSidebarGroupByInstance: vi.fn(), setIsHideFriendsInSameInstance: vi.fn(), setIsSidebarDivideByFriendGroup: vi.fn(), setSidebarFavoriteGroups: vi.fn() }),
|
||||
useFavoriteStore: () => ({ favoriteFriendGroups: ref([]), localFriendFavoriteGroups: ref([]) })
|
||||
}));
|
||||
vi.mock('../../../stores/globalSearch', () => ({ useGlobalSearchStore: () => ({ open: (...a) => mocks.openSearch(...a) }) }));
|
||||
vi.mock('../../../coordinators/friendSyncCoordinator', () => ({ runRefreshFriendsListFlow: (...a) => mocks.refreshFriends(...a) }));
|
||||
vi.mock('../sidebarSettingsUtils', () => ({ normalizeFavoriteGroupsChange: (v) => v, resolveFavoriteGroups: (v) => v }));
|
||||
vi.mock('@/components/ui/button', () => ({ Button: { emits: ['click'], template: '<button data-testid="btn" @click="$emit(\'click\')"><slot /></button>' } }));
|
||||
vi.mock('@/components/ui/context-menu', () => ({ ContextMenu: { template: '<div><slot /></div>' }, ContextMenuTrigger: { template: '<div><slot /></div>' }, ContextMenuContent: { template: '<div><slot /></div>' }, ContextMenuItem: { emits: ['click'], template: '<button data-testid="ctx" @click="$emit(\'click\')"><slot /></button>' } }));
|
||||
vi.mock('@/components/ui/popover', () => ({ Popover: { template: '<div><slot /></div>' }, PopoverTrigger: { template: '<div><slot /></div>' }, PopoverContent: { template: '<div><slot /></div>' } }));
|
||||
vi.mock('@/components/ui/select', () => ({ Select: { template: '<div><slot /></div>' }, SelectTrigger: { template: '<div><slot /></div>' }, SelectValue: { template: '<div><slot /></div>' }, SelectContent: { template: '<div><slot /></div>' }, SelectGroup: { template: '<div><slot /></div>' }, SelectItem: { template: '<div><slot /></div>' }, SelectSeparator: { template: '<hr />' } }));
|
||||
vi.mock('@/components/ui/field', () => ({ Field: { template: '<div><slot /></div>' }, FieldLabel: { template: '<div><slot /></div>' }, FieldContent: { template: '<div><slot /></div>' } }));
|
||||
vi.mock('@/components/ui/tabs', () => ({ TabsUnderline: { template: '<div><slot name="friends" /><slot name="groups" /></div>' } }));
|
||||
vi.mock('@/components/ui/switch', () => ({ Switch: { template: '<div />' } }));
|
||||
vi.mock('@/components/ui/spinner', () => ({ Spinner: { template: '<div />' } }));
|
||||
vi.mock('@/components/ui/tooltip', () => ({ TooltipWrapper: { template: '<div><slot /></div>' } }));
|
||||
vi.mock('@/components/ui/kbd', () => ({ Kbd: { template: '<kbd><slot /></kbd>' } }));
|
||||
vi.mock('@/components/ui/separator', () => ({ Separator: { template: '<hr />' } }));
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
Bell: { template: '<i />' },
|
||||
RefreshCw: { template: '<i />' },
|
||||
Search: { template: '<i />' },
|
||||
Settings: { template: '<i />' }
|
||||
}));
|
||||
vi.mock('../components/FriendsSidebar.vue', () => ({ default: { template: '<div />' } }));
|
||||
vi.mock('../components/GroupsSidebar.vue', () => ({ default: { template: '<div />' } }));
|
||||
vi.mock('../components/GroupOrderSheet.vue', () => ({ default: { template: '<div />' } }));
|
||||
vi.mock('../components/NotificationCenterSheet.vue', () => ({ default: { template: '<div />' } }));
|
||||
vi.mock('../../../components/GlobalSearchDialog.vue', () => ({ default: { template: '<div />' } }));
|
||||
|
||||
import Sidebar from '../Sidebar.vue';
|
||||
|
||||
describe('Sidebar.vue', () => {
|
||||
beforeEach(() => {
|
||||
mocks.openSearch.mockClear();
|
||||
mocks.markAllAsSeen.mockClear();
|
||||
});
|
||||
|
||||
it('opens global search and marks notifications read', async () => {
|
||||
const wrapper = mount(Sidebar);
|
||||
const buttons = wrapper.findAll('button');
|
||||
for (const button of buttons) {
|
||||
await button.trigger('click');
|
||||
if (mocks.openSearch.mock.calls.length > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
await wrapper.get('[data-testid="ctx"]').trigger('click');
|
||||
|
||||
expect(mocks.openSearch).toHaveBeenCalled();
|
||||
expect(mocks.markAllAsSeen).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
145
src/views/Sidebar/components/__tests__/GroupsSidebar.test.js
Normal file
145
src/views/Sidebar/components/__tests__/GroupsSidebar.test.js
Normal file
@@ -0,0 +1,145 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
isAgeGatedInstancesVisible: { value: true },
|
||||
groupInstances: {
|
||||
value: [
|
||||
{
|
||||
group: {
|
||||
groupId: 'grp_1',
|
||||
name: 'Group One',
|
||||
iconUrl: 'https://example.com/icon.png'
|
||||
},
|
||||
instance: {
|
||||
id: 'inst_1',
|
||||
ownerId: 'usr_owner',
|
||||
userCount: 1,
|
||||
capacity: 16,
|
||||
location: 'wrld_1:123'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
sortGroupInstancesByInGame: (a, b) => a[0].group.name.localeCompare(b[0].group.name),
|
||||
showLaunchDialog: vi.fn(),
|
||||
checkCanInviteSelf: vi.fn(() => true),
|
||||
selfInvite: vi.fn().mockResolvedValue({}),
|
||||
showGroupDialog: vi.fn(),
|
||||
toastSuccess: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('pinia', async (i) => ({ ...(await i()), storeToRefs: (s) => s }));
|
||||
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (k) => k }) }));
|
||||
|
||||
vi.mock('@tanstack/vue-virtual', () => ({
|
||||
useVirtualizer: (optionsRef) => ({
|
||||
value: {
|
||||
getVirtualItems: () =>
|
||||
Array.from({ length: optionsRef.value.count }, (_, index) => ({
|
||||
index,
|
||||
key: optionsRef.value.getItemKey(index),
|
||||
start: index * 52
|
||||
})),
|
||||
getTotalSize: () => optionsRef.value.count * 52,
|
||||
measure: vi.fn(),
|
||||
measureElement: vi.fn()
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../../stores', () => ({
|
||||
useAppearanceSettingsStore: () => ({
|
||||
isAgeGatedInstancesVisible: mocks.isAgeGatedInstancesVisible
|
||||
}),
|
||||
useGroupStore: () => ({
|
||||
sortGroupInstancesByInGame: mocks.sortGroupInstancesByInGame,
|
||||
groupInstances: mocks.groupInstances
|
||||
}),
|
||||
useLaunchStore: () => ({ showLaunchDialog: (...a) => mocks.showLaunchDialog(...a) })
|
||||
}));
|
||||
|
||||
vi.mock('../../../../composables/useInviteChecks', () => ({
|
||||
useInviteChecks: () => ({ checkCanInviteSelf: (...a) => mocks.checkCanInviteSelf(...a) })
|
||||
}));
|
||||
|
||||
vi.mock('../../../../shared/utils', () => ({
|
||||
convertFileUrlToImageUrl: (url) => `${url}?small`,
|
||||
parseLocation: (location) => ({
|
||||
isRealInstance: !!location,
|
||||
worldId: location.split(':')[0],
|
||||
instanceId: location.split(':')[1]
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../../coordinators/groupCoordinator', () => ({
|
||||
showGroupDialog: (...a) => mocks.showGroupDialog(...a)
|
||||
}));
|
||||
|
||||
vi.mock('../../../../api', () => ({
|
||||
instanceRequest: {
|
||||
selfInvite: (...a) => mocks.selfInvite(...a)
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('vue-sonner', () => ({
|
||||
toast: {
|
||||
success: (...a) => mocks.toastSuccess(...a)
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('../../../../components/ui/context-menu', () => ({
|
||||
ContextMenu: { template: '<div><slot /></div>' },
|
||||
ContextMenuTrigger: { template: '<div><slot /></div>' },
|
||||
ContextMenuContent: { template: '<div><slot /></div>' },
|
||||
ContextMenuItem: {
|
||||
emits: ['click'],
|
||||
props: ['disabled'],
|
||||
template:
|
||||
'<button data-testid="ctx-item" :disabled="disabled" @click="$emit(\'click\')"><slot /></button>'
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('../../../../components/BackToTop.vue', () => ({
|
||||
default: { template: '<div data-testid="back-to-top" />' }
|
||||
}));
|
||||
|
||||
vi.mock('../../../../components/Location.vue', () => ({
|
||||
default: { props: ['location'], template: '<span data-testid="location">{{ location }}</span>' }
|
||||
}));
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
ChevronDown: { template: '<i />' }
|
||||
}));
|
||||
|
||||
import GroupsSidebar from '../GroupsSidebar.vue';
|
||||
|
||||
describe('GroupsSidebar.vue', () => {
|
||||
beforeEach(() => {
|
||||
mocks.showLaunchDialog.mockClear();
|
||||
mocks.selfInvite.mockClear();
|
||||
mocks.showGroupDialog.mockClear();
|
||||
mocks.toastSuccess.mockClear();
|
||||
});
|
||||
|
||||
it('renders group rows and handles launch/self-invite actions', async () => {
|
||||
const wrapper = mount(GroupsSidebar);
|
||||
|
||||
expect(wrapper.text()).toContain('Group One');
|
||||
|
||||
await wrapper.get('[data-testid="location"]').trigger('click');
|
||||
expect(mocks.showGroupDialog).toHaveBeenCalledWith('usr_owner');
|
||||
|
||||
const items = wrapper.findAll('[data-testid="ctx-item"]');
|
||||
await items[0].trigger('click');
|
||||
expect(mocks.showLaunchDialog).toHaveBeenCalledWith('wrld_1:123');
|
||||
|
||||
await items[1].trigger('click');
|
||||
await Promise.resolve();
|
||||
expect(mocks.selfInvite).toHaveBeenCalledWith({
|
||||
worldId: 'wrld_1',
|
||||
instanceId: '123'
|
||||
});
|
||||
expect(mocks.toastSuccess).toHaveBeenCalledWith('message.invite.self_sent');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user