Restructure omni services and add Chatwoot research snapshot
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { actions } from '../../agent';
|
||||
import { agents } from './data';
|
||||
import { getFromCache, setCache } from 'shared/helpers/cache';
|
||||
import { getAvailableAgents } from 'widget/api/agent';
|
||||
|
||||
let commit = vi.fn();
|
||||
vi.mock('widget/helpers/axios');
|
||||
|
||||
vi.mock('widget/api/agent');
|
||||
vi.mock('shared/helpers/cache');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#fetchAvailableAgents', () => {
|
||||
const websiteToken = 'test-token';
|
||||
|
||||
beforeEach(() => {
|
||||
commit = vi.fn();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('returns cached data if available', async () => {
|
||||
getFromCache.mockReturnValue(agents);
|
||||
await actions.fetchAvailableAgents({ commit }, websiteToken);
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
`chatwoot_available_agents_${websiteToken}`
|
||||
);
|
||||
expect(getAvailableAgents).not.toHaveBeenCalled();
|
||||
expect(setCache).not.toHaveBeenCalled();
|
||||
expect(commit).toHaveBeenCalledWith('setAgents', agents);
|
||||
expect(commit).toHaveBeenCalledWith('setError', false);
|
||||
expect(commit).toHaveBeenCalledWith('setHasFetched', true);
|
||||
});
|
||||
|
||||
it('fetches and caches data if no cache available', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
getAvailableAgents.mockReturnValue({ data: { payload: agents } });
|
||||
|
||||
await actions.fetchAvailableAgents({ commit }, websiteToken);
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
`chatwoot_available_agents_${websiteToken}`
|
||||
);
|
||||
expect(getAvailableAgents).toHaveBeenCalledWith(websiteToken);
|
||||
expect(setCache).toHaveBeenCalledWith(
|
||||
`chatwoot_available_agents_${websiteToken}`,
|
||||
agents
|
||||
);
|
||||
expect(commit).toHaveBeenCalledWith('setAgents', agents);
|
||||
expect(commit).toHaveBeenCalledWith('setError', false);
|
||||
expect(commit).toHaveBeenCalledWith('setHasFetched', true);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is success', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
|
||||
getAvailableAgents.mockReturnValue({ data: { payload: agents } });
|
||||
await actions.fetchAvailableAgents({ commit }, 'Hi');
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setAgents', agents],
|
||||
['setError', false],
|
||||
['setHasFetched', true],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
|
||||
getAvailableAgents.mockRejectedValue({
|
||||
message: 'Authentication required',
|
||||
});
|
||||
await actions.fetchAvailableAgents({ commit }, 'Hi');
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setError', true],
|
||||
['setHasFetched', true],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updatePresence', () => {
|
||||
it('commits the correct presence value', () => {
|
||||
actions.updatePresence({ commit }, { 1: 'online' });
|
||||
expect(commit.mock.calls).toEqual([['updatePresence', { 1: 'online' }]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
export const agents = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Xavier',
|
||||
avatar_url: '',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Pranav',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Nithin',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,30 @@
|
||||
import { getters } from '../../agent';
|
||||
import { agents } from './data';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('availableAgents', () => {
|
||||
const state = {
|
||||
records: agents,
|
||||
};
|
||||
expect(getters.availableAgents(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Pranav',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Nithin',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
import { mutations } from '../../agent';
|
||||
import { agents } from './data';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#setAgents', () => {
|
||||
it('set agent records', () => {
|
||||
const state = { records: [] };
|
||||
mutations.setAgents(state, agents);
|
||||
expect(state.records).toEqual(agents);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setError', () => {
|
||||
it('set error flag', () => {
|
||||
const state = { records: [], uiFlags: {} };
|
||||
mutations.setError(state, true);
|
||||
expect(state.uiFlags.isError).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setHasFetched', () => {
|
||||
it('set fetched flag', () => {
|
||||
const state = { records: [], uiFlags: {} };
|
||||
mutations.setHasFetched(state, true);
|
||||
expect(state.uiFlags.hasFetched).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updatePresence', () => {
|
||||
it('updates agent presence', () => {
|
||||
const state = { records: agents };
|
||||
mutations.updatePresence(state, { 1: 'busy', 2: 'online' });
|
||||
expect(state.records).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'John',
|
||||
avatar_url: '',
|
||||
availability_status: 'busy',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Xavier',
|
||||
avatar_url: '',
|
||||
availability_status: 'online',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Pranav',
|
||||
avatar_url: '',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Nithin',
|
||||
avatar_url: '',
|
||||
availability_status: 'offline',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { actions } from '../../appConfig';
|
||||
|
||||
const commit = vi.fn();
|
||||
describe('#actions', () => {
|
||||
describe('#setReferrerHost', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setReferrerHost({ commit }, 'www.chatwoot.com');
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_REFERRER_HOST', 'www.chatwoot.com'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setBubbleVisibility', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setBubbleVisibility({ commit }, false);
|
||||
expect(commit.mock.calls).toEqual([['SET_BUBBLE_VISIBILITY', false]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setWidgetColor', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setWidgetColor({ commit }, '#eaeaea');
|
||||
expect(commit.mock.calls).toEqual([['SET_WIDGET_COLOR', '#eaeaea']]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setColorScheme', () => {
|
||||
it('creates actions for dark mode properly', () => {
|
||||
actions.setColorScheme({ commit }, 'dark');
|
||||
expect(commit.mock.calls).toEqual([['SET_COLOR_SCHEME', 'dark']]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setRouteTransitionState', () => {
|
||||
it('creates actions properly', () => {
|
||||
actions.setRouteTransitionState({ commit }, false);
|
||||
expect(commit.mock.calls).toEqual([['SET_ROUTE_UPDATE_STATE', false]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { getters } from '../../appConfig';
|
||||
|
||||
describe('#getters', () => {
|
||||
describe('#getWidgetColor', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { widgetColor: '#00bcd4' };
|
||||
expect(getters.getWidgetColor(state)).toEqual('#00bcd4');
|
||||
});
|
||||
});
|
||||
describe('#getReferrerHost', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { referrerHost: 'www.chatwoot.com' };
|
||||
expect(getters.getReferrerHost(state)).toEqual('www.chatwoot.com');
|
||||
});
|
||||
});
|
||||
describe('#getShowUnreadMessagesDialog', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { showUnreadMessagesDialog: true };
|
||||
expect(getters.getShowUnreadMessagesDialog(state)).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#getAvailableMessage', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { availableMessage: 'We reply quickly' };
|
||||
expect(getters.getAvailableMessage(state)).toEqual('We reply quickly');
|
||||
});
|
||||
});
|
||||
describe('#getWelcomeHeading', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { welcomeTitle: 'Hello!' };
|
||||
expect(getters.getWelcomeHeading(state)).toEqual('Hello!');
|
||||
});
|
||||
});
|
||||
describe('#getWelcomeTagline', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { welcomeDescription: 'Welcome to our site' };
|
||||
expect(getters.getWelcomeTagline(state)).toEqual('Welcome to our site');
|
||||
});
|
||||
});
|
||||
describe('#getShouldShowFilePicker', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { enableFileUpload: true };
|
||||
expect(getters.getShouldShowFilePicker(state)).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#getShouldShowEmojiPicker', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { enableEmojiPicker: true };
|
||||
expect(getters.getShouldShowEmojiPicker(state)).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#getCanUserEndConversation', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { enableEndConversation: true };
|
||||
expect(getters.getCanUserEndConversation(state)).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('#getUnavailableMessage', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { unavailableMessage: 'We are offline' };
|
||||
expect(getters.getUnavailableMessage(state)).toEqual('We are offline');
|
||||
});
|
||||
});
|
||||
describe('#getIsUpdatingRoute', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = { isUpdatingRoute: true };
|
||||
expect(getters.getIsUpdatingRoute(state)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import { mutations } from '../../appConfig';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_REFERRER_HOST', () => {
|
||||
it('sets referrer host properly', () => {
|
||||
const state = { referrerHost: '' };
|
||||
mutations.SET_REFERRER_HOST(state, 'www.chatwoot.com');
|
||||
expect(state.referrerHost).toEqual('www.chatwoot.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_BUBBLE_VISIBILITY', () => {
|
||||
it('sets bubble visibility properly', () => {
|
||||
const state = { hideMessageBubble: false };
|
||||
mutations.SET_BUBBLE_VISIBILITY(state, true);
|
||||
expect(state.hideMessageBubble).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_WIDGET_COLOR', () => {
|
||||
it('sets widget color properly', () => {
|
||||
const state = { widgetColor: '' };
|
||||
mutations.SET_WIDGET_COLOR(state, '#00bcd4');
|
||||
expect(state.widgetColor).toEqual('#00bcd4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_COLOR_SCHEME', () => {
|
||||
it('sets dark mode properly', () => {
|
||||
const state = { darkMode: 'light' };
|
||||
mutations.SET_COLOR_SCHEME(state, 'dark');
|
||||
expect(state.darkMode).toEqual('dark');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_ROUTE_UPDATE_STATE', () => {
|
||||
it('sets dark mode properly', () => {
|
||||
const state = { isUpdatingRoute: false };
|
||||
mutations.SET_ROUTE_UPDATE_STATE(state, true);
|
||||
expect(state.isUpdatingRoute).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,170 @@
|
||||
import { mutations, actions, getters } from '../articles';
|
||||
import { getMostReadArticles } from 'widget/api/article';
|
||||
import { getFromCache, setCache } from 'shared/helpers/cache';
|
||||
|
||||
vi.mock('widget/api/article');
|
||||
vi.mock('shared/helpers/cache');
|
||||
|
||||
describe('Vuex Articles Module', () => {
|
||||
let state;
|
||||
|
||||
beforeEach(() => {
|
||||
state = {
|
||||
records: [],
|
||||
uiFlags: {
|
||||
isError: false,
|
||||
hasFetched: false,
|
||||
isFetching: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('Mutations', () => {
|
||||
it('sets articles correctly', () => {
|
||||
const articles = [{ id: 1 }, { id: 2 }];
|
||||
mutations.setArticles(state, articles);
|
||||
expect(state.records).toEqual(articles);
|
||||
});
|
||||
|
||||
it('sets error flag correctly', () => {
|
||||
mutations.setError(state, true);
|
||||
expect(state.uiFlags.isError).toBe(true);
|
||||
});
|
||||
|
||||
it('sets fetching state correctly', () => {
|
||||
mutations.setIsFetching(state, true);
|
||||
expect(state.uiFlags.isFetching).toBe(true);
|
||||
});
|
||||
|
||||
it('does not mutate records when no articles are provided', () => {
|
||||
const previousState = { ...state };
|
||||
mutations.setArticles(state, []);
|
||||
expect(state.records).toEqual(previousState.records);
|
||||
});
|
||||
|
||||
it('toggles the error state correctly', () => {
|
||||
mutations.setError(state, true);
|
||||
expect(state.uiFlags.isError).toBe(true);
|
||||
mutations.setError(state, false);
|
||||
expect(state.uiFlags.isError).toBe(false);
|
||||
});
|
||||
|
||||
it('toggles the fetching state correctly', () => {
|
||||
mutations.setIsFetching(state, true);
|
||||
expect(state.uiFlags.isFetching).toBe(true);
|
||||
mutations.setIsFetching(state, false);
|
||||
expect(state.uiFlags.isFetching).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Actions', () => {
|
||||
describe('#fetch', () => {
|
||||
const slug = 'test-slug';
|
||||
const locale = 'en';
|
||||
const articles = [
|
||||
{ id: 1, title: 'Test' },
|
||||
{ id: 2, title: 'Test 2' },
|
||||
];
|
||||
let commit;
|
||||
|
||||
beforeEach(() => {
|
||||
commit = vi.fn();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('returns cached data if available', async () => {
|
||||
getFromCache.mockReturnValue(articles);
|
||||
|
||||
await actions.fetch({ commit }, { slug, locale });
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
`chatwoot_most_read_articles_${slug}_${locale}`
|
||||
);
|
||||
expect(getMostReadArticles).not.toHaveBeenCalled();
|
||||
expect(setCache).not.toHaveBeenCalled();
|
||||
expect(commit).toHaveBeenCalledWith('setArticles', articles);
|
||||
expect(commit).toHaveBeenCalledWith('setError', false);
|
||||
});
|
||||
|
||||
it('fetches and caches data if no cache available', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
getMostReadArticles.mockReturnValue({ data: { payload: articles } });
|
||||
|
||||
await actions.fetch({ commit }, { slug, locale });
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
`chatwoot_most_read_articles_${slug}_${locale}`
|
||||
);
|
||||
expect(getMostReadArticles).toHaveBeenCalledWith(slug, locale);
|
||||
expect(setCache).toHaveBeenCalledWith(
|
||||
`chatwoot_most_read_articles_${slug}_${locale}`,
|
||||
articles
|
||||
);
|
||||
expect(commit).toHaveBeenCalledWith('setArticles', articles);
|
||||
expect(commit).toHaveBeenCalledWith('setError', false);
|
||||
});
|
||||
|
||||
it('handles API errors correctly', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
getMostReadArticles.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
await actions.fetch({ commit }, { slug, locale });
|
||||
|
||||
expect(commit).toHaveBeenCalledWith('setError', true);
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', false);
|
||||
});
|
||||
|
||||
it('does not mutate state when fetching returns an empty payload', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
getMostReadArticles.mockReturnValue({ data: { payload: [] } });
|
||||
|
||||
await actions.fetch({ commit }, { slug, locale });
|
||||
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', true);
|
||||
expect(commit).toHaveBeenCalledWith('setError', false);
|
||||
expect(commit).not.toHaveBeenCalledWith(
|
||||
'setArticles',
|
||||
expect.any(Array)
|
||||
);
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', false);
|
||||
});
|
||||
|
||||
it('sets loading state during fetch', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
getMostReadArticles.mockReturnValue({ data: { payload: articles } });
|
||||
|
||||
await actions.fetch({ commit }, { slug, locale });
|
||||
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', true);
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', false);
|
||||
});
|
||||
});
|
||||
|
||||
it('sets error state when fetching fails', async () => {
|
||||
const commit = vi.fn();
|
||||
getMostReadArticles.mockRejectedValueOnce(new Error('Network error'));
|
||||
|
||||
await actions.fetch(
|
||||
{ commit },
|
||||
{ websiteToken: 'token', slug: 'slug', locale: 'en' }
|
||||
);
|
||||
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', true);
|
||||
expect(commit).toHaveBeenCalledWith('setError', true);
|
||||
expect(commit).not.toHaveBeenCalledWith('setArticles', expect.any(Array));
|
||||
expect(commit).toHaveBeenCalledWith('setIsFetching', false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Getters', () => {
|
||||
it('returns uiFlags correctly', () => {
|
||||
const result = getters.uiFlags(state);
|
||||
expect(result).toEqual(state.uiFlags);
|
||||
});
|
||||
|
||||
it('returns popularArticles correctly', () => {
|
||||
const result = getters.popularArticles(state);
|
||||
expect(result).toEqual(state.records);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,273 @@
|
||||
import { API } from 'widget/helpers/axios';
|
||||
import { actions } from '../../campaign';
|
||||
import { campaigns } from './data';
|
||||
import { getFromCache, setCache } from 'shared/helpers/cache';
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
vi.mock('widget/helpers/axios');
|
||||
vi.mock('shared/helpers/cache');
|
||||
|
||||
import campaignTimer from 'widget/helpers/campaignTimer';
|
||||
vi.mock('widget/helpers/campaignTimer', () => ({
|
||||
default: {
|
||||
initTimers: vi.fn().mockReturnValue({ mock: true }),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#fetchCampaigns', () => {
|
||||
beforeEach(() => {
|
||||
commit.mockClear();
|
||||
getFromCache.mockClear();
|
||||
setCache.mockClear();
|
||||
API.get.mockClear();
|
||||
campaignTimer.initTimers.mockClear();
|
||||
});
|
||||
|
||||
it('uses cached data when available', async () => {
|
||||
getFromCache.mockReturnValue(campaigns);
|
||||
|
||||
await actions.fetchCampaigns(
|
||||
{ commit },
|
||||
{
|
||||
websiteToken: 'XDsafmADasd',
|
||||
currentURL: 'https://chatwoot.com',
|
||||
isInBusinessHours: true,
|
||||
}
|
||||
);
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
'chatwoot_campaigns_XDsafmADasd',
|
||||
60 * 60 * 1000
|
||||
);
|
||||
expect(API.get).not.toHaveBeenCalled();
|
||||
expect(setCache).not.toHaveBeenCalled();
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setCampaigns', campaigns],
|
||||
['setError', false],
|
||||
]);
|
||||
expect(campaignTimer.initTimers).toHaveBeenCalledWith(
|
||||
{
|
||||
campaigns: [
|
||||
{
|
||||
id: 11,
|
||||
timeOnPage: '20',
|
||||
url: 'https://chatwoot.com',
|
||||
triggerOnlyDuringBusinessHours: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
'XDsafmADasd'
|
||||
);
|
||||
});
|
||||
|
||||
it('fetches and caches data when cache is not available', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
API.get.mockResolvedValue({ data: campaigns });
|
||||
|
||||
await actions.fetchCampaigns(
|
||||
{ commit },
|
||||
{
|
||||
websiteToken: 'XDsafmADasd',
|
||||
currentURL: 'https://chatwoot.com',
|
||||
isInBusinessHours: true,
|
||||
}
|
||||
);
|
||||
|
||||
expect(getFromCache).toHaveBeenCalledWith(
|
||||
'chatwoot_campaigns_XDsafmADasd',
|
||||
60 * 60 * 1000
|
||||
);
|
||||
expect(API.get).toHaveBeenCalled();
|
||||
expect(setCache).toHaveBeenCalledWith(
|
||||
'chatwoot_campaigns_XDsafmADasd',
|
||||
campaigns
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setCampaigns', campaigns],
|
||||
['setError', false],
|
||||
]);
|
||||
expect(campaignTimer.initTimers).toHaveBeenCalledWith(
|
||||
{
|
||||
campaigns: [
|
||||
{
|
||||
id: 11,
|
||||
timeOnPage: '20',
|
||||
url: 'https://chatwoot.com',
|
||||
triggerOnlyDuringBusinessHours: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
'XDsafmADasd'
|
||||
);
|
||||
});
|
||||
|
||||
it('sends correct actions if API is error', async () => {
|
||||
getFromCache.mockReturnValue(null);
|
||||
API.get.mockRejectedValue({ message: 'Authentication required' });
|
||||
await actions.fetchCampaigns(
|
||||
{ commit },
|
||||
{
|
||||
websiteToken: 'XDsafmADasd',
|
||||
currentURL: 'https://www.chatwoot.com',
|
||||
isInBusinessHours: true,
|
||||
}
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([['setError', true]]);
|
||||
});
|
||||
});
|
||||
describe('#initCampaigns', () => {
|
||||
const actionParams = {
|
||||
websiteToken: 'XDsafmADasd',
|
||||
currentURL: 'https://chatwoot.com',
|
||||
};
|
||||
it('sends correct actions if campaigns are empty', async () => {
|
||||
await actions.initCampaigns(
|
||||
{
|
||||
dispatch,
|
||||
getters: { getCampaigns: [], getUIFlags: { hasFetched: false } },
|
||||
},
|
||||
actionParams
|
||||
);
|
||||
expect(dispatch.mock.calls).toEqual([['fetchCampaigns', actionParams]]);
|
||||
expect(campaignTimer.initTimers).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('do not refetch if the campaigns are fetched once', async () => {
|
||||
await actions.initCampaigns(
|
||||
{
|
||||
dispatch,
|
||||
getters: { getCampaigns: [], getUIFlags: { hasFetched: true } },
|
||||
},
|
||||
actionParams
|
||||
);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
expect(campaignTimer.initTimers).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('resets time if campaigns are available', async () => {
|
||||
await actions.initCampaigns(
|
||||
{
|
||||
dispatch,
|
||||
getters: {
|
||||
getCampaigns: campaigns,
|
||||
getUIFlags: { hasFetched: true },
|
||||
},
|
||||
},
|
||||
actionParams
|
||||
);
|
||||
expect(dispatch.mock.calls).toEqual([]);
|
||||
expect(campaignTimer.initTimers).toHaveBeenCalledWith(
|
||||
{
|
||||
campaigns: [
|
||||
{
|
||||
id: 11,
|
||||
timeOnPage: '20',
|
||||
url: 'https://chatwoot.com',
|
||||
triggerOnlyDuringBusinessHours: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
'XDsafmADasd'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('#startCampaign', () => {
|
||||
it('reset campaign if campaign id is not present in the campaign list', async () => {
|
||||
API.get.mockResolvedValue({ data: campaigns });
|
||||
await actions.startCampaign(
|
||||
{
|
||||
dispatch,
|
||||
getters: { getCampaigns: campaigns },
|
||||
commit,
|
||||
rootState: {
|
||||
appConfig: { isWidgetOpen: true },
|
||||
},
|
||||
},
|
||||
{ campaignId: 32 }
|
||||
);
|
||||
});
|
||||
it('start campaign if campaign id passed', async () => {
|
||||
API.get.mockResolvedValue({ data: campaigns });
|
||||
await actions.startCampaign(
|
||||
{
|
||||
dispatch,
|
||||
getters: { getCampaigns: campaigns },
|
||||
commit,
|
||||
rootState: {
|
||||
appConfig: { isWidgetOpen: false },
|
||||
},
|
||||
},
|
||||
{ campaignId: 1 }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([['setActiveCampaign', campaigns[0]]]);
|
||||
});
|
||||
});
|
||||
describe('#executeCampaign', () => {
|
||||
it('sends correct actions if execute campaign API is success', async () => {
|
||||
const params = { campaignId: 12, websiteToken: 'XDsafmADasd' };
|
||||
API.post.mockResolvedValue({});
|
||||
await actions.executeCampaign({ commit }, params);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
'conversation/setConversationUIFlag',
|
||||
{
|
||||
isCreating: true,
|
||||
},
|
||||
{
|
||||
root: true,
|
||||
},
|
||||
],
|
||||
['setCampaignExecuted', true],
|
||||
['setActiveCampaign', {}],
|
||||
[
|
||||
'conversation/setConversationUIFlag',
|
||||
{
|
||||
isCreating: false,
|
||||
},
|
||||
{
|
||||
root: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if execute campaign API is failed', async () => {
|
||||
const params = { campaignId: 12, websiteToken: 'XDsafmADasd' };
|
||||
API.post.mockRejectedValue({ message: 'Authentication required' });
|
||||
await actions.executeCampaign({ commit }, params);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[
|
||||
'conversation/setConversationUIFlag',
|
||||
{
|
||||
isCreating: true,
|
||||
},
|
||||
{
|
||||
root: true,
|
||||
},
|
||||
],
|
||||
['setError', true],
|
||||
[
|
||||
'conversation/setConversationUIFlag',
|
||||
{
|
||||
isCreating: false,
|
||||
},
|
||||
{
|
||||
root: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#resetCampaign', () => {
|
||||
it('sends correct actions if execute campaign API is success', async () => {
|
||||
API.post.mockResolvedValue({});
|
||||
await actions.resetCampaign({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setCampaignExecuted', false],
|
||||
['setActiveCampaign', {}],
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
export const campaigns = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Welcome',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'Chatwoot',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'sojan@chatwoot.com',
|
||||
available_name: 'Sojan',
|
||||
id: 10,
|
||||
name: 'Sojan',
|
||||
},
|
||||
message: 'Hey, What brings you today',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://github.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
created_at: '2021-05-03T04:53:36.354Z',
|
||||
updated_at: '2021-05-03T04:53:36.354Z',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
title: 'Onboarding Campaign',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'GitX',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'sojan@chatwoot.com',
|
||||
available_name: 'Sojan',
|
||||
id: 10,
|
||||
},
|
||||
message: 'Begin your onboarding campaign with a welcome message',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://chatwoot.com',
|
||||
time_on_page: '20',
|
||||
},
|
||||
created_at: '2021-05-03T08:15:35.828Z',
|
||||
updated_at: '2021-05-03T08:15:35.828Z',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
title: 'Thanks',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'Chatwoot',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'nithin@chatwoot.com',
|
||||
available_name: 'Nithin',
|
||||
},
|
||||
message: 'Thanks for coming to the show. How may I help you?',
|
||||
enabled: false,
|
||||
trigger_rules: {
|
||||
url: 'https://noshow.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
created_at: '2021-05-03T10:22:51.025Z',
|
||||
updated_at: '2021-05-03T10:22:51.025Z',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,133 @@
|
||||
import { getters } from '../../campaign';
|
||||
import { campaigns } from './data';
|
||||
vi.mock('widget/store/index.js', () => ({
|
||||
default: {},
|
||||
}));
|
||||
describe('#getters', () => {
|
||||
it('getCampaigns', () => {
|
||||
const state = {
|
||||
records: campaigns,
|
||||
};
|
||||
expect(getters.getCampaigns(state)).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
title: 'Welcome',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'Chatwoot',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'sojan@chatwoot.com',
|
||||
available_name: 'Sojan',
|
||||
id: 10,
|
||||
name: 'Sojan',
|
||||
},
|
||||
message: 'Hey, What brings you today',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://github.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
created_at: '2021-05-03T04:53:36.354Z',
|
||||
updated_at: '2021-05-03T04:53:36.354Z',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
title: 'Onboarding Campaign',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'GitX',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'sojan@chatwoot.com',
|
||||
available_name: 'Sojan',
|
||||
id: 10,
|
||||
},
|
||||
message: 'Begin your onboarding campaign with a welcome message',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://chatwoot.com',
|
||||
time_on_page: '20',
|
||||
},
|
||||
created_at: '2021-05-03T08:15:35.828Z',
|
||||
updated_at: '2021-05-03T08:15:35.828Z',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
title: 'Thanks',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'Chatwoot',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'nithin@chatwoot.com',
|
||||
available_name: 'Nithin',
|
||||
},
|
||||
message: 'Thanks for coming to the show. How may I help you?',
|
||||
enabled: false,
|
||||
trigger_rules: {
|
||||
url: 'https://noshow.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
created_at: '2021-05-03T10:22:51.025Z',
|
||||
updated_at: '2021-05-03T10:22:51.025Z',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('getActiveCampaign', () => {
|
||||
const state = {
|
||||
records: campaigns[0],
|
||||
};
|
||||
expect(getters.getCampaigns(state)).toEqual({
|
||||
id: 1,
|
||||
title: 'Welcome',
|
||||
description: null,
|
||||
account_id: 1,
|
||||
inbox: {
|
||||
id: 37,
|
||||
channel_id: 1,
|
||||
name: 'Chatwoot',
|
||||
channel_type: 'Channel::WebWidget',
|
||||
},
|
||||
sender: {
|
||||
account_id: 1,
|
||||
availability_status: 'offline',
|
||||
confirmed: true,
|
||||
email: 'sojan@chatwoot.com',
|
||||
available_name: 'Sojan',
|
||||
id: 10,
|
||||
name: 'Sojan',
|
||||
},
|
||||
message: 'Hey, What brings you today',
|
||||
enabled: true,
|
||||
trigger_rules: {
|
||||
url: 'https://github.com',
|
||||
time_on_page: 10,
|
||||
},
|
||||
created_at: '2021-05-03T04:53:36.354Z',
|
||||
updated_at: '2021-05-03T04:53:36.354Z',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { mutations } from '../../campaign';
|
||||
import { campaigns } from './data';
|
||||
vi.mock('widget/store/index.js', () => ({
|
||||
default: {},
|
||||
}));
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#setCampaigns', () => {
|
||||
it('set campaign records', () => {
|
||||
const state = { records: [], uiFlags: {} };
|
||||
mutations.setCampaigns(state, campaigns);
|
||||
expect(state.records).toEqual(campaigns);
|
||||
expect(state.uiFlags.hasFetched).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setError', () => {
|
||||
it('set error flag', () => {
|
||||
const state = { records: [], uiFlags: {} };
|
||||
mutations.setError(state, true);
|
||||
expect(state.uiFlags.isError).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setActiveCampaign', () => {
|
||||
it('set active campaign', () => {
|
||||
const state = { records: [] };
|
||||
mutations.setActiveCampaign(state, campaigns[0]);
|
||||
expect(state.activeCampaign).toEqual(campaigns[0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setCampaignExecuted', () => {
|
||||
it('set campaign executed flag', () => {
|
||||
const state = { records: [], uiFlags: {}, campaignHasExecuted: false };
|
||||
mutations.setCampaignExecuted(state, true);
|
||||
expect(state.campaignHasExecuted).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
import { API } from 'widget/helpers/axios';
|
||||
import { sendMessage } from 'widget/helpers/utils';
|
||||
import { actions } from '../../contacts';
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
|
||||
vi.mock('widget/helpers/axios');
|
||||
vi.mock('widget/helpers/utils', () => ({
|
||||
sendMessage: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#setUser', () => {
|
||||
it('sends correct actions if contact object is refreshed ', async () => {
|
||||
const user = {
|
||||
email: 'thoma@sphadikam.com',
|
||||
name: 'Adu Thoma',
|
||||
avatar_url: '',
|
||||
};
|
||||
vi.spyOn(API, 'patch').mockResolvedValue({
|
||||
data: { widget_auth_token: 'token' },
|
||||
});
|
||||
await actions.setUser({ commit, dispatch }, { identifier: 1, user });
|
||||
expect(sendMessage.mock.calls).toEqual([
|
||||
[{ data: { widgetAuthToken: 'token' }, event: 'setAuthCookie' }],
|
||||
]);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
['get'],
|
||||
['conversation/clearConversations', {}, { root: true }],
|
||||
['conversation/fetchOldConversations', {}, { root: true }],
|
||||
['conversationAttributes/getAttributes', {}, { root: true }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('sends correct actions if identifierHash is passed ', async () => {
|
||||
const user = {
|
||||
email: 'thoma@sphadikam.com',
|
||||
name: 'Adu Thoma',
|
||||
avatar_url: '',
|
||||
identifier_hash: '12345',
|
||||
};
|
||||
vi.spyOn(API, 'patch').mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.setUser({ commit, dispatch }, { identifier: 1, user });
|
||||
expect(sendMessage.mock.calls).toEqual([]);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
['get'],
|
||||
['conversation/clearConversations', {}, { root: true }],
|
||||
['conversation/fetchOldConversations', {}, { root: true }],
|
||||
['conversationAttributes/getAttributes', {}, { root: true }],
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not call sendMessage if contact object is not refreshed ', async () => {
|
||||
const user = {
|
||||
email: 'thoma@sphadikam.com',
|
||||
name: 'Adu Thoma',
|
||||
avatar_url: '',
|
||||
};
|
||||
API.patch.mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.setUser({ commit, dispatch }, { identifier: 1, user });
|
||||
expect(sendMessage.mock.calls).toEqual([]);
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([['get']]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update', () => {
|
||||
it('sends correct actions', async () => {
|
||||
const user = {
|
||||
email: 'thoma@sphadikam.com',
|
||||
name: 'Adu Thoma',
|
||||
avatar_url: '',
|
||||
identifier_hash: 'random_hex_identifier_hash',
|
||||
};
|
||||
API.patch.mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.update({ commit, dispatch }, { identifier: 1, user });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
expect(dispatch.mock.calls).toEqual([['get']]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { getters } from '../../contacts';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getCurrentUser', () => {
|
||||
const user = {
|
||||
has_email: true,
|
||||
has_name: true,
|
||||
avatar_url: '',
|
||||
identifier_hash: 'malana_hash',
|
||||
};
|
||||
const state = {
|
||||
currentUser: user,
|
||||
};
|
||||
expect(getters.getCurrentUser(state)).toEqual({
|
||||
has_email: true,
|
||||
has_name: true,
|
||||
avatar_url: '',
|
||||
identifier_hash: 'malana_hash',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { mutations } from '../../contacts';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CURRENT_USER', () => {
|
||||
it('set current user', () => {
|
||||
const user = {
|
||||
has_email: true,
|
||||
has_name: true,
|
||||
avatar_url: '',
|
||||
identifier_hash: 'malana_hash',
|
||||
};
|
||||
const state = { currentUser: {} };
|
||||
mutations.SET_CURRENT_USER(state, user);
|
||||
expect(state.currentUser).toEqual(user);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,434 @@
|
||||
import { actions } from '../../conversation/actions';
|
||||
import getUuid from '../../../../helpers/uuid';
|
||||
import { API } from 'widget/helpers/axios';
|
||||
|
||||
vi.mock('../../../../helpers/uuid');
|
||||
vi.mock('widget/helpers/axios');
|
||||
|
||||
const commit = vi.fn();
|
||||
const dispatch = vi.fn();
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#createConversation', () => {
|
||||
it('sends correct mutations', async () => {
|
||||
API.post.mockResolvedValue({
|
||||
data: {
|
||||
contact: { name: 'contact-name' },
|
||||
messages: [{ id: 1, content: 'This is a test message' }],
|
||||
},
|
||||
});
|
||||
|
||||
let windowSpy = vi.spyOn(window, 'window', 'get');
|
||||
windowSpy.mockImplementation(() => ({
|
||||
WOOT_WIDGET: {
|
||||
$root: {
|
||||
$i18n: {
|
||||
locale: 'el',
|
||||
},
|
||||
},
|
||||
},
|
||||
location: {
|
||||
search: '?param=1',
|
||||
},
|
||||
}));
|
||||
await actions.createConversation(
|
||||
{ commit },
|
||||
{ contact: {}, message: 'This is a test message' }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setConversationUIFlag', { isCreating: true }],
|
||||
[
|
||||
'pushMessageToConversation',
|
||||
{ id: 1, content: 'This is a test message' },
|
||||
],
|
||||
['setConversationUIFlag', { isCreating: false }],
|
||||
]);
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addOrUpdateMessage', () => {
|
||||
it('sends correct actions for non-deleted message', () => {
|
||||
actions.addOrUpdateMessage(
|
||||
{ commit },
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hey',
|
||||
content_attributes: {},
|
||||
}
|
||||
);
|
||||
expect(commit).toBeCalledWith('pushMessageToConversation', {
|
||||
id: 1,
|
||||
content: 'Hey',
|
||||
content_attributes: {},
|
||||
});
|
||||
});
|
||||
it('sends correct actions for non-deleted message', () => {
|
||||
actions.addOrUpdateMessage(
|
||||
{ commit },
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hey',
|
||||
content_attributes: { deleted: true },
|
||||
}
|
||||
);
|
||||
expect(commit).toBeCalledWith('deleteMessage', 1);
|
||||
});
|
||||
|
||||
it('plays audio when agent sends a message', () => {
|
||||
actions.addOrUpdateMessage({ commit }, { id: 1, message_type: 1 });
|
||||
expect(commit).toBeCalledWith('pushMessageToConversation', {
|
||||
id: 1,
|
||||
message_type: 1,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#toggleAgentTyping', () => {
|
||||
it('sends correct mutations', () => {
|
||||
actions.toggleAgentTyping({ commit }, { status: true });
|
||||
expect(commit).toBeCalledWith('toggleAgentTypingStatus', {
|
||||
status: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#sendMessage', () => {
|
||||
it('sends correct mutations', async () => {
|
||||
const mockDate = new Date(1466424490000);
|
||||
getUuid.mockImplementationOnce(() => '1111');
|
||||
const spy = vi.spyOn(global, 'Date').mockImplementation(() => mockDate);
|
||||
const windowSpy = vi.spyOn(window, 'window', 'get');
|
||||
windowSpy.mockImplementation(() => ({
|
||||
WOOT_WIDGET: {
|
||||
$root: {
|
||||
$i18n: {
|
||||
locale: 'ar',
|
||||
},
|
||||
},
|
||||
},
|
||||
location: {
|
||||
search: '?param=1',
|
||||
},
|
||||
}));
|
||||
await actions.sendMessage(
|
||||
{ commit, dispatch },
|
||||
{ content: 'hello', replyTo: 124 }
|
||||
);
|
||||
spy.mockRestore();
|
||||
windowSpy.mockRestore();
|
||||
expect(dispatch).toBeCalledWith('sendMessageWithData', {
|
||||
attachments: undefined,
|
||||
content: 'hello',
|
||||
created_at: 1466424490,
|
||||
id: '1111',
|
||||
message_type: 0,
|
||||
replyTo: 124,
|
||||
status: 'in_progress',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#sendAttachment', () => {
|
||||
it('sends correct mutations', () => {
|
||||
const mockDate = new Date(1466424490000);
|
||||
getUuid.mockImplementationOnce(() => '1111');
|
||||
const spy = vi.spyOn(global, 'Date').mockImplementation(() => mockDate);
|
||||
const thumbUrl = '';
|
||||
const attachment = { thumbUrl, fileType: 'file' };
|
||||
|
||||
actions.sendAttachment(
|
||||
{ commit, dispatch },
|
||||
{ attachment, replyTo: 135 }
|
||||
);
|
||||
spy.mockRestore();
|
||||
expect(commit).toBeCalledWith('pushMessageToConversation', {
|
||||
id: '1111',
|
||||
content: undefined,
|
||||
status: 'in_progress',
|
||||
created_at: 1466424490,
|
||||
message_type: 0,
|
||||
replyTo: 135,
|
||||
attachments: [
|
||||
{
|
||||
thumb_url: '',
|
||||
data_url: '',
|
||||
file_type: 'file',
|
||||
status: 'in_progress',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setUserLastSeen', () => {
|
||||
it('sends correct mutations', async () => {
|
||||
API.post.mockResolvedValue({ data: { success: true } });
|
||||
await actions.setUserLastSeen({
|
||||
commit,
|
||||
getters: { getConversationSize: 2 },
|
||||
});
|
||||
expect(commit.mock.calls[0][0]).toEqual('setMetaUserLastSeenAt');
|
||||
});
|
||||
it('sends correct mutations', async () => {
|
||||
API.post.mockResolvedValue({ data: { success: true } });
|
||||
await actions.setUserLastSeen({
|
||||
commit,
|
||||
getters: { getConversationSize: 0 },
|
||||
});
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearConversations', () => {
|
||||
it('sends correct mutations', () => {
|
||||
actions.clearConversations({ commit });
|
||||
expect(commit).toBeCalledWith('clearConversations');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fetchOldConversations', () => {
|
||||
it('sends correct actions', async () => {
|
||||
API.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [
|
||||
{
|
||||
id: 1,
|
||||
text: 'hey',
|
||||
content_attributes: {},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'welcome',
|
||||
content_attributes: { deleted: true },
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
contact_last_seen_at: 1466424490,
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.fetchOldConversations({ commit }, {});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['setConversationListLoading', true],
|
||||
['conversation/setMetaUserLastSeenAt', 1466424490, { root: true }],
|
||||
[
|
||||
'setMessagesInConversation',
|
||||
[
|
||||
{
|
||||
id: 1,
|
||||
text: 'hey',
|
||||
content_attributes: {},
|
||||
},
|
||||
],
|
||||
],
|
||||
['setConversationListLoading', false],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#syncLatestMessages', () => {
|
||||
it('latest message should append to end of list', async () => {
|
||||
const state = {
|
||||
uiFlags: { allMessagesLoaded: false },
|
||||
conversations: {
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682244355, // Sunday, 23 April 2023 10:05:55
|
||||
conversation_id: 20,
|
||||
},
|
||||
463: {
|
||||
id: 463,
|
||||
content: 'ss',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729, // Wednesday, 26 April 2023 06:32:09
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
lastMessageId: 463,
|
||||
};
|
||||
API.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [
|
||||
{
|
||||
id: 465,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682504326, // Wednesday, 26 April 2023 10:18:46
|
||||
conversation_id: 20,
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
contact_last_seen_at: 1466424490,
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.syncLatestMessages({ state, commit }, {});
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['conversation/setMetaUserLastSeenAt', 1466424490, { root: true }],
|
||||
[
|
||||
'setMissingMessagesInConversation',
|
||||
|
||||
{
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682244355,
|
||||
conversation_id: 20,
|
||||
},
|
||||
463: {
|
||||
id: 463,
|
||||
content: 'ss',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729,
|
||||
conversation_id: 20,
|
||||
},
|
||||
465: {
|
||||
id: 465,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682504326,
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('old message should insert to exact position', async () => {
|
||||
const state = {
|
||||
uiFlags: { allMessagesLoaded: false },
|
||||
conversations: {
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682244355, // Sunday, 23 April 2023 10:05:55
|
||||
conversation_id: 20,
|
||||
},
|
||||
463: {
|
||||
id: 463,
|
||||
content: 'ss',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729, // Wednesday, 26 April 2023 06:32:09
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
lastMessageId: 463,
|
||||
};
|
||||
API.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [
|
||||
{
|
||||
id: 460,
|
||||
content: 'Hi how are you',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682417926, // Tuesday, 25 April 2023 10:18:46
|
||||
conversation_id: 20,
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
contact_last_seen_at: 14664223490,
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.syncLatestMessages({ state, commit }, {});
|
||||
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['conversation/setMetaUserLastSeenAt', 14664223490, { root: true }],
|
||||
[
|
||||
'setMissingMessagesInConversation',
|
||||
|
||||
{
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682244355,
|
||||
conversation_id: 20,
|
||||
},
|
||||
460: {
|
||||
id: 460,
|
||||
content: 'Hi how are you',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682417926,
|
||||
conversation_id: 20,
|
||||
},
|
||||
463: {
|
||||
id: 463,
|
||||
content: 'ss',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729,
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('abort syncing if there is no missing messages ', async () => {
|
||||
const state = {
|
||||
uiFlags: { allMessagesLoaded: false },
|
||||
conversation: {
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682244355, // Sunday, 23 April 2023 10:05:55
|
||||
conversation_id: 20,
|
||||
},
|
||||
463: {
|
||||
id: 463,
|
||||
content: 'ss',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729, // Wednesday, 26 April 2023 06:32:09
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
lastMessageId: 463,
|
||||
};
|
||||
API.get.mockResolvedValue({
|
||||
data: {
|
||||
payload: [],
|
||||
meta: {
|
||||
contact_last_seen_at: 14664223490,
|
||||
},
|
||||
},
|
||||
});
|
||||
await actions.syncLatestMessages({ state, commit }, {});
|
||||
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,477 @@
|
||||
import { getters } from '../../conversation/getters';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getConversation', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
content: 'hello',
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getters.getConversation(state)).toEqual({
|
||||
1: {
|
||||
content: 'hello',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('getIsCreating', () => {
|
||||
const state = { uiFlags: { isCreating: true } };
|
||||
expect(getters.getIsCreating(state)).toEqual(true);
|
||||
});
|
||||
|
||||
it('getConversationSize', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
content: 'hello',
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getters.getConversationSize(state)).toEqual(1);
|
||||
});
|
||||
|
||||
it('getEarliestMessage', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
content: 'hello',
|
||||
},
|
||||
2: {
|
||||
content: 'hello1',
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getters.getEarliestMessage(state)).toEqual({
|
||||
content: 'hello',
|
||||
});
|
||||
});
|
||||
|
||||
it('uiFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
allMessagesLoaded: false,
|
||||
isFetchingList: false,
|
||||
isAgentTyping: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getAllMessagesLoaded(state)).toEqual(false);
|
||||
expect(getters.getIsFetchingList(state)).toEqual(false);
|
||||
expect(getters.getIsAgentTyping(state)).toEqual(false);
|
||||
});
|
||||
|
||||
it('getGroupedConversation', () => {
|
||||
expect(
|
||||
getters.getGroupedConversation({
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 0,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
4: {
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
},
|
||||
5: {
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
date: 'Nov 18, 2019',
|
||||
messages: [
|
||||
{
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
showAvatar: false,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: 'Dec 14, 2019',
|
||||
messages: [
|
||||
{
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
showAvatar: false,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
showAvatar: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(
|
||||
getters.getGroupedConversation({
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 0,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
4: {
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
},
|
||||
5: {
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
content_attributes: {
|
||||
submitted_values: [{ name: 'text', value: 'sample text' }],
|
||||
},
|
||||
},
|
||||
6: {
|
||||
id: 6,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
},
|
||||
7: {
|
||||
id: 7,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
content_attributes: {
|
||||
submitted_values: [{ name: 'text', value: 'sample text' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
date: 'Nov 18, 2019',
|
||||
messages: [
|
||||
{
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
showAvatar: false,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 0,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'Hey',
|
||||
created_at: 1574092218,
|
||||
showAvatar: true,
|
||||
message_type: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: 'Dec 14, 2019',
|
||||
messages: [
|
||||
{
|
||||
id: 4,
|
||||
content: 'Hey',
|
||||
created_at: 1576340623,
|
||||
showAvatar: true,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
content_attributes: {
|
||||
submitted_values: [{ name: 'text', value: 'sample text' }],
|
||||
},
|
||||
showAvatar: false,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
showAvatar: true,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
content: 'How may I help you',
|
||||
created_at: 1576340626,
|
||||
message_type: 2,
|
||||
content_type: 'form',
|
||||
content_attributes: {
|
||||
submitted_values: [{ name: 'text', value: 'sample text' }],
|
||||
},
|
||||
|
||||
showAvatar: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe('getUnreadMessageCount returns', () => {
|
||||
it('0 if there are no messages and last seen is undefined', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: undefined,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
|
||||
it('0 if there are no messages and last seen is present', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: Date.now(),
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
|
||||
it('unread count if there are messages and last seen is before messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1474075964,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(2);
|
||||
});
|
||||
|
||||
it('unread count if there are messages and last seen is after messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1674075964,
|
||||
},
|
||||
};
|
||||
expect(getters.getUnreadMessageCount(state)).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUnreadTextMessages returns', () => {
|
||||
it('no messages if there are no messages and last seen is undefined', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: undefined,
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 0 })
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it('0 if there are no messages and last seen is present', () => {
|
||||
const state = {
|
||||
conversations: {},
|
||||
meta: {
|
||||
userLastSeenAt: Date.now(),
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 0 })
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it('only unread text messages from agent if there are messages and last seen is before messages created-at', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 1 })
|
||||
).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('unread messages omitting seen messages ', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1674075965,
|
||||
message_type: 1,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1674075964,
|
||||
},
|
||||
};
|
||||
expect(
|
||||
getters.getUnreadTextMessages(state, { getUnreadMessageCount: 1 })
|
||||
).toEqual([
|
||||
{
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1674075965,
|
||||
message_type: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it('getMessageCount', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
content: 'hey, how are you?',
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(getters.getMessageCount(state)).toEqual(1);
|
||||
});
|
||||
|
||||
it('getLastMessage', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Thanks for the help',
|
||||
created_at: 1574075964,
|
||||
message_type: 1,
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 1,
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'Yes, It makes sense',
|
||||
created_at: 1574092218,
|
||||
message_type: 0,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
userLastSeenAt: 1674075964,
|
||||
},
|
||||
};
|
||||
expect(getters.getLastMessage(state).id).toEqual(3);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
findUndeliveredMessage,
|
||||
createTemporaryMessage,
|
||||
getNonDeletedMessages,
|
||||
} from '../../conversation/helpers';
|
||||
|
||||
describe('#findUndeliveredMessage', () => {
|
||||
it('returns message objects if exist', () => {
|
||||
const conversation = {
|
||||
1: {
|
||||
id: 1,
|
||||
content: 'Hello',
|
||||
status: 'in_progress',
|
||||
},
|
||||
2: {
|
||||
id: 2,
|
||||
content: 'Hello',
|
||||
status: 'sent',
|
||||
},
|
||||
3: {
|
||||
id: 3,
|
||||
content: 'How may I help you',
|
||||
status: 'sent',
|
||||
},
|
||||
};
|
||||
expect(
|
||||
findUndeliveredMessage(conversation, { content: 'Hello' })
|
||||
).toStrictEqual([{ id: 1, content: 'Hello', status: 'in_progress' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createTemporaryMessage', () => {
|
||||
it('returns message object', () => {
|
||||
const message = createTemporaryMessage({ content: 'hello' });
|
||||
expect(message.content).toBe('hello');
|
||||
expect(message.status).toBe('in_progress');
|
||||
});
|
||||
it('returns message object with reply to', () => {
|
||||
const message = createTemporaryMessage({
|
||||
content: 'hello',
|
||||
replyTo: 124,
|
||||
});
|
||||
expect(message.content).toBe('hello');
|
||||
expect(message.status).toBe('in_progress');
|
||||
expect(message.replyTo).toBe(124);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getNonDeletedMessages', () => {
|
||||
it('returns non-deleted messages', () => {
|
||||
const messages = [
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hello',
|
||||
content_attributes: {},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: 'Hey',
|
||||
content_attributes: { deleted: true },
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'How may I help you',
|
||||
content_attributes: {},
|
||||
},
|
||||
];
|
||||
expect(getNonDeletedMessages({ messages })).toStrictEqual([
|
||||
{
|
||||
id: 1,
|
||||
content: 'Hello',
|
||||
content_attributes: {},
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: 'How may I help you',
|
||||
content_attributes: {},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,254 @@
|
||||
import { mutations } from '../../conversation/mutations';
|
||||
|
||||
const temporaryMessagePayload = {
|
||||
content: 'hello',
|
||||
id: 1,
|
||||
message_type: 0,
|
||||
status: 'in_progress',
|
||||
};
|
||||
|
||||
const incomingMessagePayload = {
|
||||
content: 'hello',
|
||||
id: 1,
|
||||
message_type: 0,
|
||||
status: 'sent',
|
||||
};
|
||||
|
||||
const outgoingMessagePayload = {
|
||||
content: 'hello',
|
||||
id: 1,
|
||||
message_type: 1,
|
||||
status: 'sent',
|
||||
};
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#pushMessageToConversation', () => {
|
||||
it('add message to conversation if outgoing', () => {
|
||||
const state = { conversations: {} };
|
||||
mutations.pushMessageToConversation(state, outgoingMessagePayload);
|
||||
expect(state.conversations).toEqual({
|
||||
1: outgoingMessagePayload,
|
||||
});
|
||||
});
|
||||
|
||||
it('add message to conversation if message in undelivered', () => {
|
||||
const state = { conversations: {} };
|
||||
mutations.pushMessageToConversation(state, temporaryMessagePayload);
|
||||
expect(state.conversations).toEqual({
|
||||
1: temporaryMessagePayload,
|
||||
});
|
||||
});
|
||||
|
||||
it('replaces temporary message in conversation with actual message', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
rand_id_123: {
|
||||
content: 'hello',
|
||||
id: 'rand_id_123',
|
||||
message_type: 0,
|
||||
status: 'in_progress',
|
||||
},
|
||||
},
|
||||
};
|
||||
mutations.pushMessageToConversation(state, incomingMessagePayload);
|
||||
expect(state.conversations).toEqual({
|
||||
1: incomingMessagePayload,
|
||||
});
|
||||
});
|
||||
|
||||
it('adds message in conversation if it is a new message', () => {
|
||||
const state = { conversations: {} };
|
||||
mutations.pushMessageToConversation(state, incomingMessagePayload);
|
||||
expect(state.conversations).toEqual({
|
||||
1: incomingMessagePayload,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setConversationListLoading', () => {
|
||||
it('set status correctly', () => {
|
||||
const state = { uiFlags: { isFetchingList: false } };
|
||||
mutations.setConversationListLoading(state, true);
|
||||
expect(state.uiFlags.isFetchingList).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setConversationUIFlag', () => {
|
||||
it('set uiFlags correctly', () => {
|
||||
const state = { uiFlags: { isFetchingList: false } };
|
||||
mutations.setConversationUIFlag(state, { isCreating: true });
|
||||
expect(state.uiFlags).toEqual({
|
||||
isFetchingList: false,
|
||||
isCreating: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setMessagesInConversation', () => {
|
||||
it('sets allMessagesLoaded flag if payload is empty', () => {
|
||||
const state = { uiFlags: { allMessagesLoaded: false } };
|
||||
mutations.setMessagesInConversation(state, []);
|
||||
expect(state.uiFlags.allMessagesLoaded).toEqual(true);
|
||||
});
|
||||
|
||||
it('sets messages if payload is not empty', () => {
|
||||
const state = {
|
||||
uiFlags: { allMessagesLoaded: false },
|
||||
conversations: {},
|
||||
};
|
||||
mutations.setMessagesInConversation(state, [{ id: 1, content: 'hello' }]);
|
||||
expect(state.conversations).toEqual({
|
||||
1: { id: 1, content: 'hello' },
|
||||
});
|
||||
expect(state.uiFlags.allMessagesLoaded).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#toggleAgentTypingStatus', () => {
|
||||
it('sets isAgentTyping flag to true', () => {
|
||||
const state = { uiFlags: { isAgentTyping: false } };
|
||||
mutations.toggleAgentTypingStatus(state, { status: 'on' });
|
||||
expect(state.uiFlags.isAgentTyping).toEqual(true);
|
||||
});
|
||||
|
||||
it('sets isAgentTyping flag to false', () => {
|
||||
const state = { uiFlags: { isAgentTyping: true } };
|
||||
mutations.toggleAgentTypingStatus(state, { status: 'off' });
|
||||
expect(state.uiFlags.isAgentTyping).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#updateAttachmentMessageStatus', () => {
|
||||
it('Updates status of loading messages if payload is not empty', () => {
|
||||
const state = {
|
||||
conversations: {
|
||||
rand_id_123: {
|
||||
content: '',
|
||||
id: 'rand_id_123',
|
||||
message_type: 0,
|
||||
status: 'in_progress',
|
||||
attachment: {
|
||||
file: '',
|
||||
file_type: 'image',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const message = {
|
||||
id: '1',
|
||||
content: '',
|
||||
status: 'sent',
|
||||
message_type: 0,
|
||||
attachments: [
|
||||
{
|
||||
file: '',
|
||||
file_type: 'image',
|
||||
},
|
||||
],
|
||||
};
|
||||
mutations.updateAttachmentMessageStatus(state, {
|
||||
message,
|
||||
tempId: 'rand_id_123',
|
||||
});
|
||||
|
||||
expect(state.conversations).toEqual({
|
||||
1: {
|
||||
id: '1',
|
||||
content: '',
|
||||
message_type: 0,
|
||||
status: 'sent',
|
||||
attachments: [
|
||||
{
|
||||
file: '',
|
||||
file_type: 'image',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearConversations', () => {
|
||||
it('clears the state', () => {
|
||||
const state = { conversations: { 1: { id: 1 } } };
|
||||
mutations.clearConversations(state);
|
||||
expect(state.conversations).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deleteMessage', () => {
|
||||
it('delete the message from conversation', () => {
|
||||
const state = { conversations: { 1: { id: 1 } } };
|
||||
mutations.deleteMessage(state, 1);
|
||||
expect(state.conversations).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setMissingMessages', () => {
|
||||
it('sets messages if payload is not empty', () => {
|
||||
const state = {
|
||||
uiFlags: { allMessagesLoaded: false },
|
||||
conversations: {
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682432667,
|
||||
conversation_id: 20,
|
||||
},
|
||||
464: {
|
||||
id: 464,
|
||||
content: 'hey will be back soon',
|
||||
message_type: 3,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729,
|
||||
conversation_id: 20,
|
||||
},
|
||||
},
|
||||
};
|
||||
mutations.setMessagesInConversation(state, [
|
||||
{
|
||||
id: 455,
|
||||
content: 'Hey billowing-grass-423 how are you?',
|
||||
message_type: 3,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682432667,
|
||||
conversation_id: 20,
|
||||
},
|
||||
]);
|
||||
expect(state.conversations).toEqual({
|
||||
454: {
|
||||
id: 454,
|
||||
content: 'hi',
|
||||
message_type: 0,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682432667,
|
||||
conversation_id: 20,
|
||||
},
|
||||
455: {
|
||||
id: 455,
|
||||
content: 'Hey billowing-grass-423 how are you?',
|
||||
message_type: 3,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682432667,
|
||||
conversation_id: 20,
|
||||
},
|
||||
464: {
|
||||
id: 464,
|
||||
content: 'hey will be back soon',
|
||||
message_type: 3,
|
||||
content_type: 'text',
|
||||
content_attributes: {},
|
||||
created_at: 1682490729,
|
||||
conversation_id: 20,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { actions } from '../../conversationAttributes';
|
||||
import { API } from 'widget/helpers/axios';
|
||||
|
||||
const commit = vi.fn();
|
||||
vi.mock('widget/helpers/axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#get attributes', () => {
|
||||
it('sends mutation if api is success', async () => {
|
||||
API.get.mockResolvedValue({ data: { id: 1, status: 'pending' } });
|
||||
await actions.getAttributes({ commit });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['SET_CONVERSATION_ATTRIBUTES', { id: 1, status: 'pending' }],
|
||||
['conversation/setMetaUserLastSeenAt', undefined, { root: true }],
|
||||
]);
|
||||
});
|
||||
it('doesnot send mutation if api is error', async () => {
|
||||
API.get.mockRejectedValue({ message: 'Invalid Headers' });
|
||||
await actions.getAttributes({ commit });
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#update attributes', () => {
|
||||
it('sends correct mutations', () => {
|
||||
actions.update({ commit }, { id: 1, status: 'pending' });
|
||||
expect(commit).toBeCalledWith('UPDATE_CONVERSATION_ATTRIBUTES', {
|
||||
id: 1,
|
||||
status: 'pending',
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('#clear attributes', () => {
|
||||
it('sends correct mutations', () => {
|
||||
actions.clearConversationAttributes({ commit });
|
||||
expect(commit).toBeCalledWith('CLEAR_CONVERSATION_ATTRIBUTES');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { getters } from '../../conversationAttributes';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getConversationParams', () => {
|
||||
const state = {
|
||||
id: 1,
|
||||
status: 'pending',
|
||||
};
|
||||
expect(getters.getConversationParams(state)).toEqual({
|
||||
id: 1,
|
||||
status: 'pending',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
import { mutations } from '../../conversationAttributes';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONVERSATION_ATTRIBUTES', () => {
|
||||
it('set status of the conversation', () => {
|
||||
const state = { id: '', status: '' };
|
||||
mutations.SET_CONVERSATION_ATTRIBUTES(state, {
|
||||
id: 1,
|
||||
status: 'open',
|
||||
});
|
||||
expect(state).toEqual({ id: 1, status: 'open' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#UPDATE_CONVERSATION_ATTRIBUTES', () => {
|
||||
it('update status if it is same conversation', () => {
|
||||
const state = { id: 1, status: 'pending' };
|
||||
mutations.UPDATE_CONVERSATION_ATTRIBUTES(state, {
|
||||
id: 1,
|
||||
status: 'open',
|
||||
});
|
||||
expect(state).toEqual({ id: 1, status: 'open' });
|
||||
});
|
||||
it('doesnot update status if it is not the same conversation', () => {
|
||||
const state = { id: 1, status: 'pending' };
|
||||
mutations.UPDATE_CONVERSATION_ATTRIBUTES(state, {
|
||||
id: 2,
|
||||
status: 'open',
|
||||
});
|
||||
expect(state).toEqual({ id: 1, status: 'pending' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('#CLEAR_CONVERSATION_ATTRIBUTES', () => {
|
||||
it('clear status if it is same conversation', () => {
|
||||
const state = { id: 1, status: 'open' };
|
||||
mutations.CLEAR_CONVERSATION_ATTRIBUTES(state, {
|
||||
id: 1,
|
||||
status: 'open',
|
||||
});
|
||||
expect(state).toEqual({ id: '', status: '' });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
import { API } from 'widget/helpers/axios';
|
||||
import { actions } from '../../message';
|
||||
|
||||
const commit = vi.fn();
|
||||
vi.mock('widget/helpers/axios');
|
||||
|
||||
describe('#actions', () => {
|
||||
describe('#update', () => {
|
||||
it('sends correct actions', async () => {
|
||||
const user = {
|
||||
email: 'john@acme.inc',
|
||||
messageId: 10,
|
||||
submittedValues: {
|
||||
email: 'john@acme.inc',
|
||||
},
|
||||
};
|
||||
API.patch.mockResolvedValue({
|
||||
data: { contact: { pubsub_token: '8npuMUfDgizrwVoqcK1t7FMY' } },
|
||||
});
|
||||
await actions.update(
|
||||
{
|
||||
commit,
|
||||
getters: {
|
||||
getUIFlags: {
|
||||
isUpdating: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
user
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
['toggleUpdateStatus', true],
|
||||
[
|
||||
'conversation/updateMessage',
|
||||
{
|
||||
id: 10,
|
||||
content_attributes: {
|
||||
submitted_email: 'john@acme.inc',
|
||||
submitted_values: null,
|
||||
},
|
||||
},
|
||||
{ root: true },
|
||||
],
|
||||
['toggleUpdateStatus', false],
|
||||
]);
|
||||
});
|
||||
|
||||
it('blocks all new action calls when isUpdating', async () => {
|
||||
await actions.update(
|
||||
{
|
||||
commit,
|
||||
getters: {
|
||||
getUIFlags: {
|
||||
isUpdating: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
expect(commit.mock.calls).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { getters } from '../../message';
|
||||
|
||||
describe('#getters', () => {
|
||||
it('getUIFlags', () => {
|
||||
const state = {
|
||||
uiFlags: {
|
||||
isUpdating: false,
|
||||
},
|
||||
};
|
||||
expect(getters.getUIFlags(state)).toEqual({
|
||||
isUpdating: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { mutations } from '../../message';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#toggleUpdateStatus', () => {
|
||||
it('set update flags', () => {
|
||||
const state = { uiFlags: { status: '' } };
|
||||
mutations.toggleUpdateStatus(state, 'sent');
|
||||
expect(state.uiFlags.isUpdating).toEqual('sent');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user