5180 fichiers 38.5 Mo 0 téléchargements 283 vues mis à jour il y a 6 heures ui
nitro-v36-with-renderer-v36 / src / components / wired / views / WiredValueOrVariableInput.test.tsx
WiredValueOrVariableInput.test.tsx 10.2 Ko Télécharger le fichier
import { cleanup, fireEvent, render, screen, within } from '@testing-library/react';
import { PropsWithChildren } from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';

vi.mock('../../../api', () => ({
    LocalizeText: (key: string) => key,
    localizeWithFallback: (key: string) => key,
    GetRoomSession: () => ({ roomId: 1 })
}));
vi.mock('../../../common', () => ({ Text: ({ children }: PropsWithChildren) => <span>{children}</span> }));

const { readWiredValueText, isWiredSameHolderEligible, WiredValueOrVariableInput } = await import('./WiredValueOrVariableInput');
const { buildWiredVariablePickerEntries } = await import('./WiredVariablePickerData');

const variable = (itemId: number, name: string, hasValue = true) => ({ itemId, name, variableType: 0, availability: 0, hasValue, isReadOnly: false });
const entries = buildWiredVariablePickerEntries('user', 'change-reference', [variable(1, 'score'), variable(2, 'Score'), variable(3, 'coins'), variable(4, 'flag', false)]);
const coins = entries.find((entry) => entry.displayLabel === 'coins');

afterEach(cleanup);

describe('readWiredValueText (AIR ValueOrVariableSection.onInputTextChanged)', () => {
    it('reads decimal, hex and binary numbers within the range as literals', () => {
        expect(readWiredValueText('-12', entries, -100, 100)).toEqual({ kind: 'literal', valid: true, value: -12 });
        expect(readWiredValueText('0x1f', entries, -100, 100)).toEqual({ kind: 'literal', valid: true, value: 31 });
        expect(readWiredValueText('0b101', entries, -100, 100)).toEqual({ kind: 'literal', valid: true, value: 5 });
        expect(readWiredValueText('101', entries, -100, 100)).toEqual({ kind: 'literal', valid: false });
        expect(readWiredValueText('-', entries, -100, 100)).toEqual({ kind: 'literal', valid: false });
    });

    it('reads other text as a variable name, in any case, valid only for one eligible match', () => {
        expect(readWiredValueText('COINS', entries, 0, 1)).toMatchObject({ kind: 'variable', valid: true, entry: coins });
        expect(readWiredValueText('score', entries, 0, 1)).toMatchObject({ kind: 'variable', valid: false, ambiguous: true });
        expect(readWiredValueText('nothing', entries, 0, 1)).toMatchObject({ kind: 'variable', valid: false, ambiguous: false });
    });

    it('allows the same holder only on the destination furni or user type', () => {
        expect(isWiredSameHolderEligible('user', 'user')).toBe(true);
        expect(isWiredSameHolderEligible('furni', 'furni')).toBe(true);
        expect(isWiredSameHolderEligible('user', 'furni')).toBe(false);
        expect(isWiredSameHolderEligible('global', 'global')).toBe(false);
        expect(isWiredSameHolderEligible('context', 'context')).toBe(false);
    });
});

const renderInput = (props: Partial<Parameters<typeof WiredValueOrVariableInput>[0]> = {}) => {
    const handlers = {
        onIsVariableChange: vi.fn(),
        onLiteralChange: vi.fn(),
        onTargetChange: vi.fn(),
        onTokenChange: vi.fn(),
        onValidityChange: vi.fn(),
        onSameHolderChange: vi.fn()
    };

    render(
        <WiredValueOrVariableInput
            entries={entries}
            isVariable={false}
            label="reference"
            literal="3"
            primaryTarget="user"
            target="user"
            targets={['furni', 'user', 'global', 'context']}
            token=""
            {...handlers}
            {...props}
        />
    );

    return handlers;
};

const field = () => screen.getByRole('textbox', { name: 'reference' });
const openPopup = () => fireEvent.click(screen.getByRole('button', { name: 'wiredfurni.params.variables.reference_value.popup' }));

describe('WiredValueOrVariableInput (AIR ValueOrVariableInputPreset)', () => {
    it('takes a typed number as the literal and a typed name as the variable', () => {
        const handlers = renderInput();

        expect(field()).toHaveValue('3');
        fireEvent.change(field(), { target: { value: '0x10' } });
        expect(handlers.onIsVariableChange).toHaveBeenLastCalledWith(false);
        expect(handlers.onLiteralChange).toHaveBeenLastCalledWith('16');
        expect(field()).toHaveValue('0x10');

        fireEvent.change(field(), { target: { value: 'Coins' } });
        expect(handlers.onIsVariableChange).toHaveBeenLastCalledWith(true);
        expect(handlers.onTokenChange).toHaveBeenLastCalledWith(coins.token);
        expect(screen.queryByRole('alert')).toBeNull();
    });

    it('marks an unknown or ambiguous name invalid with the official texts', () => {
        const handlers = renderInput();

        fireEvent.change(field(), { target: { value: 'score' } });
        expect(screen.getByRole('alert')).toHaveTextContent('wiredfurni.params.variables.reference_value.ambiguous');
        expect(handlers.onValidityChange).toHaveBeenLastCalledWith(false);

        fireEvent.change(field(), { target: { value: 'missing' } });
        expect(screen.getByRole('alert')).toHaveTextContent('wiredfurni.params.variables.reference_value.invalid');
    });

    it('shows a saved variable by name with the target indicator, and a missing one as invalid', () => {
        renderInput({ isVariable: true, token: coins.token });

        expect(field()).toHaveValue('coins');
        expect(screen.getByTitle('wiredfurni.params.sourcetype.users')).toBeTruthy();
        cleanup();

        renderInput({ isVariable: true, token: '' });
        expect(screen.getByRole('alert')).toBeTruthy();
        cleanup();

        renderInput({ isVariable: false, targets: ['user'] });
        expect(screen.queryByTitle('wiredfurni.params.sourcetype.users')).toBeNull();
    });

    it('a disabled section greys the field, shows no error and keeps the popup shut', () => {
        const handlers = renderInput({ disabled: true, isVariable: true, token: '' });

        expect(field()).toBeDisabled();
        expect(screen.queryByRole('alert')).toBeNull();
        expect(handlers.onValidityChange).toHaveBeenLastCalledWith(true);
        expect(screen.getByRole('button', { name: 'wiredfurni.params.variables.reference_value.popup' })).toBeDisabled();
    });
});

