When an inbox has **"Allow messages after conversation is resolved"** disabled, the live-chat widget should hide the reply box once a conversation is resolved — but users could still send a reply, silently reopening it. This syncs the widget's conversation status on reconnect so the reply box hides correctly. ## Closes - CW-7272 ## How to reproduce 1. Disable **Allow messages after conversation is resolved** on an inbox. 2. Open the widget, then let its websocket drop (background tab / lose network). 3. While disconnected, get the conversation resolved (e.g. auto-resolve on inactivity). 4. Reconnect → reply box is still visible and a sent message reopens the resolved conversation. ## Why Reply-box hiding is gated on the widget's local status, updated via the `conversation.status_changed` socket event. If the resolve happens while disconnected, the event is missed — and on reconnect the widget only re-synced messages, never the status, so it stayed stale at `open`. ## What changed - `onReconnect` now also dispatches `conversationAttributes/getAttributes` to refresh status after a missed event. - Added a spec covering the reconnect behavior. Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
54 lines
1.3 KiB
JavaScript
54 lines
1.3 KiB
JavaScript
import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest';
|
|
import ActionCableConnector from '../actionCable';
|
|
|
|
vi.mock('@rails/actioncable', () => ({
|
|
createConsumer: () => ({
|
|
subscriptions: { create: () => ({}) },
|
|
disconnect: vi.fn(),
|
|
}),
|
|
}));
|
|
|
|
describe('Widget ActionCableConnector', () => {
|
|
let app;
|
|
let mockDispatch;
|
|
let connector;
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
mockDispatch = vi.fn();
|
|
app = {
|
|
$store: {
|
|
dispatch: mockDispatch,
|
|
getters: {
|
|
getCurrentAccountId: 1,
|
|
getCurrentUserID: 1,
|
|
},
|
|
},
|
|
};
|
|
connector = new ActionCableConnector(app, 'test-token');
|
|
mockDispatch.mockClear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('registers the conversation.status_changed event handler', () => {
|
|
expect(connector.events['conversation.status_changed']).toBe(
|
|
connector.onStatusChange
|
|
);
|
|
});
|
|
|
|
it('re-fetches conversation attributes on reconnect so a status change missed while disconnected is reflected', () => {
|
|
connector.onReconnect();
|
|
|
|
expect(mockDispatch).toHaveBeenCalledWith(
|
|
'conversation/syncLatestMessages'
|
|
);
|
|
expect(mockDispatch).toHaveBeenCalledWith(
|
|
'conversationAttributes/getAttributes'
|
|
);
|
|
});
|
|
});
|