Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import axios from 'axios';
|
||||
import { actions, getters } from '../../accounts';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const accountData = {
|
||||
id: 1,
|
||||
name: 'Company one',
|
||||
locale: 'en',
|
||||
};
|
||||
|
||||
const newAccountInfo = {
|
||||
accountName: 'Company two',
|
||||
};
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: accountData });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.default.ADD_ACCOUNT, accountData],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({
|
||||
data: { id: 1, name: 'John' },
|
||||
});
|
||||
await actions.update({ commit, getters }, accountData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.EDIT_ACCOUNT, { id: 1, name: 'John' }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit, getters }, accountData)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { data: { id: 1, name: 'John' } },
|
||||
});
|
||||
await actions.create({ commit, getters }, newAccountInfo);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.create({ commit, getters }, newAccountInfo)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#toggleDeletion', () => {
|
||||
it('sends correct actions with delete action if API is success', async () => {
|
||||
axios.post.mockResolvedValue({});
|
||||
await actions.toggleDeletion({ commit }, { action_type: 'delete' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
expect(axios.post.mock.calls[0][1]).toEqual({
|
||||
action_type: 'delete',
|
||||
});
|
||||
});
|
||||
|
||||
it('sends correct actions with undelete action if API is success', async () => {
|
||||
axios.post.mockResolvedValue({});
|
||||
await actions.toggleDeletion({ commit }, { action_type: 'undelete' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
expect(axios.post.mock.calls[0][1]).toEqual({
|
||||
action_type: 'undelete',
|
||||
});
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.toggleDeletion({ commit }, { action_type: 'delete' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,122 @@
|
||||
import { getters } from '../../accounts';
|
||||
import * as languageHelpers from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
||||
|
||||
const accountData = {
|
||||
id: 1,
|
||||
name: 'Company one',
|
||||
locale: 'en',
|
||||
features: {
|
||||
auto_resolve_conversations: true,
|
||||
agent_management: false,
|
||||
},
|
||||
};
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAccount', () => {
|
||||
const state = {
|
||||
records: [accountData],
|
||||
};
|
||||
expect(getters.getAccount(state)(1)).toEqual(accountData);
|
||||
});
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('isFeatureEnabledonAccount', () => {
|
||||
const state = {
|
||||
records: [accountData],
|
||||
};
|
||||
expect(
|
||||
getters.isFeatureEnabledonAccount(
|
||||
state,
|
||||
null,
|
||||
null
|
||||
)(1, 'auto_resolve_conversations')
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
describe('isRTL', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('returns false when accountId is not present and userLocale is not set', () => {
|
||||
const state = { records: [accountData] };
|
||||
const rootState = { route: { params: {} } };
|
||||
const rootGetters = {};
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
|
||||
});
|
||||
|
||||
it('uses userLocale when present (no accountId)', () => {
|
||||
const state = { records: [accountData] };
|
||||
const rootState = { route: { params: {} } };
|
||||
const rootGetters = { getUISettings: { locale: 'ar' } };
|
||||
const spy = vi
|
||||
.spyOn(languageHelpers, 'getLanguageDirection')
|
||||
.mockReturnValue(true);
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
|
||||
expect(spy).toHaveBeenCalledWith('ar');
|
||||
});
|
||||
|
||||
it('prefers userLocale over account locale when both are present', () => {
|
||||
const state = { records: [{ id: 1, locale: 'en' }] };
|
||||
const rootState = { route: { params: { accountId: '1' } } };
|
||||
const rootGetters = { getUISettings: { locale: 'ar' } };
|
||||
const spy = vi
|
||||
.spyOn(languageHelpers, 'getLanguageDirection')
|
||||
.mockReturnValue(true);
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
|
||||
expect(spy).toHaveBeenCalledWith('ar');
|
||||
});
|
||||
|
||||
it('falls back to account locale when userLocale is not provided', () => {
|
||||
const state = { records: [{ id: 1, locale: 'ar' }] };
|
||||
const rootState = { route: { params: { accountId: '1' } } };
|
||||
const rootGetters = {};
|
||||
const spy = vi
|
||||
.spyOn(languageHelpers, 'getLanguageDirection')
|
||||
.mockReturnValue(true);
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
|
||||
expect(spy).toHaveBeenCalledWith('ar');
|
||||
});
|
||||
|
||||
it('returns false for LTR language when userLocale is provided', () => {
|
||||
const state = { records: [{ id: 1, locale: 'en' }] };
|
||||
const rootState = { route: { params: { accountId: '1' } } };
|
||||
const rootGetters = { getUISettings: { locale: 'en' } };
|
||||
const spy = vi
|
||||
.spyOn(languageHelpers, 'getLanguageDirection')
|
||||
.mockReturnValue(false);
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
|
||||
expect(spy).toHaveBeenCalledWith('en');
|
||||
});
|
||||
|
||||
it('returns false when accountId present but user locale is null', () => {
|
||||
const state = { records: [{ id: 1, locale: 'en' }] };
|
||||
const rootState = { route: { params: { accountId: '1' } } };
|
||||
const rootGetters = { getUISettings: { locale: null } };
|
||||
const spy = vi.spyOn(languageHelpers, 'getLanguageDirection');
|
||||
|
||||
expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
|
||||
expect(spy).toHaveBeenCalledWith('en');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../accounts';
|
||||
|
||||
const accountData = {
|
||||
id: 1,
|
||||
name: 'Company one',
|
||||
locale: 'en',
|
||||
};
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#ADD_ACCOUNT', () => {
|
||||
it('push contact data to the store', () => {
|
||||
const state = {
|
||||
records: [],
|
||||
};
|
||||
mutations[types.default.ADD_ACCOUNT](state, accountData);
|
||||
expect(state.records).toEqual([accountData]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_ACCOUNT', () => {
|
||||
it('update contact', () => {
|
||||
const state = {
|
||||
records: [{ ...accountData, locale: 'fr' }],
|
||||
};
|
||||
mutations[types.default.EDIT_ACCOUNT](state, accountData);
|
||||
expect(state.records).toEqual([accountData]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,190 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../agentBots';
|
||||
import types from '../../../mutation-types';
|
||||
import { agentBotRecords, agentBotData } from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: agentBotRecords });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_AGENT_BOTS, agentBotRecords],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: agentBotRecords[0] });
|
||||
await actions.create({ commit }, agentBotData);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isCreating: true }],
|
||||
[types.ADD_AGENT_BOT, agentBotRecords[0]],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
|
||||
expect(axios.post.mock.calls.length).toBe(1);
|
||||
const formDataArg = axios.post.mock.calls[0][1];
|
||||
expect(formDataArg instanceof FormData).toBe(true);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit }, {})).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: agentBotRecords[0] });
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{
|
||||
id: agentBotRecords[0].id,
|
||||
data: agentBotData,
|
||||
}
|
||||
);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_AGENT_BOT, agentBotRecords[0]],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
|
||||
expect(axios.patch.mock.calls.length).toBe(1);
|
||||
const formDataArg = axios.patch.mock.calls[0][1];
|
||||
expect(formDataArg instanceof FormData).toBe(true);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, { id: 1, data: {} })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: agentBotRecords[0] });
|
||||
await actions.delete({ commit }, agentBotRecords[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_AGENT_BOT, agentBotRecords[0].id],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, agentBotRecords[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#setAgentBotInbox', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: {} });
|
||||
await actions.setAgentBotInbox({ commit }, { inboxId: 2, botId: 3 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isSettingAgentBot: true }],
|
||||
[types.SET_AGENT_BOT_INBOX, { inboxId: 2, agentBotId: 3 }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isSettingAgentBot: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.setAgentBotInbox({ commit }, { inboxId: 2, botId: 3 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isSettingAgentBot: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isSettingAgentBot: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#fetchAgentBotInbox', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { agent_bot: { id: 3 } } });
|
||||
await actions.fetchAgentBotInbox({ commit }, 2);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetchingAgentBot: true }],
|
||||
[types.SET_AGENT_BOT_INBOX, { inboxId: 2, agentBotId: 3 }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetchingAgentBot: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.fetchAgentBotInbox({ commit }, { inboxId: 2, agentBotId: 3 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetchingAgentBot: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isFetchingAgentBot: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#disconnectBot', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: {} });
|
||||
await actions.disconnectBot({ commit }, { inboxId: 2 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDisconnecting: true }],
|
||||
[types.SET_AGENT_BOT_INBOX, { inboxId: 2, agentBotId: '' }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDisconnecting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.disconnectBot({ commit }, { inboxId: 2, agentBotId: '' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDisconnecting: true }],
|
||||
[types.SET_AGENT_BOT_UI_FLAG, { isDisconnecting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#resetAccessToken', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const mockResponse = {
|
||||
data: { ...agentBotRecords[0], access_token: 'new_token_123' },
|
||||
};
|
||||
axios.post.mockResolvedValue(mockResponse);
|
||||
const result = await actions.resetAccessToken(
|
||||
{ commit },
|
||||
agentBotRecords[0].id
|
||||
);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.EDIT_AGENT_BOT, mockResponse.data],
|
||||
]);
|
||||
expect(result).toBe(mockResponse.data);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
export const agentBotRecords = [
|
||||
{
|
||||
account_id: 1,
|
||||
id: 11,
|
||||
name: 'Agent Bot 11',
|
||||
description: 'Agent Bot Description',
|
||||
bot_type: 'webhook',
|
||||
thumbnail: 'https://example.com/thumbnail.jpg',
|
||||
bot_config: {},
|
||||
outgoing_url: 'https://example.com/outgoing',
|
||||
access_token: 'hN8QwG769RqBXmme',
|
||||
system_bot: false,
|
||||
},
|
||||
|
||||
{
|
||||
account_id: 1,
|
||||
id: 12,
|
||||
name: 'Agent Bot 12',
|
||||
description: 'Agent Bot Description 12',
|
||||
bot_type: 'webhook',
|
||||
thumbnail: 'https://example.com/thumbnail.jpg',
|
||||
bot_config: {},
|
||||
outgoing_url: 'https://example.com/outgoing',
|
||||
access_token: 'hN8QwG769RqBXmme',
|
||||
system_bot: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const agentBotData = {
|
||||
name: 'Test Bot',
|
||||
description: 'Test Description',
|
||||
outgoing_url: 'https://test.com',
|
||||
bot_type: 'webhook',
|
||||
avatar: new File([''], 'filename'),
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import { getters } from '../../agentBots';
|
||||
import { agentBotRecords } from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getBots', () => {
|
||||
const state = { records: agentBotRecords };
|
||||
expect(getters.getBots(state)).toEqual(agentBotRecords);
|
||||
});
|
||||
|
||||
it('getBot', () => {
|
||||
const state = { records: agentBotRecords };
|
||||
expect(getters.getBot(state)(11)).toEqual(agentBotRecords[0]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../agentBots';
|
||||
import { agentBotRecords } from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_AGENT_BOT_UI_FLAG', () => {
|
||||
it('set uiFlags', () => {
|
||||
const state = { uiFlags: { isFetchingItem: false } };
|
||||
mutations[types.SET_AGENT_BOT_UI_FLAG](state, { isFetchingItem: true });
|
||||
expect(state.uiFlags.isFetchingItem).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#SET_AGENT_BOTS', () => {
|
||||
it('set agent bot records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_AGENT_BOTS](state, agentBotRecords);
|
||||
expect(state.records).toEqual(agentBotRecords);
|
||||
});
|
||||
});
|
||||
describe('#ADD_AGENT_BOT', () => {
|
||||
it('push newly created bot to the store', () => {
|
||||
const state = { records: [agentBotRecords[0]] };
|
||||
mutations[types.ADD_AGENT_BOT](state, agentBotRecords[1]);
|
||||
expect(state.records).toEqual([agentBotRecords[0], agentBotRecords[1]]);
|
||||
});
|
||||
});
|
||||
describe('#EDIT_AGENT_BOT', () => {
|
||||
it('update agent bot record', () => {
|
||||
const state = { records: [agentBotRecords[0]] };
|
||||
mutations[types.EDIT_AGENT_BOT](state, {
|
||||
id: 11,
|
||||
name: 'agent-bot-11',
|
||||
});
|
||||
expect(state.records[0].name).toEqual('agent-bot-11');
|
||||
});
|
||||
});
|
||||
describe('#DELETE_AGENT_BOT', () => {
|
||||
it('delete agent bot record', () => {
|
||||
const state = { records: [agentBotRecords[0]] };
|
||||
mutations[types.DELETE_AGENT_BOT](state, agentBotRecords[0]);
|
||||
expect(state.records).toEqual([agentBotRecords[0]]);
|
||||
});
|
||||
});
|
||||
describe('#SET_AGENT_BOT_INBOX', () => {
|
||||
it('set agent bot in the object', () => {
|
||||
const state = { agentBotInbox: {} };
|
||||
mutations[types.SET_AGENT_BOT_INBOX](state, {
|
||||
agentBotId: 2,
|
||||
inboxId: 3,
|
||||
});
|
||||
expect(state.agentBotInbox).toEqual({ 3: 2 });
|
||||
});
|
||||
});
|
||||
describe('#UPDATE_AGENT_BOT_AVATAR', () => {
|
||||
it('update agent bot avatar', () => {
|
||||
const state = { records: [agentBotRecords[0]] };
|
||||
mutations[types.UPDATE_AGENT_BOT_AVATAR](state, {
|
||||
id: 11,
|
||||
thumbnail: 'https://example.com/thumbnail.jpg',
|
||||
});
|
||||
expect(state.records[0].thumbnail).toEqual(
|
||||
'https://example.com/thumbnail.jpg'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,408 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../agentCapacityPolicies';
|
||||
import types from '../../../mutation-types';
|
||||
import agentCapacityPoliciesList, {
|
||||
camelCaseFixtures,
|
||||
mockUsers,
|
||||
mockInboxLimits,
|
||||
camelCaseMockInboxLimits,
|
||||
} from './fixtures';
|
||||
import camelcaseKeys from 'camelcase-keys';
|
||||
import snakecaseKeys from 'snakecase-keys';
|
||||
|
||||
const commit = vi.fn();
|
||||
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
vi.mock('camelcase-keys');
|
||||
vi.mock('snakecase-keys');
|
||||
vi.mock('../../../utils/api');
|
||||
|
||||
describe('#actions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: agentCapacityPoliciesList });
|
||||
camelcaseKeys.mockReturnValue(camelCaseFixtures);
|
||||
|
||||
await actions.get({ commit });
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(agentCapacityPoliciesList, {
|
||||
deep: true,
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES, camelCaseFixtures],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
|
||||
await actions.get({ commit });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#show', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyData = agentCapacityPoliciesList[0];
|
||||
const camelCasedPolicy = camelCaseFixtures[0];
|
||||
|
||||
axios.get.mockResolvedValue({ data: policyData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedPolicy);
|
||||
|
||||
await actions.show({ commit }, 1);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(policyData, {
|
||||
deep: true,
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICY, camelCasedPolicy],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Not found' });
|
||||
|
||||
await actions.show({ commit }, 1);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const newPolicy = agentCapacityPoliciesList[0];
|
||||
const camelCasedData = camelCaseFixtures[0];
|
||||
const snakeCasedPolicy = { default_capacity: 10 };
|
||||
|
||||
axios.post.mockResolvedValue({ data: newPolicy });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
snakecaseKeys.mockReturnValue(snakeCasedPolicy);
|
||||
|
||||
const result = await actions.create({ commit }, newPolicy);
|
||||
|
||||
expect(snakecaseKeys).toHaveBeenCalledWith(newPolicy);
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(newPolicy, {
|
||||
deep: true,
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: true }],
|
||||
[types.ADD_AGENT_CAPACITY_POLICY, camelCasedData],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
expect(result).toEqual(newPolicy);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(actions.create({ commit }, {})).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const updateParams = { id: 1, name: 'Updated Policy' };
|
||||
const responseData = {
|
||||
...agentCapacityPoliciesList[0],
|
||||
name: 'Updated Policy',
|
||||
};
|
||||
const camelCasedData = {
|
||||
...camelCaseFixtures[0],
|
||||
name: 'Updated Policy',
|
||||
};
|
||||
const snakeCasedParams = { name: 'Updated Policy' };
|
||||
|
||||
axios.patch.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
snakecaseKeys.mockReturnValue(snakeCasedParams);
|
||||
|
||||
const result = await actions.update({ commit }, updateParams);
|
||||
|
||||
expect(snakecaseKeys).toHaveBeenCalledWith({ name: 'Updated Policy' });
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData, {
|
||||
deep: true,
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_AGENT_CAPACITY_POLICY, camelCasedData],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(
|
||||
actions.update({ commit }, { id: 1, name: 'Test' })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
axios.delete.mockResolvedValue({});
|
||||
|
||||
await actions.delete({ commit }, policyId);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_AGENT_CAPACITY_POLICY, policyId],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(actions.delete({ commit }, 1)).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUsers', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const userData = [
|
||||
{ id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
|
||||
{ id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
|
||||
];
|
||||
const camelCasedUsers = [
|
||||
{ id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
|
||||
{ id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
|
||||
];
|
||||
|
||||
axios.get.mockResolvedValue({ data: userData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedUsers);
|
||||
|
||||
const result = await actions.getUsers({ commit }, policyId);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(userData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_AGENT_CAPACITY_POLICIES_USERS,
|
||||
{ policyId, users: camelCasedUsers },
|
||||
],
|
||||
[
|
||||
types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
|
||||
{ isFetching: false },
|
||||
],
|
||||
]);
|
||||
expect(result).toEqual(userData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API fails', async () => {
|
||||
axios.get.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
await expect(actions.getUsers({ commit }, 1)).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
|
||||
{ isFetching: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addUser', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const userData = { user_id: 3, capacity: 12 };
|
||||
const responseData = mockUsers[2];
|
||||
const camelCasedUser = mockUsers[2];
|
||||
|
||||
axios.post.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedUser);
|
||||
|
||||
const result = await actions.addUser({ commit }, { policyId, userData });
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.ADD_AGENT_CAPACITY_POLICIES_USERS,
|
||||
{ policyId, user: camelCasedUser },
|
||||
],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(
|
||||
actions.addUser({ commit }, { policyId: 1, userData: {} })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeUser', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const userId = 2;
|
||||
axios.delete.mockResolvedValue({});
|
||||
|
||||
await actions.removeUser({ commit }, { policyId, userId });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_AGENT_CAPACITY_POLICIES_USERS, { policyId, userId }],
|
||||
[
|
||||
types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
|
||||
{ isDeleting: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(
|
||||
actions.removeUser({ commit }, { policyId: 1, userId: 2 })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isDeleting: true }],
|
||||
[
|
||||
types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
|
||||
{ isDeleting: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createInboxLimit', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const limitData = { inbox_id: 3, conversation_limit: 20 };
|
||||
const responseData = mockInboxLimits[2];
|
||||
const camelCasedData = camelCaseMockInboxLimits[2];
|
||||
|
||||
axios.post.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
|
||||
const result = await actions.createInboxLimit(
|
||||
{ commit },
|
||||
{ policyId, limitData }
|
||||
);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_AGENT_CAPACITY_POLICIES_INBOXES, camelCasedData],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(
|
||||
actions.createInboxLimit({ commit }, { policyId: 1, limitData: {} })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateInboxLimit', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const limitId = 1;
|
||||
const limitData = { conversation_limit: 25 };
|
||||
const responseData = {
|
||||
...mockInboxLimits[0],
|
||||
conversation_limit: 25,
|
||||
};
|
||||
const camelCasedData = {
|
||||
...camelCaseMockInboxLimits[0],
|
||||
conversationLimit: 25,
|
||||
};
|
||||
|
||||
axios.put.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
|
||||
const result = await actions.updateInboxLimit(
|
||||
{ commit },
|
||||
{ policyId, limitId, limitData }
|
||||
);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES, camelCasedData],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.put.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(
|
||||
actions.updateInboxLimit(
|
||||
{ commit },
|
||||
{ policyId: 1, limitId: 1, limitData: {} }
|
||||
)
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteInboxLimit', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const limitId = 1;
|
||||
axios.delete.mockResolvedValue({});
|
||||
|
||||
await actions.deleteInboxLimit({ commit }, { policyId, limitId });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES, { policyId, limitId }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(
|
||||
actions.deleteInboxLimit({ commit }, { policyId: 1, limitId: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,199 @@
|
||||
export default [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Standard Capacity Policy',
|
||||
description: 'Default capacity policy for agents',
|
||||
default_capacity: 10,
|
||||
enabled: true,
|
||||
account_id: 1,
|
||||
assigned_agent_count: 3,
|
||||
created_at: '2024-01-01T10:00:00.000Z',
|
||||
updated_at: '2024-01-01T10:00:00.000Z',
|
||||
users: [],
|
||||
inbox_capacity_limits: [
|
||||
{
|
||||
id: 1,
|
||||
inbox_id: 1,
|
||||
conversation_limit: 15,
|
||||
agent_capacity_policy_id: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inbox_id: 2,
|
||||
conversation_limit: 8,
|
||||
agent_capacity_policy_id: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'High Capacity Policy',
|
||||
description: 'High capacity policy for senior agents',
|
||||
default_capacity: 20,
|
||||
enabled: true,
|
||||
account_id: 1,
|
||||
assigned_agent_count: 5,
|
||||
created_at: '2024-01-01T11:00:00.000Z',
|
||||
updated_at: '2024-01-01T11:00:00.000Z',
|
||||
users: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent Smith',
|
||||
email: 'agent.smith@example.com',
|
||||
capacity: 25,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent Johnson',
|
||||
email: 'agent.johnson@example.com',
|
||||
capacity: 18,
|
||||
},
|
||||
],
|
||||
inbox_capacity_limits: [],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Disabled Policy',
|
||||
description: 'Disabled capacity policy',
|
||||
default_capacity: 5,
|
||||
enabled: false,
|
||||
account_id: 1,
|
||||
assigned_agent_count: 0,
|
||||
created_at: '2024-01-01T12:00:00.000Z',
|
||||
updated_at: '2024-01-01T12:00:00.000Z',
|
||||
users: [],
|
||||
inbox_capacity_limits: [],
|
||||
},
|
||||
];
|
||||
|
||||
export const camelCaseFixtures = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Standard Capacity Policy',
|
||||
description: 'Default capacity policy for agents',
|
||||
defaultCapacity: 10,
|
||||
enabled: true,
|
||||
accountId: 1,
|
||||
assignedAgentCount: 3,
|
||||
createdAt: '2024-01-01T10:00:00.000Z',
|
||||
updatedAt: '2024-01-01T10:00:00.000Z',
|
||||
users: [],
|
||||
inboxCapacityLimits: [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
agentCapacityPolicyId: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
agentCapacityPolicyId: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'High Capacity Policy',
|
||||
description: 'High capacity policy for senior agents',
|
||||
defaultCapacity: 20,
|
||||
enabled: true,
|
||||
accountId: 1,
|
||||
assignedAgentCount: 5,
|
||||
createdAt: '2024-01-01T11:00:00.000Z',
|
||||
updatedAt: '2024-01-01T11:00:00.000Z',
|
||||
users: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent Smith',
|
||||
email: 'agent.smith@example.com',
|
||||
capacity: 25,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent Johnson',
|
||||
email: 'agent.johnson@example.com',
|
||||
capacity: 18,
|
||||
},
|
||||
],
|
||||
inboxCapacityLimits: [],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Disabled Policy',
|
||||
description: 'Disabled capacity policy',
|
||||
defaultCapacity: 5,
|
||||
enabled: false,
|
||||
accountId: 1,
|
||||
assignedAgentCount: 0,
|
||||
createdAt: '2024-01-01T12:00:00.000Z',
|
||||
updatedAt: '2024-01-01T12:00:00.000Z',
|
||||
users: [],
|
||||
inboxCapacityLimits: [],
|
||||
},
|
||||
];
|
||||
|
||||
// Additional test data for user and inbox limit operations
|
||||
export const mockUsers = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent Smith',
|
||||
email: 'agent.smith@example.com',
|
||||
capacity: 25,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent Johnson',
|
||||
email: 'agent.johnson@example.com',
|
||||
capacity: 18,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Agent Brown',
|
||||
email: 'agent.brown@example.com',
|
||||
capacity: 12,
|
||||
},
|
||||
];
|
||||
|
||||
export const mockInboxLimits = [
|
||||
{
|
||||
id: 1,
|
||||
inbox_id: 1,
|
||||
conversation_limit: 15,
|
||||
agent_capacity_policy_id: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inbox_id: 2,
|
||||
conversation_limit: 8,
|
||||
agent_capacity_policy_id: 1,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
inbox_id: 3,
|
||||
conversation_limit: 20,
|
||||
agent_capacity_policy_id: 2,
|
||||
},
|
||||
];
|
||||
|
||||
export const camelCaseMockInboxLimits = [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
agentCapacityPolicyId: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
agentCapacityPolicyId: 1,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
inboxId: 3,
|
||||
conversationLimit: 20,
|
||||
agentCapacityPolicyId: 2,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,51 @@
|
||||
import { getters } from '../../agentCapacityPolicies';
|
||||
import agentCapacityPoliciesList from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAgentCapacityPolicies', () => {
|
||||
const state = { records: agentCapacityPoliciesList };
|
||||
expect(getters.getAgentCapacityPolicies(state)).toEqual(
|
||||
agentCapacityPoliciesList
|
||||
);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isFetchingItem: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isFetchingItem: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getUsersUIFlags', () => {
|
||||
const state = {
|
||||
usersUiFlags: {
|
||||
isFetching: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUsersUIFlags(state)).toEqual({
|
||||
isFetching: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getAgentCapacityPolicyById', () => {
|
||||
const state = { records: agentCapacityPoliciesList };
|
||||
expect(getters.getAgentCapacityPolicyById(state)(1)).toEqual(
|
||||
agentCapacityPoliciesList[0]
|
||||
);
|
||||
expect(getters.getAgentCapacityPolicyById(state)(4)).toEqual({});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,619 @@
|
||||
import { mutations } from '../../agentCapacityPolicies';
|
||||
import types from '../../../mutation-types';
|
||||
import agentCapacityPoliciesList, { mockUsers } from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_AGENT_CAPACITY_POLICIES_UI_FLAG', () => {
|
||||
it('sets single ui flag', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isCreating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('sets multiple ui flags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
isCreating: true,
|
||||
});
|
||||
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: true,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_AGENT_CAPACITY_POLICIES', () => {
|
||||
it('sets agent capacity policies records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES](
|
||||
state,
|
||||
agentCapacityPoliciesList
|
||||
);
|
||||
|
||||
expect(state.records).toEqual(agentCapacityPoliciesList);
|
||||
});
|
||||
|
||||
it('replaces existing records', () => {
|
||||
const state = { records: [{ id: 999, name: 'Old Policy' }] };
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES](
|
||||
state,
|
||||
agentCapacityPoliciesList
|
||||
);
|
||||
|
||||
expect(state.records).toEqual(agentCapacityPoliciesList);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_AGENT_CAPACITY_POLICY', () => {
|
||||
it('sets single agent capacity policy record', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICY](
|
||||
state,
|
||||
agentCapacityPoliciesList[0]
|
||||
);
|
||||
|
||||
expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('replaces existing record', () => {
|
||||
const state = { records: [{ id: 1, name: 'Old Policy' }] };
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICY](
|
||||
state,
|
||||
agentCapacityPoliciesList[0]
|
||||
);
|
||||
|
||||
expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_AGENT_CAPACITY_POLICY', () => {
|
||||
it('adds new policy to empty records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICY](
|
||||
state,
|
||||
agentCapacityPoliciesList[0]
|
||||
);
|
||||
|
||||
expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('adds new policy to existing records', () => {
|
||||
const state = { records: [agentCapacityPoliciesList[0]] };
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICY](
|
||||
state,
|
||||
agentCapacityPoliciesList[1]
|
||||
);
|
||||
|
||||
expect(state.records).toEqual([
|
||||
agentCapacityPoliciesList[0],
|
||||
agentCapacityPoliciesList[1],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_AGENT_CAPACITY_POLICY', () => {
|
||||
it('updates existing policy by id', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{ ...agentCapacityPoliciesList[0] },
|
||||
{ ...agentCapacityPoliciesList[1] },
|
||||
],
|
||||
};
|
||||
|
||||
const updatedPolicy = {
|
||||
...agentCapacityPoliciesList[0],
|
||||
name: 'Updated Policy Name',
|
||||
description: 'Updated Description',
|
||||
};
|
||||
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, updatedPolicy);
|
||||
|
||||
expect(state.records[0]).toEqual(updatedPolicy);
|
||||
expect(state.records[1]).toEqual(agentCapacityPoliciesList[1]);
|
||||
});
|
||||
|
||||
it('updates policy with camelCase properties', () => {
|
||||
const camelCasePolicy = {
|
||||
id: 1,
|
||||
name: 'Camel Case Policy',
|
||||
defaultCapacity: 15,
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
const state = {
|
||||
records: [camelCasePolicy],
|
||||
};
|
||||
|
||||
const updatedPolicy = {
|
||||
...camelCasePolicy,
|
||||
name: 'Updated Camel Case',
|
||||
defaultCapacity: 25,
|
||||
};
|
||||
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, updatedPolicy);
|
||||
|
||||
expect(state.records[0]).toEqual(updatedPolicy);
|
||||
});
|
||||
|
||||
it('does nothing if policy id not found', () => {
|
||||
const state = {
|
||||
records: [agentCapacityPoliciesList[0]],
|
||||
};
|
||||
|
||||
const nonExistentPolicy = {
|
||||
id: 999,
|
||||
name: 'Non-existent',
|
||||
};
|
||||
|
||||
const originalRecords = [...state.records];
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, nonExistentPolicy);
|
||||
|
||||
expect(state.records).toEqual(originalRecords);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_AGENT_CAPACITY_POLICY', () => {
|
||||
it('deletes policy by id', () => {
|
||||
const state = {
|
||||
records: [agentCapacityPoliciesList[0], agentCapacityPoliciesList[1]],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 1);
|
||||
|
||||
expect(state.records).toEqual([agentCapacityPoliciesList[1]]);
|
||||
});
|
||||
|
||||
it('does nothing if id not found', () => {
|
||||
const state = {
|
||||
records: [agentCapacityPoliciesList[0]],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 999);
|
||||
|
||||
expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('handles empty records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 1);
|
||||
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG', () => {
|
||||
it('sets users ui flags', () => {
|
||||
const state = {
|
||||
usersUiFlags: {
|
||||
isFetching: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.usersUiFlags).toEqual({
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('merges with existing flags', () => {
|
||||
const state = {
|
||||
usersUiFlags: {
|
||||
isFetching: false,
|
||||
isDeleting: true,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.usersUiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isDeleting: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_AGENT_CAPACITY_POLICIES_USERS', () => {
|
||||
it('sets users for existing policy', () => {
|
||||
const testUsers = [
|
||||
{ id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
|
||||
{ id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
|
||||
];
|
||||
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', users: [] },
|
||||
{ id: 2, name: 'Policy 2', users: [] },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
users: testUsers,
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual(testUsers);
|
||||
expect(state.records[1].users).toEqual([]);
|
||||
});
|
||||
|
||||
it('replaces existing users', () => {
|
||||
const oldUsers = [{ id: 99, name: 'Old Agent', capacity: 5 }];
|
||||
const newUsers = [{ id: 1, name: 'New Agent', capacity: 15 }];
|
||||
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', users: oldUsers }],
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
users: newUsers,
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual(newUsers);
|
||||
});
|
||||
|
||||
it('does nothing if policy not found', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', users: [] }],
|
||||
};
|
||||
|
||||
const originalState = JSON.parse(JSON.stringify(state));
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 999,
|
||||
users: [{ id: 1, name: 'Test' }],
|
||||
});
|
||||
|
||||
expect(state).toEqual(originalState);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_AGENT_CAPACITY_POLICIES_USERS', () => {
|
||||
it('adds user to existing policy', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', users: [] },
|
||||
{ id: 2, name: 'Policy 2', users: [] },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
user: mockUsers[0],
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual([mockUsers[0]]);
|
||||
expect(state.records[1].users).toEqual([]);
|
||||
});
|
||||
|
||||
it('adds user to policy with existing users', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', users: [mockUsers[0]] }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
user: mockUsers[1],
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual([mockUsers[0], mockUsers[1]]);
|
||||
});
|
||||
|
||||
it('initializes users array if undefined', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1' }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
user: mockUsers[0],
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual([mockUsers[0]]);
|
||||
});
|
||||
|
||||
it('updates assigned agent count', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', users: [] }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
user: mockUsers[0],
|
||||
});
|
||||
|
||||
expect(state.records[0].assignedAgentCount).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_AGENT_CAPACITY_POLICIES_USERS', () => {
|
||||
it('removes user from policy', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
users: [mockUsers[0], mockUsers[1], mockUsers[2]],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
userId: 2,
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual([mockUsers[0], mockUsers[2]]);
|
||||
});
|
||||
|
||||
it('handles removing non-existent user', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
users: [mockUsers[0]],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
userId: 999,
|
||||
});
|
||||
|
||||
expect(state.records[0].users).toEqual([mockUsers[0]]);
|
||||
});
|
||||
|
||||
it('updates assigned agent count', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', users: [mockUsers[0]] }],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
|
||||
policyId: 1,
|
||||
userId: 1,
|
||||
});
|
||||
|
||||
expect(state.records[0].assignedAgentCount).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_AGENT_CAPACITY_POLICIES_INBOXES', () => {
|
||||
it('adds inbox limit to policy', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
inboxCapacityLimits: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const inboxLimitData = {
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
agentCapacityPolicyId: 1,
|
||||
};
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_INBOXES](
|
||||
state,
|
||||
inboxLimitData
|
||||
);
|
||||
|
||||
expect(state.records[0].inboxCapacityLimits).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('does nothing if policy not found', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', inboxCapacityLimits: [] }],
|
||||
};
|
||||
|
||||
const originalState = JSON.parse(JSON.stringify(state));
|
||||
|
||||
mutations[types.SET_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
agentCapacityPolicyId: 999,
|
||||
});
|
||||
|
||||
expect(state).toEqual(originalState);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_AGENT_CAPACITY_POLICIES_INBOXES', () => {
|
||||
it('updates existing inbox limit', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
inboxCapacityLimits: [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 25,
|
||||
agentCapacityPolicyId: 1,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxCapacityLimits[0]).toEqual({
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 25,
|
||||
});
|
||||
expect(state.records[0].inboxCapacityLimits[1]).toEqual({
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
});
|
||||
});
|
||||
|
||||
it('does nothing if limit not found', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
inboxCapacityLimits: [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const originalLimits = [...state.records[0].inboxCapacityLimits];
|
||||
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
id: 999,
|
||||
inboxId: 1,
|
||||
conversationLimit: 25,
|
||||
agentCapacityPolicyId: 1,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxCapacityLimits).toEqual(originalLimits);
|
||||
});
|
||||
|
||||
it('does nothing if policy not found', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', inboxCapacityLimits: [] }],
|
||||
};
|
||||
|
||||
const originalState = JSON.parse(JSON.stringify(state));
|
||||
|
||||
mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 25,
|
||||
agentCapacityPolicyId: 999,
|
||||
});
|
||||
|
||||
expect(state).toEqual(originalState);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_AGENT_CAPACITY_POLICIES_INBOXES', () => {
|
||||
it('removes inbox limit from policy', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
inboxCapacityLimits: [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
limitId: 1,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxCapacityLimits).toEqual([
|
||||
{
|
||||
id: 2,
|
||||
inboxId: 2,
|
||||
conversationLimit: 8,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('handles removing non-existent limit', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
inboxCapacityLimits: [
|
||||
{
|
||||
id: 1,
|
||||
inboxId: 1,
|
||||
conversationLimit: 15,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const originalLimits = [...state.records[0].inboxCapacityLimits];
|
||||
|
||||
mutations[types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
limitId: 999,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxCapacityLimits).toEqual(originalLimits);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../agents';
|
||||
import * as types from '../../../mutation-types';
|
||||
import agentList from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: agentList });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_FETCHING_STATUS, true],
|
||||
[types.default.SET_AGENT_FETCHING_STATUS, false],
|
||||
[types.default.SET_AGENTS, agentList],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_FETCHING_STATUS, true],
|
||||
[types.default.SET_AGENT_FETCHING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: agentList[0] });
|
||||
await actions.create({ commit }, agentList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_CREATING_STATUS, true],
|
||||
[types.default.ADD_AGENT, agentList[0]],
|
||||
[types.default.SET_AGENT_CREATING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toEqual({
|
||||
message: 'Incorrect header',
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_CREATING_STATUS, true],
|
||||
[types.default.SET_AGENT_CREATING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: agentList[0] });
|
||||
await actions.update({ commit }, agentList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_UPDATING_STATUS, true],
|
||||
[types.default.EDIT_AGENT, agentList[0]],
|
||||
[types.default.SET_AGENT_UPDATING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, agentList[0])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_UPDATING_STATUS, true],
|
||||
[types.default.SET_AGENT_UPDATING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: agentList[0] });
|
||||
await actions.delete({ commit }, agentList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_DELETING_STATUS, true],
|
||||
[types.default.DELETE_AGENT, agentList[0].id],
|
||||
[types.default.SET_AGENT_DELETING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.delete({ commit }, agentList[0].id)).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AGENT_DELETING_STATUS, true],
|
||||
[types.default.SET_AGENT_DELETING_STATUS, false],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updatePresence', () => {
|
||||
it('sends correct actions', async () => {
|
||||
const data = { users: { 1: 'online' }, contacts: { 2: 'online' } };
|
||||
actions.updatePresence({ commit, dispatch }, data);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.UPDATE_AGENTS_PRESENCE, data],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateSingleAgentPresence', () => {
|
||||
it('sends correct actions', async () => {
|
||||
const data = { id: 1, availabilityStatus: 'online' };
|
||||
actions.updateSingleAgentPresence({ commit, dispatch }, data);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.UPDATE_SINGLE_AGENT_PRESENCE, data],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
export default [
|
||||
{
|
||||
id: 1,
|
||||
provider: 'email',
|
||||
uid: 'agent1@chatwoot.com',
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
account_id: 1,
|
||||
created_at: '2019-11-18T02:21:06.225Z',
|
||||
updated_at: '2019-12-20T07:43:35.794Z',
|
||||
pubsub_token: 'random-1',
|
||||
role: 'agent',
|
||||
confirmed: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
provider: 'email',
|
||||
uid: 'agent2@chatwoot.com',
|
||||
name: 'Agent2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
account_id: 1,
|
||||
created_at: '2019-11-18T02:21:06.225Z',
|
||||
updated_at: '2019-12-20T07:43:35.794Z',
|
||||
pubsub_token: 'random-2',
|
||||
role: 'agent',
|
||||
confirmed: true,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,132 @@
|
||||
import { getters } from '../../agents';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAgents', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent 2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
confirmed: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getAgents(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent 2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
confirmed: false,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getVerifiedAgents', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent 2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
confirmed: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getVerifiedAgents(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getAgentStatus', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent 2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
confirmed: false,
|
||||
availability_status: 'offline',
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getAgentStatus(state)).toEqual({
|
||||
online: 1,
|
||||
busy: 0,
|
||||
offline: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('getAgentStatus', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent 1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
confirmed: true,
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent 2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
confirmed: false,
|
||||
availability_status: 'offline',
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getAgentStatus(state)).toEqual({
|
||||
online: 1,
|
||||
busy: 0,
|
||||
offline: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,140 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../agents';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_AGENTS', () => {
|
||||
it('set agent records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.default.SET_AGENTS](state, [
|
||||
{ id: 1, name: 'Agent1', email: 'agent1@chatwoot.com' },
|
||||
]);
|
||||
expect(state.records).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_AGENT', () => {
|
||||
it('push newly created agent data to the store', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Agent1', email: 'agent1@chatwoot.com' }],
|
||||
};
|
||||
mutations[types.default.ADD_AGENT](state, {
|
||||
id: 2,
|
||||
name: 'Agent2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
});
|
||||
expect(state.records).toEqual([
|
||||
{ id: 1, name: 'Agent1', email: 'agent1@chatwoot.com' },
|
||||
{ id: 2, name: 'Agent2', email: 'agent2@chatwoot.com' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_AGENT', () => {
|
||||
it('update agent record', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Agent1', email: 'agent1@chatwoot.com' }],
|
||||
};
|
||||
mutations[types.default.EDIT_AGENT](state, {
|
||||
id: 1,
|
||||
name: 'Agent2',
|
||||
email: 'agent2@chatwoot.com',
|
||||
});
|
||||
expect(state.records).toEqual([
|
||||
{ id: 1, name: 'Agent2', email: 'agent2@chatwoot.com' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_AGENT', () => {
|
||||
it('delete agent record', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Agent1', email: 'agent1@chatwoot.com' }],
|
||||
};
|
||||
mutations[types.default.DELETE_AGENT](state, 1);
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_AGENTS_PRESENCE', () => {
|
||||
it('updates agent presence', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'online',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.default.UPDATE_AGENTS_PRESENCE](state, { 1: 'busy' });
|
||||
expect(state.records).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'busy',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_SINGLE_AGENT_PRESENCE', () => {
|
||||
it('updates single agent presence', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'online',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.default.UPDATE_SINGLE_AGENT_PRESENCE](state, {
|
||||
id: 1,
|
||||
availabilityStatus: 'busy',
|
||||
});
|
||||
expect(state.records).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'busy',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Agent1',
|
||||
email: 'agent1@chatwoot.com',
|
||||
availability_status: 'online',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,326 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../assignmentPolicies';
|
||||
import types from '../../../mutation-types';
|
||||
import assignmentPoliciesList, { camelCaseFixtures } from './fixtures';
|
||||
import camelcaseKeys from 'camelcase-keys';
|
||||
import snakecaseKeys from 'snakecase-keys';
|
||||
|
||||
const commit = vi.fn();
|
||||
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
vi.mock('camelcase-keys');
|
||||
vi.mock('snakecase-keys');
|
||||
vi.mock('../../../utils/api');
|
||||
|
||||
describe('#actions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: assignmentPoliciesList });
|
||||
camelcaseKeys.mockReturnValue(camelCaseFixtures);
|
||||
|
||||
await actions.get({ commit });
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(assignmentPoliciesList);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES, camelCaseFixtures],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
|
||||
await actions.get({ commit });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#show', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyData = assignmentPoliciesList[0];
|
||||
const camelCasedPolicy = camelCaseFixtures[0];
|
||||
|
||||
axios.get.mockResolvedValue({ data: policyData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedPolicy);
|
||||
|
||||
await actions.show({ commit }, 1);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(policyData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_ASSIGNMENT_POLICY, camelCasedPolicy],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Not found' });
|
||||
|
||||
await actions.show({ commit }, 1);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const newPolicy = assignmentPoliciesList[0];
|
||||
const camelCasedData = camelCaseFixtures[0];
|
||||
const snakeCasedPolicy = { assignment_order: 'round_robin' };
|
||||
|
||||
axios.post.mockResolvedValue({ data: newPolicy });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
snakecaseKeys.mockReturnValue(snakeCasedPolicy);
|
||||
|
||||
const result = await actions.create({ commit }, newPolicy);
|
||||
|
||||
expect(snakecaseKeys).toHaveBeenCalledWith(newPolicy);
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(newPolicy);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: true }],
|
||||
[types.ADD_ASSIGNMENT_POLICY, camelCasedData],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
expect(result).toEqual(newPolicy);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(actions.create({ commit }, {})).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const updateParams = { id: 1, name: 'Updated Policy' };
|
||||
const responseData = {
|
||||
...assignmentPoliciesList[0],
|
||||
name: 'Updated Policy',
|
||||
};
|
||||
const camelCasedData = {
|
||||
...camelCaseFixtures[0],
|
||||
name: 'Updated Policy',
|
||||
};
|
||||
const snakeCasedParams = { name: 'Updated Policy' };
|
||||
|
||||
axios.patch.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
snakecaseKeys.mockReturnValue(snakeCasedParams);
|
||||
|
||||
const result = await actions.update({ commit }, updateParams);
|
||||
|
||||
expect(snakecaseKeys).toHaveBeenCalledWith({ name: 'Updated Policy' });
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_ASSIGNMENT_POLICY, camelCasedData],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue(new Error('Validation error'));
|
||||
|
||||
await expect(
|
||||
actions.update({ commit }, { id: 1, name: 'Test' })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
axios.delete.mockResolvedValue({});
|
||||
|
||||
await actions.delete({ commit }, policyId);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_ASSIGNMENT_POLICY, policyId],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(actions.delete({ commit }, 1)).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getInboxes', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const inboxData = {
|
||||
inboxes: [
|
||||
{ id: 1, name: 'Support' },
|
||||
{ id: 2, name: 'Sales' },
|
||||
],
|
||||
};
|
||||
const camelCasedInboxes = [
|
||||
{ id: 1, name: 'Support' },
|
||||
{ id: 2, name: 'Sales' },
|
||||
];
|
||||
|
||||
axios.get.mockResolvedValue({ data: inboxData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedInboxes);
|
||||
|
||||
await actions.getInboxes({ commit }, policyId);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(inboxData.inboxes);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_ASSIGNMENT_POLICIES_INBOXES,
|
||||
{ policyId, inboxes: camelCasedInboxes },
|
||||
],
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API fails', async () => {
|
||||
axios.get.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
await expect(actions.getInboxes({ commit }, 1)).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setInboxPolicy', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const responseData = { success: true, policy_id: 2 };
|
||||
const camelCasedData = { success: true, policyId: 2 };
|
||||
|
||||
axios.post.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
|
||||
const result = await actions.setInboxPolicy(
|
||||
{ commit },
|
||||
{ inboxId: 1, policyId: 2 }
|
||||
);
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ADD_ASSIGNMENT_POLICIES_INBOXES, camelCasedData],
|
||||
]);
|
||||
expect(result).toEqual(responseData);
|
||||
});
|
||||
|
||||
it('throws error if API fails', async () => {
|
||||
axios.post.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
await expect(
|
||||
actions.setInboxPolicy({ commit }, { inboxId: 1, policyId: 2 })
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getInboxPolicy', () => {
|
||||
it('returns camelCased response data if API is success', async () => {
|
||||
const responseData = { policy_id: 1, name: 'Round Robin' };
|
||||
const camelCasedData = { policyId: 1, name: 'Round Robin' };
|
||||
|
||||
axios.get.mockResolvedValue({ data: responseData });
|
||||
camelcaseKeys.mockReturnValue(camelCasedData);
|
||||
|
||||
const result = await actions.getInboxPolicy({}, { inboxId: 1 });
|
||||
|
||||
expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
|
||||
expect(result).toEqual(camelCasedData);
|
||||
});
|
||||
|
||||
it('throws error if API fails', async () => {
|
||||
axios.get.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(
|
||||
actions.getInboxPolicy({}, { inboxId: 999 })
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateInboxPolicy', () => {
|
||||
it('commits EDIT_ASSIGNMENT_POLICY mutation', async () => {
|
||||
const policy = { id: 1, name: 'Updated Policy' };
|
||||
|
||||
await actions.updateInboxPolicy({ commit }, { policy });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.EDIT_ASSIGNMENT_POLICY, policy],
|
||||
]);
|
||||
});
|
||||
|
||||
it('throws error if commit fails', async () => {
|
||||
commit.mockImplementation(() => {
|
||||
throw new Error('Commit failed');
|
||||
});
|
||||
|
||||
await expect(
|
||||
actions.updateInboxPolicy({ commit }, { policy: {} })
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeInboxPolicy', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const policyId = 1;
|
||||
const inboxId = 2;
|
||||
|
||||
axios.delete.mockResolvedValue({});
|
||||
|
||||
await actions.removeInboxPolicy({ commit }, { policyId, inboxId });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_ASSIGNMENT_POLICIES_INBOXES, { policyId, inboxId }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API fails', async () => {
|
||||
axios.delete.mockRejectedValue(new Error('Not found'));
|
||||
|
||||
await expect(
|
||||
actions.removeInboxPolicy({ commit }, { policyId: 1, inboxId: 999 })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
export default [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Round Robin Policy',
|
||||
description: 'Distributes conversations evenly among agents',
|
||||
assignment_order: 'round_robin',
|
||||
conversation_priority: 'earliest_created',
|
||||
fair_distribution_limit: 100,
|
||||
fair_distribution_window: 3600,
|
||||
enabled: true,
|
||||
assigned_inbox_count: 3,
|
||||
created_at: 1704110400,
|
||||
updated_at: 1704110400,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Balanced Policy',
|
||||
description: 'Assigns conversations based on agent capacity',
|
||||
assignment_order: 'balanced',
|
||||
conversation_priority: 'longest_waiting',
|
||||
fair_distribution_limit: 50,
|
||||
fair_distribution_window: 1800,
|
||||
enabled: false,
|
||||
assigned_inbox_count: 1,
|
||||
created_at: 1704114000,
|
||||
updated_at: 1704114000,
|
||||
},
|
||||
];
|
||||
|
||||
export const camelCaseFixtures = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Round Robin Policy',
|
||||
description: 'Distributes conversations evenly among agents',
|
||||
assignmentOrder: 'round_robin',
|
||||
conversationPriority: 'earliest_created',
|
||||
fairDistributionLimit: 100,
|
||||
fairDistributionWindow: 3600,
|
||||
enabled: true,
|
||||
assignedInboxCount: 3,
|
||||
createdAt: 1704110400,
|
||||
updatedAt: 1704110400,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Balanced Policy',
|
||||
description: 'Assigns conversations based on agent capacity',
|
||||
assignmentOrder: 'balanced',
|
||||
conversationPriority: 'longest_waiting',
|
||||
fairDistributionLimit: 50,
|
||||
fairDistributionWindow: 1800,
|
||||
enabled: false,
|
||||
assignedInboxCount: 1,
|
||||
createdAt: 1704114000,
|
||||
updatedAt: 1704114000,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,51 @@
|
||||
import { getters } from '../../assignmentPolicies';
|
||||
import assignmentPoliciesList from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAssignmentPolicies', () => {
|
||||
const state = { records: assignmentPoliciesList };
|
||||
expect(getters.getAssignmentPolicies(state)).toEqual(
|
||||
assignmentPoliciesList
|
||||
);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isFetchingItem: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isFetchingItem: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getInboxUiFlags', () => {
|
||||
const state = {
|
||||
inboxUiFlags: {
|
||||
isFetching: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getInboxUiFlags(state)).toEqual({
|
||||
isFetching: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getAssignmentPolicyById', () => {
|
||||
const state = { records: assignmentPoliciesList };
|
||||
expect(getters.getAssignmentPolicyById(state)(1)).toEqual(
|
||||
assignmentPoliciesList[0]
|
||||
);
|
||||
expect(getters.getAssignmentPolicyById(state)(3)).toEqual({});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,385 @@
|
||||
import { mutations } from '../../assignmentPolicies';
|
||||
import types from '../../../mutation-types';
|
||||
import assignmentPoliciesList from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_ASSIGNMENT_POLICIES_UI_FLAG', () => {
|
||||
it('sets single ui flag', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isCreating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('sets multiple ui flags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
isCreating: true,
|
||||
});
|
||||
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: true,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ASSIGNMENT_POLICIES', () => {
|
||||
it('sets assignment policies records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES](state, assignmentPoliciesList);
|
||||
|
||||
expect(state.records).toEqual(assignmentPoliciesList);
|
||||
});
|
||||
|
||||
it('replaces existing records', () => {
|
||||
const state = { records: [{ id: 999, name: 'Old Policy' }] };
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES](state, assignmentPoliciesList);
|
||||
|
||||
expect(state.records).toEqual(assignmentPoliciesList);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ASSIGNMENT_POLICY', () => {
|
||||
it('sets single assignment policy record', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
|
||||
|
||||
expect(state.records).toEqual([assignmentPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('replaces existing record', () => {
|
||||
const state = { records: [{ id: 1, name: 'Old Policy' }] };
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
|
||||
|
||||
expect(state.records).toEqual([assignmentPoliciesList[0]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_ASSIGNMENT_POLICY', () => {
|
||||
it('adds new policy to empty records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.ADD_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
|
||||
|
||||
expect(state.records).toEqual([assignmentPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('adds new policy to existing records', () => {
|
||||
const state = { records: [assignmentPoliciesList[0]] };
|
||||
|
||||
mutations[types.ADD_ASSIGNMENT_POLICY](state, assignmentPoliciesList[1]);
|
||||
|
||||
expect(state.records).toEqual([
|
||||
assignmentPoliciesList[0],
|
||||
assignmentPoliciesList[1],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_ASSIGNMENT_POLICY', () => {
|
||||
it('updates existing policy by id', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{ ...assignmentPoliciesList[0] },
|
||||
{ ...assignmentPoliciesList[1] },
|
||||
],
|
||||
};
|
||||
|
||||
const updatedPolicy = {
|
||||
...assignmentPoliciesList[0],
|
||||
name: 'Updated Policy Name',
|
||||
description: 'Updated Description',
|
||||
};
|
||||
|
||||
mutations[types.EDIT_ASSIGNMENT_POLICY](state, updatedPolicy);
|
||||
|
||||
expect(state.records[0]).toEqual(updatedPolicy);
|
||||
expect(state.records[1]).toEqual(assignmentPoliciesList[1]);
|
||||
});
|
||||
|
||||
it('updates policy with camelCase properties', () => {
|
||||
const camelCasePolicy = {
|
||||
id: 1,
|
||||
name: 'Camel Case Policy',
|
||||
assignmentOrder: 'round_robin',
|
||||
conversationPriority: 'earliest_created',
|
||||
};
|
||||
|
||||
const state = {
|
||||
records: [camelCasePolicy],
|
||||
};
|
||||
|
||||
const updatedPolicy = {
|
||||
...camelCasePolicy,
|
||||
name: 'Updated Camel Case',
|
||||
assignmentOrder: 'balanced',
|
||||
};
|
||||
|
||||
mutations[types.EDIT_ASSIGNMENT_POLICY](state, updatedPolicy);
|
||||
|
||||
expect(state.records[0]).toEqual(updatedPolicy);
|
||||
});
|
||||
|
||||
it('does nothing if policy id not found', () => {
|
||||
const state = {
|
||||
records: [assignmentPoliciesList[0]],
|
||||
};
|
||||
|
||||
const nonExistentPolicy = {
|
||||
id: 999,
|
||||
name: 'Non-existent',
|
||||
};
|
||||
|
||||
const originalRecords = [...state.records];
|
||||
mutations[types.EDIT_ASSIGNMENT_POLICY](state, nonExistentPolicy);
|
||||
|
||||
expect(state.records).toEqual(originalRecords);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_ASSIGNMENT_POLICY', () => {
|
||||
it('deletes policy by id', () => {
|
||||
const state = {
|
||||
records: [assignmentPoliciesList[0], assignmentPoliciesList[1]],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICY](state, 1);
|
||||
|
||||
expect(state.records).toEqual([assignmentPoliciesList[1]]);
|
||||
});
|
||||
|
||||
it('does nothing if id not found', () => {
|
||||
const state = {
|
||||
records: [assignmentPoliciesList[0]],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICY](state, 999);
|
||||
|
||||
expect(state.records).toEqual([assignmentPoliciesList[0]]);
|
||||
});
|
||||
|
||||
it('handles empty records', () => {
|
||||
const state = { records: [] };
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICY](state, 1);
|
||||
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG', () => {
|
||||
it('sets inbox ui flags', () => {
|
||||
const state = {
|
||||
inboxUiFlags: {
|
||||
isFetching: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.inboxUiFlags).toEqual({
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('merges with existing flags', () => {
|
||||
const state = {
|
||||
inboxUiFlags: {
|
||||
isFetching: false,
|
||||
isLoading: true,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG](state, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
expect(state.inboxUiFlags).toEqual({
|
||||
isFetching: true,
|
||||
isLoading: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ASSIGNMENT_POLICIES_INBOXES', () => {
|
||||
it('sets inboxes for existing policy', () => {
|
||||
const mockInboxes = [
|
||||
{ id: 1, name: 'Support Inbox' },
|
||||
{ id: 2, name: 'Sales Inbox' },
|
||||
];
|
||||
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', inboxes: [] },
|
||||
{ id: 2, name: 'Policy 2', inboxes: [] },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
inboxes: mockInboxes,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxes).toEqual(mockInboxes);
|
||||
expect(state.records[1].inboxes).toEqual([]);
|
||||
});
|
||||
|
||||
it('replaces existing inboxes', () => {
|
||||
const oldInboxes = [{ id: 99, name: 'Old Inbox' }];
|
||||
const newInboxes = [{ id: 1, name: 'New Inbox' }];
|
||||
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', inboxes: oldInboxes }],
|
||||
};
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
inboxes: newInboxes,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxes).toEqual(newInboxes);
|
||||
});
|
||||
|
||||
it('does nothing if policy not found', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', inboxes: [] }],
|
||||
};
|
||||
|
||||
const originalState = JSON.parse(JSON.stringify(state));
|
||||
|
||||
mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 999,
|
||||
inboxes: [{ id: 1, name: 'Test' }],
|
||||
});
|
||||
|
||||
expect(state).toEqual(originalState);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_ASSIGNMENT_POLICIES_INBOXES', () => {
|
||||
it('removes inbox from policy', () => {
|
||||
const mockInboxes = [
|
||||
{ id: 1, name: 'Support Inbox' },
|
||||
{ id: 2, name: 'Sales Inbox' },
|
||||
{ id: 3, name: 'Marketing Inbox' },
|
||||
];
|
||||
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', inboxes: mockInboxes },
|
||||
{ id: 2, name: 'Policy 2', inboxes: [] },
|
||||
],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
inboxId: 2,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxes).toEqual([
|
||||
{ id: 1, name: 'Support Inbox' },
|
||||
{ id: 3, name: 'Marketing Inbox' },
|
||||
]);
|
||||
expect(state.records[1].inboxes).toEqual([]);
|
||||
});
|
||||
|
||||
it('does nothing if policy not found', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', inboxes: [{ id: 1, name: 'Test' }] },
|
||||
],
|
||||
};
|
||||
|
||||
const originalState = JSON.parse(JSON.stringify(state));
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 999,
|
||||
inboxId: 1,
|
||||
});
|
||||
|
||||
expect(state).toEqual(originalState);
|
||||
});
|
||||
|
||||
it('does nothing if inbox not found in policy', () => {
|
||||
const mockInboxes = [{ id: 1, name: 'Support Inbox' }];
|
||||
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1', inboxes: mockInboxes }],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
inboxId: 999,
|
||||
});
|
||||
|
||||
expect(state.records[0].inboxes).toEqual(mockInboxes);
|
||||
});
|
||||
|
||||
it('handles policy with no inboxes', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, name: 'Policy 1' }],
|
||||
};
|
||||
|
||||
mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
|
||||
policyId: 1,
|
||||
inboxId: 1,
|
||||
});
|
||||
|
||||
expect(state.records[0]).toEqual({ id: 1, name: 'Policy 1' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_ASSIGNMENT_POLICIES_INBOXES', () => {
|
||||
it('updates policy attributes using MutationHelpers.updateAttributes', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{ id: 1, name: 'Policy 1', assignedInboxCount: 2 },
|
||||
{ id: 2, name: 'Policy 2', assignedInboxCount: 1 },
|
||||
],
|
||||
};
|
||||
|
||||
const updatedPolicy = {
|
||||
id: 1,
|
||||
name: 'Policy 1',
|
||||
assignedInboxCount: 3,
|
||||
inboxes: [{ id: 1, name: 'New Inbox' }],
|
||||
};
|
||||
|
||||
mutations[types.ADD_ASSIGNMENT_POLICIES_INBOXES](state, updatedPolicy);
|
||||
|
||||
expect(state.records[0]).toEqual(updatedPolicy);
|
||||
expect(state.records[1]).toEqual({
|
||||
id: 2,
|
||||
name: 'Policy 2',
|
||||
assignedInboxCount: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../attributes';
|
||||
import * as types from '../../../mutation-types';
|
||||
import attributesList from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: attributesList });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE, attributesList],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: attributesList[0] });
|
||||
await actions.create({ commit }, attributesList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isCreating: true }],
|
||||
[types.default.ADD_CUSTOM_ATTRIBUTE, attributesList[0]],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: attributesList[0] });
|
||||
await actions.update({ commit }, attributesList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.EDIT_CUSTOM_ATTRIBUTE, attributesList[0]],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, attributesList[0])
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: attributesList[0] });
|
||||
await actions.delete({ commit }, attributesList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.DELETE_CUSTOM_ATTRIBUTE, attributesList[0].id],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, attributesList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.SET_CUSTOM_ATTRIBUTE_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
export default [
|
||||
{
|
||||
attribute_display_name: 'Language',
|
||||
attribute_display_type: 1,
|
||||
attribute_description: 'The conversation language',
|
||||
attribute_key: 'language',
|
||||
attribute_model: 0,
|
||||
},
|
||||
{
|
||||
attribute_display_name: 'Language one',
|
||||
attribute_display_type: 2,
|
||||
attribute_description: 'The conversation language one',
|
||||
attribute_key: 'language_one',
|
||||
attribute_model: 1,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,50 @@
|
||||
import { getters } from '../../attributes';
|
||||
import attributesList from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAttributes', () => {
|
||||
const state = { records: attributesList };
|
||||
expect(getters.getAttributes(state)).toEqual([
|
||||
{
|
||||
attribute_display_name: 'Language',
|
||||
attribute_display_type: 1,
|
||||
attribute_description: 'The conversation language',
|
||||
attribute_key: 'language',
|
||||
attribute_model: 0,
|
||||
},
|
||||
{
|
||||
attribute_display_name: 'Language one',
|
||||
attribute_display_type: 2,
|
||||
attribute_description: 'The conversation language one',
|
||||
attribute_key: 'language_one',
|
||||
attribute_model: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getAttributesByModel', () => {
|
||||
const state = { records: attributesList };
|
||||
expect(getters.getAttributesByModel(state)(1)).toEqual([
|
||||
{
|
||||
attribute_display_name: 'Language one',
|
||||
attribute_display_type: 2,
|
||||
attribute_description: 'The conversation language one',
|
||||
attribute_key: 'language_one',
|
||||
attribute_model: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../attributes';
|
||||
import attributesList from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CUSTOM_ATTRIBUTE', () => {
|
||||
it('set attribute records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_CUSTOM_ATTRIBUTE](state, attributesList);
|
||||
expect(state.records).toEqual(attributesList);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CUSTOM_ATTRIBUTE', () => {
|
||||
it('push newly created attributes to the store', () => {
|
||||
const state = { records: [attributesList[0]] };
|
||||
mutations[types.ADD_CUSTOM_ATTRIBUTE](state, attributesList[1]);
|
||||
expect(state.records).toEqual([attributesList[0], attributesList[1]]);
|
||||
});
|
||||
});
|
||||
describe('#EDIT_CUSTOM_ATTRIBUTE', () => {
|
||||
it('update attribute record', () => {
|
||||
const state = { records: [attributesList[0]] };
|
||||
mutations[types.EDIT_CUSTOM_ATTRIBUTE](state, {
|
||||
attribute_display_name: 'Language',
|
||||
attribute_display_type: 0,
|
||||
attribute_description: 'The conversation language',
|
||||
attribute_key: 'language',
|
||||
attribute_model: 0,
|
||||
});
|
||||
expect(state.records[0].attribute_description).toEqual(
|
||||
'The conversation language'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_CUSTOM_ATTRIBUTE', () => {
|
||||
it('delete attribute record', () => {
|
||||
const state = { records: [attributesList[0]] };
|
||||
mutations[types.DELETE_CUSTOM_ATTRIBUTE](state, attributesList[0]);
|
||||
expect(state.records).toEqual([attributesList[0]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,247 @@
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
import { actions } from '../../auth';
|
||||
import types from '../../../mutation-types';
|
||||
import * as APIHelpers from '../../../utils/api';
|
||||
import '../../../../routes';
|
||||
|
||||
vi.spyOn(APIHelpers, 'setUser');
|
||||
vi.spyOn(APIHelpers, 'clearCookiesOnLogout');
|
||||
vi.spyOn(APIHelpers, 'getHeaderExpiry');
|
||||
vi.spyOn(Cookies, 'get');
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#validityCheck', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { data: { id: 1, name: 'John' } } },
|
||||
headers: { expiry: 581842904 },
|
||||
});
|
||||
await actions.validityCheck({ commit });
|
||||
expect(APIHelpers.setUser).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER, { id: 1, name: 'John' }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({
|
||||
response: { status: 401 },
|
||||
});
|
||||
await actions.validityCheck({ commit });
|
||||
expect(APIHelpers.clearCookiesOnLogout);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateProfile', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.put.mockResolvedValue({
|
||||
data: { id: 1, name: 'John' },
|
||||
headers: { expiry: 581842904 },
|
||||
});
|
||||
await actions.updateProfile({ commit }, { name: 'Pranav' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER, { id: 1, name: 'John' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateAvailability', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: {
|
||||
id: 1,
|
||||
name: 'John',
|
||||
accounts: [{ account_id: 1, availability_status: 'offline' }],
|
||||
},
|
||||
headers: { expiry: 581842904 },
|
||||
});
|
||||
await actions.updateAvailability(
|
||||
{ commit, dispatch, getters: { getCurrentUserAvailability: 'online' } },
|
||||
{ availability: 'offline', account_id: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER_AVAILABILITY, 'offline'],
|
||||
[
|
||||
types.SET_CURRENT_USER,
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
accounts: [{ account_id: 1, availability_status: 'offline' }],
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[
|
||||
'agents/updateSingleAgentPresence',
|
||||
{ availabilityStatus: 'offline', id: 1 },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is a failure', async () => {
|
||||
axios.post.mockRejectedValue({ error: 'Authentication Failure' });
|
||||
await actions.updateAvailability(
|
||||
{ commit, dispatch, getters: { getCurrentUserAvailability: 'online' } },
|
||||
{ availability: 'offline', account_id: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER_AVAILABILITY, 'offline'],
|
||||
[types.SET_CURRENT_USER_AVAILABILITY, 'online'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateAutoOffline', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: {
|
||||
id: 1,
|
||||
name: 'John',
|
||||
accounts: [
|
||||
{
|
||||
account_id: 1,
|
||||
auto_offline: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
headers: { expiry: 581842904 },
|
||||
});
|
||||
await actions.updateAutoOffline(
|
||||
{ commit, dispatch, getters: { getCurrentUserAutoOffline: true } },
|
||||
{ autoOffline: false, accountId: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER_AUTO_OFFLINE, false],
|
||||
[
|
||||
types.SET_CURRENT_USER,
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
accounts: [{ account_id: 1, auto_offline: false }],
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is failure', async () => {
|
||||
axios.post.mockRejectedValue({ error: 'Authentication Failure' });
|
||||
await actions.updateAutoOffline(
|
||||
{ commit, dispatch, getters: { getCurrentUserAutoOffline: true } },
|
||||
{ autoOffline: false, accountId: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER_AUTO_OFFLINE, false],
|
||||
[types.SET_CURRENT_USER_AUTO_OFFLINE, true],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateUISettings', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.put.mockResolvedValue({
|
||||
data: {
|
||||
id: 1,
|
||||
name: 'John',
|
||||
availability_status: 'offline',
|
||||
ui_settings: { is_contact_sidebar_open: true },
|
||||
},
|
||||
headers: { expiry: 581842904 },
|
||||
});
|
||||
await actions.updateUISettings(
|
||||
{ commit, dispatch },
|
||||
{ uiSettings: { is_contact_sidebar_open: false } }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_CURRENT_USER_UI_SETTINGS,
|
||||
{ uiSettings: { is_contact_sidebar_open: false } },
|
||||
],
|
||||
[
|
||||
types.SET_CURRENT_USER,
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
availability_status: 'offline',
|
||||
ui_settings: { is_contact_sidebar_open: true },
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setUser', () => {
|
||||
it('sends correct actions if user is logged in', async () => {
|
||||
Cookies.get.mockImplementation(() => true);
|
||||
actions.setUser({ commit, dispatch });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([['validityCheck']]);
|
||||
});
|
||||
|
||||
it('sends correct actions if user is not logged in', async () => {
|
||||
Cookies.get.mockImplementation(() => false);
|
||||
actions.setUser({ commit, dispatch });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.CLEAR_USER],
|
||||
[types.SET_CURRENT_USER_UI_FLAGS, { isFetching: false }],
|
||||
]);
|
||||
expect(dispatch).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setCurrentUserAvailability', () => {
|
||||
it('sends correct mutations if user id is available', async () => {
|
||||
actions.setCurrentUserAvailability(
|
||||
{
|
||||
commit,
|
||||
state: { currentUser: { id: 1 } },
|
||||
},
|
||||
{ 1: 'online' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER_AVAILABILITY, 'online'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not send correct mutations if user id is not available', async () => {
|
||||
actions.setCurrentUserAvailability(
|
||||
{
|
||||
commit,
|
||||
state: { currentUser: { id: 1 } },
|
||||
},
|
||||
{}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setActiveAccount', () => {
|
||||
it('sends correct mutations if account id is available', async () => {
|
||||
actions.setActiveAccount(
|
||||
{
|
||||
commit,
|
||||
},
|
||||
{ accountId: 1 }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#resetAccessToken', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const mockResponse = {
|
||||
data: { id: 1, name: 'John', access_token: 'new_token_123' },
|
||||
headers: { expiry: 581842904 },
|
||||
};
|
||||
axios.post.mockResolvedValue(mockResponse);
|
||||
const result = await actions.resetAccessToken({ commit });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_USER, mockResponse.data],
|
||||
]);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,160 @@
|
||||
import { getters } from '../../auth';
|
||||
|
||||
describe('#getters', () => {
|
||||
describe('#isLoggedIn', () => {
|
||||
it('return correct value if user data is available', () => {
|
||||
expect(getters.isLoggedIn({ currentUser: { id: null } })).toEqual(false);
|
||||
expect(getters.isLoggedIn({ currentUser: { id: 1 } })).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentUser', () => {
|
||||
it('returns current user id', () => {
|
||||
expect(getters.getCurrentUserID({ currentUser: { id: 1 } })).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentUser', () => {
|
||||
it('returns current user object', () => {
|
||||
expect(
|
||||
getters.getCurrentUser({ currentUser: { id: 1, name: 'Pranav' } })
|
||||
).toEqual({ id: 1, name: 'Pranav' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentRole', () => {
|
||||
it('returns current role if account is available', () => {
|
||||
expect(
|
||||
getters.getCurrentRole(
|
||||
{ currentUser: { accounts: [{ id: 1, role: 'admin' }] } },
|
||||
{ getCurrentAccountId: 1 }
|
||||
)
|
||||
).toEqual('admin');
|
||||
});
|
||||
|
||||
it('returns undefined if account is not available', () => {
|
||||
expect(
|
||||
getters.getCurrentRole(
|
||||
{ currentUser: { accounts: [{ id: 1, role: 'admin' }] } },
|
||||
{ getCurrentAccountId: 2 }
|
||||
)
|
||||
).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentCustomRoleId', () => {
|
||||
it('returns current custom role id', () => {
|
||||
expect(
|
||||
getters.getCurrentCustomRoleId(
|
||||
{ currentUser: { accounts: [{ id: 1, custom_role_id: 1 }] } },
|
||||
{ getCurrentAccountId: 1 }
|
||||
)
|
||||
).toEqual(1);
|
||||
});
|
||||
|
||||
it('returns undefined if account is not available', () => {
|
||||
expect(
|
||||
getters.getCurrentCustomRoleId(
|
||||
{ currentUser: { accounts: [{ id: 1, custom_role_id: 1 }] } },
|
||||
{ getCurrentAccountId: 2 }
|
||||
)
|
||||
).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentUserAvailability', () => {
|
||||
it('returns correct availability status', () => {
|
||||
expect(
|
||||
getters.getCurrentUserAvailability(
|
||||
{
|
||||
currentAccountId: 1,
|
||||
currentUser: {
|
||||
id: 1,
|
||||
accounts: [{ id: 1, availability: 'busy' }],
|
||||
},
|
||||
},
|
||||
{ getCurrentAccountId: 1 }
|
||||
)
|
||||
).toEqual('busy');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUISettings', () => {
|
||||
it('return correct UI Settings', () => {
|
||||
expect(
|
||||
getters.getUISettings({
|
||||
currentUser: { ui_settings: { is_contact_sidebar_open: true } },
|
||||
})
|
||||
).toEqual({ is_contact_sidebar_open: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getMessageSignature', () => {
|
||||
it('Return signature when signature is present', () => {
|
||||
expect(
|
||||
getters.getMessageSignature({
|
||||
currentUser: { message_signature: 'Thanks' },
|
||||
})
|
||||
).toEqual('Thanks');
|
||||
});
|
||||
it('Return empty string when signature is not present', () => {
|
||||
expect(getters.getMessageSignature({ currentUser: {} })).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrentAccount', () => {
|
||||
it('returns correct values', () => {
|
||||
expect(
|
||||
getters.getCurrentAccount({
|
||||
currentUser: {},
|
||||
})
|
||||
).toEqual({});
|
||||
expect(
|
||||
getters.getCurrentAccount(
|
||||
{
|
||||
currentUser: {
|
||||
accounts: [
|
||||
{
|
||||
name: 'Chatwoot',
|
||||
id: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
currentAccountId: 1,
|
||||
},
|
||||
{ getCurrentAccountId: 1 }
|
||||
)
|
||||
).toEqual({
|
||||
name: 'Chatwoot',
|
||||
id: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUserAccounts', () => {
|
||||
it('returns correct values', () => {
|
||||
expect(
|
||||
getters.getUserAccounts({
|
||||
currentUser: {},
|
||||
})
|
||||
).toEqual([]);
|
||||
expect(
|
||||
getters.getUserAccounts({
|
||||
currentUser: {
|
||||
accounts: [
|
||||
{
|
||||
name: 'Chatwoot',
|
||||
id: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
name: 'Chatwoot',
|
||||
id: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../auth';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CURRENT_USER_UI_SETTINGS', () => {
|
||||
it('set ui flags', () => {
|
||||
const state = {
|
||||
currentUser: {
|
||||
ui_settings: { is_contact_sidebar_open: true, icon_type: 'emoji' },
|
||||
},
|
||||
};
|
||||
mutations[types.SET_CURRENT_USER_UI_SETTINGS](state, {
|
||||
uiSettings: { is_contact_sidebar_open: false },
|
||||
});
|
||||
expect(state.currentUser.ui_settings).toEqual({
|
||||
is_contact_sidebar_open: false,
|
||||
icon_type: 'emoji',
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#SET_CURRENT_USER_UI_FLAGS', () => {
|
||||
it('set auth ui flags', () => {
|
||||
const state = {
|
||||
uiFlags: { isFetching: false },
|
||||
};
|
||||
mutations[types.SET_CURRENT_USER_UI_FLAGS](state, { isFetching: true });
|
||||
expect(state.uiFlags.isFetching).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#CLEAR_USER', () => {
|
||||
it('set auth ui flags', () => {
|
||||
const state = {
|
||||
currentUser: { id: 1 },
|
||||
};
|
||||
mutations[types.CLEAR_USER](state);
|
||||
expect(state.currentUser).toEqual({
|
||||
id: null,
|
||||
account_id: null,
|
||||
accounts: [],
|
||||
email: null,
|
||||
name: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#SET_CURRENT_USER_AVAILABILITY', () => {
|
||||
const state = {
|
||||
currentUser: {
|
||||
id: 1,
|
||||
accounts: [{ id: 1, availability_status: 'offline' }],
|
||||
account_id: 1,
|
||||
},
|
||||
};
|
||||
it('set availability status for current user', () => {
|
||||
mutations[types.SET_CURRENT_USER_AVAILABILITY](state, 'online');
|
||||
expect(state.currentUser.accounts[0].availability_status).toEqual(
|
||||
'online'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,107 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../automations';
|
||||
import * as types from '../../../mutation-types';
|
||||
import automationsList from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { payload: automationsList } });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_AUTOMATIONS, automationsList],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: automationsList[0] });
|
||||
await actions.create({ commit }, automationsList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCreating: true }],
|
||||
[types.default.ADD_AUTOMATION, automationsList[0]],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({
|
||||
data: { payload: automationsList[0] },
|
||||
});
|
||||
await actions.update({ commit }, automationsList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.EDIT_AUTOMATION, automationsList[0]],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, automationsList[0])
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: automationsList[0] });
|
||||
await actions.delete({ commit }, automationsList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.DELETE_AUTOMATION, automationsList[0].id],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, automationsList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clone', () => {
|
||||
it('clones the automation', async () => {
|
||||
axios.post.mockResolvedValue({ data: automationsList[0] });
|
||||
await actions.clone({ commit }, automationsList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCloning: true }],
|
||||
[types.default.SET_AUTOMATION_UI_FLAG, { isCloning: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
export default [
|
||||
{
|
||||
name: 'Test 5',
|
||||
description: 'Hello',
|
||||
id: 46,
|
||||
account_id: 1,
|
||||
event_name: 'conversation_created',
|
||||
conditions: [
|
||||
{
|
||||
values: ['open'],
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
},
|
||||
],
|
||||
actions: [{ action_name: 'add_label', action_params: ['testlabel'] }],
|
||||
created_on: '2022-02-08T10:46:32.387Z',
|
||||
active: true,
|
||||
},
|
||||
{
|
||||
id: 47,
|
||||
account_id: 1,
|
||||
name: 'Snooze',
|
||||
description: 'Test Description',
|
||||
event_name: 'conversation_created',
|
||||
conditions: [
|
||||
{
|
||||
values: ['pending'],
|
||||
attribute_key: 'status',
|
||||
filter_operator: 'equal_to',
|
||||
},
|
||||
],
|
||||
actions: [{ action_name: 'assign_team', action_params: [1] }],
|
||||
created_on: '2022-02-08T11:19:44.714Z',
|
||||
active: true,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,25 @@
|
||||
import { getters } from '../../automations';
|
||||
import automations from './fixtures';
|
||||
describe('#getters', () => {
|
||||
it('getAutomations', () => {
|
||||
const state = { records: automations };
|
||||
expect(getters.getAutomations(state)).toEqual(automations);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isUpdating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../automations';
|
||||
import automations from './fixtures';
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_automations', () => {
|
||||
it('set autonmation records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_AUTOMATIONS](state, automations);
|
||||
expect(state.records).toEqual(automations);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_AUTOMATION', () => {
|
||||
it('push newly created automatuion to the store', () => {
|
||||
const state = { records: [automations[0]] };
|
||||
mutations[types.ADD_AUTOMATION](state, automations[1]);
|
||||
expect(state.records).toEqual([automations[0], automations[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_AUTOMATION', () => {
|
||||
it('update automation record', () => {
|
||||
const state = { records: [automations[0]] };
|
||||
mutations[types.EDIT_AUTOMATION](state, automations[0]);
|
||||
expect(state.records[0].name).toEqual('Test 5');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_AUTOMATION', () => {
|
||||
it('delete automation record', () => {
|
||||
const state = { records: [automations[0]] };
|
||||
mutations[types.DELETE_AUTOMATION](state, 46);
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../bulkActions';
|
||||
import * as types from '../../../mutation-types';
|
||||
import payload from './fixtures';
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: payload });
|
||||
await actions.process({ commit }, payload);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_BULK_ACTIONS_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_BULK_ACTIONS_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.process({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_BULK_ACTIONS_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_BULK_ACTIONS_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#setSelectedConversationIds', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
await actions.setSelectedConversationIds({ commit }, payload.ids);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_SELECTED_CONVERSATION_IDS, payload.ids],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#removeSelectedConversationIds', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
await actions.removeSelectedConversationIds({ commit }, payload.ids);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.REMOVE_SELECTED_CONVERSATION_IDS, payload.ids],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#clearSelectedConversationIds', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
await actions.clearSelectedConversationIds({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.CLEAR_SELECTED_CONVERSATION_IDS],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
type: 'Conversation',
|
||||
ids: [64, 39],
|
||||
fields: { assignee_id: 6 },
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { getters } from '../../bulkActions';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
it('getSelectedConversationIds', () => {
|
||||
const state = {
|
||||
selectedConversationIds: [1, 2, 3],
|
||||
};
|
||||
expect(getters.getSelectedConversationIds(state)).toEqual([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../bulkActions';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#toggleUiFlag', () => {
|
||||
it('set update flags', () => {
|
||||
const state = { uiFlags: { isUpdating: false } };
|
||||
mutations[types.SET_BULK_ACTIONS_FLAG](state, { isUpdating: true });
|
||||
expect(state.uiFlags.isUpdating).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#setSelectedConversationIds', () => {
|
||||
it('set selected conversation ids', () => {
|
||||
const state = { selectedConversationIds: [] };
|
||||
mutations[types.SET_SELECTED_CONVERSATION_IDS](state, [1, 2, 3]);
|
||||
expect(state.selectedConversationIds).toEqual([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
describe('#removeSelectedConversationIds', () => {
|
||||
it('remove selected conversation ids', () => {
|
||||
const state = { selectedConversationIds: [1, 2, 3] };
|
||||
mutations[types.REMOVE_SELECTED_CONVERSATION_IDS](state, 1);
|
||||
expect(state.selectedConversationIds).toEqual([2, 3]);
|
||||
});
|
||||
});
|
||||
describe('#clearSelectedConversationIds', () => {
|
||||
it('clear selected conversation ids', () => {
|
||||
const state = { selectedConversationIds: [1, 2, 3] };
|
||||
mutations[types.CLEAR_SELECTED_CONVERSATION_IDS](state);
|
||||
expect(state.selectedConversationIds).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../campaigns';
|
||||
import * as types from '../../../mutation-types';
|
||||
import campaignList from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: campaignList });
|
||||
await actions.get({ commit }, { inboxId: 23 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CAMPAIGNS, campaignList],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit }, { inboxId: 23 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: campaignList[0] });
|
||||
await actions.create({ commit }, campaignList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isCreating: true }],
|
||||
[types.default.ADD_CAMPAIGN, campaignList[0]],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: campaignList[0] });
|
||||
await actions.update({ commit }, campaignList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.EDIT_CAMPAIGN, campaignList[0]],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, campaignList[0])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isUpdating: true }],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: campaignList[0] });
|
||||
await actions.delete({ commit }, campaignList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.DELETE_CAMPAIGN, campaignList[0].id],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, campaignList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.SET_CAMPAIGN_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,100 @@
|
||||
export default [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Welcome',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
campaign_type: 'ongoing',
|
||||
message: 'Hey, What brings you today',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://github.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
inbox: {
|
||||
id: 1,
|
||||
channel_type: 'Channel::WebWidget',
|
||||
name: 'Web Widget',
|
||||
},
|
||||
created_at: '2021-05-03T04:53:36.354Z',
|
||||
updated_at: '2021-05-03T04:53:36.354Z',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Onboarding Campaign',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
campaign_type: 'one_off',
|
||||
trigger_rules: {
|
||||
url: 'https://chatwoot.com',
|
||||
time_on_page: '20',
|
||||
},
|
||||
inbox: {
|
||||
id: 2,
|
||||
channel_type: 'Channel::TwilioSms',
|
||||
name: 'Twilio SMS',
|
||||
},
|
||||
created_at: '2021-05-03T08:15:35.828Z',
|
||||
updated_at: '2021-05-03T08:15:35.828Z',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Thanks',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
campaign_type: 'ongoing',
|
||||
message: 'Thanks for coming to the show. How may I help you?',
|
||||
enabled: false,
|
||||
trigger_rules: {
|
||||
url: 'https://noshow.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
inbox: {
|
||||
id: 3,
|
||||
channel_type: 'Channel::WebWidget',
|
||||
name: 'Web Widget 2',
|
||||
},
|
||||
created_at: '2021-05-03T10:22:51.025Z',
|
||||
updated_at: '2021-05-03T10:22:51.025Z',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: 'WhatsApp Campaign',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
campaign_type: 'one_off',
|
||||
message: 'Hello {{name}}, your order is ready!',
|
||||
enabled: true,
|
||||
trigger_rules: {},
|
||||
inbox: {
|
||||
id: 4,
|
||||
channel_type: 'Channel::Whatsapp',
|
||||
name: 'WhatsApp Business',
|
||||
},
|
||||
template_params: {
|
||||
name: 'order_ready',
|
||||
namespace: 'business_namespace',
|
||||
language: 'en_US',
|
||||
processed_params: { name: 'John' },
|
||||
},
|
||||
created_at: '2021-05-03T12:15:35.828Z',
|
||||
updated_at: '2021-05-03T12:15:35.828Z',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: 'SMS Promotion',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
campaign_type: 'one_off',
|
||||
message: 'Get 20% off your next order!',
|
||||
enabled: true,
|
||||
trigger_rules: {},
|
||||
inbox: {
|
||||
id: 5,
|
||||
channel_type: 'Channel::Sms',
|
||||
name: 'SMS Channel',
|
||||
},
|
||||
created_at: '2021-05-03T14:15:35.828Z',
|
||||
updated_at: '2021-05-03T14:15:35.828Z',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,88 @@
|
||||
import { getters } from '../../campaigns';
|
||||
import campaigns from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('get ongoing campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
expect(getters.getCampaigns(state)('ongoing')).toEqual([
|
||||
campaigns[0],
|
||||
campaigns[2],
|
||||
]);
|
||||
});
|
||||
|
||||
it('get one_off campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
expect(getters.getCampaigns(state)('one_off')).toEqual([
|
||||
campaigns[1],
|
||||
campaigns[3],
|
||||
campaigns[4],
|
||||
]);
|
||||
});
|
||||
|
||||
it('get campaigns by channel type', () => {
|
||||
const state = { records: campaigns };
|
||||
expect(
|
||||
getters.getCampaigns(state)('one_off', ['Channel::Whatsapp'])
|
||||
).toEqual([campaigns[3]]);
|
||||
});
|
||||
|
||||
it('get campaigns by multiple channel types', () => {
|
||||
const state = { records: campaigns };
|
||||
expect(
|
||||
getters.getCampaigns(state)('one_off', [
|
||||
'Channel::TwilioSms',
|
||||
'Channel::Sms',
|
||||
])
|
||||
).toEqual([campaigns[1], campaigns[4]]);
|
||||
});
|
||||
|
||||
it('get SMS campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
const mockGetters = {
|
||||
getCampaigns: getters.getCampaigns(state),
|
||||
};
|
||||
expect(getters.getSMSCampaigns(state, mockGetters)).toEqual([
|
||||
campaigns[1],
|
||||
campaigns[4],
|
||||
]);
|
||||
});
|
||||
|
||||
it('get WhatsApp campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
const mockGetters = {
|
||||
getCampaigns: getters.getCampaigns(state),
|
||||
};
|
||||
expect(getters.getWhatsAppCampaigns(state, mockGetters)).toEqual([
|
||||
campaigns[3],
|
||||
]);
|
||||
});
|
||||
|
||||
it('get Live Chat campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
const mockGetters = {
|
||||
getCampaigns: getters.getCampaigns(state),
|
||||
};
|
||||
expect(getters.getLiveChatCampaigns(state, mockGetters)).toEqual([
|
||||
campaigns[0],
|
||||
campaigns[2],
|
||||
]);
|
||||
});
|
||||
|
||||
it('get all campaigns', () => {
|
||||
const state = { records: campaigns };
|
||||
expect(getters.getAllCampaigns(state)).toEqual(campaigns);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../campaigns';
|
||||
import campaigns from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CAMPAIGNS', () => {
|
||||
it('set campaigns records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_CAMPAIGNS](state, campaigns);
|
||||
expect(state.records).toEqual(campaigns);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CAMPAIGN', () => {
|
||||
it('push newly created campaigns to the store', () => {
|
||||
const state = { records: [campaigns[0]] };
|
||||
mutations[types.ADD_CAMPAIGN](state, campaigns[1]);
|
||||
expect(state.records).toEqual([campaigns[0], campaigns[1]]);
|
||||
});
|
||||
});
|
||||
describe('#EDIT_CAMPAIGN', () => {
|
||||
it('update campaign record', () => {
|
||||
const state = { records: [campaigns[0]] };
|
||||
mutations[types.EDIT_CAMPAIGN](state, {
|
||||
id: 1,
|
||||
title: 'Welcome',
|
||||
account_id: 1,
|
||||
message: 'Hey, What brings you today',
|
||||
});
|
||||
expect(state.records[0].message).toEqual('Hey, What brings you today');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_LABEL', () => {
|
||||
it('delete campaign record', () => {
|
||||
const state = { records: [campaigns[0]] };
|
||||
mutations[types.DELETE_CAMPAIGN](state, 1);
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import CannedResponses from '../../cannedResponse';
|
||||
|
||||
const CANNED_RESPONSES = [
|
||||
{ short_code: 'hello', content: 'Hi ' },
|
||||
{ short_code: 'ask', content: 'Ask questions' },
|
||||
{ short_code: 'greet', content: 'Good morning' },
|
||||
];
|
||||
|
||||
const getters = CannedResponses.getters;
|
||||
|
||||
describe('#getCannedResponses', () => {
|
||||
it('returns canned responses', () => {
|
||||
const state = { records: CANNED_RESPONSES };
|
||||
expect(getters.getCannedResponses(state)).toEqual(CANNED_RESPONSES);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getSortedCannedResponses', () => {
|
||||
it('returns sort canned responses in ascending order', () => {
|
||||
const state = { records: CANNED_RESPONSES };
|
||||
expect(getters.getSortedCannedResponses(state)('asc')).toEqual([
|
||||
CANNED_RESPONSES[1],
|
||||
CANNED_RESPONSES[2],
|
||||
CANNED_RESPONSES[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('returns sort canned responses in descending order', () => {
|
||||
const state = { records: CANNED_RESPONSES };
|
||||
expect(getters.getSortedCannedResponses(state)('desc')).toEqual([
|
||||
CANNED_RESPONSES[0],
|
||||
CANNED_RESPONSES[2],
|
||||
CANNED_RESPONSES[1],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getUIFlags', () => {
|
||||
it('returns uiFlags', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
expect(getters.getUIFlags(state)).toEqual({ isFetching: true });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,307 @@
|
||||
import axios from 'axios';
|
||||
import {
|
||||
actions,
|
||||
createMessagePayload,
|
||||
createConversationPayload,
|
||||
createWhatsAppConversationPayload,
|
||||
} from '../../contactConversations';
|
||||
import * as types from '../../../mutation-types';
|
||||
import conversationList from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { payload: conversationList } });
|
||||
await actions.get({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isFetching: true }],
|
||||
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS,
|
||||
{ id: 1, data: conversationList },
|
||||
],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isFetching: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isFetching: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: conversationList[0] });
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{
|
||||
params: {
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
assigneeId: 6,
|
||||
files: [],
|
||||
},
|
||||
isFromWhatsApp: false,
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.ADD_CONTACT_CONVERSATION,
|
||||
{ id: 4, data: conversationList[0] },
|
||||
],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isCreating: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions with files if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: conversationList[0] });
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{
|
||||
params: {
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
assigneeId: 6,
|
||||
files: ['file1.pdf', 'file2.jpg'],
|
||||
},
|
||||
isFromWhatsApp: false,
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.ADD_CONTACT_CONVERSATION,
|
||||
{ id: 4, data: conversationList[0] },
|
||||
],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isCreating: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions actions if API is success for whatsapp conversation', async () => {
|
||||
axios.post.mockResolvedValue({ data: conversationList[0] });
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{
|
||||
params: {
|
||||
inboxId: 1,
|
||||
message: {
|
||||
content: 'hi',
|
||||
template_params: {
|
||||
name: 'hello_world',
|
||||
category: 'MARKETING',
|
||||
language: 'en_US',
|
||||
processed_params: {},
|
||||
},
|
||||
},
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
assigneeId: 6,
|
||||
},
|
||||
isFromWhatsApp: true,
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.ADD_CONTACT_CONVERSATION,
|
||||
{ id: 4, data: conversationList[0] },
|
||||
],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isCreating: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.create(
|
||||
{ commit },
|
||||
{
|
||||
params: {
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
assigneeId: 6,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
},
|
||||
isFromWhatsApp: false,
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isCreating: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions with files if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.create(
|
||||
{ commit },
|
||||
{
|
||||
params: {
|
||||
inboxId: 1,
|
||||
message: { content: 'hi' },
|
||||
contactId: 4,
|
||||
sourceId: 5,
|
||||
mailSubject: 'Mail Subject',
|
||||
assigneeId: 6,
|
||||
files: ['file1.pdf', 'file2.jpg'],
|
||||
},
|
||||
isFromWhatsApp: false,
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG,
|
||||
{ isCreating: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createMessagePayload', () => {
|
||||
it('creates message payload with cc and bcc emails', () => {
|
||||
const payload = new FormData();
|
||||
const message = {
|
||||
content: 'Test message content',
|
||||
cc_emails: 'cc@example.com',
|
||||
bcc_emails: 'bcc@example.com',
|
||||
};
|
||||
|
||||
createMessagePayload(payload, message);
|
||||
|
||||
expect(payload.get('message[content]')).toBe(message.content);
|
||||
expect(payload.get('message[cc_emails]')).toBe(message.cc_emails);
|
||||
expect(payload.get('message[bcc_emails]')).toBe(message.bcc_emails);
|
||||
});
|
||||
|
||||
it('creates message payload without cc and bcc emails', () => {
|
||||
const payload = new FormData();
|
||||
const message = {
|
||||
content: 'Test message content',
|
||||
};
|
||||
|
||||
createMessagePayload(payload, message);
|
||||
|
||||
expect(payload.get('message[content]')).toBe(message.content);
|
||||
expect(payload.get('message[cc_emails]')).toBeNull();
|
||||
expect(payload.get('message[bcc_emails]')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createConversationPayload', () => {
|
||||
it('creates conversation payload with message and attachments', () => {
|
||||
const options = {
|
||||
params: {
|
||||
inboxId: '1',
|
||||
message: {
|
||||
content: 'Test message content',
|
||||
},
|
||||
sourceId: '12',
|
||||
mailSubject: 'Test Subject',
|
||||
assigneeId: '123',
|
||||
},
|
||||
contactId: '23',
|
||||
files: ['file1.pdf', 'file2.jpg'],
|
||||
};
|
||||
|
||||
const payload = createConversationPayload(options);
|
||||
|
||||
expect(payload.get('message[content]')).toBe(
|
||||
options.params.message.content
|
||||
);
|
||||
expect(payload.get('inbox_id')).toBe(options.params.inboxId);
|
||||
expect(payload.get('contact_id')).toBe(options.contactId);
|
||||
expect(payload.get('source_id')).toBe(options.params.sourceId);
|
||||
expect(payload.get('additional_attributes[mail_subject]')).toBe(
|
||||
options.params.mailSubject
|
||||
);
|
||||
expect(payload.get('assignee_id')).toBe(options.params.assigneeId);
|
||||
expect(payload.getAll('message[attachments][]')).toEqual(options.files);
|
||||
});
|
||||
|
||||
it('creates conversation payload with message and without attachments', () => {
|
||||
const options = {
|
||||
params: {
|
||||
inboxId: '1',
|
||||
message: {
|
||||
content: 'Test message content',
|
||||
},
|
||||
sourceId: '12',
|
||||
mailSubject: 'Test Subject',
|
||||
assigneeId: '123',
|
||||
},
|
||||
contactId: '23',
|
||||
};
|
||||
|
||||
const payload = createConversationPayload(options);
|
||||
|
||||
expect(payload.get('message[content]')).toBe(
|
||||
options.params.message.content
|
||||
);
|
||||
expect(payload.get('inbox_id')).toBe(options.params.inboxId);
|
||||
expect(payload.get('contact_id')).toBe(options.contactId);
|
||||
expect(payload.get('source_id')).toBe(options.params.sourceId);
|
||||
expect(payload.get('additional_attributes[mail_subject]')).toBe(
|
||||
options.params.mailSubject
|
||||
);
|
||||
expect(payload.get('assignee_id')).toBe(options.params.assigneeId);
|
||||
expect(payload.getAll('message[attachments][]')).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createWhatsAppConversationPayload', () => {
|
||||
it('creates conversation payload with message', () => {
|
||||
const options = {
|
||||
params: {
|
||||
inboxId: '1',
|
||||
message: {
|
||||
content: 'Test message content',
|
||||
},
|
||||
sourceId: '12',
|
||||
assigneeId: '123',
|
||||
},
|
||||
};
|
||||
|
||||
const payload = createWhatsAppConversationPayload(options);
|
||||
|
||||
expect(payload.message).toBe(options.params.message);
|
||||
expect(payload.inbox_id).toBe(options.params.inboxId);
|
||||
expect(payload.source_id).toBe(options.params.sourceId);
|
||||
expect(payload.assignee_id).toBe(options.params.assigneeId);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
export default [
|
||||
{
|
||||
meta: {
|
||||
sender: {
|
||||
id: 1,
|
||||
name: 'sender1',
|
||||
thumbnail: '',
|
||||
channel: 'Channel::WebWidget',
|
||||
},
|
||||
assignee: null,
|
||||
},
|
||||
id: 1,
|
||||
messages: [
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hello',
|
||||
account_id: 1,
|
||||
inbox_id: 1,
|
||||
conversation_id: 1,
|
||||
message_type: 1,
|
||||
created_at: 1578555084,
|
||||
updated_at: '2020-01-09T07:31:24.419Z',
|
||||
private: false,
|
||||
user_id: 1,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender: {
|
||||
name: 'Sender 1',
|
||||
avatar_url: 'random_url',
|
||||
},
|
||||
},
|
||||
],
|
||||
inbox_id: 1,
|
||||
status: 0,
|
||||
timestamp: 1578555084,
|
||||
contact_last_seen_at: 0,
|
||||
agent_last_seen_at: 1578555084,
|
||||
unread_count: 0,
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
sender: {
|
||||
id: 2,
|
||||
name: 'sender1',
|
||||
thumbnail: '',
|
||||
channel: 'Channel::WebWidget',
|
||||
},
|
||||
assignee: null,
|
||||
},
|
||||
id: 2,
|
||||
messages: [
|
||||
{
|
||||
id: 2,
|
||||
content: 'Hello',
|
||||
account_id: 1,
|
||||
inbox_id: 2,
|
||||
conversation_id: 2,
|
||||
message_type: 1,
|
||||
created_at: 1578555084,
|
||||
updated_at: '2020-01-09T07:31:24.419Z',
|
||||
private: false,
|
||||
user_id: 2,
|
||||
status: 'sent',
|
||||
source_id: null,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
sender: {
|
||||
name: 'Sender 1',
|
||||
avatar_url: 'random_url',
|
||||
},
|
||||
},
|
||||
],
|
||||
inbox_id: 2,
|
||||
status: 0,
|
||||
timestamp: 1578555084,
|
||||
contact_last_seen_at: 0,
|
||||
agent_last_seen_at: 1578555084,
|
||||
unread_count: 0,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,23 @@
|
||||
import { getters } from '../../contactConversations';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getContactConversation', () => {
|
||||
const state = {
|
||||
records: { 1: [{ id: 1, contact_id: 1, message: 'Hello' }] },
|
||||
};
|
||||
expect(getters.getContactConversation(state)(1)).toEqual([
|
||||
{ id: 1, contact_id: 1, message: 'Hello' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../contactConversations';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONTACT_CONVERSATIONS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
mutations[types.default.SET_CONTACT_CONVERSATIONS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONTACT_CONVERSATIONS', () => {
|
||||
it('set contact conversation records', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.SET_CONTACT_CONVERSATIONS](state, {
|
||||
id: 1,
|
||||
data: [{ id: 1, contact_id: 1, message: 'hello' }],
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [{ id: 1, contact_id: 1, message: 'hello' }],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CONTACT_CONVERSATION', () => {
|
||||
it('Adds new contact conversation to records', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.ADD_CONTACT_CONVERSATION](state, {
|
||||
id: 1,
|
||||
data: { id: 1, contact_id: 1, message: 'hello' },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [{ id: 1, contact_id: 1, message: 'hello' }],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../contactLabels';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: ['customer-success', 'on-hold'] },
|
||||
});
|
||||
await actions.get({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isFetching: true }],
|
||||
|
||||
[
|
||||
types.default.SET_CONTACT_LABELS,
|
||||
{ id: 1, data: ['customer-success', 'on-hold'] },
|
||||
],
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('updates correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { payload: { contactId: '1', labels: ['on-hold'] } },
|
||||
});
|
||||
await actions.update({ commit }, { contactId: '1', labels: ['on-hold'] });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.default.SET_CONTACT_LABELS,
|
||||
{
|
||||
id: '1',
|
||||
data: { contactId: '1', labels: ['on-hold'] },
|
||||
},
|
||||
],
|
||||
[
|
||||
types.default.SET_CONTACT_LABELS_UI_FLAG,
|
||||
{ isUpdating: false, isError: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, { contactId: '1', labels: ['on-hold'] })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_LABELS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.default.SET_CONTACT_LABELS_UI_FLAG,
|
||||
{ isUpdating: false, isError: true },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { getters } from '../../contactLabels';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getContactLabels', () => {
|
||||
const state = {
|
||||
records: { 1: ['customer-success', 'on-hold'] },
|
||||
};
|
||||
expect(getters.getContactLabels(state)(1)).toEqual([
|
||||
'customer-success',
|
||||
'on-hold',
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../contactLabels';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONTACT_LABELS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
mutations[types.default.SET_CONTACT_LABELS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONTACT_LABELS', () => {
|
||||
it('set contact labels', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.SET_CONTACT_LABELS](state, {
|
||||
id: 1,
|
||||
data: ['customer-success', 'on-hold'],
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: ['customer-success', 'on-hold'],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../contactNotes';
|
||||
import * as types from '../../../mutation-types';
|
||||
import notesData from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: notesData });
|
||||
await actions.get({ commit }, { contactId: 23 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CONTACT_NOTES, { contactId: 23, data: notesData }],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.get({ commit }, { contactId: 23 })).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: { id: 2, content: 'hi' } });
|
||||
await actions.create({ commit }, { contactId: 1, content: 'hi' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.ADD_CONTACT_NOTE,
|
||||
{ contactId: 1, data: { id: 2, content: 'hi' } },
|
||||
],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.create({ commit }, { contactId: 1, content: 'hi' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: notesData[0] });
|
||||
await actions.delete({ commit }, { contactId: 1, noteId: 2 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.DELETE_CONTACT_NOTE, { contactId: 1, noteId: 2 }],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, { contactId: 1, noteId: 2 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.SET_CONTACT_NOTES_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
export default [
|
||||
{
|
||||
id: 12345,
|
||||
content: 'It is a long established fact that a reader will be distracted.',
|
||||
user: {
|
||||
name: 'John Doe',
|
||||
thumbnail: 'https://randomuser.me/api/portraits/men/69.jpg',
|
||||
},
|
||||
created_at: 1618046084,
|
||||
},
|
||||
{
|
||||
id: 12346,
|
||||
content:
|
||||
'It is simply dummy text of the printing and typesetting industry.',
|
||||
user: {
|
||||
name: 'Pearl Cruz',
|
||||
thumbnail: 'https://randomuser.me/api/portraits/women/29.jpg',
|
||||
},
|
||||
created_at: 1616046076,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,24 @@
|
||||
import { getters } from '../../contactNotes';
|
||||
import notesData from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getAllNotesByContact', () => {
|
||||
const state = { records: { 1: notesData } };
|
||||
expect(getters.getAllNotesByContact(state)(1)).toEqual(notesData);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../contactNotes';
|
||||
import allNotes from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONTACT_NOTES', () => {
|
||||
it('set allNotes records', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.SET_CONTACT_NOTES](state, {
|
||||
data: allNotes,
|
||||
contactId: 1,
|
||||
});
|
||||
expect(state.records).toEqual({ 1: allNotes });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CONTACT_NOTE', () => {
|
||||
it('push newly created note to the store', () => {
|
||||
const state = { records: { 1: [allNotes[0]] } };
|
||||
mutations[types.ADD_CONTACT_NOTE](state, {
|
||||
data: allNotes[1],
|
||||
contactId: 1,
|
||||
});
|
||||
expect(state.records[1]).toEqual([allNotes[0], allNotes[1]]);
|
||||
});
|
||||
});
|
||||
describe('#DELETE_CONTACT_NOTE', () => {
|
||||
it('Delete existing note from records', () => {
|
||||
const state = { records: { 1: [{ id: 2 }] } };
|
||||
mutations[types.DELETE_CONTACT_NOTE](state, {
|
||||
noteId: 2,
|
||||
contactId: 1,
|
||||
});
|
||||
expect(state.records[1]).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,441 @@
|
||||
import axios from 'axios';
|
||||
import Contacts from '../../contacts';
|
||||
import types from '../../../mutation-types';
|
||||
import contactList from './fixtures';
|
||||
import {
|
||||
DuplicateContactException,
|
||||
ExceptionWithMessage,
|
||||
} from '../../../../../shared/helpers/CustomErrors';
|
||||
import { filterApiResponse } from './filterApiResponse';
|
||||
|
||||
const { actions } = Contacts;
|
||||
|
||||
const filterQueryData = {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'email',
|
||||
filter_operator: 'contains',
|
||||
values: ['fayaz'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: contactList, meta: { count: 100, current_page: 1 } },
|
||||
});
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: true }],
|
||||
[types.CLEAR_CONTACTS],
|
||||
[types.SET_CONTACTS, contactList],
|
||||
[types.SET_CONTACT_META, { count: 100, current_page: 1 }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#show', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { payload: contactList[0] } });
|
||||
await actions.show({ commit }, { id: contactList[0].id });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_CONTACT_ITEM, contactList[0]],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.show({ commit }, { id: contactList[0].id });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetchingItem: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetchingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#active', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: contactList, meta: { count: 100, current_page: 1 } },
|
||||
});
|
||||
await actions.active({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: true }],
|
||||
[types.CLEAR_CONTACTS],
|
||||
[types.SET_CONTACTS, contactList],
|
||||
[types.SET_CONTACT_META, { count: 100, current_page: 1 }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct mutations if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.active({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: { payload: contactList[0] } });
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{
|
||||
id: contactList[0].id,
|
||||
contactParams: contactList[0],
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_CONTACT, contactList[0]],
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, contactList[0])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if duplicate contact is found', async () => {
|
||||
axios.patch.mockRejectedValue({
|
||||
response: {
|
||||
status: 422,
|
||||
data: {
|
||||
message: 'Incorrect header',
|
||||
attributes: ['email'],
|
||||
},
|
||||
},
|
||||
});
|
||||
await expect(
|
||||
actions.update(
|
||||
{ commit },
|
||||
{
|
||||
id: contactList[0].id,
|
||||
contactParams: contactList[0],
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(DuplicateContactException);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { payload: { contact: contactList[0] } },
|
||||
});
|
||||
await actions.create(
|
||||
{ commit },
|
||||
{
|
||||
contactParams: contactList[0],
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_CONTACT_ITEM, contactList[0]],
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit }, contactList[0])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if email is already present', async () => {
|
||||
axios.post.mockRejectedValue({
|
||||
response: {
|
||||
data: {
|
||||
message: 'Email exists already',
|
||||
},
|
||||
},
|
||||
});
|
||||
await expect(
|
||||
actions.create(
|
||||
{ commit },
|
||||
{
|
||||
contactParams: contactList[0],
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(ExceptionWithMessage);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.delete.mockResolvedValue();
|
||||
await actions.delete({ commit }, contactList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, contactList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setContact', () => {
|
||||
it('returns correct mutations', () => {
|
||||
const data = { id: 1, name: 'john doe', availability_status: 'online' };
|
||||
actions.setContact({ commit }, data);
|
||||
expect(commit.mock.calls).toEqual([[types.SET_CONTACT_ITEM, data]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#merge', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: contactList[0],
|
||||
});
|
||||
await actions.merge({ commit }, { childId: 0, parentId: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isMerging: true }],
|
||||
[types.SET_CONTACT_ITEM, contactList[0]],
|
||||
[types.SET_CONTACT_UI_FLAG, { isMerging: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.merge({ commit }, { childId: 0, parentId: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isMerging: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isMerging: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteContactThroughConversations', () => {
|
||||
it('returns correct mutations', () => {
|
||||
actions.deleteContactThroughConversations({ commit }, contactList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.DELETE_CONTACT, contactList[0].id],
|
||||
[types.CLEAR_CONTACT_CONVERSATIONS, contactList[0].id, { root: true }],
|
||||
[
|
||||
`contactConversations/${types.DELETE_CONTACT_CONVERSATION}`,
|
||||
contactList[0].id,
|
||||
{ root: true },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateContact', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: { payload: contactList[0] } });
|
||||
await actions.updateContact({ commit }, contactList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_CONTACT, contactList[0]],
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, contactList[0])).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#deleteCustomAttributes', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: { payload: contactList[0] } });
|
||||
await actions.deleteCustomAttributes(
|
||||
{ commit },
|
||||
{ id: 1, customAttributes: ['cloud-customer'] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([[types.EDIT_CONTACT, contactList[0]]]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.deleteCustomAttributes(
|
||||
{ commit },
|
||||
{ id: 1, customAttributes: ['cloud-customer'] }
|
||||
)
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fetchFilteredContacts', () => {
|
||||
it('fetches filtered conversations with a mock commit', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: filterApiResponse,
|
||||
});
|
||||
await actions.filter({ commit }, filterQueryData);
|
||||
expect(commit).toHaveBeenCalledTimes(5);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_CONTACT_UI_FLAG', { isFetching: true }],
|
||||
['CLEAR_CONTACTS'],
|
||||
['SET_CONTACTS', filterApiResponse.payload],
|
||||
['SET_CONTACT_META', filterApiResponse.meta],
|
||||
['SET_CONTACT_UI_FLAG', { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setContactsFilter', () => {
|
||||
it('commits the correct mutation and sets filter state', () => {
|
||||
const filters = [
|
||||
{
|
||||
attribute_key: 'email',
|
||||
filter_operator: 'contains',
|
||||
values: ['fayaz'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
actions.setContactFilters({ commit }, filters);
|
||||
expect(commit.mock.calls).toEqual([[types.SET_CONTACT_FILTERS, filters]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearContactFilters', () => {
|
||||
it('commits the correct mutation and clears filter state', () => {
|
||||
actions.clearContactFilters({ commit });
|
||||
expect(commit.mock.calls).toEqual([[types.CLEAR_CONTACT_FILTERS]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteAvatar', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: { payload: contactList[0] } });
|
||||
await actions.deleteAvatar({ commit }, contactList[0].id);
|
||||
expect(commit.mock.calls).toEqual([[types.EDIT_CONTACT, contactList[0]]]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.deleteAvatar({ commit }, contactList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#initiateCall', () => {
|
||||
const contactId = 123;
|
||||
const inboxId = 456;
|
||||
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
conversation_id: 789,
|
||||
status: 'initiated',
|
||||
},
|
||||
};
|
||||
axios.post.mockResolvedValue(mockResponse);
|
||||
|
||||
const result = await actions.initiateCall(
|
||||
{ commit },
|
||||
{ contactId, inboxId }
|
||||
);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: false }],
|
||||
]);
|
||||
expect(result).toEqual(mockResponse.data);
|
||||
});
|
||||
|
||||
it('sends correct actions if API returns error with message', async () => {
|
||||
const errorMessage = 'Failed to initiate call';
|
||||
axios.post.mockRejectedValue({
|
||||
response: {
|
||||
data: {
|
||||
message: errorMessage,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await expect(
|
||||
actions.initiateCall({ commit }, { contactId, inboxId })
|
||||
).rejects.toThrow(ExceptionWithMessage);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API returns error with error field', async () => {
|
||||
const errorMessage = 'Call initiation error';
|
||||
axios.post.mockRejectedValue({
|
||||
response: {
|
||||
data: {
|
||||
error: errorMessage,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await expect(
|
||||
actions.initiateCall({ commit }, { contactId, inboxId })
|
||||
).rejects.toThrow(ExceptionWithMessage);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API returns generic error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Network error' });
|
||||
|
||||
await expect(
|
||||
actions.initiateCall({ commit }, { contactId, inboxId })
|
||||
).rejects.toThrow(Error);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: true }],
|
||||
[types.SET_CONTACT_UI_FLAG, { isInitiatingCall: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
export const filterApiResponse = {
|
||||
meta: {
|
||||
count: {
|
||||
all_count: 2,
|
||||
},
|
||||
current_page: '1',
|
||||
},
|
||||
payload: [
|
||||
{
|
||||
additional_attributes: {},
|
||||
availability_status: 'offline',
|
||||
email: 'fayaz@g.com',
|
||||
id: 8,
|
||||
name: 'fayaz',
|
||||
phone_number: null,
|
||||
identifier: null,
|
||||
thumbnail:
|
||||
'https://www.gravatar.com/avatar/f2e86d3a78353cdf51002f44cf6ea846?d=404',
|
||||
custom_attributes: {},
|
||||
conversations_count: 1,
|
||||
last_activity_at: 1631081845,
|
||||
},
|
||||
{
|
||||
additional_attributes: {},
|
||||
availability_status: 'offline',
|
||||
email: 'fayaz@gma.com',
|
||||
id: 9,
|
||||
name: 'fayaz',
|
||||
phone_number: null,
|
||||
identifier: null,
|
||||
thumbnail:
|
||||
'https://www.gravatar.com/avatar/792af86e3ad4591552e1025a6415baa6?d=404',
|
||||
custom_attributes: {},
|
||||
conversations_count: 1,
|
||||
last_activity_at: 1631614585,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
export default [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Contact 1',
|
||||
email: 'contact1@chatwoot.com',
|
||||
phone_number: '9000000001',
|
||||
thumbnail: 'contact1.png',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Contact 2',
|
||||
email: 'contact2@chatwoot.com',
|
||||
phone_number: '9000000002',
|
||||
thumbnail: 'contact2.png',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Contact 3',
|
||||
email: 'contact3@chatwoot.com',
|
||||
phone_number: '9000000003',
|
||||
thumbnail: 'contact3.png',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Contact 4',
|
||||
email: 'contact4@chatwoot.com',
|
||||
phone_number: '9000000004',
|
||||
thumbnail: 'contact4.png',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,53 @@
|
||||
import Contacts from '../../contacts';
|
||||
import contactList from './fixtures';
|
||||
|
||||
const { getters } = Contacts;
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getContacts', () => {
|
||||
const state = {
|
||||
records: { 1: contactList[0], 3: contactList[2] },
|
||||
sortOrder: [3, 1],
|
||||
};
|
||||
expect(getters.getContacts(state)).toEqual([
|
||||
contactList[2],
|
||||
contactList[0],
|
||||
]);
|
||||
});
|
||||
|
||||
it('getContact', () => {
|
||||
const state = {
|
||||
records: { 2: contactList[1] },
|
||||
};
|
||||
expect(getters.getContact(state)(2)).toEqual(contactList[1]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isFetchingItem: true,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isFetchingItem: true,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
it('getAppliedContactFilters', () => {
|
||||
const filters = [
|
||||
{
|
||||
attribute_key: 'email',
|
||||
filter_operator: 'contains',
|
||||
values: 'a',
|
||||
query_operator: null,
|
||||
},
|
||||
];
|
||||
const state = {
|
||||
appliedFilters: filters,
|
||||
};
|
||||
expect(getters.getAppliedContactFilters(state)).toEqual(filters);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,105 @@
|
||||
import types from '../../../mutation-types';
|
||||
import Contacts from '../../contacts';
|
||||
const { mutations } = Contacts;
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONTACTS', () => {
|
||||
it('set contact records', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.SET_CONTACTS](state, [
|
||||
{ id: 2, name: 'contact2', email: 'contact2@chatwoot.com' },
|
||||
{ id: 1, name: 'contact1', email: 'contact1@chatwoot.com' },
|
||||
]);
|
||||
expect(state.records).toEqual({
|
||||
1: {
|
||||
id: 1,
|
||||
name: 'contact1',
|
||||
email: 'contact1@chatwoot.com',
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
name: 'contact2',
|
||||
email: 'contact2@chatwoot.com',
|
||||
},
|
||||
});
|
||||
expect(state.sortOrder).toEqual([2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONTACT_ITEM', () => {
|
||||
it('push contact data to the store', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: { id: 1, name: 'contact1', email: 'contact1@chatwoot.com' },
|
||||
},
|
||||
sortOrder: [1],
|
||||
};
|
||||
mutations[types.SET_CONTACT_ITEM](state, {
|
||||
id: 2,
|
||||
name: 'contact2',
|
||||
email: 'contact2@chatwoot.com',
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: { id: 1, name: 'contact1', email: 'contact1@chatwoot.com' },
|
||||
2: { id: 2, name: 'contact2', email: 'contact2@chatwoot.com' },
|
||||
});
|
||||
expect(state.sortOrder).toEqual([1, 2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_CONTACT', () => {
|
||||
it('update contact', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: { id: 1, name: 'contact1', email: 'contact1@chatwoot.com' },
|
||||
},
|
||||
};
|
||||
mutations[types.EDIT_CONTACT](state, {
|
||||
id: 1,
|
||||
name: 'contact2',
|
||||
email: 'contact2@chatwoot.com',
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: { id: 1, name: 'contact2', email: 'contact2@chatwoot.com' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONTACT_FILTERS', () => {
|
||||
it('set contact filter', () => {
|
||||
const appliedFilters = [
|
||||
{
|
||||
attribute_key: 'name',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['fayaz'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
];
|
||||
mutations[types.SET_CONTACT_FILTERS](appliedFilters);
|
||||
expect(appliedFilters).toEqual([
|
||||
{
|
||||
attribute_key: 'name',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['fayaz'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#CLEAR_CONTACT_FILTERS', () => {
|
||||
it('clears applied contact filters', () => {
|
||||
const state = {
|
||||
appliedFilters: [
|
||||
{
|
||||
attribute_key: 'name',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['fayaz'],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
};
|
||||
mutations[types.CLEAR_CONTACT_FILTERS](state);
|
||||
expect(state.appliedFilters).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../conversationLabels';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: ['customer-success', 'on-hold'] },
|
||||
});
|
||||
await actions.get({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: true }],
|
||||
|
||||
[
|
||||
types.default.SET_CONVERSATION_LABELS,
|
||||
{ id: 1, data: ['customer-success', 'on-hold'] },
|
||||
],
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('updates correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({
|
||||
data: { payload: { conversationId: '1', labels: ['on-hold'] } },
|
||||
});
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{ conversationId: '1', labels: ['on-hold'] }
|
||||
);
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.default.SET_CONVERSATION_LABELS,
|
||||
{
|
||||
id: '1',
|
||||
data: { conversationId: '1', labels: ['on-hold'] },
|
||||
},
|
||||
],
|
||||
[
|
||||
types.default.SET_CONVERSATION_LABELS_UI_FLAG,
|
||||
{ isUpdating: false, isError: false },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{ conversationId: '1', labels: ['on-hold'] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONVERSATION_LABELS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.default.SET_CONVERSATION_LABELS_UI_FLAG,
|
||||
{ isUpdating: false, isError: true },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setBulkConversationLabels', () => {
|
||||
it('it send correct mutations', () => {
|
||||
actions.setBulkConversationLabels({ commit }, [
|
||||
{ id: 1, labels: ['customer-support'] },
|
||||
]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.default.SET_BULK_CONVERSATION_LABELS,
|
||||
[{ id: 1, labels: ['customer-support'] }],
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setBulkConversationLabels', () => {
|
||||
it('it send correct mutations', () => {
|
||||
actions.setConversationLabel(
|
||||
{ commit },
|
||||
{ id: 1, data: ['customer-support'] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.default.SET_CONVERSATION_LABELS,
|
||||
{ id: 1, data: ['customer-support'] },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { getters } from '../../conversationLabels';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getConversationLabels', () => {
|
||||
const state = {
|
||||
records: { 1: ['customer-success', 'on-hold'] },
|
||||
};
|
||||
expect(getters.getConversationLabels(state)(1)).toEqual([
|
||||
'customer-success',
|
||||
'on-hold',
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationLabels';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONVERSATION_LABELS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
mutations[types.default.SET_CONVERSATION_LABELS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_LABELS', () => {
|
||||
it('set contact labels', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.SET_CONVERSATION_LABELS](state, {
|
||||
id: 1,
|
||||
data: ['customer-success', 'on-hold'],
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: ['customer-success', 'on-hold'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_BULK_CONVERSATION_LABELS', () => {
|
||||
it('set contact labels in bulk', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.SET_BULK_CONVERSATION_LABELS](state, [
|
||||
{
|
||||
id: 1,
|
||||
labels: ['customer-success', 'on-hold'],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
labels: ['customer-success'],
|
||||
},
|
||||
]);
|
||||
expect(state.records).toEqual({
|
||||
1: ['customer-success', 'on-hold'],
|
||||
2: ['customer-success'],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { getters } from '../../conversationMetadata';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getConversationMetadata', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: {
|
||||
browser: { name: 'Chrome' },
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getters.getConversationMetadata(state)(1)).toEqual({
|
||||
browser: { name: 'Chrome' },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationMetadata';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_INBOXES', () => {
|
||||
it('set inbox records', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.SET_CONVERSATION_METADATA](state, {
|
||||
id: 1,
|
||||
data: { browser: { name: 'Chrome' } },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: { browser: { name: 'Chrome' } },
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { actions } from '../../conversationPage';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#setCurrentPage', () => {
|
||||
it('sends correct actions', () => {
|
||||
actions.setCurrentPage({ commit }, { filter: 'me', page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CURRENT_PAGE, { filter: 'me', page: 1 }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setEndReached', () => {
|
||||
it('sends correct actions', () => {
|
||||
actions.setEndReached({ commit }, { filter: 'me' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONVERSATION_END_REACHED, { filter: 'me' }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#reset', () => {
|
||||
it('sends correct actions', () => {
|
||||
actions.reset({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.CLEAR_CONVERSATION_PAGE],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { getters } from '../../conversationPage';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getCurrentPage', () => {
|
||||
const state = {
|
||||
currentPage: {
|
||||
me: 1,
|
||||
unassigned: 2,
|
||||
all: 3,
|
||||
},
|
||||
};
|
||||
expect(getters.getCurrentPage(state)).toHaveProperty('me');
|
||||
expect(getters.getCurrentPage(state)).toHaveProperty('unassigned');
|
||||
expect(getters.getCurrentPage(state)).toHaveProperty('all');
|
||||
});
|
||||
|
||||
it('getCurrentPageFilter', () => {
|
||||
const state = {
|
||||
currentPage: {
|
||||
me: 1,
|
||||
unassigned: 2,
|
||||
all: 3,
|
||||
},
|
||||
};
|
||||
expect(getters.getCurrentPageFilter(state)('me')).toEqual(1);
|
||||
expect(getters.getCurrentPageFilter(state)('unassigned')).toEqual(2);
|
||||
expect(getters.getCurrentPageFilter(state)('all')).toEqual(3);
|
||||
});
|
||||
|
||||
it('getHasEndReached', () => {
|
||||
const state = {
|
||||
hasEndReached: {
|
||||
me: false,
|
||||
unassigned: true,
|
||||
all: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getHasEndReached(state)('me')).toEqual(false);
|
||||
expect(getters.getHasEndReached(state)('unassigned')).toEqual(true);
|
||||
expect(getters.getHasEndReached(state)('all')).toEqual(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationPage';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CURRENT_PAGE', () => {
|
||||
it('set current page correctly', () => {
|
||||
const state = { currentPage: { me: 1 } };
|
||||
mutations[types.default.SET_CURRENT_PAGE](state, {
|
||||
filter: 'me',
|
||||
page: 2,
|
||||
});
|
||||
expect(state.currentPage).toEqual({
|
||||
me: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_CONVERSATION_PAGE', () => {
|
||||
it('resets the state to initial state', () => {
|
||||
const state = {
|
||||
currentPage: { me: 1, unassigned: 2, all: 3 },
|
||||
hasEndReached: { me: true, unassigned: true, all: true },
|
||||
};
|
||||
mutations[types.default.CLEAR_CONVERSATION_PAGE](state);
|
||||
expect(state).toEqual({
|
||||
currentPage: { me: 0, unassigned: 0, all: 0, appliedFilters: 0 },
|
||||
hasEndReached: {
|
||||
me: false,
|
||||
unassigned: false,
|
||||
all: false,
|
||||
appliedFilters: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_END_REACHED', () => {
|
||||
it('set conversation end reached correctly', () => {
|
||||
const state = {
|
||||
hasEndReached: { me: false, unassigned: false, all: false },
|
||||
};
|
||||
mutations[types.default.SET_CONVERSATION_END_REACHED](state, {
|
||||
filter: 'me',
|
||||
});
|
||||
expect(state.hasEndReached).toEqual({
|
||||
me: true,
|
||||
unassigned: false,
|
||||
all: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('set all state to true if all end has reached', () => {
|
||||
const state = {
|
||||
hasEndReached: { me: false, unassigned: false, all: false },
|
||||
};
|
||||
mutations[types.default.SET_CONVERSATION_END_REACHED](state, {
|
||||
filter: 'all',
|
||||
});
|
||||
expect(state.hasEndReached).toEqual({
|
||||
me: true,
|
||||
unassigned: true,
|
||||
all: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,210 @@
|
||||
import { actions } from '../../conversationSearch';
|
||||
import types from '../../../mutation-types';
|
||||
import axios from 'axios';
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
beforeEach(() => {
|
||||
commit.mockClear();
|
||||
dispatch.mockClear();
|
||||
axios.get.mockClear();
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if no query param is provided', () => {
|
||||
actions.get({ commit }, { q: '' });
|
||||
expect(commit.mock.calls).toEqual([[types.SEARCH_CONVERSATIONS_SET, []]]);
|
||||
});
|
||||
|
||||
it('sends correct actions if query param is provided and API call is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [{ messages: [{ id: 1, content: 'value testing' }], id: 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
await actions.get({ commit }, { q: 'value' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SEARCH_CONVERSATIONS_SET, []],
|
||||
[types.SEARCH_CONVERSATIONS_SET_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SEARCH_CONVERSATIONS_SET,
|
||||
[{ messages: [{ id: 1, content: 'value testing' }], id: 1 }],
|
||||
],
|
||||
[types.SEARCH_CONVERSATIONS_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if query param is provided and API call is errored', async () => {
|
||||
axios.get.mockRejectedValue({});
|
||||
await actions.get({ commit }, { q: 'value' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SEARCH_CONVERSATIONS_SET, []],
|
||||
[types.SEARCH_CONVERSATIONS_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.SEARCH_CONVERSATIONS_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fullSearch', () => {
|
||||
it('should not dispatch any actions if no query provided', async () => {
|
||||
await actions.fullSearch({ commit, dispatch }, { q: '' });
|
||||
expect(dispatch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should dispatch all search actions and set UI flags correctly', async () => {
|
||||
await actions.fullSearch({ commit, dispatch }, { q: 'test' });
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.FULL_SEARCH_SET_UI_FLAG,
|
||||
{ isFetching: true, isSearchCompleted: false },
|
||||
],
|
||||
[
|
||||
types.FULL_SEARCH_SET_UI_FLAG,
|
||||
{ isFetching: false, isSearchCompleted: true },
|
||||
],
|
||||
]);
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith('contactSearch', { q: 'test' });
|
||||
expect(dispatch).toHaveBeenCalledWith('conversationSearch', {
|
||||
q: 'test',
|
||||
});
|
||||
expect(dispatch).toHaveBeenCalledWith('messageSearch', { q: 'test' });
|
||||
expect(dispatch).toHaveBeenCalledWith('articleSearch', { q: 'test' });
|
||||
});
|
||||
|
||||
it('should pass filters to all search actions including articleSearch', async () => {
|
||||
const payload = { q: 'test', since: 1700000000, until: 1732000000 };
|
||||
await actions.fullSearch({ commit, dispatch }, payload);
|
||||
|
||||
expect(dispatch).toHaveBeenCalledWith('contactSearch', payload);
|
||||
expect(dispatch).toHaveBeenCalledWith('conversationSearch', payload);
|
||||
expect(dispatch).toHaveBeenCalledWith('messageSearch', payload);
|
||||
expect(dispatch).toHaveBeenCalledWith('articleSearch', payload);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#contactSearch', () => {
|
||||
it('should handle successful contact search', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { contacts: [{ id: 1 }] } },
|
||||
});
|
||||
|
||||
await actions.contactSearch({ commit }, { q: 'test', page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.CONTACT_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.CONTACT_SEARCH_SET, [{ id: 1 }]],
|
||||
[types.CONTACT_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle failed contact search', async () => {
|
||||
axios.get.mockRejectedValue({});
|
||||
await actions.contactSearch({ commit }, { q: 'test' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.CONTACT_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.CONTACT_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#conversationSearch', () => {
|
||||
it('should handle successful conversation search', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { conversations: [{ id: 1 }] } },
|
||||
});
|
||||
|
||||
await actions.conversationSearch({ commit }, { q: 'test', page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.CONVERSATION_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.CONVERSATION_SEARCH_SET, [{ id: 1 }]],
|
||||
[types.CONVERSATION_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle failed conversation search', async () => {
|
||||
axios.get.mockRejectedValue({});
|
||||
await actions.conversationSearch({ commit }, { q: 'test' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.CONVERSATION_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.CONVERSATION_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#messageSearch', () => {
|
||||
it('should handle successful message search', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { messages: [{ id: 1 }] } },
|
||||
});
|
||||
|
||||
await actions.messageSearch({ commit }, { q: 'test', page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.MESSAGE_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.MESSAGE_SEARCH_SET, [{ id: 1 }]],
|
||||
[types.MESSAGE_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle failed message search', async () => {
|
||||
axios.get.mockRejectedValue({});
|
||||
await actions.messageSearch({ commit }, { q: 'test' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.MESSAGE_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.MESSAGE_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#articleSearch', () => {
|
||||
it('should handle successful article search', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { articles: [{ id: 1 }] } },
|
||||
});
|
||||
|
||||
await actions.articleSearch({ commit }, { q: 'test', page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.ARTICLE_SEARCH_SET, [{ id: 1 }]],
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle article search with date filters', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: { payload: { articles: [{ id: 1 }] } },
|
||||
});
|
||||
|
||||
await actions.articleSearch(
|
||||
{ commit },
|
||||
{ q: 'test', page: 1, since: 1700000000, until: 1732000000 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.ARTICLE_SEARCH_SET, [{ id: 1 }]],
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle failed article search', async () => {
|
||||
axios.get.mockRejectedValue({});
|
||||
await actions.articleSearch({ commit }, { q: 'test' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: true }],
|
||||
[types.ARTICLE_SEARCH_SET_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearSearchResults', () => {
|
||||
it('should commit clear search results mutation', () => {
|
||||
actions.clearSearchResults({ commit });
|
||||
expect(commit).toHaveBeenCalledWith(types.CLEAR_SEARCH_RESULTS);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { getters } from '../../conversationSearch';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getConversations', () => {
|
||||
const state = {
|
||||
records: [{ id: 1, messages: [{ id: 1, content: 'value' }] }],
|
||||
};
|
||||
expect(getters.getConversations(state)).toEqual([
|
||||
{ id: 1, messages: [{ id: 1, content: 'value' }] },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getContactRecords', () => {
|
||||
const state = {
|
||||
contactRecords: [{ id: 1, name: 'Contact 1' }],
|
||||
};
|
||||
expect(getters.getContactRecords(state)).toEqual([
|
||||
{ id: 1, name: 'Contact 1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getConversationRecords', () => {
|
||||
const state = {
|
||||
conversationRecords: [{ id: 1, title: 'Conversation 1' }],
|
||||
};
|
||||
expect(getters.getConversationRecords(state)).toEqual([
|
||||
{ id: 1, title: 'Conversation 1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getMessageRecords', () => {
|
||||
const state = {
|
||||
messageRecords: [{ id: 1, content: 'Message 1' }],
|
||||
};
|
||||
expect(getters.getMessageRecords(state)).toEqual([
|
||||
{ id: 1, content: 'Message 1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getArticleRecords', () => {
|
||||
const state = {
|
||||
articleRecords: [{ id: 1, title: 'Article 1' }],
|
||||
};
|
||||
expect(getters.getArticleRecords(state)).toEqual([
|
||||
{ id: 1, title: 'Article 1' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isSearchCompleted: true,
|
||||
contact: { isFetching: true },
|
||||
message: { isFetching: false },
|
||||
conversation: { isFetching: false },
|
||||
article: { isFetching: false },
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: false,
|
||||
isSearchCompleted: true,
|
||||
contact: { isFetching: true },
|
||||
message: { isFetching: false },
|
||||
conversation: { isFetching: false },
|
||||
article: { isFetching: false },
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,139 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationSearch';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SEARCH_CONVERSATIONS_SET', () => {
|
||||
it('set records correctly', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SEARCH_CONVERSATIONS_SET](state, [{ id: 1 }]);
|
||||
expect(state.records).toEqual([{ id: 1 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SEARCH_CONVERSATIONS_SET_UI_FLAG', () => {
|
||||
it('set uiFlags correctly', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
mutations[types.SEARCH_CONVERSATIONS_SET_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CONTACT_SEARCH_SET', () => {
|
||||
it('should append new contact records to existing ones', () => {
|
||||
const state = { contactRecords: [{ id: 1 }] };
|
||||
mutations[types.CONTACT_SEARCH_SET](state, [{ id: 2 }]);
|
||||
expect(state.contactRecords).toEqual([{ id: 1 }, { id: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CONVERSATION_SEARCH_SET', () => {
|
||||
it('should append new conversation records to existing ones', () => {
|
||||
const state = { conversationRecords: [{ id: 1 }] };
|
||||
mutations[types.CONVERSATION_SEARCH_SET](state, [{ id: 2 }]);
|
||||
expect(state.conversationRecords).toEqual([{ id: 1 }, { id: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#MESSAGE_SEARCH_SET', () => {
|
||||
it('should append new message records to existing ones', () => {
|
||||
const state = { messageRecords: [{ id: 1 }] };
|
||||
mutations[types.MESSAGE_SEARCH_SET](state, [{ id: 2 }]);
|
||||
expect(state.messageRecords).toEqual([{ id: 1 }, { id: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#FULL_SEARCH_SET_UI_FLAG', () => {
|
||||
it('set full search UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isSearchCompleted: false,
|
||||
},
|
||||
};
|
||||
mutations[types.FULL_SEARCH_SET_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
isSearchCompleted: true,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
isSearchCompleted: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CONTACT_SEARCH_SET_UI_FLAG', () => {
|
||||
it('set contact search UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
contact: { isFetching: true },
|
||||
},
|
||||
};
|
||||
mutations[types.CONTACT_SEARCH_SET_UI_FLAG](state, { isFetching: false });
|
||||
expect(state.uiFlags.contact).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CONVERSATION_SEARCH_SET_UI_FLAG', () => {
|
||||
it('set conversation search UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
conversation: { isFetching: true },
|
||||
},
|
||||
};
|
||||
mutations[types.CONVERSATION_SEARCH_SET_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags.conversation).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#MESSAGE_SEARCH_SET_UI_FLAG', () => {
|
||||
it('set message search UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
message: { isFetching: true },
|
||||
},
|
||||
};
|
||||
mutations[types.MESSAGE_SEARCH_SET_UI_FLAG](state, { isFetching: false });
|
||||
expect(state.uiFlags.message).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ARTICLE_SEARCH_SET', () => {
|
||||
it('should append new article records to existing ones', () => {
|
||||
const state = { articleRecords: [{ id: 1 }] };
|
||||
mutations[types.ARTICLE_SEARCH_SET](state, [{ id: 2 }]);
|
||||
expect(state.articleRecords).toEqual([{ id: 1 }, { id: 2 }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ARTICLE_SEARCH_SET_UI_FLAG', () => {
|
||||
it('set article search UI flags correctly', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
article: { isFetching: true },
|
||||
},
|
||||
};
|
||||
mutations[types.ARTICLE_SEARCH_SET_UI_FLAG](state, { isFetching: false });
|
||||
expect(state.uiFlags.article).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_SEARCH_RESULTS', () => {
|
||||
it('should clear all search records', () => {
|
||||
const state = {
|
||||
contactRecords: [{ id: 1 }],
|
||||
conversationRecords: [{ id: 1 }],
|
||||
messageRecords: [{ id: 1 }],
|
||||
articleRecords: [{ id: 1 }],
|
||||
};
|
||||
mutations[types.CLEAR_SEARCH_RESULTS](state);
|
||||
expect(state.contactRecords).toEqual([]);
|
||||
expect(state.conversationRecords).toEqual([]);
|
||||
expect(state.messageRecords).toEqual([]);
|
||||
expect(state.articleRecords).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../conversationStats';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
vi.mock('@chatwoot/utils', () => ({
|
||||
debounce: vi.fn(fn => {
|
||||
return fn;
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('#actions', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers(); // Set up fake timers
|
||||
commit.mockClear();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers(); // Reset to real timers after each test
|
||||
});
|
||||
|
||||
describe('#get', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { meta: { mine_count: 1 } } });
|
||||
actions.get(
|
||||
{ commit, state: { allCount: 0 } },
|
||||
{ inboxId: 1, assigneeTpe: 'me', status: 'open' }
|
||||
);
|
||||
|
||||
await vi.runAllTimersAsync();
|
||||
await vi.waitFor(() => expect(commit).toHaveBeenCalled());
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CONV_TAB_META, { mine_count: 1 }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
actions.get(
|
||||
{ commit, state: { allCount: 0 } },
|
||||
{ inboxId: 1, assigneeTpe: 'me', status: 'open' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#set', () => {
|
||||
it('sends correct mutations', async () => {
|
||||
actions.set(
|
||||
{ commit },
|
||||
{ mine_count: 1, unassigned_count: 1, all_count: 2 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.default.SET_CONV_TAB_META,
|
||||
{ mine_count: 1, unassigned_count: 1, all_count: 2 },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { getters } from '../../conversationStats';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getCurrentPage', () => {
|
||||
const state = {
|
||||
mineCount: 1,
|
||||
unAssignedCount: 1,
|
||||
allCount: 2,
|
||||
};
|
||||
expect(getters.getStats(state)).toEqual({
|
||||
mineCount: 1,
|
||||
unAssignedCount: 1,
|
||||
allCount: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationStats';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONV_TAB_META', () => {
|
||||
it('set conversation stats correctly', () => {
|
||||
const state = {};
|
||||
mutations[types.SET_CONV_TAB_META](state, {
|
||||
mine_count: 1,
|
||||
unassigned_count: 1,
|
||||
all_count: 2,
|
||||
});
|
||||
expect(state).toEqual({
|
||||
mineCount: 1,
|
||||
unAssignedCount: 1,
|
||||
allCount: 2,
|
||||
updatedOn: expect.any(Date),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { actions } from '../../conversationTypingStatus';
|
||||
import * as types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#create', () => {
|
||||
it('sends correct actions', () => {
|
||||
actions.create(
|
||||
{ commit },
|
||||
{ conversationId: 1, user: { id: 1, name: 'user-1' } }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.default.ADD_USER_TYPING_TO_CONVERSATION,
|
||||
{ conversationId: 1, user: { id: 1, name: 'user-1' } },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#destroy', () => {
|
||||
it('sends correct actions', () => {
|
||||
actions.destroy(
|
||||
{ commit },
|
||||
{ conversationId: 1, user: { id: 1, name: 'user-1' } }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.default.REMOVE_USER_TYPING_FROM_CONVERSATION,
|
||||
{ conversationId: 1, user: { id: 1, name: 'user-1' } },
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { getters } from '../../conversationTypingStatus';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getUserList', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: [
|
||||
{ id: 1, name: 'user-1' },
|
||||
{ id: 2, name: 'user-2' },
|
||||
],
|
||||
},
|
||||
};
|
||||
expect(getters.getUserList(state)(1)).toEqual([
|
||||
{ id: 1, name: 'user-1' },
|
||||
{ id: 2, name: 'user-2' },
|
||||
]);
|
||||
expect(getters.getUserList(state)(2)).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import * as types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationTypingStatus';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#ADD_USER_TYPING_TO_CONVERSATION', () => {
|
||||
it('add user to state', () => {
|
||||
const state = { records: {} };
|
||||
mutations[types.default.ADD_USER_TYPING_TO_CONVERSATION](state, {
|
||||
conversationId: 1,
|
||||
user: { id: 1, type: 'contact', name: 'user-1' },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [{ id: 1, type: 'contact', name: 'user-1' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('doesnot add user if user already exist', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: [{ id: 1, type: 'contact', name: 'user-1' }],
|
||||
},
|
||||
};
|
||||
mutations[types.default.ADD_USER_TYPING_TO_CONVERSATION](state, {
|
||||
conversationId: 1,
|
||||
user: { id: 1, type: 'contact', name: 'user-1' },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [{ id: 1, type: 'contact', name: 'user-1' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('add user to state if no matching user profiles are seen', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: [{ id: 1, type: 'user', name: 'user-1' }],
|
||||
},
|
||||
};
|
||||
mutations[types.default.ADD_USER_TYPING_TO_CONVERSATION](state, {
|
||||
conversationId: 1,
|
||||
user: { id: 1, type: 'contact', name: 'user-1' },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [
|
||||
{ id: 1, type: 'user', name: 'user-1' },
|
||||
{ id: 1, type: 'contact', name: 'user-1' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#REMOVE_USER_TYPING_FROM_CONVERSATION', () => {
|
||||
it('remove add user if user exist', () => {
|
||||
const state = {
|
||||
records: {
|
||||
1: [{ id: 1, type: 'contact', name: 'user-1' }],
|
||||
},
|
||||
};
|
||||
mutations[types.default.REMOVE_USER_TYPING_FROM_CONVERSATION](state, {
|
||||
conversationId: 1,
|
||||
user: { id: 1, type: 'contact', name: 'user-1' },
|
||||
});
|
||||
expect(state.records).toEqual({
|
||||
1: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../conversationWatchers';
|
||||
import types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.show({ commit }, { conversationId: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_PARTICIPANTS,
|
||||
{ conversationId: 1, data: { id: 1 } },
|
||||
],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.show({ commit }, { conversationId: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: [{ id: 2 }] });
|
||||
await actions.update(
|
||||
{ commit },
|
||||
{ conversationId: 2, userIds: [{ id: 2 }] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_PARTICIPANTS,
|
||||
{ conversationId: 2, data: [{ id: 2 }] },
|
||||
],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, { conversationId: 1, content: 'hi' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
export const data = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Uno',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Dos',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Tres',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,22 @@
|
||||
import { getters } from '../../conversationWatchers';
|
||||
import watchersData from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getByConversationId', () => {
|
||||
const state = { records: { 1: watchersData } };
|
||||
expect(getters.getByConversationId(state)(1)).toEqual(watchersData);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationWatchers';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONVERSATION_PARTICIPANTS', () => {
|
||||
it('sets an individual record', () => {
|
||||
let state = {
|
||||
records: {},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_PARTICIPANTS](state, {
|
||||
data: [],
|
||||
conversationId: 1,
|
||||
});
|
||||
expect(state.records).toEqual({ 1: [] });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_PARTICIPANTS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
let state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetching: false,
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,799 @@
|
||||
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(
|
||||
{ dispatch },
|
||||
{ conversationId: 1, agentId: 1 }
|
||||
);
|
||||
expect(dispatch).toHaveBeenCalledWith('setCurrentChatAssignee', {
|
||||
conversationId: 1,
|
||||
assignee: { id: 1, name: 'User' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setCurrentChatAssignee', () => {
|
||||
it('sends correct mutations if assignment is successful', async () => {
|
||||
const payload = {
|
||||
conversationId: 1,
|
||||
assignee: { id: 1, name: 'User' },
|
||||
};
|
||||
await actions.setCurrentChatAssignee({ commit }, payload);
|
||||
expect(commit).toHaveBeenCalledTimes(1);
|
||||
expect(commit.mock.calls).toEqual([['ASSIGN_AGENT', payload]]);
|
||||
});
|
||||
});
|
||||
|
||||
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,
|
||||
{
|
||||
conversationId: 1,
|
||||
customAttributes: { 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('#setActiveChat', () => {
|
||||
it('should commit SET_CHAT_DATA_FETCHED with conversation ID after fetch', async () => {
|
||||
const localCommit = vi.fn();
|
||||
const localDispatch = vi.fn().mockResolvedValue();
|
||||
const data = { id: 42, messages: [{ id: 100 }] };
|
||||
|
||||
await actions.setActiveChat(
|
||||
{ commit: localCommit, dispatch: localDispatch },
|
||||
{ data, after: 99 }
|
||||
);
|
||||
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_CHAT_WINDOW, data],
|
||||
[types.CLEAR_ALL_MESSAGES_LOADED, 42],
|
||||
[types.SET_CHAT_DATA_FETCHED, 42],
|
||||
]);
|
||||
expect(localDispatch).toHaveBeenCalledWith('fetchPreviousMessages', {
|
||||
after: 99,
|
||||
before: 100,
|
||||
conversationId: 42,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not dispatch fetchPreviousMessages if dataFetched is already set', async () => {
|
||||
const localCommit = vi.fn();
|
||||
const localDispatch = vi.fn();
|
||||
const data = { id: 42, messages: [{ id: 100 }], dataFetched: true };
|
||||
|
||||
await actions.setActiveChat(
|
||||
{ commit: localCommit, dispatch: localDispatch },
|
||||
{ data }
|
||||
);
|
||||
|
||||
expect(localCommit.mock.calls).toEqual([
|
||||
[types.SET_CURRENT_CHAT_WINDOW, data],
|
||||
[types.CLEAR_ALL_MESSAGES_LOADED, 42],
|
||||
]);
|
||||
expect(localDispatch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should commit SET_CHAT_DATA_FETCHED by ID, not mutate the data object directly (race condition fix)', async () => {
|
||||
const localCommit = vi.fn();
|
||||
const localDispatch = vi.fn().mockResolvedValue();
|
||||
const data = { id: 42, messages: [{ id: 100 }] };
|
||||
|
||||
await actions.setActiveChat(
|
||||
{ commit: localCommit, dispatch: localDispatch },
|
||||
{ data }
|
||||
);
|
||||
|
||||
// The action must NOT set dataFetched on the data object directly
|
||||
expect(data.dataFetched).toBeUndefined();
|
||||
|
||||
// Instead it commits a mutation that finds the conversation by ID in the store
|
||||
expect(localCommit).toHaveBeenCalledWith(types.SET_CHAT_DATA_FETCHED, 42);
|
||||
});
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../csat';
|
||||
import types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: [{ id: 1, rating: 1, feedback_text: 'Bad' }],
|
||||
});
|
||||
await actions.get({ commit }, { page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CSAT_RESPONSE, [{ id: 1, rating: 1, feedback_text: 'Bad' }]],
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit }, { page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getMetrics', () => {
|
||||
it('sends correct mutations if API is success', async () => {
|
||||
axios.get.mockResolvedValue({
|
||||
data: {
|
||||
total_count: 29,
|
||||
ratings_count: { 1: 10, 2: 10, 3: 3, 4: 3, 5: 3 },
|
||||
total_sent_messages_count: 120,
|
||||
},
|
||||
});
|
||||
await actions.getMetrics({ commit }, { page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetchingMetrics: true }],
|
||||
[
|
||||
types.SET_CSAT_RESPONSE_METRICS,
|
||||
{
|
||||
total_count: 29,
|
||||
ratings_count: { 1: 10, 2: 10, 3: 3, 4: 3, 5: 3 },
|
||||
total_sent_messages_count: 120,
|
||||
},
|
||||
],
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetchingMetrics: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.getMetrics({ commit }, { page: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetchingMetrics: true }],
|
||||
[types.SET_CSAT_RESPONSE_UI_FLAG, { isFetchingMetrics: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
import { getters } from '../../csat';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getUIFlags', () => {
|
||||
const state = { uiFlags: { isFetching: false } };
|
||||
expect(getters.getUIFlags(state)).toEqual({ isFetching: false });
|
||||
});
|
||||
|
||||
it('getCSATResponses', () => {
|
||||
const state = { records: [{ id: 1, raring: 1, feedback_text: 'Bad' }] };
|
||||
expect(getters.getCSATResponses(state)).toEqual([
|
||||
{ id: 1, raring: 1, feedback_text: 'Bad' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('getMetrics', () => {
|
||||
const state = {
|
||||
metrics: {
|
||||
totalResponseCount: 0,
|
||||
ratingsCount: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
|
||||
},
|
||||
};
|
||||
expect(getters.getMetrics(state)).toEqual(state.metrics);
|
||||
});
|
||||
|
||||
it('getRatingPercentage', () => {
|
||||
let state = {
|
||||
metrics: {
|
||||
totalResponseCount: 0,
|
||||
ratingsCount: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
|
||||
},
|
||||
};
|
||||
expect(getters.getRatingPercentage(state)).toEqual({
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
});
|
||||
|
||||
state = {
|
||||
metrics: {
|
||||
totalResponseCount: 50,
|
||||
ratingsCount: { 1: 10, 2: 20, 3: 15, 4: 3, 5: 2 },
|
||||
},
|
||||
};
|
||||
expect(getters.getRatingPercentage(state)).toEqual({
|
||||
1: '20.00',
|
||||
2: '40.00',
|
||||
3: '30.00',
|
||||
4: '6.00',
|
||||
5: '4.00',
|
||||
});
|
||||
});
|
||||
|
||||
it('getResponseRate', () => {
|
||||
expect(
|
||||
getters.getResponseRate({
|
||||
metrics: { totalResponseCount: 0, totalSentMessagesCount: 0 },
|
||||
})
|
||||
).toEqual(0);
|
||||
|
||||
expect(
|
||||
getters.getResponseRate({
|
||||
metrics: { totalResponseCount: 20, totalSentMessagesCount: 50 },
|
||||
})
|
||||
).toEqual('40.00');
|
||||
});
|
||||
|
||||
it('getSatisfactionScore', () => {
|
||||
expect(
|
||||
getters.getSatisfactionScore({
|
||||
metrics: {
|
||||
totalResponseCount: 0,
|
||||
ratingsCount: { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 },
|
||||
},
|
||||
})
|
||||
).toEqual(0);
|
||||
|
||||
expect(
|
||||
getters.getSatisfactionScore({
|
||||
metrics: {
|
||||
totalResponseCount: 54,
|
||||
ratingsCount: { 1: 0, 2: 0, 3: 0, 4: 12, 5: 15 },
|
||||
},
|
||||
})
|
||||
).toEqual('50.00');
|
||||
});
|
||||
|
||||
it('getRatingCount', () => {
|
||||
const state = {
|
||||
metrics: {
|
||||
ratingsCount: { 1: 10, 2: 20, 3: 15, 4: 3, 5: 2 },
|
||||
},
|
||||
};
|
||||
expect(getters.getRatingCount(state)).toEqual({
|
||||
1: 10,
|
||||
2: 20,
|
||||
3: 15,
|
||||
4: 3,
|
||||
5: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../csat';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CSAT_RESPONSE_UI_FLAG', () => {
|
||||
it('set uiFlags correctly', () => {
|
||||
const state = { uiFlags: { isFetching: true } };
|
||||
mutations[types.SET_CSAT_RESPONSE_UI_FLAG](state, { isFetching: false });
|
||||
expect(state.uiFlags).toEqual({ isFetching: false });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CSAT_RESPONSE', () => {
|
||||
it('set records correctly', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_CSAT_RESPONSE](state, [
|
||||
{ id: 1, rating: 1, feedback_text: 'Bad' },
|
||||
]);
|
||||
expect(state.records).toEqual([
|
||||
{ id: 1, rating: 1, feedback_text: 'Bad' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CSAT_RESPONSE_METRICS', () => {
|
||||
it('set metrics correctly', () => {
|
||||
const state = { metrics: {} };
|
||||
mutations[types.SET_CSAT_RESPONSE_METRICS](state, {
|
||||
total_count: 29,
|
||||
ratings_count: { 1: 10, 2: 10, 3: 3, 4: 3, 5: 3 },
|
||||
total_sent_messages_count: 120,
|
||||
});
|
||||
expect(state.metrics).toEqual({
|
||||
totalResponseCount: 29,
|
||||
ratingsCount: { 1: 10, 2: 10, 3: 3, 4: 3, 5: 3 },
|
||||
totalSentMessagesCount: 120,
|
||||
});
|
||||
});
|
||||
|
||||
it('set ratingsCount correctly', () => {
|
||||
const state = { metrics: {} };
|
||||
mutations[types.SET_CSAT_RESPONSE_METRICS](state, {
|
||||
ratings_count: { 1: 5 },
|
||||
});
|
||||
expect(state.metrics).toEqual({
|
||||
totalResponseCount: 0,
|
||||
ratingsCount: { 1: 5, 2: 0, 3: 0, 4: 0, 5: 0 },
|
||||
totalSentMessagesCount: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../customRole';
|
||||
import * as types from '../../../mutation-types';
|
||||
import { customRoleList } from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#getCustomRole', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: customRoleList });
|
||||
await actions.getCustomRole({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { fetchingList: true }],
|
||||
[types.default.SET_CUSTOM_ROLE, customRoleList],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { fetchingList: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.getCustomRole({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { fetchingList: true }],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { fetchingList: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createCustomRole', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: customRoleList[0] });
|
||||
await actions.createCustomRole({ commit }, customRoleList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { creatingItem: true }],
|
||||
[types.default.ADD_CUSTOM_ROLE, customRoleList[0]],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { creatingItem: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.createCustomRole({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { creatingItem: true }],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { creatingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateCustomRole', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: customRoleList[0] });
|
||||
await actions.updateCustomRole(
|
||||
{ commit },
|
||||
{ id: 1, ...customRoleList[0] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { updatingItem: true }],
|
||||
[types.default.EDIT_CUSTOM_ROLE, customRoleList[0]],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { updatingItem: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.updateCustomRole({ commit }, { id: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { updatingItem: true }],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { updatingItem: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteCustomRole', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: customRoleList[0] });
|
||||
await actions.deleteCustomRole({ commit }, 1);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { deletingItem: true }],
|
||||
[types.default.DELETE_CUSTOM_ROLE, 1],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { deletingItem: true }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.deleteCustomRole({ commit }, 1)).rejects.toThrow(
|
||||
Error
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { deletingItem: true }],
|
||||
[types.default.SET_CUSTOM_ROLE_UI_FLAG, { deletingItem: true }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
export const customRoleList = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Super Custom Role',
|
||||
description: 'Role with all available custom role permissions',
|
||||
permissions: [
|
||||
'conversation_participating_manage',
|
||||
'conversation_unassigned_manage',
|
||||
'conversation_manage',
|
||||
'contact_manage',
|
||||
'report_manage',
|
||||
'knowledge_base_manage',
|
||||
],
|
||||
created_at: '2024-09-04T05:30:22.282Z',
|
||||
updated_at: '2024-09-05T09:21:02.844Z',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Conversation Manager Role',
|
||||
description: 'Role for managing all aspects of conversations',
|
||||
permissions: [
|
||||
'conversation_unassigned_manage',
|
||||
'conversation_participating_manage',
|
||||
'conversation_manage',
|
||||
],
|
||||
created_at: '2024-09-05T09:21:38.692Z',
|
||||
updated_at: '2024-09-05T09:21:38.692Z',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Participating Agent Role',
|
||||
description: 'Role for agents participating in conversations',
|
||||
permissions: ['conversation_participating_manage'],
|
||||
created_at: '2024-09-06T08:03:14.550Z',
|
||||
updated_at: '2024-09-06T08:03:14.550Z',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Contact Manager Role',
|
||||
description: 'Role for managing contacts only',
|
||||
permissions: ['contact_manage'],
|
||||
created_at: '2024-09-06T08:15:56.877Z',
|
||||
updated_at: '2024-09-06T09:53:28.103Z',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Report Analyst Role',
|
||||
description: 'Role for accessing and managing reports',
|
||||
permissions: ['report_manage'],
|
||||
created_at: '2024-09-06T09:53:58.277Z',
|
||||
updated_at: '2024-09-06T09:53:58.277Z',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Knowledge Base Editor Role',
|
||||
description: 'Role for managing the knowledge base',
|
||||
permissions: ['knowledge_base_manage'],
|
||||
created_at: '2024-09-06T09:54:27.649Z',
|
||||
updated_at: '2024-09-06T09:54:27.649Z',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Unassigned Queue Manager Role',
|
||||
description: 'Role for managing unassigned conversations',
|
||||
permissions: ['conversation_unassigned_manage'],
|
||||
created_at: '2024-09-06T09:55:00.503Z',
|
||||
updated_at: '2024-09-06T09:55:00.503Z',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Basic Conversation Handler Role',
|
||||
description: 'Role for basic conversation management',
|
||||
permissions: ['conversation_manage'],
|
||||
created_at: '2024-09-06T09:55:19.519Z',
|
||||
updated_at: '2024-09-06T09:55:19.519Z',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,26 @@
|
||||
import { getters } from '../../customRole';
|
||||
import { customRoleList } from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getCustomRoles', () => {
|
||||
const state = { records: customRoleList };
|
||||
expect(getters.getCustomRoles(state)).toEqual(customRoleList);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
fetchingList: true,
|
||||
creatingItem: false,
|
||||
updatingItem: false,
|
||||
deletingItem: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
fetchingList: true,
|
||||
creatingItem: false,
|
||||
updatingItem: false,
|
||||
deletingItem: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../customRole';
|
||||
import { customRoleList } from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CUSTOM_ROLE', () => {
|
||||
it('set custom role records', () => {
|
||||
const state = { records: [] };
|
||||
mutations[types.SET_CUSTOM_ROLE](state, customRoleList);
|
||||
expect(state.records).toEqual(customRoleList);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CUSTOM_ROLE', () => {
|
||||
it('push newly created custom role to the store', () => {
|
||||
const state = { records: [customRoleList[0]] };
|
||||
mutations[types.ADD_CUSTOM_ROLE](state, customRoleList[1]);
|
||||
expect(state.records).toEqual([customRoleList[0], customRoleList[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_CUSTOM_ROLE', () => {
|
||||
it('update custom role record', () => {
|
||||
const state = { records: [customRoleList[0]] };
|
||||
const updatedRole = { ...customRoleList[0], name: 'Updated Role' };
|
||||
mutations[types.EDIT_CUSTOM_ROLE](state, updatedRole);
|
||||
expect(state.records).toEqual([updatedRole]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_CUSTOM_ROLE', () => {
|
||||
it('delete custom role record', () => {
|
||||
const state = { records: [customRoleList[0], customRoleList[1]] };
|
||||
mutations[types.DELETE_CUSTOM_ROLE](state, customRoleList[0].id);
|
||||
expect(state.records).toEqual([customRoleList[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CUSTOM_ROLE_UI_FLAG', () => {
|
||||
it('set custom role UI flags', () => {
|
||||
const state = { uiFlags: {} };
|
||||
mutations[types.SET_CUSTOM_ROLE_UI_FLAG](state, {
|
||||
fetchingList: true,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({ fetchingList: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,110 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../customViews';
|
||||
import * as types from '../../../mutation-types';
|
||||
import { customViewList, updateCustomViewList } from './fixtures';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: customViewList });
|
||||
await actions.get({ commit }, 'conversation');
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.default.SET_CUSTOM_VIEW,
|
||||
{ data: customViewList, filterType: 'conversation' },
|
||||
],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.get.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: true }],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const firstItem = customViewList[0];
|
||||
axios.post.mockResolvedValue({ data: firstItem });
|
||||
await actions.create({ commit }, firstItem);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.ADD_CUSTOM_VIEW,
|
||||
{ data: firstItem, filterType: 'conversation' },
|
||||
],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: customViewList[0] });
|
||||
await actions.delete({ commit }, { id: 1, filterType: 'contact' });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.DELETE_CUSTOM_VIEW, { data: 1, filterType: 'contact' }],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.delete({ commit }, 1)).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: true }],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
const item = updateCustomViewList[0];
|
||||
axios.patch.mockResolvedValue({ data: item });
|
||||
await actions.update({ commit }, item);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
|
||||
[
|
||||
types.default.UPDATE_CUSTOM_VIEW,
|
||||
{ data: item, filterType: 'conversation' },
|
||||
],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.update({ commit }, 1)).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: true }],
|
||||
[types.default.SET_CUSTOM_VIEW_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setActiveConversationFolder', () => {
|
||||
it('set active conversation folder', async () => {
|
||||
await actions.setActiveConversationFolder({ commit }, customViewList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.default.SET_ACTIVE_CONVERSATION_FOLDER, customViewList[0]],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
export const contactViewList = [
|
||||
{
|
||||
name: 'Custom view 1',
|
||||
filter_type: 1,
|
||||
query: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'name',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['john doe'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const customViewList = [
|
||||
{
|
||||
name: 'Custom view',
|
||||
filter_type: 0,
|
||||
query: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'assignee_id',
|
||||
filter_operator: 'equal_to',
|
||||
values: [45],
|
||||
query_operator: 'and',
|
||||
},
|
||||
{
|
||||
attribute_key: 'inbox_id',
|
||||
filter_operator: 'equal_to',
|
||||
values: [144],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Custom view 1',
|
||||
filter_type: 0,
|
||||
query: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'assignee_id',
|
||||
filter_operator: 'equal_to',
|
||||
values: [45],
|
||||
query_operator: 'and',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const updateCustomViewList = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Open',
|
||||
filter_type: 'conversation',
|
||||
query: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'status',
|
||||
attribute_model: 'standard',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['open'],
|
||||
query_operator: 'and',
|
||||
custom_attribute_type: '',
|
||||
},
|
||||
{
|
||||
attribute_key: 'assignee_id',
|
||||
filter_operator: 'equal_to',
|
||||
values: [52],
|
||||
custom_attribute_type: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
created_at: '2022-02-08T03:17:38.761Z',
|
||||
updated_at: '2023-06-05T13:57:48.478Z',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,46 @@
|
||||
import { getters } from '../../customViews';
|
||||
import { contactViewList, customViewList } from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getCustomViewsByFilterType', () => {
|
||||
const state = { contact: { records: contactViewList } };
|
||||
expect(getters.getCustomViewsByFilterType(state)(1)).toEqual([
|
||||
{
|
||||
name: 'Custom view 1',
|
||||
filter_type: 1,
|
||||
query: {
|
||||
payload: [
|
||||
{
|
||||
attribute_key: 'name',
|
||||
filter_operator: 'equal_to',
|
||||
values: ['john doe'],
|
||||
query_operator: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('getActiveConversationFolder', () => {
|
||||
const state = { activeConversationFolder: customViewList[0] };
|
||||
expect(getters.getActiveConversationFolder(state)).toEqual(
|
||||
customViewList[0]
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,133 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../customViews';
|
||||
import { customViewList, updateCustomViewList } from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CUSTOM_VIEW', () => {
|
||||
it('[Conversation] set custom view records', () => {
|
||||
const state = {
|
||||
records: [],
|
||||
conversation: { records: [] },
|
||||
contact: { records: [] },
|
||||
};
|
||||
mutations[types.SET_CUSTOM_VIEW](state, {
|
||||
data: customViewList,
|
||||
filterType: 'conversation',
|
||||
});
|
||||
expect(state.conversation.records).toEqual(customViewList);
|
||||
expect(state.contact.records).toEqual([]);
|
||||
});
|
||||
|
||||
it('[Contact] set custom view records', () => {
|
||||
const state = {
|
||||
records: [],
|
||||
conversation: { records: [] },
|
||||
contact: { records: [] },
|
||||
};
|
||||
mutations[types.SET_CUSTOM_VIEW](state, {
|
||||
data: customViewList,
|
||||
filterType: 'contact',
|
||||
});
|
||||
expect(state.contact.records).toEqual(customViewList);
|
||||
expect(state.conversation.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_CUSTOM_VIEW', () => {
|
||||
it('[Conversation] push newly created custom views to the store', () => {
|
||||
const state = {
|
||||
conversation: { records: [customViewList] },
|
||||
contact: { records: [] },
|
||||
};
|
||||
mutations[types.ADD_CUSTOM_VIEW](state, {
|
||||
data: customViewList[0],
|
||||
filterType: 'conversation',
|
||||
});
|
||||
expect(state.conversation.records).toEqual([
|
||||
customViewList,
|
||||
customViewList[0],
|
||||
]);
|
||||
expect(state.contact.records).toEqual([]);
|
||||
});
|
||||
|
||||
it('[Contact] push newly created custom views to the store', () => {
|
||||
const state = {
|
||||
conversation: { records: [] },
|
||||
contact: { records: [customViewList] },
|
||||
};
|
||||
mutations[types.ADD_CUSTOM_VIEW](state, {
|
||||
data: customViewList[0],
|
||||
filterType: 'contact',
|
||||
});
|
||||
expect(state.contact.records).toEqual([
|
||||
customViewList,
|
||||
customViewList[0],
|
||||
]);
|
||||
expect(state.conversation.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_CUSTOM_VIEW', () => {
|
||||
it('[Conversation] delete custom view record', () => {
|
||||
const state = {
|
||||
conversation: { records: [customViewList[0]] },
|
||||
contact: { records: [] },
|
||||
};
|
||||
mutations[types.DELETE_CUSTOM_VIEW](state, {
|
||||
data: customViewList[0],
|
||||
filterType: 'conversation',
|
||||
});
|
||||
expect(state.conversation.records).toEqual([customViewList[0]]);
|
||||
expect(state.contact.records).toEqual([]);
|
||||
});
|
||||
|
||||
it('[Contact] delete custom view record', () => {
|
||||
const state = {
|
||||
contact: { records: [customViewList[0]] },
|
||||
conversation: { records: [] },
|
||||
};
|
||||
mutations[types.DELETE_CUSTOM_VIEW](state, {
|
||||
data: customViewList[0],
|
||||
filterType: 'contact',
|
||||
});
|
||||
expect(state.contact.records).toEqual([customViewList[0]]);
|
||||
expect(state.conversation.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_CUSTOM_VIEW', () => {
|
||||
it('[Conversation] update custom view record', () => {
|
||||
const state = {
|
||||
conversation: { records: [updateCustomViewList[0]] },
|
||||
contact: { records: [] },
|
||||
};
|
||||
mutations[types.UPDATE_CUSTOM_VIEW](state, {
|
||||
data: updateCustomViewList[0],
|
||||
filterType: 'conversation',
|
||||
});
|
||||
expect(state.conversation.records).toEqual(updateCustomViewList);
|
||||
expect(state.contact.records).toEqual([]);
|
||||
});
|
||||
|
||||
it('[Contact] update custom view record', () => {
|
||||
const state = {
|
||||
contact: { records: [updateCustomViewList[0]] },
|
||||
conversation: { records: [] },
|
||||
};
|
||||
mutations[types.UPDATE_CUSTOM_VIEW](state, {
|
||||
data: updateCustomViewList[0],
|
||||
filterType: 'contact',
|
||||
});
|
||||
expect(state.contact.records).toEqual(updateCustomViewList);
|
||||
expect(state.conversation.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ACTIVE_CONVERSATION_FOLDER', () => {
|
||||
it('set active conversation folder', () => {
|
||||
const state = { activeConversationFolder: customViewList[0] };
|
||||
mutations[types.SET_ACTIVE_CONVERSATION_FOLDER](state, customViewList[0]);
|
||||
expect(state.activeConversationFolder).toEqual(customViewList[0]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../dashboardApps';
|
||||
import types from '../../../mutation-types';
|
||||
import { payload, automationsList } from './fixtures';
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.get.mockResolvedValue({ data: [{ title: 'Title 1' }] });
|
||||
await actions.get({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_DASHBOARD_APPS, [{ title: 'Title 1' }]],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#create', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.post.mockResolvedValue({ data: payload });
|
||||
await actions.create({ commit }, payload);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isCreating: true }],
|
||||
[types.CREATE_DASHBOARD_APP, payload],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.post.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(actions.create({ commit })).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isCreating: true }],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isCreating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.patch.mockResolvedValue({ data: automationsList[0] });
|
||||
await actions.update({ commit }, automationsList[0]);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isUpdating: true }],
|
||||
[types.EDIT_DASHBOARD_APP, automationsList[0]],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.patch.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.update({ commit }, automationsList[0])
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions if API is success', async () => {
|
||||
axios.delete.mockResolvedValue({ data: automationsList[0] });
|
||||
await actions.delete({ commit }, automationsList[0].id);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isDeleting: true }],
|
||||
[types.DELETE_DASHBOARD_APP, automationsList[0].id],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
axios.delete.mockRejectedValue({ message: 'Incorrect header' });
|
||||
await expect(
|
||||
actions.delete({ commit }, automationsList[0].id)
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isDeleting: true }],
|
||||
[types.SET_DASHBOARD_APPS_UI_FLAG, { isDeleting: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
export const payload = {
|
||||
title: 'Test',
|
||||
content: [
|
||||
{ url: 'https://example.com', type: 'frame' },
|
||||
{ url: 'https://chatwoot.com', type: 'frame' },
|
||||
],
|
||||
};
|
||||
|
||||
export const automationsList = [
|
||||
{
|
||||
id: 15,
|
||||
title: 'Test',
|
||||
content: [
|
||||
{ url: 'https://example.com', type: 'frame' },
|
||||
{ url: 'https://chatwoot.com', type: 'frame' },
|
||||
],
|
||||
created_at: '2022-06-27T08:28:29.841Z',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,29 @@
|
||||
import { getters } from '../../dashboardApps';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getRecords', () => {
|
||||
const state = {
|
||||
records: [
|
||||
{
|
||||
title: '1',
|
||||
content: [{ link: 'https://google.com', type: 'frame' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(getters.getRecords(state)).toEqual(state.records);
|
||||
});
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isFetching: true,
|
||||
isCreating: false,
|
||||
isDeleting: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import types from '../../../mutation-types';
|
||||
import { mutations } from '../../dashboardApps';
|
||||
import { automationsList } from './fixtures';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_DASHBOARD_APPS_UI_FLAG', () => {
|
||||
it('set dashboard app ui flags', () => {
|
||||
const state = { uiFlags: { isCreating: false, isUpdating: false } };
|
||||
mutations[types.SET_DASHBOARD_APPS_UI_FLAG](state, { isUpdating: true });
|
||||
expect(state.uiFlags).toEqual({ isCreating: false, isUpdating: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_DASHBOARD_APPS', () => {
|
||||
it('set dashboard records', () => {
|
||||
const state = { records: [{ title: 'Title 0' }] };
|
||||
mutations[types.SET_DASHBOARD_APPS](state, [{ title: 'Title 1' }]);
|
||||
expect(state.records).toEqual([{ title: 'Title 1' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ADD_DASHBOARD_APP', () => {
|
||||
it('push newly created app to the store', () => {
|
||||
const state = { records: [automationsList[0]] };
|
||||
mutations[types.CREATE_DASHBOARD_APP](state, automationsList[1]);
|
||||
expect(state.records).toEqual([automationsList[0], automationsList[1]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#EDIT_DASHBOARD_APP', () => {
|
||||
it('update label record', () => {
|
||||
const state = { records: [automationsList[0]] };
|
||||
mutations[types.EDIT_DASHBOARD_APP](state, {
|
||||
id: 15,
|
||||
title: 'updated-title',
|
||||
});
|
||||
expect(state.records[0].title).toEqual('updated-title');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#DELETE_DASHBOARD_APP', () => {
|
||||
it('delete label record', () => {
|
||||
const state = { records: [automationsList[0]] };
|
||||
mutations[types.DELETE_DASHBOARD_APP](state, 15);
|
||||
expect(state.records).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import axios from 'axios';
|
||||
import { actions } from '../../draftMessages';
|
||||
import types from '../../../mutation-types';
|
||||
|
||||
const commit = vi.fn();
|
||||
global.axios = axios;
|
||||
vi.mock('axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#set', () => {
|
||||
it('sends correct actions', async () => {
|
||||
await actions.set(
|
||||
{
|
||||
commit,
|
||||
state: {
|
||||
draftMessages: {},
|
||||
},
|
||||
},
|
||||
{ key: 'draft-32-REPLY', message: 'Hey how ' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_DRAFT_MESSAGES,
|
||||
{
|
||||
key: 'draft-32-REPLY',
|
||||
message: 'Hey how ',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#delete', () => {
|
||||
it('sends correct actions', async () => {
|
||||
await actions.delete(
|
||||
{
|
||||
commit,
|
||||
state: {
|
||||
draftMessages: {},
|
||||
},
|
||||
},
|
||||
{ key: 'draft-32-REPLY' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_DRAFT_MESSAGES,
|
||||
{
|
||||
key: 'draft-32-REPLY',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setReplyEditorMode', () => {
|
||||
it('sends correct actions', async () => {
|
||||
await actions.setReplyEditorMode(
|
||||
{
|
||||
commit,
|
||||
state: {
|
||||
draftMessages: {},
|
||||
},
|
||||
},
|
||||
{ mode: 'reply' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
types.SET_REPLY_EDITOR_MODE,
|
||||
{
|
||||
mode: 'reply',
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
export const data = { 'draft-32-REPLY': 'Hey how ', 'draft-31-REPLY': 'Nice' };
|
||||
@@ -0,0 +1,25 @@
|
||||
import { getters } from '../../draftMessages';
|
||||
import { data } from './fixtures';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('return the payload if key is present', () => {
|
||||
const state = {
|
||||
records: data,
|
||||
};
|
||||
expect(getters.get(state)('draft-32-REPLY')).toEqual('Hey how ');
|
||||
});
|
||||
|
||||
it('return empty string if key is not present', () => {
|
||||
const state = {
|
||||
records: data,
|
||||
};
|
||||
expect(getters.get(state)('draft-22-REPLY')).toEqual('');
|
||||
});
|
||||
|
||||
it('return replyEditorMode', () => {
|
||||
const state = {
|
||||
replyEditorMode: 'reply',
|
||||
};
|
||||
expect(getters.getReplyEditorMode(state)).toEqual('reply');
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user