Files
leadchat/app/javascript/dashboard/store/modules/specs/conversations/getters.spec.js
Shivam Mishra e393bcf125 fix: Update the logic to handle attachments in a conversation (#9784)
When the chat is viewed, a function `fetchAllAttachments` is run to get all attachments for a particular conversation. This function, before updating the record creates the `attachments` property on the `chat` object in the store.
If in any case this function fails, the `attachments` property is not created, and when the code reaches the `dashboard/store/modules/conversations/index.js` the error occurs

This PR fixes it by ensuring that `SET_ALL_ATTACHMENTS` is always run. And it handles the default case as well


---

Sentry Issue:
[CHATWOOT-FRONTEND-APP-5Y](https://chatwoot-p3.sentry.io/issues/5459056982/)

```
TypeError: Cannot read properties of undefined (reading 'some')
  at forEach(./app/javascript/dashboard/store/modules/conversations/index.js:160:31)
  at Array.forEach(<anonymous>)
  at mutations(./app/javascript/dashboard/store/modules/conversations/index.js:159:27)
  at handler(./node_modules/vuex/dist/vuex.js:771:7)
  at forEach(./node_modules/vuex/dist/vuex.js:470:9)
  at Array.forEach(<anonymous>)
  at fn(./node_modules/vuex/dist/vuex.js:469:13)
  at Store.prototype._withCommit(./node_modules/vuex/dist/vuex.js:574:5)
  at Store.prototype.commit(./node_modules/vuex/dist/vuex.js:468:10)
  at this.commit(./node_modules/vuex/dist/vuex.js:420:21)
  at call(./app/javascript/dashboard/store/modules/conversations/actions.js:273:7)
  at tryCatch(./node_modules/videojs-record/dist/videojs.record.js:2868:27)
  at _invoke(./node_modules/videojs-record/dist/videojs.record.js:3088:32)
  at prototype[method](./node_modules/videojs-record/dist/videojs.record.js:2921:31)
  at as(/packs/js/application-cf716bca3c984faeb095.js:4:76)
  at as(/packs/js/application-cf716bca3c984faeb095.js:4:76)
  at nrWrapper(/app/accounts/81898/conversations/95:6:17817)
```

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2024-08-06 18:13:41 -07:00

312 lines
8.6 KiB
JavaScript

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'],
},
],
});
});
});
});