import { describe, expect, it } from 'vitest';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import { FinalMaskField } from '@/lib/xray/forms/fields';
import { listSelectOptions, renderWithProviders } from './test-utils';
describe('FinalMaskForm item types', () => {
// Only the noise mask parses tag expressions; header-custom items go through the
// core's PraseByteSlice, which refuses "exp" and fails the whole config load.
it('offers the exp type to noise items only', () => {
renderWithProviders(
,
);
// An opened dropdown stays in the DOM, so read header-custom's before noise's.
expect(listSelectOptions('finalmask_udp_1_settings_client_0_type')).not.toContain('Expression');
expect(listSelectOptions('finalmask_udp_0_settings_noise_0_type')).toContain('Expression');
});
});
describe('FinalMaskForm salamander password', () => {
// xray-core loads a salamander password under 4 bytes and refuses it only when the socket
// opens: on an inbound that stops Xray. It counts bytes, so "a€" (4 bytes) is long enough.
it('flags a password under 4 bytes and accepts a 4-byte one', async () => {
renderWithProviders(
,
);
const input = document.getElementById('finalmask_udp_0_settings_password') as HTMLInputElement;
fireEvent.change(input, { target: { value: 'abc' } });
expect(await screen.findByText(/at least 4 bytes/)).toBeTruthy();
fireEvent.change(input, { target: { value: 'a€' } });
await waitFor(() => expect(screen.queryByText(/at least 4 bytes/)).toBeNull());
});
});