This commit is contained in:
pa
2026-03-09 10:49:01 +09:00
parent 90a17bb0ba
commit cd832fb96a
20 changed files with 4655 additions and 6 deletions

View File

@@ -0,0 +1,269 @@
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import { nextTick, ref } from 'vue';
const mocks = vi.hoisted(() => ({
randomUserColours: null,
photonLoggingEnabled: null,
chatboxUserBlacklist: null,
lastLocation: null,
currentInstanceLocation: null,
currentInstanceWorld: null,
currentInstanceUsersData: null,
currentUser: null,
saveChatboxUserBlacklist: vi.fn(),
showUserDialog: vi.fn(),
lookupUser: vi.fn(),
showWorldDialog: vi.fn(),
showFullscreenImageDialog: vi.fn(),
getCurrentInstanceUserList: vi.fn(),
tableSetOptions: vi.fn(),
photonColumnToggleVisibility: vi.fn()
}));
vi.mock('pinia', () => ({
storeToRefs: (store) => store
}));
vi.mock('vue-i18n', () => ({
useI18n: () => ({
t: (key) => key
})
}));
vi.mock('../../../stores', () => ({
useAppearanceSettingsStore: () => ({
randomUserColours: mocks.randomUserColours
}),
usePhotonStore: () => ({
photonLoggingEnabled: mocks.photonLoggingEnabled,
chatboxUserBlacklist: mocks.chatboxUserBlacklist,
saveChatboxUserBlacklist: (...args) => mocks.saveChatboxUserBlacklist(...args)
}),
useUserStore: () => ({
currentUser: mocks.currentUser,
showUserDialog: (...args) => mocks.showUserDialog(...args),
lookupUser: (...args) => mocks.lookupUser(...args)
}),
useWorldStore: () => ({
showWorldDialog: (...args) => mocks.showWorldDialog(...args)
}),
useLocationStore: () => ({
lastLocation: mocks.lastLocation
}),
useInstanceStore: () => ({
currentInstanceLocation: mocks.currentInstanceLocation,
currentInstanceWorld: mocks.currentInstanceWorld,
currentInstanceUsersData: mocks.currentInstanceUsersData,
getCurrentInstanceUserList: (...args) => mocks.getCurrentInstanceUserList(...args)
}),
useGalleryStore: () => ({
showFullscreenImageDialog: (...args) => mocks.showFullscreenImageDialog(...args)
})
}));
vi.mock('../../../lib/table/useVrcxVueTable', () => ({
useVrcxVueTable: () => ({
table: {
setOptions: (...args) => mocks.tableSetOptions(...args),
getColumn: (id) =>
id === 'photonId'
? {
toggleVisibility: (...args) => mocks.photonColumnToggleVisibility(...args)
}
: null,
getRowModel: () => ({ rows: mocks.currentInstanceUsersData.value })
}
})
}));
vi.mock('../../../composables/useDataTableScrollHeight', () => ({
useDataTableScrollHeight: () => ({
tableStyle: {}
})
}));
vi.mock('../columns.jsx', () => ({
createColumns: () => [{ id: 'photonId' }]
}));
vi.mock('../../../shared/utils', () => ({
commaNumber: (value) => String(value ?? ''),
formatDateFilter: (value) => String(value ?? '')
}));
vi.mock('@/components/ui/data-table', () => ({
DataTableLayout: {
props: ['onRowClick'],
template:
'<div>' +
'<button data-testid="row-click-with-id" @click="onRowClick?.({ original: { ref: { id: \'usr_1\', displayName: \'Alice\' } } })">row-id</button>' +
'<button data-testid="row-click-without-id" @click="onRowClick?.({ original: { ref: { displayName: \'Bob\' } } })">row-no-id</button>' +
'</div>'
}
}));
vi.mock('@/components/ui/badge', () => ({
Badge: { template: '<span><slot /></span>' }
}));
vi.mock('@/components/ui/tooltip', () => ({
TooltipWrapper: { template: '<div><slot /></div>' }
}));
vi.mock('../../../components/LocationWorld.vue', () => ({
default: { template: '<div />' }
}));
vi.mock('../../../components/Timer.vue', () => ({
default: { template: '<span />' }
}));
vi.mock('../dialogs/ChatboxBlacklistDialog.vue', () => ({
default: {
props: ['chatboxBlacklistDialog'],
emits: ['delete-chatbox-user-blacklist'],
template:
'<div data-testid="chatbox-dialog" :data-visible="String(chatboxBlacklistDialog.visible)">' +
'<button data-testid="emit-delete-chatbox" @click="$emit(\'delete-chatbox-user-blacklist\', \'usr_blocked\')">delete</button>' +
'</div>'
}
}));
vi.mock('lucide-vue-next', () => ({
Apple: { template: '<span />' },
Home: { template: '<span />' },
Monitor: { template: '<span />' },
Smartphone: { template: '<span />' }
}));
import PlayerList from '../PlayerList.vue';
describe('PlayerList.vue', () => {
beforeEach(() => {
mocks.randomUserColours = ref(false);
mocks.photonLoggingEnabled = ref(false);
mocks.chatboxUserBlacklist = ref(new Map([['usr_blocked', 'Blocked User']]));
mocks.lastLocation = ref({
playerList: new Set(),
friendList: new Set(),
date: null
});
mocks.currentInstanceLocation = ref({});
mocks.currentInstanceWorld = ref({
ref: {
id: '',
thumbnailImageUrl: '',
imageUrl: '',
name: '',
authorId: '',
authorName: '',
releaseStatus: 'public',
description: ''
},
fileAnalysis: {},
isPC: false,
isQuest: false,
isIos: false
});
mocks.currentInstanceUsersData = ref([]);
mocks.currentUser = ref({
id: 'usr_me',
$homeLocation: null
});
mocks.saveChatboxUserBlacklist.mockReset();
mocks.showUserDialog.mockReset();
mocks.lookupUser.mockReset();
mocks.showWorldDialog.mockReset();
mocks.showFullscreenImageDialog.mockReset();
mocks.getCurrentInstanceUserList.mockReset();
mocks.tableSetOptions.mockReset();
mocks.photonColumnToggleVisibility.mockReset();
mocks.saveChatboxUserBlacklist.mockResolvedValue(undefined);
});
test('loads current instance user list on mount and wires table options', () => {
mount(PlayerList, {
global: {
stubs: {
TooltipWrapper: { template: '<div><slot /></div>' },
LocationWorld: { template: '<div />' }
}
}
});
expect(mocks.getCurrentInstanceUserList).toHaveBeenCalledTimes(1);
expect(mocks.tableSetOptions).toHaveBeenCalledTimes(1);
expect(mocks.photonColumnToggleVisibility).toHaveBeenCalledWith(false);
});
test('row click opens user dialog when id exists, otherwise lookups user', async () => {
const wrapper = mount(PlayerList, {
global: {
stubs: {
TooltipWrapper: { template: '<div><slot /></div>' },
LocationWorld: { template: '<div />' }
}
}
});
await wrapper.get('[data-testid="row-click-with-id"]').trigger('click');
await wrapper.get('[data-testid="row-click-without-id"]').trigger('click');
expect(mocks.showUserDialog).toHaveBeenCalledWith('usr_1');
expect(mocks.lookupUser).toHaveBeenCalledWith({ displayName: 'Bob' });
});
test('toggles photonId column visibility when photon logging changes', async () => {
mount(PlayerList, {
global: {
stubs: {
TooltipWrapper: { template: '<div><slot /></div>' },
LocationWorld: { template: '<div />' }
}
}
});
mocks.photonColumnToggleVisibility.mockClear();
mocks.photonLoggingEnabled.value = true;
await nextTick();
expect(mocks.photonColumnToggleVisibility).toHaveBeenCalledWith(true);
});
test('opens chatbox blacklist dialog from photon event table', async () => {
const wrapper = mount(PlayerList, {
global: {
stubs: {
TooltipWrapper: { template: '<div><slot /></div>' },
LocationWorld: { template: '<div />' }
}
}
});
expect(wrapper.get('[data-testid="chatbox-dialog"]').attributes('data-visible')).toBe('false');
wrapper.vm.showChatboxBlacklistDialog();
await nextTick();
expect(wrapper.get('[data-testid="chatbox-dialog"]').attributes('data-visible')).toBe('true');
});
test('deletes chatbox blacklist user and refreshes list', async () => {
const wrapper = mount(PlayerList, {
global: {
stubs: {
TooltipWrapper: { template: '<div><slot /></div>' },
LocationWorld: { template: '<div />' }
}
}
});
await wrapper.get('[data-testid="emit-delete-chatbox"]').trigger('click');
expect(mocks.chatboxUserBlacklist.value.has('usr_blocked')).toBe(false);
expect(mocks.saveChatboxUserBlacklist).toHaveBeenCalledTimes(1);
expect(mocks.getCurrentInstanceUserList).toHaveBeenCalledTimes(2);
});
});