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:
ciat-777
2026-03-14 13:31:15 +08:00
parent ad791d87bb
commit 1a1f0452b3
18 changed files with 595 additions and 58 deletions
+55
View File
@@ -85,4 +85,59 @@ describe('Sites edit behavior', () => {
root?.unmount();
}
});
it('restores header add button label after closing add modal', async () => {
apiMock.getSites.mockResolvedValue([]);
let root: ReturnType<typeof create> | null = null;
try {
await act(async () => {
root = create(
<MemoryRouter initialEntries={['/sites']}>
<ToastProvider>
<Sites />
</ToastProvider>
</MemoryRouter>,
);
});
await flushMicrotasks();
const openAddButton = root.root.find((node) => (
node.type === 'button'
&& typeof node.props.onClick === 'function'
&& typeof node.props.className === 'string'
&& node.props.className.includes('btn btn-primary')
&& collectText(node).includes('添加站点')
));
await act(async () => {
openAddButton.props.onClick();
});
await flushMicrotasks();
const closeModalButton = root.root.find((node) => (
node.type === 'button'
&& typeof node.props.onClick === 'function'
&& typeof node.props.className === 'string'
&& node.props.className.includes('btn btn-ghost')
&& collectText(node).trim() === '取消'
));
await act(async () => {
closeModalButton.props.onClick();
});
await flushMicrotasks();
const headerAddButton = root.root.find((node) => (
node.type === 'button'
&& typeof node.props.className === 'string'
&& node.props.className.includes('btn btn-primary')
&& collectText(node).includes('添加站点')
));
expect(collectText(headerAddButton)).toContain('添加站点');
} finally {
root?.unmount();
}
});
});