Initial commit: Add logistics and order_detail message types
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
- Add Logistics component with progress tracking - Add OrderDetail component for order information - Support data-driven steps and actions - Add blue color scale to widget SCSS - Fix node overflow and progress bar rendering issues - Add English translations for dashboard components Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,731 @@
|
||||
import axios from 'axios';
|
||||
import actions, {
|
||||
hasMessageFailedWithExternalError,
|
||||
} from '../../conversations/actions';
|
||||
import types from '../../../mutation-types';
|
||||
const dataToSend = {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['open'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
import { dataReceived } from './testConversationResponse';
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#hasMessageFailedWithExternalError', () => {
|
||||
it('returns false if message is sent', () => {
|
||||
const pendingMessage = {
|
||||
status: 'sent',
|
||||
content_attributes: {},
|
||||
};
|
||||
expect(hasMessageFailedWithExternalError(pendingMessage)).toBe(false);
|
||||
});
|
||||
it('returns false if status is not failed', () => {
|
||||
const pendingMessage = {
|
||||
status: 'progress',
|
||||
content_attributes: {},
|
||||
};
|
||||
expect(hasMessageFailedWithExternalError(pendingMessage)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false if status is failed but no external error', () => {
|
||||
const pendingMessage = {
|
||||
status: 'failed',
|
||||
content_attributes: {},
|
||||
};
|
||||
expect(hasMessageFailedWithExternalError(pendingMessage)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true if status is failed and has external error', () => {
|
||||
const pendingMessage = {
|
||||
status: 'failed',
|
||||
content_attributes: {
|
||||
external_error: 'error',
|
||||
},
|
||||
};
|
||||
expect(hasMessageFailedWithExternalError(pendingMessage)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#getConversation', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { id: 1, meta: { sender: { id: 1, name: 'Contact 1' } } },
|
||||
});
|
||||
await actions.getConversation({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.UPDATE_CONVERSATION,
|
||||
{ id: 1, meta: { sender: { id: 1, name: 'Contact 1' } } },
|
||||
],
|
||||
['contacts/SET_CONTACT_ITEM', { id: 1, name: 'Contact 1' }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.getConversation({ commit });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
describe('#muteConversation', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue(null);
|
||||
await actions.muteConversation({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([[types.MUTE_CONVERSATION]]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.getConversation({ commit });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateConversation', () => {
|
||||
it('sends setContact action and update_conversation mutation', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
labels: ['support'],
|
||||
};
|
||||
actions.updateConversation(
|
||||
{ commit, rootState: { route: { name: 'home' } }, dispatch },
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.UPDATE_CONVERSATION, conversation],
|
||||
]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[
|
||||
'conversationLabels/setConversationLabel',
|
||||
{ id: 1, data: ['support'] },
|
||||
],
|
||||
[
|
||||
'contacts/setContact',
|
||||
{
|
||||
id: 1,
|
||||
name: 'john-doe',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addConversation', () => {
|
||||
it('doesnot send mutation if conversation is from a different inbox', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 2,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'home' } },
|
||||
dispatch,
|
||||
state: { currentInbox: 1, appliedFilters: [] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
it('doesnot send mutation if conversation filters are applied', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'home' } },
|
||||
dispatch,
|
||||
state: { currentInbox: 1, appliedFilters: [{ id: 'random-filter' }] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
it('doesnot send mutation if the view is conversation mentions', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'conversation_mentions' } },
|
||||
dispatch,
|
||||
state: { currentInbox: 1, appliedFilters: [{ id: 'random-filter' }] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
it('doesnot send mutation if the view is conversation folders', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'folder_conversations' } },
|
||||
dispatch,
|
||||
state: { currentInbox: 1, appliedFilters: [{ id: 'random-filter' }] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
it('sends correct mutations', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'home' } },
|
||||
dispatch,
|
||||
state: { currentInbox: 1, appliedFilters: [] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ADD_CONVERSATION, conversation],
|
||||
]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[
|
||||
'contacts/setContact',
|
||||
{
|
||||
id: 1,
|
||||
name: 'john-doe',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct mutations if inbox filter is not available', () => {
|
||||
const conversation = {
|
||||
id: 1,
|
||||
messages: [],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
};
|
||||
actions.addConversation(
|
||||
{
|
||||
commit,
|
||||
rootState: { route: { name: 'home' } },
|
||||
dispatch,
|
||||
state: { appliedFilters: [] },
|
||||
},
|
||||
conversation
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ADD_CONVERSATION, conversation],
|
||||
]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[
|
||||
'contacts/setContact',
|
||||
{
|
||||
id: 1,
|
||||
name: 'john-doe',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addMessage', () => {
|
||||
it('sends correct mutations if message is incoming', () => {
|
||||
const message = {
|
||||
id: 1,
|
||||
message_type: 0,
|
||||
conversation_id: 1,
|
||||
};
|
||||
actions.addMessage({ commit }, message);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ADD_MESSAGE, message],
|
||||
[
|
||||
types.SET_CONVERSATION_CAN_REPLY,
|
||||
{ conversationId: 1, canReply: true },
|
||||
],
|
||||
[types.ADD_CONVERSATION_ATTACHMENTS, message],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if message is not an incoming message', () => {
|
||||
const message = {
|
||||
id: 1,
|
||||
message_type: 1,
|
||||
conversation_id: 1,
|
||||
};
|
||||
actions.addMessage({ commit }, message);
|
||||
expect(commit.mock.calls).toEqual([[types.ADD_MESSAGE, message]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#markMessagesRead', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
it('sends correct mutations if api is successful', async () => {
|
||||
const lastSeen = new Date().getTime() / 1000;
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, agent_last_seen_at: lastSeen },
|
||||
});
|
||||
await actions.markMessagesRead({ commit }, { id: 1 });
|
||||
vi.runAllTimers();
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.UPDATE_MESSAGE_UNREAD_COUNT, { id: 1, lastSeen }],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if api is unsuccessful', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.markMessagesRead({ commit }, { id: 1 });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#markMessagesUnread', () => {
|
||||
it('sends correct mutations if API is successful', async () => {
|
||||
const lastSeen = new Date().getTime() / 1000;
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, agent_last_seen_at: lastSeen, unread_count: 1 },
|
||||
});
|
||||
await actions.markMessagesUnread({ commit }, { id: 1 });
|
||||
vi.runAllTimers();
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.UPDATE_MESSAGE_UNREAD_COUNT,
|
||||
{ id: 1, lastSeen, unreadCount: 1 },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if API is unsuccessful', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.markMessagesUnread({ commit }, { id: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#sendEmailTranscript', () => {
|
||||
it('sends correct mutations if api is successful', async () => {
|
||||
axios.post.mockResolvedValue({});
|
||||
await actions.sendEmailTranscript(
|
||||
{ commit },
|
||||
{ conversationId: 1, email: 'testemail@example.com' }
|
||||
);
|
||||
expect(commit).toHaveBeenCalledTimes(0);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#assignAgent', () => {
|
||||
it('sends correct mutations if assignment is successful', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, name: 'User' },
|
||||
});
|
||||
await actions.assignAgent({ commit }, { conversationId: 1, agentId: 1 });
|
||||
expect(commit).toHaveBeenCalledTimes(0);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setCurrentChatAssignee', () => {
|
||||
it('sends correct mutations if assignment is successful', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, name: 'User' },
|
||||
});
|
||||
await actions.setCurrentChatAssignee({ commit }, { id: 1, name: 'User' });
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['ASSIGN_AGENT', { id: 1, name: 'User' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#toggleStatus', () => {
|
||||
it('sends correct mutations if toggle status is successful', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: {
|
||||
payload: {
|
||||
conversation_id: 1,
|
||||
current_status: 'snoozed',
|
||||
snoozed_until: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.toggleStatus(
|
||||
{ commit },
|
||||
{ conversationId: 1, status: 'snoozed' }
|
||||
);
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
'CHANGE_CONVERSATION_STATUS',
|
||||
{ conversationId: 1, status: 'snoozed', snoozedUntil: null },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#assignTeam', () => {
|
||||
it('sends correct mutations if assignment is successful', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, name: 'Team' },
|
||||
});
|
||||
await actions.assignTeam({ commit }, { conversationId: 1, teamId: 1 });
|
||||
expect(commit).toHaveBeenCalledTimes(0);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setCurrentChatTeam', () => {
|
||||
it('sends correct mutations if assignment is successful', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { id: 1, name: 'Team' },
|
||||
});
|
||||
await actions.setCurrentChatTeam(
|
||||
{ commit },
|
||||
{ team: { id: 1, name: 'Team' }, conversationId: 1 }
|
||||
);
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['ASSIGN_TEAM', { team: { id: 1, name: 'Team' }, conversationId: 1 }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fetchFilteredConversations', () => {
|
||||
it('fetches filtered conversations with a mock commit', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: dataReceived,
|
||||
});
|
||||
await actions.fetchFilteredConversations({ commit }, dataToSend);
|
||||
expect(commit).toHaveBeenCalledTimes(2);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_LIST_LOADING_STATUS'],
|
||||
['SET_ALL_CONVERSATION', dataReceived.payload],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setConversationFilter', () => {
|
||||
it('commits the correct mutation and sets filter state', () => {
|
||||
const filters = [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
actions.setConversationFilters({ commit }, filters);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_FILTERS, filters],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearConversationFilter', () => {
|
||||
it('commits the correct mutation and clears filter state', () => {
|
||||
actions.clearConversationFilters({ commit });
|
||||
expect(commit.mock.calls).toEqual([[types.CLEAR_CONVERSATION_FILTERS]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateConversationLastActivity', () => {
|
||||
it('sends correct action', async () => {
|
||||
await actions.updateConversationLastActivity(
|
||||
{ commit },
|
||||
{ conversationId: 1, lastActivityAt: 12121212 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
'UPDATE_CONVERSATION_LAST_ACTIVITY',
|
||||
{ conversationId: 1, lastActivityAt: 12121212 },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setChatSortFilter', () => {
|
||||
it('sends correct action', async () => {
|
||||
await actions.setChatSortFilter(
|
||||
{ commit },
|
||||
{ data: 'sort_on_created_at' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['CHANGE_CHAT_SORT_FILTER', { data: 'sort_on_created_at' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteMessage', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const [conversationId, messageId] = [1, 1];
|
||||
axios.delete.mockResolvedValue({
|
||||
data: { id: 1, content: 'deleted' },
|
||||
});
|
||||
await actions.deleteMessage({ commit }, { conversationId, messageId });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ADD_MESSAGE, { id: 1, content: 'deleted' }],
|
||||
[types.DELETE_CONVERSATION_ATTACHMENTS, { id: 1, content: 'deleted' }],
|
||||
]);
|
||||
});
|
||||
it('sends no actions if API is error', async () => {
|
||||
const [conversationId, messageId] = [1, 1];
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.deleteMessage({ commit }, { conversationId, messageId })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
describe('#deleteConversation', () => {
|
||||
it('send correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({
|
||||
data: { id: 1 },
|
||||
});
|
||||
await actions.deleteConversation({ commit, dispatch }, 1);
|
||||
expect(commit.mock.calls).toEqual([[types.DELETE_CONVERSATION, 1]]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
['conversationStats/get', {}, { root: true }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('send no actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.deleteConversation({ commit, dispatch }, 1)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateCustomAttributes', () => {
|
||||
it('update conversation custom attributes', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { custom_attributes: { order_d: '1001' } },
|
||||
});
|
||||
await actions.updateCustomAttributes(
|
||||
{ commit },
|
||||
{
|
||||
conversationId: 1,
|
||||
customAttributes: { order_d: '1001' },
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.UPDATE_CONVERSATION_CUSTOM_ATTRIBUTES, { order_d: '1001' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addMentions', () => {
|
||||
it('does not send mutations if the view is not mentions', () => {
|
||||
actions.addMentions(
|
||||
{ commit, dispatch, rootState: { route: { name: 'home' } } },
|
||||
{ id: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
it('send mutations if the view is mentions', () => {
|
||||
actions.addMentions(
|
||||
{
|
||||
dispatch,
|
||||
rootState: { route: { name: 'conversation_mentions' } },
|
||||
},
|
||||
{ id: 1, meta: { sender: { id: 1 } } }
|
||||
);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
['updateConversation', { id: 1, meta: { sender: { id: 1 } } }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('#syncActiveConversationMessages', async () => {
|
||||
const conversations = [
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hello',
|
||||
},
|
||||
],
|
||||
meta: { sender: { id: 1, name: 'john-doe' } },
|
||||
inbox_id: 1,
|
||||
},
|
||||
];
|
||||
axios.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [{ id: 2, content: 'Welcome' }],
|
||||
meta: {
|
||||
agent_last_seen_at: '2023-04-20T05:22:42.990Z',
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.syncActiveConversationMessages(
|
||||
{
|
||||
commit,
|
||||
dispatch,
|
||||
state: {
|
||||
allConversations: conversations,
|
||||
syncConversationsMessages: {
|
||||
1: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ conversationId: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
'conversationMetadata/SET_CONVERSATION_METADATA',
|
||||
{
|
||||
id: 1,
|
||||
data: {
|
||||
agent_last_seen_at: '2023-04-20T05:22:42.990Z',
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
'SET_MISSING_MESSAGES',
|
||||
{
|
||||
id: 1,
|
||||
data: [
|
||||
{ id: 1, content: 'Hello' },
|
||||
{ id: 2, content: 'Welcome' },
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
'SET_LAST_MESSAGE_ID_FOR_SYNC_CONVERSATION',
|
||||
{ conversationId: 1, messageId: null },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
describe('#fetchAllAttachments', () => {
|
||||
it('fetches all attachments', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [
|
||||
{
|
||||
id: 1,
|
||||
message_id: 1,
|
||||
file_type: 'image',
|
||||
data_url: '',
|
||||
thumb_url: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await actions.fetchAllAttachments({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_ALL_ATTACHMENTS,
|
||||
{
|
||||
id: 1,
|
||||
data: [
|
||||
{
|
||||
id: 1,
|
||||
message_id: 1,
|
||||
file_type: 'image',
|
||||
data_url: '',
|
||||
thumb_url: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setContextMenuChatId', () => {
|
||||
it('sets the context menu chat id', () => {
|
||||
actions.setContextMenuChatId({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([[types.SET_CONTEXT_MENU_CHAT_ID, 1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setChatListFilters', () => {
|
||||
it('set chat list filters', () => {
|
||||
const filters = {
|
||||
inboxId: 1,
|
||||
assigneeType: 'me',
|
||||
status: 'open',
|
||||
sortBy: 'created_at',
|
||||
page: 1,
|
||||
labels: ['label'],
|
||||
teamId: 1,
|
||||
conversationType: 'mention',
|
||||
};
|
||||
actions.setChatListFilters({ commit }, filters);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CHAT_LIST_FILTERS, filters],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateChatListFilters', () => {
|
||||
it('update chat list filters', () => {
|
||||
actions.updateChatListFilters({ commit }, { updatedWithin: 20 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.UPDATE_CHAT_LIST_FILTERS, { updatedWithin: 20 }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getInboxCaptainAssistantById', () => {
|
||||
it('fetches inbox assistant by id', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: {
|
||||
id: 1,
|
||||
name: 'Assistant',
|
||||
description: 'Assistant description',
|
||||
},
|
||||
});
|
||||
await actions.getInboxCaptainAssistantById({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_INBOX_CAPTAIN_ASSISTANT,
|
||||
{ id: 1, name: 'Assistant', description: 'Assistant description' },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
export default [
|
||||
{
|
||||
created_at: 1702411932, // Dec 12, 2023 12:12:12
|
||||
id: 1,
|
||||
last_activity_at: 1704408443, // Jan 04, 2024 14:47:23
|
||||
messages: [{ content: 'test1' }],
|
||||
priority: 'medium',
|
||||
waiting_since: 0, // not waiting
|
||||
},
|
||||
{
|
||||
created_at: 1699819932, // Nov 12, 2023 12:12:12
|
||||
id: 2,
|
||||
last_activity_at: 1704485532, // Jan 05, 2024 12:12:12
|
||||
messages: [{ content: 'test2' }],
|
||||
priority: 'low',
|
||||
waiting_since: 1683645800, // May 09 2023 15:23:20
|
||||
},
|
||||
{
|
||||
created_at: 1641413532, // Jan 05, 2022 12:12:12
|
||||
id: 3,
|
||||
last_activity_at: 1704408567, // Jan 04, 2024 14:49:27
|
||||
messages: [{ content: 'test3' }],
|
||||
priority: 'low',
|
||||
waiting_since: 0, // not waiting
|
||||
},
|
||||
{
|
||||
created_at: 1641413531, // Jan 05, 2022 12:12:11
|
||||
id: 4,
|
||||
last_activity_at: 1704408566, // Jan 04, 2024 14:49:26
|
||||
messages: [{ content: 'test4' }],
|
||||
priority: 'high',
|
||||
waiting_since: 1683645801, // May 09 2023 15:23:21
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,632 @@
|
||||
import commonHelpers from '../../../../helper/commons';
|
||||
import getters from '../../conversations/getters';
|
||||
/*
|
||||
Order of conversations in the fixture is as follows:
|
||||
- lastActivity: c0 < c3 < c2 < c1
|
||||
- createdAt: c3 < c2 < c1 < c0
|
||||
- priority: c1 < c2 < c0 < c3
|
||||
- waitingSince: c1 > c3 > c0 < c2
|
||||
*/
|
||||
import conversations from './conversations.fixtures';
|
||||
|
||||
// loads .last() helper
|
||||
commonHelpers();
|
||||
|
||||
describe('#getters', () => {
|
||||
describe('#getAllConversations', () => {
|
||||
it('returns conversations ordered by lastActivityAt in descending order if no sort order is available', () => {
|
||||
const state = { allConversations: [...conversations] };
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
conversations[3],
|
||||
conversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by lastActivityAt in descending order if invalid sort order is available', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'latest',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
conversations[3],
|
||||
conversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by lastActivityAt in descending order if chatStatusFilter = last_activity_at_desc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
conversations[3],
|
||||
conversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by lastActivityAt in ascending order if chatStatusFilter = last_activity_at_asc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'last_activity_at_asc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[0],
|
||||
conversations[3],
|
||||
conversations[2],
|
||||
conversations[1],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by createdAt in descending order if chatStatusFilter = created_at_desc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'created_at_desc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[0],
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
conversations[3],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by createdAt in ascending order if chatStatusFilter = created_at_asc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'created_at_asc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[3],
|
||||
conversations[2],
|
||||
conversations[1],
|
||||
conversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by priority in descending order if chatStatusFilter = priority_desc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'priority_desc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[3],
|
||||
conversations[0],
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by priority in ascending order if chatStatusFilter = priority_asc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'priority_asc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[1],
|
||||
conversations[2],
|
||||
conversations[0],
|
||||
conversations[3],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns conversations ordered by longest waiting if chatStatusFilter = waiting_since_asc', () => {
|
||||
const state = {
|
||||
allConversations: [...conversations],
|
||||
chatSortFilter: 'waiting_since_asc',
|
||||
};
|
||||
expect(getters.getAllConversations(state)).toEqual([
|
||||
conversations[1],
|
||||
conversations[3],
|
||||
conversations[2],
|
||||
conversations[0],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#getUnAssignedChats', () => {
|
||||
it('order returns only chats assigned to user', () => {
|
||||
const conversationList = [
|
||||
{
|
||||
id: 1,
|
||||
inbox_id: 2,
|
||||
status: 1,
|
||||
meta: { assignee: { id: 1 } },
|
||||
labels: ['sales', 'dev'],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inbox_id: 2,
|
||||
status: 1,
|
||||
meta: {},
|
||||
labels: ['dev'],
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
inbox_id: 3,
|
||||
status: 1,
|
||||
meta: { assignee: { id: 1 } },
|
||||
labels: [],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
inbox_id: 4,
|
||||
status: 1,
|
||||
meta: { team: { id: 5 } },
|
||||
labels: ['sales'],
|
||||
},
|
||||
];
|
||||
|
||||
expect(
|
||||
getters.getUnAssignedChats({ allConversations: conversationList })({
|
||||
status: 1,
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
id: 2,
|
||||
inbox_id: 2,
|
||||
status: 1,
|
||||
meta: {},
|
||||
labels: ['dev'],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
inbox_id: 4,
|
||||
status: 1,
|
||||
meta: { team: { id: 5 } },
|
||||
labels: ['sales'],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#getConversationById', () => {
|
||||
it('get conversations based on id', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getConversationById(state)(1)).toEqual({ id: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAppliedConversationFilters', () => {
|
||||
it('getAppliedConversationFilters', () => {
|
||||
const filtersList = [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
const state = {
|
||||
appliedFilters: filtersList,
|
||||
};
|
||||
expect(getters.getAppliedConversationFilters(state)).toEqual(filtersList);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLastEmailInSelectedChat', () => {
|
||||
it('Returns cc in last email', () => {
|
||||
const state = {};
|
||||
const getSelectedChat = {
|
||||
messages: [
|
||||
{
|
||||
message_type: 1,
|
||||
content_attributes: {
|
||||
email: {
|
||||
from: 'why@how.my',
|
||||
cc: ['nithin@me.co', 'we@who.why'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(
|
||||
getters.getLastEmailInSelectedChat(state, { getSelectedChat })
|
||||
).toEqual({
|
||||
message_type: 1,
|
||||
content_attributes: {
|
||||
email: {
|
||||
from: 'why@how.my',
|
||||
cc: ['nithin@me.co', 'we@who.why'],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getSelectedChatAttachments', () => {
|
||||
it('Returns attachments in selected chat', () => {
|
||||
const attachments = {
|
||||
1: [
|
||||
{ id: 1, file_name: 'test1' },
|
||||
{ id: 2, file_name: 'test2' },
|
||||
],
|
||||
};
|
||||
const selectedChatId = 1;
|
||||
expect(
|
||||
getters.getSelectedChatAttachments({ selectedChatId, attachments })
|
||||
).toEqual([
|
||||
{ id: 1, file_name: 'test1' },
|
||||
{ id: 2, file_name: 'test2' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getContextMenuChatId', () => {
|
||||
it('returns the context menu chat id', () => {
|
||||
const state = { contextMenuChatId: 1 };
|
||||
expect(getters.getContextMenuChatId(state)).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getChatListFilters', () => {
|
||||
it('get chat list filters', () => {
|
||||
const conversationFilters = {
|
||||
inboxId: 1,
|
||||
assigneeType: 'me',
|
||||
status: 'open',
|
||||
sortBy: 'created_at',
|
||||
page: 1,
|
||||
labels: ['label'],
|
||||
teamId: 1,
|
||||
conversationType: 'mention',
|
||||
};
|
||||
const state = { conversationFilters: conversationFilters };
|
||||
expect(getters.getChatListFilters(state)).toEqual(conversationFilters);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getAppliedConversationFiltersQuery', () => {
|
||||
it('get applied conversation filters query', () => {
|
||||
const filtersList = [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
const state = { appliedFilters: filtersList };
|
||||
expect(getters.getAppliedConversationFiltersQuery(state)).toEqual({
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
query_operator: undefined,
|
||||
values: ['snoozed'],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCopilotAssistant', () => {
|
||||
it('get copilot assistant', () => {
|
||||
const state = {
|
||||
copilotAssistant: {
|
||||
id: 1,
|
||||
name: 'Assistant',
|
||||
description: 'Assistant description',
|
||||
},
|
||||
};
|
||||
expect(getters.getCopilotAssistant(state)).toEqual({
|
||||
id: 1,
|
||||
name: 'Assistant',
|
||||
description: 'Assistant description',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getFilteredConversations', () => {
|
||||
const mockConversations = [
|
||||
{
|
||||
id: 1,
|
||||
status: 'open',
|
||||
meta: { assignee: { id: 1 } },
|
||||
last_activity_at: 1000,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
status: 'open',
|
||||
meta: {},
|
||||
last_activity_at: 2000,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
status: 'resolved',
|
||||
meta: { assignee: { id: 2 } },
|
||||
last_activity_at: 3000,
|
||||
},
|
||||
];
|
||||
|
||||
const mockRootGetters = {
|
||||
getCurrentUser: {
|
||||
id: 1,
|
||||
accounts: [{ id: 1, role: 'agent', permissions: [] }],
|
||||
},
|
||||
getCurrentAccountId: 1,
|
||||
};
|
||||
|
||||
it('filters conversations based on role permissions for administrator', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [{ id: 1, role: 'administrator', permissions: [] }],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
mockConversations[2],
|
||||
mockConversations[1],
|
||||
mockConversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('filters conversations based on role permissions for agent', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [{ id: 1, role: 'agent', permissions: [] }],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
mockConversations[2],
|
||||
mockConversations[1],
|
||||
mockConversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('filters conversations for custom role with conversation_manage permission', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
custom_role_id: 5,
|
||||
permissions: ['conversation_manage'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
mockConversations[2],
|
||||
mockConversations[1],
|
||||
mockConversations[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('filters conversations for custom role with conversation_unassigned_manage permission', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
custom_role_id: 5,
|
||||
permissions: ['conversation_unassigned_manage'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
// Should include conversation assigned to user (id: 1) and unassigned conversation
|
||||
expect(result).toEqual([mockConversations[1], mockConversations[0]]);
|
||||
});
|
||||
|
||||
it('filters conversations for custom role with conversation_participating_manage permission', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
custom_role_id: 5,
|
||||
permissions: ['conversation_participating_manage'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
// Should only include conversation assigned to user (id: 1)
|
||||
expect(result).toEqual([mockConversations[0]]);
|
||||
});
|
||||
|
||||
it('filters conversations for custom role with no permissions', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
custom_role_id: 5,
|
||||
permissions: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
// Should return empty array as user has no permissions
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('applies filters and role permissions together', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['open'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const rootGetters = {
|
||||
...mockRootGetters,
|
||||
getCurrentUser: {
|
||||
...mockRootGetters.getCurrentUser,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
custom_role_id: 5,
|
||||
permissions: ['conversation_participating_manage'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
rootGetters
|
||||
);
|
||||
|
||||
// Should only include open conversation assigned to user (id: 1)
|
||||
expect(result).toEqual([mockConversations[0]]);
|
||||
});
|
||||
|
||||
it('returns empty array when no conversations match filters', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_desc',
|
||||
appliedFilters: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['pending'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
mockRootGetters
|
||||
);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('sorts filtered conversations according to chatSortFilter', () => {
|
||||
const state = {
|
||||
allConversations: mockConversations,
|
||||
chatSortFilter: 'last_activity_at_asc',
|
||||
appliedFilters: [],
|
||||
};
|
||||
|
||||
const result = getters.getFilteredConversations(
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
mockRootGetters
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
mockConversations[0],
|
||||
mockConversations[1],
|
||||
mockConversations[2],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,174 @@
|
||||
import {
|
||||
findPendingMessageIndex,
|
||||
applyPageFilters,
|
||||
filterByInbox,
|
||||
filterByTeam,
|
||||
filterByLabel,
|
||||
filterByUnattended,
|
||||
} from '../../conversations/helpers';
|
||||
|
||||
const conversationList = [
|
||||
{
|
||||
id: 1,
|
||||
inbox_id: 2,
|
||||
status: 'open',
|
||||
meta: {},
|
||||
labels: ['sales', 'dev'],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inbox_id: 2,
|
||||
status: 'open',
|
||||
meta: {},
|
||||
labels: ['dev'],
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
inbox_id: 3,
|
||||
status: 'resolved',
|
||||
meta: { team: { id: 5 } },
|
||||
labels: [],
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
inbox_id: 4,
|
||||
status: 'pending',
|
||||
meta: { team: { id: 5 } },
|
||||
labels: ['sales'],
|
||||
},
|
||||
];
|
||||
|
||||
describe('#findPendingMessageIndex', () => {
|
||||
it('returns the correct index of pending message with id', () => {
|
||||
const chat = {
|
||||
messages: [{ id: 1, status: 'progress' }],
|
||||
};
|
||||
const message = { echo_id: 1 };
|
||||
expect(findPendingMessageIndex(chat, message)).toEqual(0);
|
||||
});
|
||||
|
||||
it('returns -1 if pending message with id is not present', () => {
|
||||
const chat = {
|
||||
messages: [{ id: 1, status: 'progress' }],
|
||||
};
|
||||
const message = { echo_id: 2 };
|
||||
expect(findPendingMessageIndex(chat, message)).toEqual(-1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#applyPageFilters', () => {
|
||||
describe('#filter-team', () => {
|
||||
it('returns true if conversation has team and team filter is active', () => {
|
||||
const filters = {
|
||||
status: 'resolved',
|
||||
teamId: 5,
|
||||
};
|
||||
expect(applyPageFilters(conversationList[2], filters)).toEqual(true);
|
||||
});
|
||||
it('returns true if conversation has no team and team filter is active', () => {
|
||||
const filters = {
|
||||
status: 'open',
|
||||
teamId: 5,
|
||||
};
|
||||
expect(applyPageFilters(conversationList[0], filters)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filter-inbox', () => {
|
||||
it('returns true if conversation has inbox and inbox filter is active', () => {
|
||||
const filters = {
|
||||
status: 'pending',
|
||||
inboxId: 4,
|
||||
};
|
||||
expect(applyPageFilters(conversationList[3], filters)).toEqual(true);
|
||||
});
|
||||
it('returns true if conversation has no inbox and inbox filter is active', () => {
|
||||
const filters = {
|
||||
status: 'open',
|
||||
inboxId: 5,
|
||||
};
|
||||
expect(applyPageFilters(conversationList[0], filters)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filter-labels', () => {
|
||||
it('returns true if conversation has labels and labels filter is active', () => {
|
||||
const filters = {
|
||||
status: 'open',
|
||||
labels: ['dev'],
|
||||
};
|
||||
expect(applyPageFilters(conversationList[0], filters)).toEqual(true);
|
||||
});
|
||||
it('returns true if conversation has no inbox and inbox filter is active', () => {
|
||||
const filters = {
|
||||
status: 'open',
|
||||
labels: ['dev'],
|
||||
};
|
||||
expect(applyPageFilters(conversationList[2], filters)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filter-status', () => {
|
||||
it('returns true if conversation has status and status filter is active', () => {
|
||||
const filters = {
|
||||
status: 'open',
|
||||
};
|
||||
expect(applyPageFilters(conversationList[1], filters)).toEqual(true);
|
||||
});
|
||||
it('returns true if conversation has status and status filter is all', () => {
|
||||
const filters = {
|
||||
status: 'all',
|
||||
};
|
||||
expect(applyPageFilters(conversationList[1], filters)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByInbox', () => {
|
||||
it('returns true if conversation has inbox filter active', () => {
|
||||
const inboxId = '1';
|
||||
const chatInboxId = 1;
|
||||
expect(filterByInbox(true, inboxId, chatInboxId)).toEqual(true);
|
||||
});
|
||||
it('returns false if inbox filter is not active', () => {
|
||||
const inboxId = '1';
|
||||
const chatInboxId = 13;
|
||||
expect(filterByInbox(true, inboxId, chatInboxId)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByTeam', () => {
|
||||
it('returns true if conversation has team and team filter is active', () => {
|
||||
const [teamId, chatTeamId] = ['1', 1];
|
||||
expect(filterByTeam(true, teamId, chatTeamId)).toEqual(true);
|
||||
});
|
||||
it('returns false if team filter is not active', () => {
|
||||
const [teamId, chatTeamId] = ['1', 12];
|
||||
expect(filterByTeam(true, teamId, chatTeamId)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByLabel', () => {
|
||||
it('returns true if conversation has labels and labels filter is active', () => {
|
||||
const labels = ['dev', 'cs'];
|
||||
const chatLabels = ['dev', 'cs', 'sales'];
|
||||
expect(filterByLabel(true, labels, chatLabels)).toEqual(true);
|
||||
});
|
||||
it('returns false if conversation has not all labels', () => {
|
||||
const labels = ['dev', 'cs', 'sales'];
|
||||
const chatLabels = ['cs', 'sales'];
|
||||
expect(filterByLabel(true, labels, chatLabels)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#filterByUnattended', () => {
|
||||
it('returns true if conversation type is unattended and has no first reply', () => {
|
||||
expect(filterByUnattended(true, 'unattended', undefined)).toEqual(true);
|
||||
});
|
||||
it('returns false if conversation type is not unattended and has no first reply', () => {
|
||||
expect(filterByUnattended(false, 'mentions', undefined)).toEqual(false);
|
||||
});
|
||||
it('returns true if conversation type is unattended and has first reply', () => {
|
||||
expect(filterByUnattended(true, 'mentions', 123)).toEqual(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,960 @@
|
||||
import { describe } from 'vitest';
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversations';
|
||||
|
||||
vi.mock('shared/helpers/mitt', () => ({
|
||||
emitter: {
|
||||
emit: vi.fn(),
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
import { emitter } from 'shared/helpers/mitt';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#EMPTY_ALL_CONVERSATION', () => {
|
||||
it('empty conversations', () => {
|
||||
const state = { allConversations: [{ id: 1 }], selectedChatId: 1 };
|
||||
mutations[types.EMPTY_ALL_CONVERSATION](state);
|
||||
expect(state.allConversations).toEqual([]);
|
||||
expect(state.selectedChatId).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_MESSAGE_UNREAD_COUNT', () => {
|
||||
it('mark conversation as read', () => {
|
||||
const state = { allConversations: [{ id: 1 }] };
|
||||
const lastSeen = new Date().getTime() / 1000;
|
||||
mutations[types.UPDATE_MESSAGE_UNREAD_COUNT](state, { id: 1, lastSeen });
|
||||
expect(state.allConversations).toEqual([
|
||||
{ id: 1, agent_last_seen_at: lastSeen, unread_count: 0 },
|
||||
]);
|
||||
});
|
||||
|
||||
it('doesnot send any mutation if chat doesnot exist', () => {
|
||||
const state = { allConversations: [] };
|
||||
const lastSeen = new Date().getTime() / 1000;
|
||||
mutations[types.UPDATE_MESSAGE_UNREAD_COUNT](state, { id: 1, lastSeen });
|
||||
expect(state.allConversations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_CURRENT_CHAT_WINDOW', () => {
|
||||
it('clears current chat window', () => {
|
||||
const state = { selectedChatId: 1 };
|
||||
mutations[types.CLEAR_CURRENT_CHAT_WINDOW](state);
|
||||
expect(state.selectedChatId).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ASSIGN_TEAM', () => {
|
||||
it('clears current chat window', () => {
|
||||
const state = { allConversations: [{ id: 1, meta: {} }] };
|
||||
mutations[types.UPDATE_CONVERSATION_LAST_ACTIVITY](state, {
|
||||
lastActivityAt: 1602256198,
|
||||
conversationId: 1,
|
||||
});
|
||||
|
||||
expect(state.allConversations).toEqual([
|
||||
{ id: 1, meta: {}, last_activity_at: 1602256198 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#UPDATE_CONVERSATION_LAST_ACTIVITY', () => {
|
||||
it('update conversation last activity', () => {
|
||||
const state = { allConversations: [{ id: 1, meta: {} }] };
|
||||
mutations[types.ASSIGN_TEAM](state, {
|
||||
team: { id: 1, name: 'Team 1' },
|
||||
conversationId: 1,
|
||||
});
|
||||
expect(state.allConversations).toEqual([
|
||||
{ id: 1, meta: { team: { id: 1, name: 'Team 1' } } },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CHANGE_CHAT_SORT_FILTER', () => {
|
||||
it('update conversation sort filter', () => {
|
||||
const state = { chatSortFilter: 'latest' };
|
||||
mutations[types.CHANGE_CHAT_SORT_FILTER](state, {
|
||||
data: 'sort_on_created_at',
|
||||
});
|
||||
expect(state.chatSortFilter).toEqual({ data: 'sort_on_created_at' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CURRENT_CHAT_WINDOW', () => {
|
||||
it('set current chat window', () => {
|
||||
const state = { selectedChatId: 1 };
|
||||
mutations[types.SET_CURRENT_CHAT_WINDOW](state, { id: 2 });
|
||||
expect(state.selectedChatId).toEqual(2);
|
||||
});
|
||||
|
||||
it('does not set current chat window', () => {
|
||||
const state = { selectedChatId: 1 };
|
||||
mutations[types.SET_CURRENT_CHAT_WINDOW](state);
|
||||
expect(state.selectedChatId).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_CAN_REPLY', () => {
|
||||
it('set canReply flag', () => {
|
||||
const state = { allConversations: [{ id: 1, can_reply: false }] };
|
||||
mutations[types.SET_CONVERSATION_CAN_REPLY](state, {
|
||||
conversationId: 1,
|
||||
canReply: true,
|
||||
});
|
||||
expect(state.allConversations[0].can_reply).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_MESSAGE', () => {
|
||||
it('does not add message to the store if conversation does not exist', () => {
|
||||
const state = { allConversations: [] };
|
||||
mutations[types.ADD_MESSAGE](state, { conversationId: 1 });
|
||||
expect(state.allConversations).toEqual([]);
|
||||
});
|
||||
|
||||
it('add message to the conversation if it does not exist in the store', () => {
|
||||
global.bus = { $emit: vi.fn() };
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [] }],
|
||||
selectedChatId: -1,
|
||||
};
|
||||
mutations[types.ADD_MESSAGE](state, {
|
||||
conversation_id: 1,
|
||||
content: 'Test message',
|
||||
created_at: 1602256198,
|
||||
});
|
||||
expect(state.allConversations).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
conversation_id: 1,
|
||||
content: 'Test message',
|
||||
created_at: 1602256198,
|
||||
},
|
||||
],
|
||||
unread_count: 0,
|
||||
timestamp: 1602256198,
|
||||
},
|
||||
]);
|
||||
expect(emitter.emit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('add message to the conversation and emit scrollToMessage if it does not exist in the store', () => {
|
||||
global.bus = { $emit: vi.fn() };
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [] }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
mutations[types.ADD_MESSAGE](state, {
|
||||
conversation_id: 1,
|
||||
content: 'Test message',
|
||||
created_at: 1602256198,
|
||||
});
|
||||
expect(state.allConversations).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
conversation_id: 1,
|
||||
content: 'Test message',
|
||||
created_at: 1602256198,
|
||||
},
|
||||
],
|
||||
unread_count: 0,
|
||||
timestamp: 1602256198,
|
||||
},
|
||||
]);
|
||||
expect(emitter.emit).toHaveBeenCalledWith('SCROLL_TO_MESSAGE');
|
||||
});
|
||||
|
||||
it('update message if it exist in the store', () => {
|
||||
global.bus = { $emit: vi.fn() };
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
conversation_id: 1,
|
||||
content: 'Test message',
|
||||
created_at: 1602256198,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
mutations[types.ADD_MESSAGE](state, {
|
||||
conversation_id: 1,
|
||||
content: 'Test message 1',
|
||||
created_at: 1602256198,
|
||||
});
|
||||
expect(state.allConversations).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
conversation_id: 1,
|
||||
content: 'Test message 1',
|
||||
created_at: 1602256198,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
expect(emitter.emit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CHANGE_CONVERSATION_STATUS', () => {
|
||||
it('updates the conversation status correctly', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [],
|
||||
status: 'open',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.CHANGE_CONVERSATION_STATUS](state, {
|
||||
conversationId: '1',
|
||||
status: 'resolved',
|
||||
});
|
||||
|
||||
expect(state.allConversations).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
messages: [],
|
||||
status: 'resolved',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('#UPDATE_CONVERSATION_CUSTOM_ATTRIBUTES', () => {
|
||||
it('update conversation custom attributes', () => {
|
||||
const custom_attributes = { order_id: 1001 };
|
||||
const state = { allConversations: [{ id: 1 }], selectedChatId: 1 };
|
||||
mutations[types.UPDATE_CONVERSATION_CUSTOM_ATTRIBUTES](state, {
|
||||
conversationId: 1,
|
||||
custom_attributes,
|
||||
});
|
||||
expect(
|
||||
state.allConversations[0].custom_attributes.custom_attributes
|
||||
).toEqual(custom_attributes);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_FILTERS', () => {
|
||||
it('set conversation filter', () => {
|
||||
const appliedFilters = [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
mutations[types.SET_CONVERSATION_FILTERS](appliedFilters);
|
||||
expect(appliedFilters).toEqual([
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_CONVERSATION_FILTERS', () => {
|
||||
it('clears applied conversation filters', () => {
|
||||
const state = {
|
||||
appliedFilters: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
values: [{ id: 'snoozed', name: 'Snoozed' }],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
};
|
||||
mutations[types.CLEAR_CONVERSATION_FILTERS](state);
|
||||
expect(state.appliedFilters).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ALL_CONVERSATION', () => {
|
||||
it('set all conversation', () => {
|
||||
const state = { allConversations: [{ id: 1 }] };
|
||||
const data = [{ id: 1, name: 'test' }];
|
||||
mutations[types.SET_ALL_CONVERSATION](state, data);
|
||||
expect(state.allConversations).toEqual(data);
|
||||
});
|
||||
|
||||
it('set all conversation in reconnect if selected chat id and conversation id is the same', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, status: 'open' }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
const data = [{ id: 1, name: 'test', status: 'resolved' }];
|
||||
mutations[types.SET_ALL_CONVERSATION](state, data);
|
||||
expect(state.allConversations).toEqual(data);
|
||||
});
|
||||
|
||||
it('set all conversation in reconnect if selected chat id and conversation id is the same then do not update messages, attachments, dataFetched, allMessagesLoaded', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
messages: [{ id: 1, content: 'test' }],
|
||||
dataFetched: true,
|
||||
allMessagesLoaded: true,
|
||||
},
|
||||
],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
const data = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'test',
|
||||
messages: [{ id: 1, content: 'updated message' }],
|
||||
dataFetched: true,
|
||||
allMessagesLoaded: true,
|
||||
},
|
||||
];
|
||||
const expected = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'test',
|
||||
messages: [{ id: 1, content: 'test' }],
|
||||
dataFetched: true,
|
||||
allMessagesLoaded: true,
|
||||
},
|
||||
];
|
||||
mutations[types.SET_ALL_CONVERSATION](state, data);
|
||||
expect(state.allConversations).toEqual(expected);
|
||||
});
|
||||
|
||||
it('set all conversation in reconnect if selected chat id and conversation id is not the same', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, status: 'open' }],
|
||||
selectedChatId: 2,
|
||||
};
|
||||
const data = [{ id: 1, name: 'test', status: 'resolved' }];
|
||||
mutations[types.SET_ALL_CONVERSATION](state, data);
|
||||
expect(state.allConversations).toEqual(data);
|
||||
});
|
||||
|
||||
it('set all conversation in reconnect if selected chat id and conversation id is not the same then update messages', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [{ id: 1, content: 'test' }] }],
|
||||
selectedChatId: 2,
|
||||
};
|
||||
const data = [
|
||||
{ id: 1, name: 'test', messages: [{ id: 1, content: 'tested' }] },
|
||||
];
|
||||
mutations[types.SET_ALL_CONVERSATION](state, data);
|
||||
expect(state.allConversations).toEqual(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ALL_ATTACHMENTS', () => {
|
||||
it('set all attachments', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: {},
|
||||
};
|
||||
const data = [{ id: 1, name: 'test' }];
|
||||
mutations[types.SET_ALL_ATTACHMENTS](state, { id: 1, data });
|
||||
expect(state.attachments[1]).toEqual(data);
|
||||
});
|
||||
it('set attachments key even if the attachments are empty', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: {},
|
||||
};
|
||||
const data = [];
|
||||
mutations[types.SET_ALL_ATTACHMENTS](state, { id: 1, data });
|
||||
expect(state.attachments[1]).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CONVERSATION_ATTACHMENTS', () => {
|
||||
it('add conversation attachments', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: {},
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 1,
|
||||
status: 'sent',
|
||||
attachments: [{ id: 1, name: 'test' }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toEqual(message.attachments);
|
||||
});
|
||||
|
||||
it('should not add duplicate attachments', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: { 1: [{ id: 1, name: 'existing' }] },
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 1,
|
||||
status: 'sent',
|
||||
attachments: [
|
||||
{ id: 1, name: 'existing' },
|
||||
{ id: 2, name: 'new' },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.ADD_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toHaveLength(2);
|
||||
expect(state.attachments[1]).toContainEqual({
|
||||
id: 1,
|
||||
name: 'existing',
|
||||
});
|
||||
expect(state.attachments[1]).toContainEqual({
|
||||
id: 2,
|
||||
name: 'new',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add attachments if chat not found', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, attachments: [] }],
|
||||
attachments: {
|
||||
1: [],
|
||||
},
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 2,
|
||||
status: 'sent',
|
||||
attachments: [{ id: 1, name: 'test' }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_CONVERSATION_ATTACHMENTS', () => {
|
||||
it('delete conversation attachments', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: {
|
||||
1: [{ id: 1, message_id: 1 }],
|
||||
},
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 1,
|
||||
status: 'sent',
|
||||
id: 1,
|
||||
};
|
||||
|
||||
mutations[types.DELETE_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should not delete attachments for non-matching message id', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: {
|
||||
1: [{ id: 1, message_id: 1 }],
|
||||
},
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 1,
|
||||
status: 'sent',
|
||||
id: 2,
|
||||
};
|
||||
|
||||
mutations[types.DELETE_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should not delete attachments if chat not found', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
attachments: { 1: [{ id: 1, message_id: 1 }] },
|
||||
};
|
||||
const message = {
|
||||
conversation_id: 2,
|
||||
status: 'sent',
|
||||
id: 1,
|
||||
};
|
||||
|
||||
mutations[types.DELETE_CONVERSATION_ATTACHMENTS](state, message);
|
||||
expect(state.attachments[1]).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONTEXT_MENU_CHAT_ID', () => {
|
||||
it('sets the context menu chat id', () => {
|
||||
const state = { contextMenuChatId: 1 };
|
||||
mutations[types.SET_CONTEXT_MENU_CHAT_ID](state, 2);
|
||||
expect(state.contextMenuChatId).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CHAT_LIST_FILTERS', () => {
|
||||
it('set chat list filters', () => {
|
||||
const conversationFilters = {
|
||||
inboxId: 1,
|
||||
assigneeType: 'me',
|
||||
status: 'open',
|
||||
sortBy: 'created_at',
|
||||
page: 1,
|
||||
labels: ['label'],
|
||||
teamId: 1,
|
||||
conversationType: 'mention',
|
||||
};
|
||||
const state = { conversationFilters: conversationFilters };
|
||||
mutations[types.SET_CHAT_LIST_FILTERS](state, conversationFilters);
|
||||
expect(state.conversationFilters).toEqual(conversationFilters);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_CHAT_LIST_FILTERS', () => {
|
||||
it('update chat list filters', () => {
|
||||
const conversationFilters = {
|
||||
inboxId: 1,
|
||||
assigneeType: 'me',
|
||||
status: 'open',
|
||||
sortBy: 'created_at',
|
||||
page: 1,
|
||||
labels: ['label'],
|
||||
teamId: 1,
|
||||
conversationType: 'mention',
|
||||
};
|
||||
const state = { conversationFilters: conversationFilters };
|
||||
mutations[types.UPDATE_CHAT_LIST_FILTERS](state, {
|
||||
inboxId: 2,
|
||||
updatedWithin: 20,
|
||||
assigneeType: 'all',
|
||||
});
|
||||
expect(state.conversationFilters).toEqual({
|
||||
inboxId: 2,
|
||||
assigneeType: 'all',
|
||||
status: 'open',
|
||||
sortBy: 'created_at',
|
||||
page: 1,
|
||||
labels: ['label'],
|
||||
teamId: 1,
|
||||
conversationType: 'mention',
|
||||
updatedWithin: 20,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_INBOX_CAPTAIN_ASSISTANT', () => {
|
||||
it('set inbox captain assistant', () => {
|
||||
const state = { copilotAssistant: {} };
|
||||
const data = {
|
||||
assistant: {
|
||||
id: 1,
|
||||
name: 'Assistant',
|
||||
description: 'Assistant description',
|
||||
},
|
||||
};
|
||||
mutations[types.SET_INBOX_CAPTAIN_ASSISTANT](state, data);
|
||||
expect(state.copilotAssistant).toEqual(data.assistant);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ALL_MESSAGES_LOADED', () => {
|
||||
it('should set allMessagesLoaded to true on selected chat', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, allMessagesLoaded: false }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
mutations[types.SET_ALL_MESSAGES_LOADED](state);
|
||||
expect(state.allConversations[0].allMessagesLoaded).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_ALL_MESSAGES_LOADED', () => {
|
||||
it('should set allMessagesLoaded to false on selected chat', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, allMessagesLoaded: true }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
mutations[types.CLEAR_ALL_MESSAGES_LOADED](state);
|
||||
expect(state.allConversations[0].allMessagesLoaded).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_PREVIOUS_CONVERSATIONS', () => {
|
||||
it('should prepend messages to conversation messages array', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [{ id: 'msg2' }] }],
|
||||
};
|
||||
const payload = { id: 1, data: [{ id: 'msg1' }] };
|
||||
|
||||
mutations[types.SET_PREVIOUS_CONVERSATIONS](state, payload);
|
||||
expect(state.allConversations[0].messages).toEqual([
|
||||
{ id: 'msg1' },
|
||||
{ id: 'msg2' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not modify messages if data is empty', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [{ id: 'msg2' }] }],
|
||||
};
|
||||
const payload = { id: 1, data: [] };
|
||||
|
||||
mutations[types.SET_PREVIOUS_CONVERSATIONS](state, payload);
|
||||
expect(state.allConversations[0].messages).toEqual([{ id: 'msg2' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_MISSING_MESSAGES', () => {
|
||||
it('should replace message array with new data', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [{ id: 'old' }] }],
|
||||
};
|
||||
const payload = { id: 1, data: [{ id: 'new' }] };
|
||||
|
||||
mutations[types.SET_MISSING_MESSAGES](state, payload);
|
||||
expect(state.allConversations[0].messages).toEqual([{ id: 'new' }]);
|
||||
});
|
||||
|
||||
it('should do nothing if conversation is not found', () => {
|
||||
const state = {
|
||||
allConversations: [],
|
||||
};
|
||||
const payload = { id: 1, data: [{ id: 'new' }] };
|
||||
|
||||
mutations[types.SET_MISSING_MESSAGES](state, payload);
|
||||
expect(state.allConversations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ASSIGN_AGENT', () => {
|
||||
it('should assign agent to selected conversation', () => {
|
||||
const assignee = { id: 1, name: 'Agent' };
|
||||
const state = {
|
||||
allConversations: [{ id: 1, meta: {} }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
|
||||
mutations[types.ASSIGN_AGENT](state, assignee);
|
||||
expect(state.allConversations[0].meta.assignee).toEqual(assignee);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ASSIGN_PRIORITY', () => {
|
||||
it('should assign priority to conversation', () => {
|
||||
const priority = { title: 'Urgent', value: 'urgent' };
|
||||
const state = {
|
||||
allConversations: [{ id: 1 }],
|
||||
};
|
||||
|
||||
mutations[types.ASSIGN_PRIORITY](state, {
|
||||
priority,
|
||||
conversationId: 1,
|
||||
});
|
||||
expect(state.allConversations[0].priority).toEqual(priority);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#MUTE_CONVERSATION', () => {
|
||||
it('should mute selected conversation', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, muted: false }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
|
||||
mutations[types.MUTE_CONVERSATION](state);
|
||||
expect(state.allConversations[0].muted).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UNMUTE_CONVERSATION', () => {
|
||||
it('should unmute selected conversation', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, muted: true }],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
|
||||
mutations[types.UNMUTE_CONVERSATION](state);
|
||||
expect(state.allConversations[0].muted).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_CONVERSATION', () => {
|
||||
it('should update existing conversation', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
status: 'open',
|
||||
updated_at: 100,
|
||||
messages: [{ id: 'msg1' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const conversation = {
|
||||
id: 1,
|
||||
status: 'resolved',
|
||||
updated_at: 200,
|
||||
messages: [{ id: 'msg2' }],
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION](state, conversation);
|
||||
expect(state.allConversations[0]).toEqual({
|
||||
id: 1,
|
||||
status: 'resolved',
|
||||
updated_at: 200,
|
||||
messages: [{ id: 'msg1' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('should add conversation if not found', () => {
|
||||
const state = {
|
||||
allConversations: [],
|
||||
};
|
||||
|
||||
const conversation = {
|
||||
id: 1,
|
||||
status: 'open',
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION](state, conversation);
|
||||
expect(state.allConversations).toEqual([conversation]);
|
||||
});
|
||||
|
||||
it('should emit events if updating selected conversation', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
status: 'open',
|
||||
updated_at: 100,
|
||||
},
|
||||
],
|
||||
selectedChatId: 1,
|
||||
};
|
||||
|
||||
const conversation = {
|
||||
id: 1,
|
||||
status: 'resolved',
|
||||
updated_at: 200,
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION](state, conversation);
|
||||
expect(emitter.emit).toHaveBeenCalledWith('SCROLL_TO_MESSAGE');
|
||||
});
|
||||
|
||||
it('should ignore updates with older timestamps', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
status: 'open',
|
||||
updated_at: 200,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const conversation = {
|
||||
id: 1,
|
||||
status: 'resolved',
|
||||
updated_at: 100,
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION](state, conversation);
|
||||
expect(state.allConversations[0].status).toEqual('open');
|
||||
});
|
||||
|
||||
it('should allow updates with same timestamps', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{
|
||||
id: 1,
|
||||
status: 'open',
|
||||
updated_at: 100,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const conversation = {
|
||||
id: 1,
|
||||
status: 'resolved',
|
||||
updated_at: 100,
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION](state, conversation);
|
||||
expect(state.allConversations[0].status).toEqual('resolved');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_CONVERSATION_CONTACT', () => {
|
||||
it('should update conversation contact data', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{ id: 1, meta: { sender: { id: 1, name: 'Old Name' } } },
|
||||
],
|
||||
};
|
||||
|
||||
const payload = {
|
||||
conversationId: 1,
|
||||
id: 1,
|
||||
name: 'New Name',
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION_CONTACT](state, payload);
|
||||
// The mutation extracts all properties except conversationId
|
||||
const { conversationId, ...contact } = payload;
|
||||
expect(state.allConversations[0].meta.sender).toEqual(contact);
|
||||
});
|
||||
|
||||
it('should do nothing if conversation is not found', () => {
|
||||
const state = {
|
||||
allConversations: [],
|
||||
};
|
||||
|
||||
const payload = {
|
||||
conversationId: 1,
|
||||
id: 1,
|
||||
name: 'New Name',
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_CONVERSATION_CONTACT](state, payload);
|
||||
expect(state.allConversations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ACTIVE_INBOX', () => {
|
||||
it('should set current inbox as integer', () => {
|
||||
const state = {
|
||||
currentInbox: null,
|
||||
};
|
||||
|
||||
mutations[types.SET_ACTIVE_INBOX](state, '1');
|
||||
expect(state.currentInbox).toBe(1);
|
||||
});
|
||||
|
||||
it('should set null if no inbox ID provided', () => {
|
||||
const state = {
|
||||
currentInbox: 1,
|
||||
};
|
||||
|
||||
mutations[types.SET_ACTIVE_INBOX](state, null);
|
||||
expect(state.currentInbox).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_CONTACT_CONVERSATIONS', () => {
|
||||
it('should remove all conversations with matching contact ID', () => {
|
||||
const state = {
|
||||
allConversations: [
|
||||
{ id: 1, meta: { sender: { id: 1 } } },
|
||||
{ id: 2, meta: { sender: { id: 2 } } },
|
||||
{ id: 3, meta: { sender: { id: 1 } } },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.CLEAR_CONTACT_CONVERSATIONS](state, 1);
|
||||
expect(state.allConversations).toHaveLength(1);
|
||||
expect(state.allConversations[0].id).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CONVERSATION', () => {
|
||||
it('should add a new conversation', () => {
|
||||
const state = {
|
||||
allConversations: [],
|
||||
};
|
||||
|
||||
const conversation = { id: 1, messages: [] };
|
||||
mutations[types.ADD_CONVERSATION](state, conversation);
|
||||
expect(state.allConversations).toEqual([conversation]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_CONVERSATION', () => {
|
||||
it('should delete a conversation', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, messages: [] }],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_CONVERSATION](state, 1);
|
||||
expect(state.allConversations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_LIST_LOADING_STATUS', () => {
|
||||
it('should set listLoadingStatus to true', () => {
|
||||
const state = {
|
||||
listLoadingStatus: false,
|
||||
};
|
||||
|
||||
mutations[types.SET_LIST_LOADING_STATUS](state);
|
||||
expect(state.listLoadingStatus).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_LIST_LOADING_STATUS', () => {
|
||||
it('should set listLoadingStatus to false', () => {
|
||||
const state = {
|
||||
listLoadingStatus: true,
|
||||
};
|
||||
|
||||
mutations[types.CLEAR_LIST_LOADING_STATUS](state);
|
||||
expect(state.listLoadingStatus).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CHANGE_CHAT_STATUS_FILTER', () => {
|
||||
it('should update chat status filter', () => {
|
||||
const state = {
|
||||
chatStatusFilter: 'open',
|
||||
};
|
||||
|
||||
mutations[types.CHANGE_CHAT_STATUS_FILTER](state, 'resolved');
|
||||
expect(state.chatStatusFilter).toBe('resolved');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_ASSIGNEE', () => {
|
||||
it('should update assignee on conversation', () => {
|
||||
const state = {
|
||||
allConversations: [{ id: 1, meta: { assignee: null } }],
|
||||
};
|
||||
|
||||
const payload = {
|
||||
id: 1,
|
||||
assignee: { id: 1, name: 'Agent' },
|
||||
};
|
||||
|
||||
mutations[types.UPDATE_ASSIGNEE](state, payload);
|
||||
expect(state.allConversations[0].meta.assignee).toEqual(payload.assignee);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_LAST_MESSAGE_ID_IN_SYNC_CONVERSATION', () => {
|
||||
it('should update the sync conversation message ID', () => {
|
||||
const state = {
|
||||
syncConversationsMessages: {},
|
||||
};
|
||||
|
||||
mutations[types.SET_LAST_MESSAGE_ID_IN_SYNC_CONVERSATION](state, {
|
||||
conversationId: 1,
|
||||
messageId: 100,
|
||||
});
|
||||
|
||||
expect(state.syncConversationsMessages[1]).toBe(100);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
export const dataReceived = {
|
||||
meta: {
|
||||
mine_count: 3,
|
||||
unassigned_count: 0,
|
||||
all_count: 4,
|
||||
},
|
||||
payload: [
|
||||
{
|
||||
meta: {
|
||||
sender: {
|
||||
additional_attributes: {},
|
||||
availability_status: 'offline',
|
||||
email: null,
|
||||
id: 40,
|
||||
name: 'damp-field-834',
|
||||
phone_number: null,
|
||||
identifier: null,
|
||||
thumbnail: '',
|
||||
custom_attributes: {},
|
||||
last_activity_at: 1635764106,
|
||||
},
|
||||
channel: 'Channel::WebWidget',
|
||||
assignee: {
|
||||
id: 1,
|
||||
account_id: 1,
|
||||
availability_status: 'online',
|
||||
auto_offline: true,
|
||||
confirmed: true,
|
||||
email: 'john@acme.inc',
|
||||
available_name: 'John',
|
||||
name: 'John',
|
||||
role: 'administrator',
|
||||
thumbnail:
|
||||
'http://0.0.0.0:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--318d40b3d34e02760df9f4ea0c5c89d1f590dda4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2QzNKbGMybDZaVWtpRERJMU1IZ3lOVEFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e0e35266e8ed66e90c51be02408be8a022aca545/profile-pic.png',
|
||||
},
|
||||
},
|
||||
id: 10,
|
||||
messages: [
|
||||
{
|
||||
id: 85,
|
||||
content: 'Ok',
|
||||
account_id: 1,
|
||||
inbox_id: 6,
|
||||
conversation_id: 10,
|
||||
message_type: 1,
|
||||
created_at: 1635764265,
|
||||
updated_at: '2021-11-01T10:57:45.790Z',
|
||||
private: false,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender_type: 'User',
|
||||
sender_id: 1,
|
||||
external_source_ids: {},
|
||||
sender: {
|
||||
id: 1,
|
||||
name: 'John',
|
||||
available_name: 'John',
|
||||
avatar_url:
|
||||
'http://0.0.0.0:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--318d40b3d34e02760df9f4ea0c5c89d1f590dda4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2QzNKbGMybDZaVWtpRERJMU1IZ3lOVEFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e0e35266e8ed66e90c51be02408be8a022aca545/profile-pic.png',
|
||||
type: 'user',
|
||||
availability_status: 'online',
|
||||
thumbnail:
|
||||
'http://0.0.0.0:3000/rails/active_storage/representations/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--318d40b3d34e02760df9f4ea0c5c89d1f590dda4/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdCem9MWm05eWJXRjBTU0lJY0c1bkJqb0dSVlE2QzNKbGMybDZaVWtpRERJMU1IZ3lOVEFHT3daVSIsImV4cCI6bnVsbCwicHVyIjoidmFyaWF0aW9uIn19--e0e35266e8ed66e90c51be02408be8a022aca545/profile-pic.png',
|
||||
},
|
||||
},
|
||||
],
|
||||
account_id: 1,
|
||||
additional_attributes: {
|
||||
browser: {
|
||||
device_name: 'Unknown',
|
||||
browser_name: 'Chrome',
|
||||
platform_name: 'macOS',
|
||||
browser_version: '95.0.4638.54',
|
||||
platform_version: '10.15.7',
|
||||
},
|
||||
referer: 'http://localhost:3000/widget_tests',
|
||||
initiated_at: {
|
||||
timestamp: 'Mon Nov 01 2021 16:25:06 GMT+0530 (India Standard Time)',
|
||||
},
|
||||
},
|
||||
agent_last_seen_at: 1635846359,
|
||||
assignee_last_seen_at: 1635846359,
|
||||
can_reply: true,
|
||||
contact_last_seen_at: 1635764265,
|
||||
custom_attributes: {},
|
||||
inbox_id: 6,
|
||||
labels: [],
|
||||
muted: false,
|
||||
snoozed_until: null,
|
||||
status: 'open',
|
||||
timestamp: 1635764265,
|
||||
unread_count: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user