HH-569: guard replayed frontend realtime messages (#144)

* fix(HH-569): guard replayed realtime messages

* fix(HH-569): gate dashboard message side effects

---------

Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Rogee
2026-08-24 00:42:05 +08:00
committed by GitHub
co-authored by rogee
parent 88ac30d0b8
commit 84a1e35294
8 changed files with 398 additions and 15 deletions
@@ -278,7 +278,11 @@ describe('#actions', () => {
message_type: 0,
conversation_id: 1,
};
actions.addMessage({ commit }, message);
const state = {
allConversations: [{ id: 1, messages: [] }],
};
const applied = actions.addMessage({ commit, state }, message);
expect(applied).toBe(true);
expect(commit.mock.calls).toEqual([
[types.ADD_MESSAGE, message],
[
@@ -294,9 +298,73 @@ describe('#actions', () => {
message_type: 1,
conversation_id: 1,
};
actions.addMessage({ commit }, message);
const state = {
allConversations: [{ id: 1, messages: [] }],
};
actions.addMessage({ commit, state }, message);
expect(commit.mock.calls).toEqual([[types.ADD_MESSAGE, message]]);
});
it('returns false if the conversation is not loaded', () => {
const message = {
id: 1,
message_type: 1,
conversation_id: 1,
};
const applied = actions.addMessage(
{ commit, state: { allConversations: [] } },
message
);
expect(applied).toBe(false);
expect(commit).not.toHaveBeenCalled();
});
it('ignores a replayed message with the same id and version', () => {
const message = {
id: 1,
message_type: 1,
conversation_id: 1,
updated_at: '2026-08-24T02:00:00Z',
};
const state = {
allConversations: [{ id: 1, messages: [message] }],
};
const isNew = actions.addMessage({ commit, state }, message);
expect(isNew).toBe(false);
expect(commit).not.toHaveBeenCalled();
});
});
describe('#updateMessage', () => {
it('ignores an older realtime update', () => {
const message = {
id: 1,
conversation_id: 1,
updated_at: '2026-08-24T01:00:00Z',
};
const state = {
allConversations: [
{
id: 1,
messages: [
{
id: 1,
updated_at: '2026-08-24T02:00:00Z',
},
],
},
],
};
const applied = actions.updateMessage({ commit, state }, message);
expect(applied).toBe(false);
expect(commit).not.toHaveBeenCalled();
});
});
describe('#sendMessageWithData', () => {