5180 fichiers 38.5 Mo 0 téléchargements 589 vues mis à jour il y a 8 heures ui
nitro-v36-with-renderer-v36 / src / components / catalog / views / page / layout / recycler / CatalogLayoutRecyclerView.test.tsx
CatalogLayoutRecyclerView.test.tsx 5.7 Ko Télécharger le fichier
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const state = vi.hoisted(() => ({ sent: [] as unknown[], handlers: new Map<unknown, (event: unknown) => void>(), groups: [] as unknown[] }));

vi.mock('../../../../../../api', async (importOriginal) => ({
    ...(await importOriginal<typeof import('../../../../../../api')>()),
    LocalizeText: (key: string) => key,
    localizeWithFallback: (key: string) => key,
    SendMessageComposer: (composer: unknown) => state.sent.push(composer)
}));

vi.mock('../../../../../../hooks', async (importOriginal) => ({
    ...(await importOriginal<typeof import('../../../../../../hooks')>()),
    useInventoryFurni: () => ({ groupItems: state.groups }),
    useMessageEvent: (type: unknown, handler: (event: unknown) => void) => state.handlers.set(type, handler)
}));

import { PurchaseErrorMessageEvent, RecycleItemsMessageComposer, RecyclerFinishedMessageEvent, RecyclerStatusMessageEvent } from '@octane/renderer';
import { CatalogLayoutRecyclerView } from './CatalogLayoutRecyclerView';

const group = (id: number, name: string) => ({ name, iconUrl: `${name}.png`, items: [{ id, recyclable: true, locked: false }] });

const setStatus = (recyclerStatus: number) =>
    act(() => state.handlers.get(RecyclerStatusMessageEvent)?.({ getParser: () => ({ recyclerStatus, recyclerTimeoutSeconds: 0 }) }));

describe('recycler page (AIR layout_recycler_xml + recyclerWidget_xml)', () => {
    afterEach(cleanup);

    beforeEach(() => {
        state.sent.length = 0;
        state.handlers.clear();
        state.groups = Array.from({ length: 9 }, (_, index) => group(100 + index, `furni${index}`));
    });

    it('fills the slots from the chooser and recycles them', () => {
        const { container } = render(<CatalogLayoutRecyclerView page={{} as any} hideNavigation={() => undefined} />);

        setStatus(RecyclerStatusMessageEvent.SYSTEM_STATUS_ENABLED);

        expect(container.querySelector('.octane-catalog-air-recycler__machine')).not.toBeNull();
        expect(container.querySelectorAll('.octane-catalog-air-recycler__slot')).toHaveLength(8);

        fireEvent.click(screen.getByRole('listitem', { name: '1' }));

        for (let index = 0; index < 8; index++) fireEvent.click(screen.getByRole('button', { name: `furni${index}` }));

        // The chooser closes when the slots are full.
        expect(screen.queryByRole('dialog')).toBeNull();

        fireEvent.click(screen.getByRole('button', { name: 'catalog.recycler.button.recycle' }));

        const recycle = state.sent.find((composer) => composer instanceof RecycleItemsMessageComposer) as any;

        expect(recycle.getMessageArray().map((entry: { itemId: number }) => entry.itemId)).toEqual([100, 101, 102, 103, 104, 105, 106, 107]);
    });

    it('takes an item back out of its slot', () => {
        render(<CatalogLayoutRecyclerView page={{} as any} hideNavigation={() => undefined} />);

        setStatus(RecyclerStatusMessageEvent.SYSTEM_STATUS_ENABLED);
        fireEvent.click(screen.getByRole('listitem', { name: '1' }));
        fireEvent.click(screen.getByRole('button', { name: 'furni0' }));
        fireEvent.click(screen.getByRole('listitem', { name: 'furni0' }));

        expect(screen.queryByRole('listitem', { name: 'furni0' })).toBeNull();
    });

    it('shows Frank when the recycler is closed', () => {
        const { container } = render(<CatalogLayoutRecyclerView page={{} as any} hideNavigation={() => undefined} />);

        setStatus(RecyclerStatusMessageEvent.SYSTEM_STATUS_DISABLED);

        expect(container.querySelector('.octane-catalog-air-recycler__frank')).not.toBeNull();
        expect(container.querySelector('.octane-catalog-air-recycler__slots')).toBeNull();
    });

    const fillAndRecycle = () => {
        fireEvent.click(screen.getByRole('listitem', { name: '1' }));

        for (let index = 0; index < 8; index++) fireEvent.click(screen.getByRole('button', { name: `furni${index}` }));

        fireEvent.click(screen.getByRole('button', { name: 'catalog.recycler.button.recycle' }));
    };

    it('keeps the furni in their slots and says so when the recycle fails (FINISHED_FAIL)', () => {
        render(<CatalogLayoutRecyclerView page={{} as any} hideNavigation={() => undefined} />);

        setStatus(RecyclerStatusMessageEvent.SYSTEM_STATUS_ENABLED);
        fillAndRecycle();

        expect(screen.getByRole('status')).toHaveTextContent('recycler.info.processing');

        act(() =>
            state.handlers.get(RecyclerFinishedMessageEvent)?.({
                getParser: () => ({ recyclerFinishedStatus: RecyclerFinishedMessageEvent.FINISHED_FAIL })
            })
        );

        expect(screen.getByRole('status')).toHaveTextContent('recycler.info.failed');
        expect(screen.getAllByRole('listitem').filter((slot) => slot.getAttribute('aria-label')?.startsWith('furni'))).toHaveLength(8);
        expect(screen.getByRole('button', { name: 'catalog.recycler.button.recycle' })).toBeEnabled();
    });

    it('ends the run on a purchase error from an emulator without FINISHED_FAIL', () => {
        render(<CatalogLayoutRecyclerView page={{} as any} hideNavigation={() => undefined} />);

        setStatus(RecyclerStatusMessageEvent.SYSTEM_STATUS_ENABLED);

        // Not recycling: a purchase error from elsewhere in the catalog changes nothing.
        act(() => state.handlers.get(PurchaseErrorMessageEvent)?.({ getParser: () => ({ code: 0 }) }));
        expect(screen.getByRole('status')).toHaveTextContent('recycler.info.ready');

        fillAndRecycle();
        act(() => state.handlers.get(PurchaseErrorMessageEvent)?.({ getParser: () => ({ code: 0 }) }));

        expect(screen.getByRole('status')).toHaveTextContent('recycler.info.failed');
    });
});
15Sujets
1Dépôts
20Membres
4En 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