5180 fichiers 38.5 Mo 0 téléchargements 262 vues mis à jour il y a 5 heures ui
nitro-v36-with-renderer-v36 / src / components / furni-editor / furniEditorSuggestions.test.ts
furniEditorSuggestions.test.ts 8.1 Ko Télécharger le fichier
import { describe, expect, it } from 'vitest';
import {
    EditableFields,
    expectationsForType,
    lineQueryFor,
    multiheightMismatch,
    relateRows,
    RelatedRow,
    spriteIdMismatch,
    suggestFromFurnidata,
    suggestFromSiblings,
    suggestInteractionType
} from './furniEditorSuggestions';

const registered = ['default', 'gate', 'guild_gate', 'teleport', 'dice', 'vendingmachine', 'multiheight', 'wf_trg_enter_room', 'wf_act_kick_user'];

const form: EditableFields = {
    width: 1,
    length: 1,
    stackHeight: 1.5,
    allowStack: false,
    allowWalk: false,
    allowSit: true,
    allowLay: false,
    allowTrade: true,
    allowRecycle: true,
    interactionType: 'default',
    interactionModesCount: 1,
    vendingIds: '',
    multiheight: ''
};

describe('suggestInteractionType', () => {
    it('takes a classname that is itself a registered type', () => {
        expect(suggestInteractionType('wf_act_kick_user', registered)).toEqual({ type: 'wf_act_kick_user', reason: 'classname is a registered type' });
    });

    it('prefers the longest registered prefix', () => {
        expect(suggestInteractionType('guild_gate_c', registered)?.type).toBe('guild_gate');
        expect(suggestInteractionType('teleport_door', registered)?.type).toBe('teleport');
    });

    it('falls back to a token inside the classname', () => {
        expect(suggestInteractionType('hc_dice_gold', registered)?.type).toBe('dice');
        expect(suggestInteractionType('rare_gate*2', registered)?.type).toBe('gate');
    });

    it('never suggests default or multiheight, and nothing for an unrelated classname', () => {
        expect(suggestInteractionType('default_chair', registered)).toBeNull();
        expect(suggestInteractionType('multiheight_bed', registered)).toBeNull();
        expect(suggestInteractionType('throne', registered)).toBeNull();
        expect(suggestInteractionType('', registered)).toBeNull();
    });
});

describe('suggestFromFurnidata', () => {
    it('proposes the furnidata footprint and flags when they differ from the form', () => {
        const entry = { xdim: 2, ydim: 3, canstandon: true, cansiton: true, canlayon: false, tradeable: false, recyclable: true, description: 'Royal seat' };

        expect(suggestFromFurnidata(entry, form)).toEqual([
            { field: 'width', value: 2, reason: 'furnidata xdim' },
            { field: 'length', value: 3, reason: 'furnidata ydim' },
            { field: 'allowWalk', value: true, reason: 'furnidata canstandon' },
            { field: 'allowTrade', value: false, reason: 'furnidata tradeable' }
        ]);
    });

    it('keeps quiet when everything agrees or the entry is missing', () => {
        const entry = { xdim: 1, ydim: 1, canstandon: false, cansiton: true, canlayon: false, tradeable: true, recyclable: true, description: 'x' };

        expect(suggestFromFurnidata(entry, form)).toEqual([]);
        expect(suggestFromFurnidata(null, form)).toEqual([]);
    });

    it('ignores a wall entry without dimensions and odd values', () => {
        expect(suggestFromFurnidata({ classname: 'post.it', xdim: 'abc', cansiton: 'maybe' }, form)).toEqual([]);
        expect(suggestFromFurnidata({ xdim: 0 }, form)).toEqual([]);
    });
});

describe('expectationsForType', () => {
    it('suggests the state count a gate drives', () => {
        expect(expectationsForType({ ...form, interactionType: 'gate' })).toEqual({
            suggestions: [{ field: 'interactionModesCount', value: 2, reason: 'gate drives 2 states' }],
            warnings: []
        });
        expect(expectationsForType({ ...form, interactionType: 'Gate', interactionModesCount: 2 }).suggestions).toEqual([]);
    });

    it('warns when a list-driven type has its list empty', () => {
        expect(expectationsForType({ ...form, interactionType: 'vendingmachine' }).warnings).toEqual([
            { field: 'vendingIds', message: 'vendingmachine hands out nothing without vending ids' }
        ]);
        expect(expectationsForType({ ...form, interactionType: 'vendingmachine', vendingIds: '1' }).warnings).toEqual([]);
        expect(expectationsForType({ ...form, interactionType: 'multiheight' }).warnings[0].field).toBe('multiheight');
    });

    it('has nothing to say for an empty or unknown type', () => {
        expect(expectationsForType(form)).toEqual({ suggestions: [], warnings: [] });
        expect(expectationsForType({ ...form, interactionType: '' })).toEqual({ suggestions: [], warnings: [] });
        expect(expectationsForType({ ...form, interactionType: 'wf_trg_enter_room' })).toEqual({ suggestions: [], warnings: [] });
    });
});

