5180 fichiers 38.5 Mo 0 téléchargements 296 vues mis à jour il y a 6 heures ui
nitro-v36-with-renderer-v36 / src / api / friends / messenger / messengerReducer.test.ts
messengerReducer.test.ts 6.5 Ko Télécharger le fichier
import { describe, expect, it } from 'vitest';
import { MessengerIconState } from '../MessengerIconState';
import { initialMessengerState, messengerReducer, selectMessageByClientId, selectMessages, selectMessengerIconState } from '.';

describe('messengerReducer', () =>
{
    it('deduplicates a realtime message already present in history', () =>
    {
        const message = { id: 41, clientId: null, conversationId: 7, senderId: 9, type: 0, message: 'hi', metadata: '', createdAt: 100, status: 'sent' as const };
        const once = messengerReducer(initialMessengerState, { type: 'historyLoaded', conversationId: 7, messages: [ message ], hasMore: false });
        const twice = messengerReducer(once, { type: 'messageReceived', message });

        expect(selectMessages(twice, 7).map(item => item.id)).toEqual([ 41 ]);
    });

    it('replaces optimistic identity on acknowledgement', () =>
    {
        const optimistic = { id: 0, clientId: 'c-9', conversationId: 7, senderId: 1, type: 0, message: 'hello', metadata: '', createdAt: 100, status: 'sending' as const };
        const pending = messengerReducer(initialMessengerState, { type: 'messageOptimistic', message: optimistic });
        const acknowledged = messengerReducer(pending, { type: 'messageAcknowledged', clientId: 'c-9', messageId: 88, conversationId: 7, createdAt: 123456 });

        expect(selectMessageByClientId(acknowledged, 'c-9')).toMatchObject({ id: 88, status: 'sent', createdAt: 123456 });
        expect(selectMessages(acknowledged, 7)).toHaveLength(1);
    });

    it('keeps a failed optimistic message available for retry', () =>
    {
        const optimistic = { id: 0, clientId: 'c-10', conversationId: 7, senderId: 1, type: 0, message: 'hello', metadata: '', createdAt: 100, status: 'sending' as const };
        const pending = messengerReducer(initialMessengerState, { type: 'messageOptimistic', message: optimistic });
        const failed = messengerReducer(pending, { type: 'messageFailed', clientId: 'c-10', errorCode: 6 });

        expect(selectMessageByClientId(failed, 'c-10')).toMatchObject({ status: 'failed', errorCode: 6 });
    });

    it('opens a direct draft and migrates it to the server conversation on acknowledgement', () =>
    {
        const opened = messengerReducer(initialMessengerState, { type: 'directConversationOpened', participantId: 9, name: 'Frank' });
        const draftId = -9;
        const optimistic = { id: 0, clientId: 'c-11', conversationId: draftId, senderId: 1, type: 0, message: 'hello', metadata: '', createdAt: 100, status: 'sending' as const };
        const pending = messengerReducer(opened, { type: 'messageOptimistic', message: optimistic });
        const acknowledged = messengerReducer(pending, { type: 'messageAcknowledged', clientId: 'c-11', messageId: 89, conversationId: 77, createdAt: 101 });

        expect(acknowledged.selectedConversationId).toBe(77);
        expect(acknowledged.conversationIds).toContain(77);
        expect(acknowledged.conversationsById[77]).toMatchObject({ participantId: 9, name: 'Frank' });
        expect(selectMessages(acknowledged, 77)).toHaveLength(1);
        expect(selectMessages(acknowledged, draftId)).toHaveLength(0);
    });

    it('marks the toolbar unread when a realtime message arrives and clears it when read', () =>
    {
        const conversation = { id: 7, type: 0, participantId: 9, name: 'Frank', lastMessageId: 0, unreadCount: 0, updatedAt: 100 };
        const loaded = messengerReducer(initialMessengerState, { type: 'summariesLoaded', conversations: [ conversation ] });
        const message = { id: 41, clientId: null, conversationId: 7, senderId: 9, type: 0, message: 'hi', metadata: '', createdAt: 101, status: 'sent' as const };
        const unread = messengerReducer(loaded, { type: 'messageReceived', message });

        expect(unread.conversationsById[7].unreadCount).toBe(1);
        expect(selectMessengerIconState(unread, false, false)).toBe(MessengerIconState.UNREAD);

        const read = messengerReducer(unread, { type: 'readCursorAdvanced', conversationId: 7, readerId: 1, messageId: 41, ownUserId: 1 });
        expect(read.conversationsById[7].unreadCount).toBe(0);
        expect(selectMessengerIconState(read, false, false)).toBe(MessengerIconState.SHOW);
    });

    it('preserves a loaded conversation and its history when a later summary refresh omits it', () =>
    {
        const conversation = { id: 7, type: 0, participantId: 9, name: 'Frank', lastMessageId: 41, unreadCount: 0, updatedAt: 100 };
        const message = { id: 41, clientId: null, conversationId: 7, senderId: 9, type: 0, message: 'history', metadata: '', createdAt: 100, status: 'sent' as const };
        const loaded = messengerReducer(initialMessengerState, { type: 'summariesLoaded', conversations: [ conversation ] });
        const withHistory = messengerReducer(loaded, { type: 'historyLoaded', conversationId: 7, messages: [ message ], hasMore: false });
        const refreshed = messengerReducer(withHistory, { type: 'summariesLoaded', conversations: [] });

        expect(refreshed.conversationIds).toEqual([ 7 ]);
        expect(refreshed.conversationsById[7]).toEqual(conversation);
        expect(selectMessages(refreshed, 7)).toEqual([ message ]);
        expect(refreshed.historyByConversation[7]).toMatchObject({ loaded: true, hasMore: false });
    });

    it('keeps only the newest Staff Chat summary when the server returns duplicate conversation ids', () =>
    {
        const older = { id: 20, type: 1, participantId: 0, name: 'Staff Chat', lastMessageId: 40, unreadCount: 0, updatedAt: 100 };
        const newer = { id: 21, type: 1, participantId: 0, name: ' staff chat ', lastMessageId: 41, unreadCount: 1, updatedAt: 110 };
        const refreshed = messengerReducer(initialMessengerState, { type: 'summariesLoaded', conversations: [ older, newer ] });

        expect(refreshed.conversationIds).toEqual([ 21 ]);
        expect(refreshed.conversationsById[21]).toEqual(newer);
    });

    it('selects the server Staff Chat instead of creating a direct draft', () =>
    {
        const staffChat = { id: 21, type: 1, participantId: 0, name: 'Staff Chat', lastMessageId: 41, unreadCount: 0, updatedAt: 110 };
        const loaded = messengerReducer(initialMessengerState, { type: 'summariesLoaded', conversations: [ staffChat ] });
        const opened = messengerReducer(loaded, { type: 'directConversationOpened', participantId: -1, name: 'Staff Chat' });

        expect(opened.selectedConversationId).toBe(21);
        expect(opened.conversationIds).toEqual([ 21 ]);
        expect(Object.values(opened.conversationsById)).toEqual([ staffChat ]);
    });
});
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