describe('WiredValueOrVariableInput popup (AIR ValueOrVariablePopupPreset)', () => {
    it('lays out the claimed source, the same-holder checkbox and then the picker', () => {
        renderInput({
            renderSource: ({ typeSelector, locked }) => (
                <div data-testid="source" data-locked={String(locked)}>
                    wiredfurni.params.sources.merged.title.variables{typeSelector}
                </div>
            )
        });
        openPopup();

        const popup = screen.getByRole('dialog', { name: 'reference' });
        const text = popup.textContent;

        expect(within(popup).getByTestId('source')).toHaveAttribute('data-locked', 'false');
        expect(text.indexOf('wiredfurni.params.sources.merged.title.variables')).toBeLessThan(text.indexOf('wiredfurni.params.variables.reference_value.same_holder'));
        // The checkbox group comes before the picker's tab row.
        const checkbox = within(popup).getByRole('checkbox');
        const firstTab = within(popup).getByRole('button', { name: 'wiredfurni.variable_picker.tab.all' });

        expect(checkbox.compareDocumentPosition(firstTab) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
        expect(within(popup).getAllByRole('button', { name: /wiredfurni\.params\.sourcetype\./ })).toHaveLength(4);
    });

    it('locks the source and the type selector while the same holder is used', () => {
        const handlers = renderInput({
            isVariable: true,
            token: coins.token,
            sameHolder: true,
            renderSource: ({ typeSelector, locked }) => (
                <div data-testid="source" data-locked={String(locked)}>
                    {typeSelector}
                </div>
            )
        });
        openPopup();

        const popup = screen.getByRole('dialog');

        expect(within(popup).getByTestId('source')).toHaveAttribute('data-locked', 'true');
        for (const button of within(popup).getAllByRole('button', { name: /wiredfurni\.params\.sourcetype\./ })) expect(button).toBeDisabled();
        fireEvent.click(within(popup).getByRole('checkbox'));
        expect(handlers.onSameHolderChange).toHaveBeenCalledWith(false);
    });

    it('keeps the stored checkbox state but disables it on another holder type, and checking it picks the variable mode', () => {
        renderInput({ target: 'global', sameHolder: true });
        openPopup();
        expect(within(screen.getByRole('dialog')).getByRole('checkbox')).toBeChecked();
        expect(within(screen.getByRole('dialog')).getByRole('checkbox')).toHaveAttribute('aria-disabled', 'true');
        cleanup();

        const handlers = renderInput({ target: 'user', sameHolder: false });
        openPopup();
        fireEvent.click(within(screen.getByRole('dialog')).getByRole('checkbox'));
        expect(handlers.onSameHolderChange).toHaveBeenCalledWith(true);
        expect(handlers.onIsVariableChange).toHaveBeenCalledWith(true);
    });

    it('a type change clears the variable; a pick sets it and closes the popup', () => {
        const handlers = renderInput();

        openPopup();
        fireEvent.click(within(screen.getByRole('dialog')).getByRole('button', { name: 'wiredfurni.params.sourcetype.furni' }));
        expect(handlers.onTargetChange).toHaveBeenCalledWith('furni');
        expect(handlers.onTokenChange).toHaveBeenLastCalledWith('');

        fireEvent.click(within(screen.getByRole('dialog')).getByRole('button', { name: 'wiredfurni.variable_picker.tab.all' }));
        fireEvent.click(screen.getAllByRole('option').find((option) => option.textContent === 'coins'));
        expect(handlers.onIsVariableChange).toHaveBeenLastCalledWith(true);
        expect(handlers.onTokenChange).toHaveBeenLastCalledWith(coins.token);
        expect(screen.queryByRole('dialog')).toBeNull();
    });

    it('closes on an outside click and on Escape', () => {
        renderInput();
        openPopup();
        fireEvent.mouseDown(document.body);
        expect(screen.queryByRole('dialog')).toBeNull();

        openPopup();
        fireEvent.keyDown(within(screen.getByRole('dialog')).getByRole('textbox'), { key: 'Escape' });
        expect(screen.queryByRole('dialog')).toBeNull();
    });
});
15Sujets
1Dépôts
20Membres
2En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser