finalmask-form.test.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { describe, expect, it } from 'vitest';
  2. import { fireEvent, screen, waitFor } from '@testing-library/react';
  3. import { FinalMaskField } from '@/lib/xray/forms/fields';
  4. import { listSelectOptions, renderWithProviders } from './test-utils';
  5. describe('FinalMaskForm item types', () => {
  6. // Only the noise mask parses tag expressions; header-custom items go through the
  7. // core's PraseByteSlice, which refuses "exp" and fails the whole config load.
  8. it('offers the exp type to noise items only', () => {
  9. renderWithProviders(
  10. <FinalMaskField
  11. network="kcp"
  12. protocol="vless"
  13. value={{
  14. tcp: [],
  15. udp: [
  16. { type: 'noise', settings: { noise: [{ type: 'array', rand: '1-8', delay: '1-2' }] } },
  17. { type: 'header-custom', settings: { client: [{ type: 'array', rand: 1 }] } },
  18. ],
  19. }}
  20. />,
  21. );
  22. // An opened dropdown stays in the DOM, so read header-custom's before noise's.
  23. expect(listSelectOptions('finalmask_udp_1_settings_client_0_type')).not.toContain('Expression');
  24. expect(listSelectOptions('finalmask_udp_0_settings_noise_0_type')).toContain('Expression');
  25. });
  26. });
  27. describe('FinalMaskForm salamander password', () => {
  28. // xray-core loads a salamander password under 4 bytes and refuses it only when the socket
  29. // opens: on an inbound that stops Xray. It counts bytes, so "a€" (4 bytes) is long enough.
  30. it('flags a password under 4 bytes and accepts a 4-byte one', async () => {
  31. renderWithProviders(
  32. <FinalMaskField
  33. network="hysteria"
  34. protocol="hysteria"
  35. value={{ tcp: [], udp: [{ type: 'salamander', settings: { password: 'long-enough' } }] }}
  36. />,
  37. );
  38. const input = document.getElementById('finalmask_udp_0_settings_password') as HTMLInputElement;
  39. fireEvent.change(input, { target: { value: 'abc' } });
  40. expect(await screen.findByText(/at least 4 bytes/)).toBeTruthy();
  41. fireEvent.change(input, { target: { value: 'a€' } });
  42. await waitFor(() => expect(screen.queryByText(/at least 4 bytes/)).toBeNull());
  43. });
  44. });