client-calendar-renewal.test.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { expect, it, vi } from 'vitest';
  2. import { fireEvent, screen, waitFor } from '@testing-library/react';
  3. import ClientFormModal from '@/pages/clients/ClientFormModal';
  4. import { HttpUtil, Msg } from '@/utils';
  5. import { chooseSelectOption, renderWithProviders } from './test-utils';
  6. it('preserves monthly clients, previews backend dates, and saves exclusive weekly or disabled modes', async () => {
  7. const post = vi.spyOn(HttpUtil, 'post').mockResolvedValue(
  8. new Msg(true, '', {
  9. timeZone: 'Asia/Taipei',
  10. renewAt: '2030-01-01T00:00:00+08:00',
  11. validThrough: '2029-12-31T23:59:59+08:00',
  12. nextExpiry: '2030-02-01T00:00:00+08:00',
  13. suggestedExpiryTime: 1893427200000,
  14. suggestedExpiry: '2030-01-01T00:00:00+08:00',
  15. renewals: 1,
  16. canRenew: true,
  17. delayedStart: false,
  18. }),
  19. );
  20. const save = vi.fn().mockResolvedValue(new Msg(true, '', null));
  21. async function submit() {
  22. const button = document.querySelector('.ant-modal-footer .ant-btn-primary');
  23. if (!button) throw new Error('Save button missing');
  24. await waitFor(() => expect(button.classList.contains('ant-btn-loading')).toBe(false));
  25. fireEvent.click(button);
  26. }
  27. try {
  28. renderWithProviders(
  29. <ClientFormModal
  30. open
  31. mode="edit"
  32. client={{
  33. email: '[email protected]',
  34. uuid: '11111111-1111-1111-1111-111111111111',
  35. subId: 'calendar-sub',
  36. enable: true,
  37. expiryTime: 1893427200000,
  38. resetDay: 1,
  39. reset: 7,
  40. resetMax: 3,
  41. traffic: { resetCount: 2 },
  42. }}
  43. attachedIds={[1]}
  44. inbounds={[{ id: 1, protocol: 'vless', tag: 'calendar' }]}
  45. save={save}
  46. onOpenChange={() => {}}
  47. />,
  48. );
  49. const mode = screen.getByLabelText('Auto renewal');
  50. expect(mode.closest('.ant-select')?.textContent).toContain('Calendar monthly');
  51. await waitFor(() => expect(document.body.textContent).toContain('2029-12-31T23:59:59+08:00'));
  52. expect(post).toHaveBeenCalledWith(
  53. '/panel/api/clients/renewalPreview',
  54. expect.objectContaining({ resetMax: 3, resetCount: 2 }),
  55. expect.anything(),
  56. );
  57. await submit();
  58. await waitFor(() =>
  59. expect(save).toHaveBeenCalledWith(
  60. expect.objectContaining({
  61. reset: 7,
  62. resetDay: 1,
  63. resetWeekday: 0,
  64. expiryTime: 1893427200000,
  65. }),
  66. expect.anything(),
  67. ),
  68. );
  69. chooseSelectOption(mode.id, 'Calendar weekly');
  70. const weekday = screen.getByLabelText('Renew on weekday');
  71. chooseSelectOption(weekday.id, 'Sunday');
  72. await waitFor(() =>
  73. expect(post).toHaveBeenCalledWith(
  74. '/panel/api/clients/renewalPreview',
  75. expect.objectContaining({ reset: 0, resetDay: 0, resetWeekday: 7 }),
  76. expect.anything(),
  77. ),
  78. );
  79. await submit();
  80. await waitFor(() =>
  81. expect(save).toHaveBeenCalledWith(
  82. expect.objectContaining({
  83. reset: 0,
  84. resetDay: 0,
  85. resetWeekday: 7,
  86. expiryTime: 1893427200000,
  87. }),
  88. expect.anything(),
  89. ),
  90. );
  91. chooseSelectOption(mode.id, 'Disabled');
  92. await submit();
  93. await waitFor(() =>
  94. expect(save).toHaveBeenCalledWith(
  95. expect.objectContaining({
  96. reset: 0,
  97. resetDay: 0,
  98. resetWeekday: 0,
  99. expiryTime: 1893427200000,
  100. }),
  101. expect.anything(),
  102. ),
  103. );
  104. } finally {
  105. post.mockRestore();
  106. }
  107. });