describe('stack height, sprite id and multiheight checks', () => {
    it('proposes the furnidata height as stack height when it differs', () => {
        expect(suggestFromFurnidata({ height: 1 }, form)).toEqual([{ field: 'stackHeight', value: 1, reason: 'furnidata height' }]);
        expect(suggestFromFurnidata({ height: 1.5 }, form)).toEqual([]);
    });

    it('reports a furnidata id that is not the sprite id', () => {
        expect(spriteIdMismatch({ id: 4201 }, 4200)).toBe(4201);
        expect(spriteIdMismatch({ id: 4200 }, 4200)).toBeNull();
        expect(spriteIdMismatch({}, 4200)).toBeNull();
        expect(spriteIdMismatch(null, 4200)).toBeNull();
    });

    it('compares the multiheight list with the asset state count', () => {
        const mh = { ...form, interactionType: 'multiheight', multiheight: '0.5, 1.0, 1.5' };
        expect(multiheightMismatch(mh, 5)).toEqual({ field: 'multiheight', message: '3 heights for 5 states in the asset' });
        expect(multiheightMismatch(mh, 3)).toBeNull();
        expect(multiheightMismatch(mh, null)).toBeNull();
        expect(multiheightMismatch({ ...mh, multiheight: '' }, 5)).toBeNull();
        expect(multiheightMismatch({ ...mh, interactionType: 'gate' }, 5)).toBeNull();
    });
});

describe('furni lines, duplicates and sibling suggestions', () => {
    const row = (id: number, itemName: string, spriteId: number, extra: Partial<RelatedRow> = {}): RelatedRow => ({
        id,
        spriteId,
        itemName,
        width: 1,
        length: 1,
        stackHeight: 1,
        allowStack: true,
        allowWalk: false,
        allowSit: false,
        allowLay: false,
        interactionType: 'default',
        interactionModesCount: 1,
        ...extra
    });

    it('derives the line prefix from the classname, ignoring the colour suffix', () => {
        expect(lineQueryFor('throne_gold*2')).toBe('throne');
        expect(lineQueryFor('rare_dragonlamp')).toBe('rare');
        expect(lineQueryFor('throne')).toBe('throne');
        expect(lineQueryFor('a_b')).toBe('a_b');
    });

    it('splits the probe rows into siblings and duplicates', () => {
        const self = { id: 1, itemName: 'throne_gold', spriteId: 100 };
        const rows = [
            row(1, 'throne_gold', 100),
            row(2, 'throne_silver', 101),
            row(3, 'throne', 102),
            row(4, 'throne_gold', 103),
            row(5, 'lamp', 100),
            row(6, 'thronex', 104)
        ];

        const related = relateRows(rows, self);

        expect(related.siblings.map((r) => r.id)).toEqual([2, 3]);
        expect(related.duplicateNames.map((r) => r.id)).toEqual([4]);
        expect(related.duplicateSprites.map((r) => r.id)).toEqual([5]);
    });

    it('proposes the value most siblings share, and stays quiet under two siblings or without a majority', () => {
        const siblings = [
            row(2, 'a', 1, { width: 2, allowWalk: true }),
            row(3, 'b', 2, { width: 2, allowWalk: true }),
            row(4, 'c', 3, { width: 3, allowWalk: false })
        ];
        const base = { ...form, allowStack: true, allowSit: false, stackHeight: 1, interactionModesCount: 1 };

        expect(suggestFromSiblings(siblings, base)).toEqual([
            { field: 'width', value: 2, reason: '2 of 3 in the line' },
            { field: 'allowWalk', value: true, reason: '2 of 3 in the line' }
        ]);
        expect(suggestFromSiblings(siblings.slice(0, 1), base)).toEqual([]);
        expect(suggestFromSiblings([siblings[0], siblings[2]], base)).toEqual([]);
    });
});
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