utopia-ui/lib/src/Components/Profile/ItemFunctions.spec.tsx
Anton Tranelis 6fcdef0433 fix(lib): ensure user_created is preserved in all item operations
- Add user_created field to all item update operations to maintain proper user association
- Update useMyProfile hook to use direct computation instead of useMemo to avoid React hook queue issues
- Refactor UserControl to use useMyProfile hook for consistency
- Fix user_created handling in LocateControl, ItemFormPopup, useSelectPosition, and itemFunctions
- Add user parameter to linkItem, unlinkItem, and related functions with proper TypeScript signatures
- Update all function calls and tests to include user parameter
- Ensure proper null safety with user ?? undefined pattern

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-20 18:55:02 +02:00

111 lines
3.0 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { describe, it, expect, vi } from 'vitest'
import { linkItem } from './itemFunctions'
import type { Item } from '#types/Item'
const toastErrorMock: (t: string) => void = vi.fn()
const toastSuccessMock: (t: string) => void = vi.fn()
const toastLoadingMock: (t: string) => number = vi.fn(() => 123)
const toastUpdateMock: (id: number, options: any) => void = vi.fn()
vi.mock('react-toastify', () => ({
toast: {
error: (t: string) => toastErrorMock(t),
success: (t: string) => toastSuccessMock(t),
loading: (t: string) => toastLoadingMock(t),
update: (id: number, options: any) => toastUpdateMock(id, options),
},
}))
describe('linkItem', () => {
const id = 'some-id'
let updateApi: (item: Partial<Item>) => Promise<Item> = vi.fn()
const mockUser = {
id: 'user-1',
first_name: 'Test',
last_name: 'User',
email: 'test@example.com',
}
const item: Item = {
layer: {
id: 'test-layer-id',
api: {
updateItem: (item) => updateApi(item),
getItems: vi.fn(),
},
name: '',
menuIcon: '',
menuColor: '',
menuText: '',
markerIcon: {
image: '',
},
markerShape: 'square',
markerDefaultColor: '',
itemType: {
name: 'Test Item Type',
show_name_input: true,
show_profile_button: false,
show_start_end: true,
show_start_end_input: true,
show_text: true,
show_text_input: true,
custom_text: 'This is a custom text for the item type.',
profileTemplate: [
{ collection: 'users', id: null, item: {} },
{ collection: 'posts', id: '123', item: {} },
],
offers_and_needs: true,
icon_as_labels: {},
relations: true,
template: 'default',
questlog: false,
},
},
id: '',
name: '',
}
const updateItem = vi.fn()
beforeEach(() => {
updateApi = vi.fn()
vi.clearAllMocks()
})
describe('api rejects', () => {
it('toasts an error', async () => {
updateApi = vi.fn().mockRejectedValue('autsch')
await linkItem(id, item, updateItem, mockUser)
expect(toastUpdateMock).toHaveBeenCalledWith(123, expect.objectContaining({ type: 'error' }))
expect(updateItem).not.toHaveBeenCalled()
expect(toastSuccessMock).not.toHaveBeenCalled()
})
})
describe('api resolves', () => {
it('toasts success and calls updateItem()', async () => {
const serverResponse = {
...item,
layer: 'test-layer-id',
relations: [{ items_id: item.id, related_items_id: id }],
}
updateApi = vi.fn().mockResolvedValue(serverResponse)
await linkItem(id, item, updateItem, mockUser)
expect(toastUpdateMock).toHaveBeenCalledWith(
123,
expect.objectContaining({ type: 'success' }),
)
expect(updateItem).toHaveBeenCalledWith(
expect.objectContaining({
...serverResponse,
layer: item.layer,
}),
)
})
})
})