mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-22 00:03:51 +02:00
fix test
This commit is contained in:
@@ -119,6 +119,7 @@ vi.mock('@/components/ui/dropdown-menu', () => ({
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
AlertTriangle: { template: '<i />' },
|
||||
Image: { template: '<i />' },
|
||||
Lock: { template: '<i />' },
|
||||
MoreHorizontal: { template: '<i />' },
|
||||
Trash2: { template: '<i />' }
|
||||
@@ -207,7 +208,7 @@ describe('FavoritesAvatarItem.vue', () => {
|
||||
).toContain('rounded-sm');
|
||||
});
|
||||
|
||||
it('shows fallback text when thumbnail is missing', () => {
|
||||
it('shows fallback icon when thumbnail is missing', () => {
|
||||
const wrapper = mountItem({
|
||||
favorite: {
|
||||
id: 'avtr_no_thumb',
|
||||
@@ -223,9 +224,9 @@ describe('FavoritesAvatarItem.vue', () => {
|
||||
expect(wrapper.find('[data-testid="avatar-image"]').exists()).toBe(
|
||||
false
|
||||
);
|
||||
expect(wrapper.get('[data-testid="avatar-fallback"]').text()).toContain(
|
||||
'B'
|
||||
);
|
||||
expect(
|
||||
wrapper.get('[data-testid="avatar-fallback"]').find('i').exists()
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('uses local delete flow for local favorites', async () => {
|
||||
|
||||
@@ -96,6 +96,7 @@ vi.mock('@/components/ui/dropdown-menu', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
Image: { template: '<i />' },
|
||||
MoreHorizontal: { template: '<i />' }
|
||||
}));
|
||||
|
||||
@@ -173,7 +174,7 @@ describe('FavoritesAvatarLocalHistoryItem.vue', () => {
|
||||
).toContain('rounded-sm');
|
||||
});
|
||||
|
||||
it('shows fallback text when thumbnail is missing', () => {
|
||||
it('shows fallback icon when thumbnail is missing', () => {
|
||||
const wrapper = mountItem({
|
||||
favorite: {
|
||||
id: 'avtr_hist_no_thumb',
|
||||
@@ -185,9 +186,9 @@ describe('FavoritesAvatarLocalHistoryItem.vue', () => {
|
||||
expect(wrapper.find('[data-testid="avatar-image"]').exists()).toBe(
|
||||
false
|
||||
);
|
||||
expect(wrapper.get('[data-testid="avatar-fallback"]').text()).toContain(
|
||||
'C'
|
||||
);
|
||||
expect(
|
||||
wrapper.get('[data-testid="avatar-fallback"]').find('i').exists()
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('runs select-avatar action from menu', async () => {
|
||||
|
||||
@@ -177,7 +177,8 @@ vi.mock('@/components/ui/dropdown-menu', () => ({
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
MoreHorizontal: { template: '<i />' },
|
||||
Trash2: { template: '<i />' }
|
||||
Trash2: { template: '<i />' },
|
||||
User: { template: '<i />' }
|
||||
}));
|
||||
|
||||
import FavoritesFriendItem from '../FavoritesFriendItem.vue';
|
||||
|
||||
@@ -109,6 +109,7 @@ vi.mock('@/components/ui/checkbox', () => ({
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
AlertTriangle: { template: '<i />' },
|
||||
Image: { template: '<i />' },
|
||||
Lock: { template: '<i />' },
|
||||
MoreHorizontal: { template: '<i />' }
|
||||
}));
|
||||
|
||||
@@ -196,6 +196,11 @@ const i18n = createI18n({
|
||||
messages: { en }
|
||||
});
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
Pencil: { template: '<span class="pencil-icon" />' },
|
||||
User: { template: '<span class="user-icon" />' }
|
||||
}));
|
||||
|
||||
// Stub all complex UI components — render slots transparently
|
||||
const stubs = {
|
||||
ContextMenu: { template: '<div data-testid="context-menu"><slot /></div>' },
|
||||
@@ -229,6 +234,7 @@ const stubs = {
|
||||
props: ['location', 'traveling', 'link', 'class']
|
||||
},
|
||||
Pencil: { template: '<span class="pencil-icon" />', props: ['class'] },
|
||||
User: { template: '<span class="user-icon" />', props: ['class', 'size'] },
|
||||
TooltipWrapper: {
|
||||
template: '<span><slot /></span>',
|
||||
props: ['content', 'disabled', 'delayDuration', 'side']
|
||||
@@ -356,11 +362,11 @@ describe('FriendsLocationsCard.vue', () => {
|
||||
expect(wrapper.text()).toContain('A');
|
||||
});
|
||||
|
||||
test('shows ? as avatar fallback when name is empty', () => {
|
||||
test('shows user icon as avatar fallback when name is empty', () => {
|
||||
const wrapper = mountCard({
|
||||
friend: makeFriend({ name: undefined })
|
||||
});
|
||||
expect(wrapper.text()).toContain('?');
|
||||
expect(wrapper.find('.user-icon').exists()).toBe(true);
|
||||
});
|
||||
|
||||
test('hides location when displayInstanceInfo is false', () => {
|
||||
|
||||
@@ -9,9 +9,13 @@ const mocks = vi.hoisted(() => ({
|
||||
}));
|
||||
|
||||
vi.mock('pinia', async (i) => ({ ...(await i()), storeToRefs: (s) => s }));
|
||||
vi.mock('vue-router', () => ({
|
||||
useRouter: () => ({ replace: (...a) => mocks.replace(...a) })
|
||||
}));
|
||||
vi.mock('vue-router', async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
useRouter: () => ({ replace: (...a) => mocks.replace(...a) })
|
||||
};
|
||||
});
|
||||
vi.mock('../../../services/watchState', () => ({
|
||||
watchState: { isLoggedIn: false }
|
||||
}));
|
||||
|
||||
@@ -44,7 +44,14 @@ vi.mock('../../../stores', () => ({
|
||||
photonLoggingEnabled: mocks.photonLoggingEnabled,
|
||||
chatboxUserBlacklist: mocks.chatboxUserBlacklist,
|
||||
saveChatboxUserBlacklist: (...args) =>
|
||||
mocks.saveChatboxUserBlacklist(...args)
|
||||
mocks.saveChatboxUserBlacklist(...args),
|
||||
photonEventTable: ref({ data: [], pageSize: 10 }),
|
||||
photonEventTablePrevious: ref({ data: [], pageSize: 10 }),
|
||||
photonEventTableTypeFilter: ref([]),
|
||||
photonEventTableFilter: ref(''),
|
||||
photonEventIcon: ref(false),
|
||||
photonEventTableFilterChange: vi.fn(),
|
||||
showUserFromPhotonId: vi.fn()
|
||||
}),
|
||||
useUserStore: () => ({
|
||||
currentUser: mocks.currentUser
|
||||
@@ -65,6 +72,18 @@ vi.mock('../../../stores', () => ({
|
||||
useGalleryStore: () => ({
|
||||
showFullscreenImageDialog: (...args) =>
|
||||
mocks.showFullscreenImageDialog(...args)
|
||||
}),
|
||||
useSearchStore: () => ({
|
||||
stringComparer: { value: (a, b) => a.localeCompare(b) }
|
||||
}),
|
||||
useAvatarStore: () => ({
|
||||
showAvatarDialog: vi.fn()
|
||||
}),
|
||||
useGroupStore: () => ({
|
||||
showGroupDialog: vi.fn()
|
||||
}),
|
||||
useVrcxStore: () => ({
|
||||
ipcEnabled: ref(false)
|
||||
})
|
||||
}));
|
||||
|
||||
@@ -142,12 +161,14 @@ vi.mock('../dialogs/ChatboxBlacklistDialog.vue', () => ({
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('lucide-vue-next', () => ({
|
||||
Apple: { template: '<span />' },
|
||||
Home: { template: '<span />' },
|
||||
Monitor: { template: '<span />' },
|
||||
Smartphone: { template: '<span />' }
|
||||
}));
|
||||
vi.mock('lucide-vue-next', async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
const stubs = {};
|
||||
for (const key of Object.keys(actual)) {
|
||||
stubs[key] = { template: '<span />' };
|
||||
}
|
||||
return stubs;
|
||||
});
|
||||
|
||||
import PlayerList from '../PlayerList.vue';
|
||||
|
||||
|
||||
@@ -33,12 +33,23 @@ vi.mock('../../../../../stores', () => ({
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../SimpleSwitch.vue', () => ({
|
||||
default: {
|
||||
props: ['label', 'disabled'],
|
||||
emits: ['change'],
|
||||
vi.mock('@/components/ui/switch', () => ({
|
||||
Switch: {
|
||||
props: ['modelValue', 'disabled'],
|
||||
emits: ['update:modelValue'],
|
||||
template:
|
||||
'<div data-testid="simple-switch" :data-label="label" :data-disabled="disabled"><button class="emit-change" @click="$emit(\'change\', true)" /></div>'
|
||||
'<button data-testid="switch" :data-disabled="disabled || undefined" @click="$emit(\'update:modelValue\', !modelValue)"><slot /></button>'
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('../../SettingsGroup.vue', () => ({
|
||||
default: { template: '<div><slot /><slot name="description" /></div>' }
|
||||
}));
|
||||
|
||||
vi.mock('../../SettingsItem.vue', () => ({
|
||||
default: {
|
||||
props: ['label', 'description'],
|
||||
template: '<div :data-label="label"><slot /></div>'
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -57,7 +68,7 @@ describe('DiscordPresenceTab.vue', () => {
|
||||
const wrapper = mount(DiscordPresenceTab);
|
||||
|
||||
const tooltipRow = wrapper
|
||||
.findAll('div.options-container-item')
|
||||
.findAll('p')
|
||||
.find((node) =>
|
||||
node
|
||||
.text()
|
||||
@@ -65,11 +76,13 @@ describe('DiscordPresenceTab.vue', () => {
|
||||
'view.settings.discord_presence.discord_presence.enable_tooltip'
|
||||
)
|
||||
);
|
||||
expect(tooltipRow).toBeTruthy();
|
||||
await tooltipRow.trigger('click');
|
||||
|
||||
expect(mocks.showVRChatConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
await wrapper.findAll('.emit-change')[0].trigger('click');
|
||||
const switches = wrapper.findAll('[data-testid="switch"]');
|
||||
await switches[0].trigger('click');
|
||||
expect(mocks.discordStore.setDiscordActive).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.discordStore.saveDiscordOption).toHaveBeenCalled();
|
||||
});
|
||||
@@ -78,12 +91,9 @@ describe('DiscordPresenceTab.vue', () => {
|
||||
mocks.discordStore.discordActive.value = false;
|
||||
const wrapper = mount(DiscordPresenceTab);
|
||||
|
||||
const worldIntegration = wrapper
|
||||
.findAll('[data-testid="simple-switch"]')
|
||||
.find((node) =>
|
||||
node.attributes('data-label')?.includes('world_integration')
|
||||
);
|
||||
const switches = wrapper.findAll('[data-testid="switch"]');
|
||||
const worldIntegrationSwitch = switches[1];
|
||||
|
||||
expect(worldIntegration?.attributes('data-disabled')).toBe('true');
|
||||
expect(worldIntegrationSwitch?.attributes('data-disabled')).toBe('true');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,6 +53,15 @@ vi.mock('@/components/ui/button', () => ({
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('@/components/ui/switch', () => ({
|
||||
Switch: {
|
||||
props: ['modelValue', 'disabled'],
|
||||
emits: ['update:modelValue'],
|
||||
template:
|
||||
'<button data-testid="switch" :data-disabled="disabled || undefined" @click="$emit(\'update:modelValue\', !modelValue)"><slot /></button>'
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('../../../../components/ui/radio-group', () => ({
|
||||
RadioGroup: {
|
||||
props: ['modelValue', 'disabled'],
|
||||
@@ -72,13 +81,12 @@ vi.mock('../../../../components/ui/toggle-group', () => ({
|
||||
ToggleGroupItem: { template: '<div><slot /></div>' }
|
||||
}));
|
||||
|
||||
vi.mock('../SimpleSwitch.vue', () => ({
|
||||
default: {
|
||||
props: ['label'],
|
||||
emits: ['change'],
|
||||
template:
|
||||
'<div data-testid="simple-switch" :data-label="label"><button class="emit-change" @click="$emit(\'change\', true)" /></div>'
|
||||
}
|
||||
vi.mock('../SettingsGroup.vue', () => ({
|
||||
default: { template: '<div><slot /><slot name="description" /></div>' }
|
||||
}));
|
||||
|
||||
vi.mock('../SettingsItem.vue', () => ({
|
||||
default: { template: '<div><slot /></div>' }
|
||||
}));
|
||||
|
||||
import WristOverlaySettings from '../WristOverlaySettings.vue';
|
||||
@@ -102,7 +110,8 @@ describe('WristOverlaySettings.vue', () => {
|
||||
await wrapper.get('[data-testid="filters-btn"]').trigger('click');
|
||||
expect(wrapper.emitted('open-feed-filters')).toBeTruthy();
|
||||
|
||||
await wrapper.findAll('.emit-change')[0].trigger('click');
|
||||
const switches = wrapper.findAll('[data-testid="switch"]');
|
||||
await switches[0].trigger('click');
|
||||
expect(mocks.notificationsStore.setOpenVR).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.saveOpenVROption).toHaveBeenCalled();
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ const mocks = vi.hoisted(() => ({
|
||||
appearanceStore: {
|
||||
isSidebarGroupByInstance: { value: false },
|
||||
isHideFriendsInSameInstance: { value: false },
|
||||
isSameInstanceAboveFavorites: { value: false },
|
||||
isSidebarDivideByFriendGroup: { value: false },
|
||||
sidebarFavoriteGroups: { value: [] },
|
||||
sidebarFavoriteGroupOrder: { value: [] },
|
||||
|
||||
@@ -39,21 +39,22 @@ vi.mock('pinia', async (importOriginal) => {
|
||||
|
||||
vi.mock('../../../stores', () => ({
|
||||
useFriendStore: () => ({ friends }),
|
||||
useGalleryStore: () => ({ showGalleryPage })
|
||||
}));
|
||||
|
||||
vi.mock('../../../stores/settings/advanced', () => ({
|
||||
useAdvancedSettingsStore: () => ({ showVRChatConfig })
|
||||
}));
|
||||
|
||||
vi.mock('../../../stores/launch', () => ({
|
||||
useLaunchStore: () => ({ showLaunchOptions })
|
||||
}));
|
||||
|
||||
vi.mock('../../../stores/vrcx', () => ({
|
||||
useGalleryStore: () => ({ showGalleryPage }),
|
||||
useToolsStore: () => ({ openDialog: vi.fn() }),
|
||||
useAdvancedSettingsStore: () => ({ showVRChatConfig }),
|
||||
useLaunchStore: () => ({ showLaunchOptions }),
|
||||
useVrcxStore: () => ({ showRegistryBackupDialog })
|
||||
}));
|
||||
|
||||
vi.mock('../../../composables/useToolNavPinning', () => ({
|
||||
useToolNavPinning: () => ({
|
||||
pinToolToNav: vi.fn(),
|
||||
pinnedToolKeys: new Set(),
|
||||
refreshPinnedState: vi.fn().mockResolvedValue(undefined),
|
||||
unpinToolFromNav: vi.fn()
|
||||
})
|
||||
}));
|
||||
|
||||
vi.mock('../../../services/config.js', () => ({
|
||||
default: {
|
||||
getString: (...args) => getString(...args),
|
||||
@@ -65,6 +66,13 @@ vi.mock('../dialogs/AutoChangeStatusDialog.vue', () => ({
|
||||
default: { template: '<div />' }
|
||||
}));
|
||||
|
||||
vi.mock('../../../components/ui/tooltip', () => ({
|
||||
TooltipWrapper: {
|
||||
template: '<div><slot /></div>',
|
||||
props: ['content', 'disabled', 'side']
|
||||
}
|
||||
}));
|
||||
|
||||
import Tools from '../Tools.vue';
|
||||
|
||||
function findToolItemByTitle(wrapper, titleKey) {
|
||||
@@ -113,7 +121,7 @@ describe('Tools.vue', () => {
|
||||
expect(galleryItem).toBeTruthy();
|
||||
await galleryItem.trigger('click');
|
||||
|
||||
expect(showGalleryPage).toHaveBeenCalled();
|
||||
expect(push).toHaveBeenCalledWith({ name: 'gallery' });
|
||||
});
|
||||
|
||||
test('toggle category persists collapsed state', async () => {
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import { defineComponent, markRaw } from 'vue';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import ToolItem from '../ToolItem.vue';
|
||||
|
||||
describe('ToolItem.vue', () => {
|
||||
test('renders icon, title and description', () => {
|
||||
const MockIcon = defineComponent({
|
||||
template: '<svg data-test="mock-icon" />'
|
||||
});
|
||||
|
||||
const wrapper = mount(ToolItem, {
|
||||
props: {
|
||||
icon: markRaw(MockIcon),
|
||||
icon: 'ri-screenshot-line',
|
||||
title: 'Test title',
|
||||
description: 'Test description'
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.find('[data-test="mock-icon"]').exists()).toBe(true);
|
||||
expect(wrapper.find('i.ri-screenshot-line').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('Test title');
|
||||
expect(wrapper.text()).toContain('Test description');
|
||||
});
|
||||
@@ -28,7 +23,7 @@ describe('ToolItem.vue', () => {
|
||||
|
||||
const wrapper = mount(ToolItem, {
|
||||
props: {
|
||||
icon: markRaw(defineComponent({ template: '<svg />' })),
|
||||
icon: 'ri-screenshot-line',
|
||||
title: 'Clickable title',
|
||||
description: 'Clickable description'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user