tests/drafts.test.ts
此代码来自构建时的仓库快照。修改源码后重新构建即可更新。
import { describe, expect, it } from 'vitest';
import { createDraftStore, draftKey } from '@/stores/drafts';
import { ticketSearchParsers } from '@/features/tickets/url-state';
const memoryStorage = () => {
const data = new Map<string, string>();
return {
getItem: (key: string) => data.get(key) ?? null,
setItem: (key: string, value: string) => {
data.set(key, value);
},
removeItem: (key: string) => {
data.delete(key);
},
};
};
describe('草稿隔离与恢复', () => {
it('同账号刷新恢复草稿,其他团队、工单和账号不串用', async () => {
const storage = memoryStorage();
const first = createDraftStore('user-a', storage);
await first.persist.rehydrate();
first
.getState()
.save(draftKey('team-a', 'ticket-a'), { text: '未发送内容' });
first.getState().save(draftKey('team-b', 'new'), {
ticket: { title: '', description: '尚未写完', priority: 'NORMAL' },
});
const refresh = createDraftStore('user-a', storage);
await refresh.persist.rehydrate();
expect(refresh.getState().drafts[draftKey('team-a', 'ticket-a')].text).toBe(
'未发送内容',
);
expect(
refresh.getState().drafts[draftKey('team-a', 'ticket-b')],
).toBeUndefined();
expect(
refresh.getState().drafts[draftKey('team-b', 'new')].ticket?.description,
).toBe('尚未写完');
const other = createDraftStore('user-b', storage);
await other.persist.rehydrate();
expect(other.getState().drafts).toEqual({});
refresh.getState().remove(draftKey('team-a', 'ticket-a'));
expect(refresh.getState().drafts[draftKey('team-b', 'new')]).toBeDefined();
refresh.persist.clearStorage();
const logout = createDraftStore('user-a', storage);
await logout.persist.rehydrate();
expect(logout.getState().drafts).toEqual({});
});
it('损坏的存储不会恢复成草稿', async () => {
const storage = memoryStorage();
storage.setItem(
'teamdesk-drafts:user-a',
JSON.stringify({ state: { drafts: { bad: { text: 123 } } }, version: 0 }),
);
const store = createDraftStore('user-a', storage);
await store.persist.rehydrate();
expect(store.getState().drafts).toEqual({});
});
});
describe('URL 参数边界', () => {
it('无效分页和枚举回落默认值,合法链接可恢复', () => {
expect(ticketSearchParsers.page.parse('-1')).toBeNull();
expect(ticketSearchParsers.page.parse('1.5')).toBeNull();
expect(ticketSearchParsers.pageSize.parse('999')).toBeNull();
expect(ticketSearchParsers.status.parse('INVALID')).toBeNull();
expect(ticketSearchParsers.page.parse('2')).toBe(2);
expect(ticketSearchParsers.status.parse('OPEN')).toBe('OPEN');
expect(ticketSearchParsers.assignment.parse('mine')).toBe('mine');
});
});