feat: add delete confirmation modal and enhance token handling
- Implemented a DeleteConfirmModal component for confirming deletions across various pages (Accounts, Sites, Tokens). - Updated Accounts and Sites pages to utilize the new modal for single and batch deletions. - Enhanced TokensPanel to support group selection and improved token deletion handling with confirmation. - Added functionality to skip confirmation for batch actions and handle token group fetching with error management. - Improved error handling for expired sessions in NewApiAdapter and OneApiAdapter. - Added tests for new delete confirmation behavior and token editing interactions.
This commit is contained in:
@@ -10,6 +10,7 @@ const { apiMock } = vi.hoisted(() => ({
|
||||
getSites: vi.fn(),
|
||||
getAccountTokens: vi.fn(),
|
||||
getAccountTokenValue: vi.fn(),
|
||||
getAccountTokenGroups: vi.fn(),
|
||||
updateAccountToken: vi.fn(),
|
||||
},
|
||||
}));
|
||||
@@ -98,6 +99,10 @@ describe('Tokens edit modal and row selection', () => {
|
||||
success: true,
|
||||
token: 'sk-focus-real',
|
||||
});
|
||||
apiMock.getAccountTokenGroups.mockResolvedValue({
|
||||
success: true,
|
||||
groups: ['default', 'vip'],
|
||||
});
|
||||
apiMock.updateAccountToken.mockResolvedValue({
|
||||
success: true,
|
||||
});
|
||||
@@ -131,11 +136,25 @@ describe('Tokens edit modal and row selection', () => {
|
||||
expect(rendered).toContain('sk-focus-real');
|
||||
expect(rendered).toContain('基本信息');
|
||||
expect(rendered).toContain('状态设置');
|
||||
expect(rendered).toContain('分组');
|
||||
const modals = root.root.findAll((node) => {
|
||||
const className = typeof node.props?.className === 'string' ? node.props.className : '';
|
||||
return className.includes('modal-content') && collectText(node).includes('编辑令牌');
|
||||
});
|
||||
expect(modals).toHaveLength(1);
|
||||
expect(apiMock.getAccountTokenGroups).toHaveBeenCalledWith(1);
|
||||
|
||||
const saveButton = root.root
|
||||
.findAll((node) => node.type === 'button')
|
||||
.find((node) => collectText(node).includes('保存修改'));
|
||||
expect(saveButton).toBeTruthy();
|
||||
|
||||
await act(async () => {
|
||||
saveButton!.props.onClick();
|
||||
});
|
||||
await flushMicrotasks();
|
||||
|
||||
expect(apiMock.updateAccountToken).toHaveBeenCalledWith(22, expect.objectContaining({ group: 'default' }));
|
||||
} finally {
|
||||
root?.unmount();
|
||||
}
|
||||
@@ -181,4 +200,32 @@ describe('Tokens edit modal and row selection', () => {
|
||||
root?.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
it('does not repeatedly refetch groups when edit-group loading fails once', async () => {
|
||||
apiMock.getAccountTokenGroups.mockRejectedValueOnce(new Error('账号会话可能已过期,请重新登录后再拉取分组'));
|
||||
|
||||
let root: ReturnType<typeof create> | null = null;
|
||||
try {
|
||||
await act(async () => {
|
||||
root = buildRoot();
|
||||
});
|
||||
await flushMicrotasks();
|
||||
|
||||
const editButton = root.root
|
||||
.findAll((node) => node.type === 'button')
|
||||
.find((node) => collectText(node).includes('编辑'));
|
||||
expect(editButton).toBeTruthy();
|
||||
|
||||
await act(async () => {
|
||||
editButton!.props.onClick({ stopPropagation: () => undefined });
|
||||
});
|
||||
|
||||
await flushMicrotasks();
|
||||
await flushMicrotasks();
|
||||
|
||||
expect(apiMock.getAccountTokenGroups).toHaveBeenCalledTimes(1);
|
||||
} finally {
|
||||
root?.unmount();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user