Restructure omni services and add Chatwoot research snapshot

This commit is contained in:
Ruslan Bakiev
2026-02-21 11:11:27 +07:00
parent edea7a0034
commit b73babbbf6
7732 changed files with 978203 additions and 32 deletions

View File

@@ -0,0 +1,41 @@
import accountAPI from '../account';
import ApiClient from '../ApiClient';
describe('#accountAPI', () => {
it('creates correct instance', () => {
expect(accountAPI).toBeInstanceOf(ApiClient);
expect(accountAPI).toHaveProperty('get');
expect(accountAPI).toHaveProperty('show');
expect(accountAPI).toHaveProperty('create');
expect(accountAPI).toHaveProperty('update');
expect(accountAPI).toHaveProperty('delete');
expect(accountAPI).toHaveProperty('createAccount');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#createAccount', () => {
accountAPI.createAccount({
name: 'Chatwoot',
});
expect(axiosMock.post).toHaveBeenCalledWith('/api/v1/accounts', {
name: 'Chatwoot',
});
});
});
});

View File

@@ -0,0 +1,38 @@
import accountActionsAPI from '../accountActions';
import ApiClient from '../ApiClient';
describe('#ContactsAPI', () => {
it('creates correct instance', () => {
expect(accountActionsAPI).toBeInstanceOf(ApiClient);
expect(accountActionsAPI).toHaveProperty('merge');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#merge', () => {
accountActionsAPI.merge(1, 2);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/actions/contact_merge',
{
base_contact_id: 1,
mergee_contact_id: 2,
}
);
});
});
});

View File

@@ -0,0 +1,14 @@
import AgentBotsAPI from '../agentBots';
import ApiClient from '../ApiClient';
describe('#AgentBotsAPI', () => {
it('creates correct instance', () => {
expect(AgentBotsAPI).toBeInstanceOf(ApiClient);
expect(AgentBotsAPI).toHaveProperty('get');
expect(AgentBotsAPI).toHaveProperty('show');
expect(AgentBotsAPI).toHaveProperty('create');
expect(AgentBotsAPI).toHaveProperty('update');
expect(AgentBotsAPI).toHaveProperty('delete');
expect(AgentBotsAPI).toHaveProperty('resetAccessToken');
});
});

View File

@@ -0,0 +1,98 @@
import agentCapacityPolicies from '../agentCapacityPolicies';
import ApiClient from '../ApiClient';
describe('#AgentCapacityPoliciesAPI', () => {
it('creates correct instance', () => {
expect(agentCapacityPolicies).toBeInstanceOf(ApiClient);
expect(agentCapacityPolicies).toHaveProperty('get');
expect(agentCapacityPolicies).toHaveProperty('show');
expect(agentCapacityPolicies).toHaveProperty('create');
expect(agentCapacityPolicies).toHaveProperty('update');
expect(agentCapacityPolicies).toHaveProperty('delete');
expect(agentCapacityPolicies).toHaveProperty('getUsers');
expect(agentCapacityPolicies).toHaveProperty('addUser');
expect(agentCapacityPolicies).toHaveProperty('removeUser');
expect(agentCapacityPolicies).toHaveProperty('createInboxLimit');
expect(agentCapacityPolicies).toHaveProperty('updateInboxLimit');
expect(agentCapacityPolicies).toHaveProperty('deleteInboxLimit');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
get: vi.fn(() => Promise.resolve()),
post: vi.fn(() => Promise.resolve()),
put: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
// Mock accountIdFromRoute
Object.defineProperty(agentCapacityPolicies, 'accountIdFromRoute', {
get: () => '1',
configurable: true,
});
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getUsers', () => {
agentCapacityPolicies.getUsers(123);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/users'
);
});
it('#addUser', () => {
const userData = { id: 456, capacity: 20 };
agentCapacityPolicies.addUser(123, userData);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/users',
{
user_id: 456,
capacity: 20,
}
);
});
it('#removeUser', () => {
agentCapacityPolicies.removeUser(123, 456);
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/users/456'
);
});
it('#createInboxLimit', () => {
const limitData = { inboxId: 1, conversationLimit: 10 };
agentCapacityPolicies.createInboxLimit(123, limitData);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits',
{
inbox_id: 1,
conversation_limit: 10,
}
);
});
it('#updateInboxLimit', () => {
const limitData = { conversationLimit: 15 };
agentCapacityPolicies.updateInboxLimit(123, 789, limitData);
expect(axiosMock.put).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits/789',
{
conversation_limit: 15,
}
);
});
it('#deleteInboxLimit', () => {
agentCapacityPolicies.deleteInboxLimit(123, 789);
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/accounts/1/agent_capacity_policies/123/inbox_limits/789'
);
});
});
});

View File

@@ -0,0 +1,38 @@
import agents from '../agents';
import ApiClient from '../ApiClient';
describe('#AgentAPI', () => {
it('creates correct instance', () => {
expect(agents).toBeInstanceOf(ApiClient);
expect(agents).toHaveProperty('get');
expect(agents).toHaveProperty('show');
expect(agents).toHaveProperty('create');
expect(agents).toHaveProperty('update');
expect(agents).toHaveProperty('delete');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#bulkInvite', () => {
agents.bulkInvite({ emails: ['hello@hi.com'] });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/agents/bulk_create',
{
emails: ['hello@hi.com'],
}
);
});
});
});

View File

@@ -0,0 +1,156 @@
import articlesAPI from '../helpCenter/articles';
import ApiClient from 'dashboard/api/helpCenter/portals';
describe('#PortalAPI', () => {
it('creates correct instance', () => {
expect(articlesAPI).toBeInstanceOf(ApiClient);
expect(articlesAPI).toHaveProperty('get');
expect(articlesAPI).toHaveProperty('show');
expect(articlesAPI).toHaveProperty('create');
expect(articlesAPI).toHaveProperty('update');
expect(articlesAPI).toHaveProperty('delete');
expect(articlesAPI).toHaveProperty('getArticles');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getArticles', () => {
articlesAPI.getArticles({
pageNumber: 1,
portalSlug: 'room-rental',
locale: 'en-US',
status: 'published',
authorId: '1',
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles?page=1&locale=en-US&status=published&author_id=1'
);
});
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getArticle', () => {
articlesAPI.getArticle({
id: 1,
portalSlug: 'room-rental',
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles/1'
);
});
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#searchArticles', () => {
articlesAPI.searchArticles({
query: 'test',
portalSlug: 'room-rental',
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles?query=test'
);
});
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#updateArticle', () => {
articlesAPI.updateArticle({
articleId: 1,
portalSlug: 'room-rental',
articleObj: { title: 'Update shipping address' },
});
expect(axiosMock.patch).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles/1',
{
title: 'Update shipping address',
}
);
});
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#deleteArticle', () => {
articlesAPI.deleteArticle({
articleId: 1,
portalSlug: 'room-rental',
});
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/portals/room-rental/articles/1'
);
});
});
});

View File

@@ -0,0 +1,30 @@
import assignableAgentsAPI from '../assignableAgents';
describe('#AssignableAgentsAPI', () => {
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getAssignableAgents', () => {
assignableAgentsAPI.get([1]);
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/assignable_agents', {
params: {
inbox_ids: [1],
},
});
});
});
});

View File

@@ -0,0 +1,70 @@
import assignmentPolicies from '../assignmentPolicies';
import ApiClient from '../ApiClient';
describe('#AssignmentPoliciesAPI', () => {
it('creates correct instance', () => {
expect(assignmentPolicies).toBeInstanceOf(ApiClient);
expect(assignmentPolicies).toHaveProperty('get');
expect(assignmentPolicies).toHaveProperty('show');
expect(assignmentPolicies).toHaveProperty('create');
expect(assignmentPolicies).toHaveProperty('update');
expect(assignmentPolicies).toHaveProperty('delete');
expect(assignmentPolicies).toHaveProperty('getInboxes');
expect(assignmentPolicies).toHaveProperty('setInboxPolicy');
expect(assignmentPolicies).toHaveProperty('getInboxPolicy');
expect(assignmentPolicies).toHaveProperty('removeInboxPolicy');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
get: vi.fn(() => Promise.resolve()),
post: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
// Mock accountIdFromRoute
Object.defineProperty(assignmentPolicies, 'accountIdFromRoute', {
get: () => '1',
configurable: true,
});
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getInboxes', () => {
assignmentPolicies.getInboxes(123);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/accounts/1/assignment_policies/123/inboxes'
);
});
it('#setInboxPolicy', () => {
assignmentPolicies.setInboxPolicy(456, 123);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/accounts/1/inboxes/456/assignment_policy',
{
assignment_policy_id: 123,
}
);
});
it('#getInboxPolicy', () => {
assignmentPolicies.getInboxPolicy(456);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/accounts/1/inboxes/456/assignment_policy'
);
});
it('#removeInboxPolicy', () => {
assignmentPolicies.removeInboxPolicy(456);
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/accounts/1/inboxes/456/assignment_policy'
);
});
});
});

View File

@@ -0,0 +1,15 @@
import automations from '../automation';
import ApiClient from '../ApiClient';
describe('#AutomationsAPI', () => {
it('creates correct instance', () => {
expect(automations).toBeInstanceOf(ApiClient);
expect(automations).toHaveProperty('get');
expect(automations).toHaveProperty('show');
expect(automations).toHaveProperty('create');
expect(automations).toHaveProperty('update');
expect(automations).toHaveProperty('delete');
expect(automations).toHaveProperty('clone');
expect(automations.url).toBe('/api/v1/automation_rules');
});
});

View File

@@ -0,0 +1,9 @@
import bulkActions from '../bulkActions';
import ApiClient from '../ApiClient';
describe('#BulkActionsAPI', () => {
it('creates correct instance', () => {
expect(bulkActions).toBeInstanceOf(ApiClient);
expect(bulkActions).toHaveProperty('create');
});
});

View File

@@ -0,0 +1,13 @@
import campaigns from '../campaigns';
import ApiClient from '../ApiClient';
describe('#CampaignAPI', () => {
it('creates correct instance', () => {
expect(campaigns).toBeInstanceOf(ApiClient);
expect(campaigns).toHaveProperty('get');
expect(campaigns).toHaveProperty('show');
expect(campaigns).toHaveProperty('create');
expect(campaigns).toHaveProperty('update');
expect(campaigns).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,54 @@
import fbChannel from '../../channel/fbChannel';
import ApiClient from '../../ApiClient';
describe('#FBChannel', () => {
it('creates correct instance', () => {
expect(fbChannel).toBeInstanceOf(ApiClient);
expect(fbChannel).toHaveProperty('get');
expect(fbChannel).toHaveProperty('show');
expect(fbChannel).toHaveProperty('create');
expect(fbChannel).toHaveProperty('update');
expect(fbChannel).toHaveProperty('delete');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#create', () => {
fbChannel.create({ omniauthToken: 'ASFM131CSF@#@$', appId: 'chatwoot' });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/callbacks/register_facebook_page',
{
omniauthToken: 'ASFM131CSF@#@$',
appId: 'chatwoot',
}
);
});
it('#reauthorize', () => {
fbChannel.reauthorizeFacebookPage({
omniauthToken: 'ASFM131CSF@#@$',
inboxId: 1,
});
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/callbacks/reauthorize_page',
{
omniauth_token: 'ASFM131CSF@#@$',
inbox_id: 1,
}
);
});
});
});

View File

@@ -0,0 +1,13 @@
import twilioChannel from '../../channel/twilioChannel';
import ApiClient from '../../ApiClient';
describe('#twilioChannel', () => {
it('creates correct instance', () => {
expect(twilioChannel).toBeInstanceOf(ApiClient);
expect(twilioChannel).toHaveProperty('get');
expect(twilioChannel).toHaveProperty('show');
expect(twilioChannel).toHaveProperty('create');
expect(twilioChannel).toHaveProperty('update');
expect(twilioChannel).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,14 @@
import twitterClient from '../../channel/twitterClient';
import ApiClient from '../../ApiClient';
describe('#TwitterClient', () => {
it('creates correct instance', () => {
expect(twitterClient).toBeInstanceOf(ApiClient);
expect(twitterClient).toHaveProperty('get');
expect(twitterClient).toHaveProperty('show');
expect(twitterClient).toHaveProperty('create');
expect(twitterClient).toHaveProperty('update');
expect(twitterClient).toHaveProperty('delete');
expect(twitterClient).toHaveProperty('generateAuthorization');
});
});

View File

@@ -0,0 +1,13 @@
import webChannelClient from '../../channel/webChannel';
import ApiClient from '../../ApiClient';
describe('#webChannelClient', () => {
it('creates correct instance', () => {
expect(webChannelClient).toBeInstanceOf(ApiClient);
expect(webChannelClient).toHaveProperty('get');
expect(webChannelClient).toHaveProperty('show');
expect(webChannelClient).toHaveProperty('create');
expect(webChannelClient).toHaveProperty('update');
expect(webChannelClient).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,142 @@
import companyAPI, {
buildCompanyParams,
buildSearchParams,
} from '../companies';
import ApiClient from '../ApiClient';
describe('#CompanyAPI', () => {
it('creates correct instance', () => {
expect(companyAPI).toBeInstanceOf(ApiClient);
expect(companyAPI).toHaveProperty('get');
expect(companyAPI).toHaveProperty('show');
expect(companyAPI).toHaveProperty('create');
expect(companyAPI).toHaveProperty('update');
expect(companyAPI).toHaveProperty('delete');
expect(companyAPI).toHaveProperty('search');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#get with default params', () => {
companyAPI.get({});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies?page=1&sort=name'
);
});
it('#get with page and sort params', () => {
companyAPI.get({ page: 2, sort: 'domain' });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies?page=2&sort=domain'
);
});
it('#get with descending sort', () => {
companyAPI.get({ page: 1, sort: '-created_at' });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies?page=1&sort=-created_at'
);
});
it('#search with query', () => {
companyAPI.search('acme', 1, 'name');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies/search?q=acme&page=1&sort=name'
);
});
it('#search with special characters in query', () => {
companyAPI.search('acme & co', 2, 'domain');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies/search?q=acme%20%26%20co&page=2&sort=domain'
);
});
it('#search with descending sort', () => {
companyAPI.search('test', 1, '-created_at');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies/search?q=test&page=1&sort=-created_at'
);
});
it('#search with empty query', () => {
companyAPI.search('', 1, 'name');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/companies/search?q=&page=1&sort=name'
);
});
});
});
describe('#buildCompanyParams', () => {
it('returns correct string with page only', () => {
expect(buildCompanyParams(1)).toBe('page=1');
});
it('returns correct string with page and sort', () => {
expect(buildCompanyParams(1, 'name')).toBe('page=1&sort=name');
});
it('returns correct string with different page', () => {
expect(buildCompanyParams(3, 'domain')).toBe('page=3&sort=domain');
});
it('returns correct string with descending sort', () => {
expect(buildCompanyParams(1, '-created_at')).toBe(
'page=1&sort=-created_at'
);
});
it('returns correct string without sort parameter', () => {
expect(buildCompanyParams(2, '')).toBe('page=2');
});
});
describe('#buildSearchParams', () => {
it('returns correct string with all parameters', () => {
expect(buildSearchParams('acme', 1, 'name')).toBe(
'q=acme&page=1&sort=name'
);
});
it('returns correct string with special characters', () => {
expect(buildSearchParams('acme & co', 2, 'domain')).toBe(
'q=acme%20%26%20co&page=2&sort=domain'
);
});
it('returns correct string with empty query', () => {
expect(buildSearchParams('', 1, 'name')).toBe('q=&page=1&sort=name');
});
it('returns correct string without sort parameter', () => {
expect(buildSearchParams('test', 1, '')).toBe('q=test&page=1');
});
it('returns correct string with descending sort', () => {
expect(buildSearchParams('company', 3, '-created_at')).toBe(
'q=company&page=3&sort=-created_at'
);
});
it('encodes special characters correctly', () => {
expect(buildSearchParams('test@example.com', 1, 'name')).toBe(
'q=test%40example.com&page=1&sort=name'
);
});
});

View File

@@ -0,0 +1,138 @@
import contactAPI, { buildContactParams } from '../contacts';
import ApiClient from '../ApiClient';
describe('#ContactsAPI', () => {
it('creates correct instance', () => {
expect(contactAPI).toBeInstanceOf(ApiClient);
expect(contactAPI).toHaveProperty('get');
expect(contactAPI).toHaveProperty('show');
expect(contactAPI).toHaveProperty('create');
expect(contactAPI).toHaveProperty('update');
expect(contactAPI).toHaveProperty('delete');
expect(contactAPI).toHaveProperty('getConversations');
expect(contactAPI).toHaveProperty('filter');
expect(contactAPI).toHaveProperty('destroyAvatar');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#get', () => {
contactAPI.get(1, 'name', 'customer-support');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/contacts?include_contact_inboxes=false&page=1&sort=name&labels[]=customer-support'
);
});
it('#getConversations', () => {
contactAPI.getConversations(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/contacts/1/conversations'
);
});
it('#getContactableInboxes', () => {
contactAPI.getContactableInboxes(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/contacts/1/contactable_inboxes'
);
});
it('#getContactLabels', () => {
contactAPI.getContactLabels(1);
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/contacts/1/labels');
});
it('#updateContactLabels', () => {
const labels = ['support-query'];
contactAPI.updateContactLabels(1, labels);
expect(axiosMock.post).toHaveBeenCalledWith('/api/v1/contacts/1/labels', {
labels,
});
});
it('#search', () => {
contactAPI.search('leads', 1, 'date', 'customer-support');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/contacts/search?include_contact_inboxes=false&page=1&sort=date&q=leads&labels[]=customer-support'
);
});
it('#destroyCustomAttributes', () => {
contactAPI.destroyCustomAttributes(1, ['cloudCustomer']);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/contacts/1/destroy_custom_attributes',
{
custom_attributes: ['cloudCustomer'],
}
);
});
it('#importContacts', () => {
const file = 'file';
contactAPI.importContacts(file);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/contacts/import',
expect.any(FormData),
{
headers: { 'Content-Type': 'multipart/form-data' },
}
);
});
it('#filter', () => {
const queryPayload = {
payload: [
{
attribute_key: 'email',
filter_operator: 'contains',
values: ['fayaz'],
query_operator: null,
},
],
};
contactAPI.filter(1, 'name', queryPayload);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/contacts/filter?include_contact_inboxes=false&page=1&sort=name',
queryPayload
);
});
it('#destroyAvatar', () => {
contactAPI.destroyAvatar(1);
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/contacts/1/avatar'
);
});
});
});
describe('#buildContactParams', () => {
it('returns correct string', () => {
expect(buildContactParams(1, 'name', '', '')).toBe(
'include_contact_inboxes=false&page=1&sort=name'
);
expect(buildContactParams(1, 'name', 'customer-support', '')).toBe(
'include_contact_inboxes=false&page=1&sort=name&labels[]=customer-support'
);
expect(
buildContactParams(1, 'name', 'customer-support', 'message-content')
).toBe(
'include_contact_inboxes=false&page=1&sort=name&q=message-content&labels[]=customer-support'
);
});
});

View File

@@ -0,0 +1,51 @@
import conversationsAPI from '../conversations';
import ApiClient from '../ApiClient';
describe('#ConversationApi', () => {
it('creates correct instance', () => {
expect(conversationsAPI).toBeInstanceOf(ApiClient);
expect(conversationsAPI).toHaveProperty('get');
expect(conversationsAPI).toHaveProperty('show');
expect(conversationsAPI).toHaveProperty('create');
expect(conversationsAPI).toHaveProperty('update');
expect(conversationsAPI).toHaveProperty('delete');
expect(conversationsAPI).toHaveProperty('getLabels');
expect(conversationsAPI).toHaveProperty('updateLabels');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getLabels', () => {
conversationsAPI.getLabels(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/conversations/1/labels'
);
});
it('#updateLabels', () => {
const labels = ['support-query'];
conversationsAPI.updateLabels(1, labels);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/1/labels',
{
labels,
}
);
});
});
});

View File

@@ -0,0 +1,70 @@
import csatReportsAPI from '../csatReports';
import ApiClient from '../ApiClient';
describe('#Reports API', () => {
it('creates correct instance', () => {
expect(csatReportsAPI).toBeInstanceOf(ApiClient);
expect(csatReportsAPI.apiVersion).toBe('/api/v1');
expect(csatReportsAPI).toHaveProperty('get');
expect(csatReportsAPI).toHaveProperty('getMetrics');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#get', () => {
csatReportsAPI.get({ page: 1, from: 1622485800, to: 1623695400 });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/csat_survey_responses',
{
params: {
page: 1,
since: 1622485800,
until: 1623695400,
sort: '-created_at',
},
}
);
});
it('#getMetrics', () => {
csatReportsAPI.getMetrics({ from: 1622485800, to: 1623695400 });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/csat_survey_responses/metrics',
{
params: { since: 1622485800, until: 1623695400 },
}
);
});
it('#download', () => {
csatReportsAPI.download({
from: 1622485800,
to: 1623695400,
user_ids: 1,
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/csat_survey_responses/download',
{
params: {
since: 1622485800,
until: 1623695400,
user_ids: 1,
sort: '-created_at',
},
}
);
});
});
});

View File

@@ -0,0 +1,13 @@
import dashboardAppsAPI from '../dashboardApps';
import ApiClient from '../ApiClient';
describe('#dashboardAppsAPI', () => {
it('creates correct instance', () => {
expect(dashboardAppsAPI).toBeInstanceOf(ApiClient);
expect(dashboardAppsAPI).toHaveProperty('get');
expect(dashboardAppsAPI).toHaveProperty('show');
expect(dashboardAppsAPI).toHaveProperty('create');
expect(dashboardAppsAPI).toHaveProperty('update');
expect(dashboardAppsAPI).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,13 @@
import endPoints from '../endPoints';
describe('#endPoints', () => {
it('it should return register url details if register page passed ', () => {
expect(endPoints('register')).toEqual({ url: 'api/v1/accounts.json' });
});
it('it should inbox url details if getInbox page passed', () => {
expect(endPoints('getInbox')).toEqual({
url: 'api/v1/conversations.json',
params: { inbox_id: null },
});
});
});

View File

@@ -0,0 +1,12 @@
import categoriesAPI from '../../helpCenter/categories';
import ApiClient from '../../ApiClient';
describe('#BulkActionsAPI', () => {
it('creates correct instance', () => {
expect(categoriesAPI).toBeInstanceOf(ApiClient);
expect(categoriesAPI).toHaveProperty('get');
expect(categoriesAPI).toHaveProperty('create');
expect(categoriesAPI).toHaveProperty('update');
expect(categoriesAPI).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,232 @@
import conversationAPI from '../../inbox/conversation';
import ApiClient from '../../ApiClient';
describe('#ConversationAPI', () => {
it('creates correct instance', () => {
expect(conversationAPI).toBeInstanceOf(ApiClient);
expect(conversationAPI).toHaveProperty('get');
expect(conversationAPI).toHaveProperty('show');
expect(conversationAPI).toHaveProperty('create');
expect(conversationAPI).toHaveProperty('update');
expect(conversationAPI).toHaveProperty('delete');
expect(conversationAPI).toHaveProperty('toggleStatus');
expect(conversationAPI).toHaveProperty('assignAgent');
expect(conversationAPI).toHaveProperty('assignTeam');
expect(conversationAPI).toHaveProperty('markMessageRead');
expect(conversationAPI).toHaveProperty('toggleTyping');
expect(conversationAPI).toHaveProperty('mute');
expect(conversationAPI).toHaveProperty('unmute');
expect(conversationAPI).toHaveProperty('meta');
expect(conversationAPI).toHaveProperty('sendEmailTranscript');
expect(conversationAPI).toHaveProperty('filter');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#get conversations', () => {
conversationAPI.get({
inboxId: 1,
status: 'open',
assigneeType: 'me',
page: 1,
labels: [],
teamId: 1,
updatedWithin: 20,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/conversations', {
params: {
inbox_id: 1,
team_id: 1,
status: 'open',
assignee_type: 'me',
page: 1,
labels: [],
updated_within: 20,
},
});
});
it('#search', () => {
conversationAPI.search({
q: 'leads',
page: 1,
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/conversations/search',
{
params: {
q: 'leads',
page: 1,
},
}
);
});
it('#toggleStatus', () => {
conversationAPI.toggleStatus({ conversationId: 12, status: 'online' });
expect(axiosMock.post).toHaveBeenCalledWith(
`/api/v1/conversations/12/toggle_status`,
{
status: 'online',
snoozed_until: null,
}
);
});
it('#assignAgent', () => {
conversationAPI.assignAgent({ conversationId: 12, agentId: 34 });
expect(axiosMock.post).toHaveBeenCalledWith(
`/api/v1/conversations/12/assignments`,
{
assignee_id: 34,
}
);
});
it('#assignTeam', () => {
conversationAPI.assignTeam({ conversationId: 12, teamId: 1 });
expect(axiosMock.post).toHaveBeenCalledWith(
`/api/v1/conversations/12/assignments`,
{
team_id: 1,
}
);
});
it('#markMessageRead', () => {
conversationAPI.markMessageRead({ id: 12 });
expect(axiosMock.post).toHaveBeenCalledWith(
`/api/v1/conversations/12/update_last_seen`
);
});
it('#toggleTyping', () => {
conversationAPI.toggleTyping({
conversationId: 12,
status: 'typing_on',
});
expect(axiosMock.post).toHaveBeenCalledWith(
`/api/v1/conversations/12/toggle_typing_status`,
{
typing_status: 'typing_on',
}
);
});
it('#mute', () => {
conversationAPI.mute(45);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/45/mute'
);
});
it('#unmute', () => {
conversationAPI.unmute(45);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/45/unmute'
);
});
it('#meta', () => {
conversationAPI.meta({
inboxId: 1,
status: 'open',
assigneeType: 'me',
labels: [],
teamId: 1,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/conversations/meta', {
params: {
inbox_id: 1,
team_id: 1,
status: 'open',
assignee_type: 'me',
labels: [],
},
});
});
it('#sendEmailTranscript', () => {
conversationAPI.sendEmailTranscript({
conversationId: 45,
email: 'john@acme.inc',
});
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/45/transcript',
{
email: 'john@acme.inc',
}
);
});
it('#updateCustomAttributes', () => {
conversationAPI.updateCustomAttributes({
conversationId: 45,
customAttributes: { order_d: '1001' },
});
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/45/custom_attributes',
{
custom_attributes: { order_d: '1001' },
}
);
});
it('#filter', () => {
const payload = {
page: 1,
queryData: {
payload: [
{
attribute_key: 'status',
filter_operator: 'equal_to',
values: ['pending', 'resolved'],
query_operator: 'and',
},
{
attribute_key: 'assignee',
filter_operator: 'equal_to',
values: [3],
query_operator: 'and',
},
{
attribute_key: 'id',
filter_operator: 'equal_to',
values: ['This is a test'],
query_operator: null,
},
],
},
};
conversationAPI.filter(payload);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/conversations/filter',
payload.queryData,
{ params: { page: payload.page } }
);
});
it('#getAllAttachments', () => {
conversationAPI.getAllAttachments(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/conversations/1/attachments'
);
});
});
});

View File

@@ -0,0 +1,87 @@
import messageAPI, { buildCreatePayload } from '../../inbox/message';
import ApiClient from '../../ApiClient';
describe('#ConversationAPI', () => {
it('creates correct instance', () => {
expect(messageAPI).toBeInstanceOf(ApiClient);
expect(messageAPI).toHaveProperty('get');
expect(messageAPI).toHaveProperty('show');
expect(messageAPI).toHaveProperty('create');
expect(messageAPI).toHaveProperty('update');
expect(messageAPI).toHaveProperty('delete');
expect(messageAPI).toHaveProperty('getPreviousMessages');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getPreviousMessages', () => {
messageAPI.getPreviousMessages({
conversationId: 12,
before: 4573,
});
expect(axiosMock.get).toHaveBeenCalledWith(
`/api/v1/conversations/12/messages`,
{
params: {
before: 4573,
},
}
);
});
});
describe('#buildCreatePayload', () => {
it('builds form payload if file is available', () => {
const formPayload = buildCreatePayload({
message: 'test content',
echoId: 12,
isPrivate: true,
contentAttributes: { in_reply_to: 12 },
files: [new Blob(['test-content'], { type: 'application/pdf' })],
});
expect(formPayload).toBeInstanceOf(FormData);
expect(formPayload.get('content')).toEqual('test content');
expect(formPayload.get('echo_id')).toEqual('12');
expect(formPayload.get('private')).toEqual('true');
expect(formPayload.get('cc_emails')).toEqual('');
expect(formPayload.get('bcc_emails')).toEqual('');
expect(formPayload.get('content_attributes')).toEqual(
'{"in_reply_to":12}'
);
});
it('builds object payload if file is not available', () => {
expect(
buildCreatePayload({
message: 'test content',
isPrivate: false,
echoId: 12,
contentAttributes: { in_reply_to: 12 },
})
).toEqual({
content: 'test content',
private: false,
echo_id: 12,
content_attributes: { in_reply_to: 12 },
cc_emails: '',
bcc_emails: '',
to_emails: '',
template_params: undefined,
});
});
});
});

View File

@@ -0,0 +1,52 @@
import inboxesAPI from '../inboxes';
import ApiClient from '../ApiClient';
describe('#InboxesAPI', () => {
it('creates correct instance', () => {
expect(inboxesAPI).toBeInstanceOf(ApiClient);
expect(inboxesAPI).toHaveProperty('get');
expect(inboxesAPI).toHaveProperty('show');
expect(inboxesAPI).toHaveProperty('create');
expect(inboxesAPI).toHaveProperty('update');
expect(inboxesAPI).toHaveProperty('delete');
expect(inboxesAPI).toHaveProperty('getCampaigns');
expect(inboxesAPI).toHaveProperty('getAgentBot');
expect(inboxesAPI).toHaveProperty('setAgentBot');
expect(inboxesAPI).toHaveProperty('syncTemplates');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getCampaigns', () => {
inboxesAPI.getCampaigns(2);
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/inboxes/2/campaigns');
});
it('#deleteInboxAvatar', () => {
inboxesAPI.deleteInboxAvatar(2);
expect(axiosMock.delete).toHaveBeenCalledWith('/api/v1/inboxes/2/avatar');
});
it('#syncTemplates', () => {
inboxesAPI.syncTemplates(2);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/inboxes/2/sync_templates'
);
});
});
});

View File

@@ -0,0 +1,88 @@
import integrationAPI from '../integrations';
import ApiClient from '../ApiClient';
describe('#integrationAPI', () => {
it('creates correct instance', () => {
expect(integrationAPI).toBeInstanceOf(ApiClient);
expect(integrationAPI).toHaveProperty('get');
expect(integrationAPI).toHaveProperty('show');
expect(integrationAPI).toHaveProperty('create');
expect(integrationAPI).toHaveProperty('update');
expect(integrationAPI).toHaveProperty('delete');
expect(integrationAPI).toHaveProperty('connectSlack');
expect(integrationAPI).toHaveProperty('updateSlack');
expect(integrationAPI).toHaveProperty('updateSlack');
expect(integrationAPI).toHaveProperty('listAllSlackChannels');
expect(integrationAPI).toHaveProperty('deleteHook');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#connectSlack', () => {
const code = 'SDNFJNSDFNDSJN';
integrationAPI.connectSlack(code);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/slack',
{
code,
}
);
});
it('#updateSlack', () => {
const updateObj = { referenceId: 'SDFSDGSVE' };
integrationAPI.updateSlack(updateObj);
expect(axiosMock.patch).toHaveBeenCalledWith(
'/api/v1/integrations/slack',
{
reference_id: updateObj.referenceId,
}
);
});
it('#listAllSlackChannels', () => {
integrationAPI.listAllSlackChannels();
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/integrations/slack/list_all_channels'
);
});
it('#delete', () => {
integrationAPI.delete(2);
expect(axiosMock.delete).toHaveBeenCalledWith('/api/v1/integrations/2');
});
it('#createHook', () => {
const hookData = {
app_id: 'fullcontact',
settings: { api_key: 'SDFSDGSVE' },
};
integrationAPI.createHook(hookData);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/hooks',
hookData
);
});
it('#deleteHook', () => {
integrationAPI.deleteHook(2);
expect(axiosMock.delete).toHaveBeenCalledWith(
'/api/v1/integrations/hooks/2'
);
});
});
});

View File

@@ -0,0 +1,66 @@
import DyteAPIClient from '../../integrations/dyte';
import ApiClient from '../../ApiClient';
describe('#accountAPI', () => {
it('creates correct instance', () => {
expect(DyteAPIClient).toBeInstanceOf(ApiClient);
expect(DyteAPIClient).toHaveProperty('createAMeeting');
expect(DyteAPIClient).toHaveProperty('addParticipantToMeeting');
});
describe('createAMeeting', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
DyteAPIClient.createAMeeting(1);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/dyte/create_a_meeting',
{
conversation_id: 1,
}
);
});
});
describe('addParticipantToMeeting', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
DyteAPIClient.addParticipantToMeeting(1);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/dyte/add_participant_to_meeting',
{
message_id: 1,
}
);
});
});
});

View File

@@ -0,0 +1,241 @@
import LinearAPIClient from '../../integrations/linear';
import ApiClient from '../../ApiClient';
describe('#linearAPI', () => {
it('creates correct instance', () => {
expect(LinearAPIClient).toBeInstanceOf(ApiClient);
expect(LinearAPIClient).toHaveProperty('getTeams');
expect(LinearAPIClient).toHaveProperty('getTeamEntities');
expect(LinearAPIClient).toHaveProperty('createIssue');
expect(LinearAPIClient).toHaveProperty('link_issue');
expect(LinearAPIClient).toHaveProperty('getLinkedIssue');
expect(LinearAPIClient).toHaveProperty('unlinkIssue');
expect(LinearAPIClient).toHaveProperty('searchIssues');
});
describe('getTeams', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
LinearAPIClient.getTeams();
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/integrations/linear/teams'
);
});
});
describe('getTeamEntities', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
LinearAPIClient.getTeamEntities(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/integrations/linear/team_entities?team_id=1'
);
});
});
describe('createIssue', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
const issueData = {
title: 'New Issue',
description: 'Issue description',
};
LinearAPIClient.createIssue(issueData);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/create_issue',
issueData
);
});
it('creates a valid request with conversation_id', () => {
const issueData = {
title: 'New Issue',
description: 'Issue description',
conversation_id: 123,
};
LinearAPIClient.createIssue(issueData);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/create_issue',
issueData
);
});
});
describe('link_issue', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
LinearAPIClient.link_issue(1, 2);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/link_issue',
{
issue_id: 2,
conversation_id: 1,
}
);
});
it('creates a valid request with title', () => {
LinearAPIClient.link_issue(1, 'ENG-123', 'Sample Issue');
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/link_issue',
{
issue_id: 'ENG-123',
conversation_id: 1,
title: 'Sample Issue',
}
);
});
});
describe('getLinkedIssue', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
LinearAPIClient.getLinkedIssue(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/integrations/linear/linked_issues?conversation_id=1'
);
});
});
describe('unlinkIssue', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request with link_id only', () => {
LinearAPIClient.unlinkIssue('link123');
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/unlink_issue',
{
link_id: 'link123',
issue_id: undefined,
conversation_id: undefined,
}
);
});
it('creates a valid request with all parameters', () => {
LinearAPIClient.unlinkIssue('link123', 'ENG-456', 789);
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/integrations/linear/unlink_issue',
{
link_id: 'link123',
issue_id: 'ENG-456',
conversation_id: 789,
}
);
});
});
describe('searchIssues', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('creates a valid request', () => {
LinearAPIClient.searchIssues('query');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/integrations/linear/search_issue?q=query'
);
});
});
});

View File

@@ -0,0 +1,14 @@
import labels from '../labels';
import ApiClient from '../ApiClient';
describe('#LabelsAPI', () => {
it('creates correct instance', () => {
expect(labels).toBeInstanceOf(ApiClient);
expect(labels).toHaveProperty('get');
expect(labels).toHaveProperty('show');
expect(labels).toHaveProperty('create');
expect(labels).toHaveProperty('update');
expect(labels).toHaveProperty('delete');
expect(labels.url).toBe('/api/v1/labels');
});
});

View File

@@ -0,0 +1,14 @@
import macros from '../macros';
import ApiClient from '../ApiClient';
describe('#macrosAPI', () => {
it('creates correct instance', () => {
expect(macros).toBeInstanceOf(ApiClient);
expect(macros).toHaveProperty('get');
expect(macros).toHaveProperty('create');
expect(macros).toHaveProperty('update');
expect(macros).toHaveProperty('delete');
expect(macros).toHaveProperty('show');
expect(macros.url).toBe('/api/v1/macros');
});
});

View File

@@ -0,0 +1,120 @@
import notificationsAPI from '../notifications';
import ApiClient from '../ApiClient';
describe('#NotificationAPI', () => {
it('creates correct instance', () => {
expect(notificationsAPI).toBeInstanceOf(ApiClient);
expect(notificationsAPI).toHaveProperty('get');
expect(notificationsAPI).toHaveProperty('getNotifications');
expect(notificationsAPI).toHaveProperty('getUnreadCount');
expect(notificationsAPI).toHaveProperty('read');
expect(notificationsAPI).toHaveProperty('readAll');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
describe('#get', () => {
it('generates the API call if both params are available', () => {
notificationsAPI.get({
page: 1,
status: 'snoozed',
type: 'read',
sortOrder: 'desc',
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/notifications', {
params: {
page: 1,
sort_order: 'desc',
includes: ['snoozed', 'read'],
},
});
});
it('generates the API call if one of the params are available', () => {
notificationsAPI.get({
page: 1,
type: 'read',
sortOrder: 'desc',
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/notifications', {
params: {
page: 1,
sort_order: 'desc',
includes: ['read'],
},
});
});
});
it('#getNotifications', () => {
notificationsAPI.getNotifications(1);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/notifications/1/notifications'
);
});
it('#getUnreadCount', () => {
notificationsAPI.getUnreadCount();
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/notifications/unread_count'
);
});
it('#read', () => {
notificationsAPI.read(48670, 'Conversation');
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/notifications/read_all',
{
primary_actor_id: 'Conversation',
primary_actor_type: 48670,
}
);
});
it('#readAll', () => {
notificationsAPI.readAll();
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/notifications/read_all'
);
});
it('#snooze', () => {
notificationsAPI.snooze({ id: 1, snoozedUntil: 12332211 });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/notifications/1/snooze',
{
snoozed_until: 12332211,
}
);
});
it('#delete', () => {
notificationsAPI.delete(1);
expect(axiosMock.delete).toHaveBeenCalledWith('/api/v1/notifications/1');
});
it('#deleteAll', () => {
notificationsAPI.deleteAll({ type: 'all' });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/notifications/destroy_all',
{
type: 'all',
}
);
});
});
});

View File

@@ -0,0 +1,13 @@
import PortalsAPI from '../helpCenter/portals';
import ApiClient from '../ApiClient';
const portalAPI = new PortalsAPI();
describe('#PortalAPI', () => {
it('creates correct instance', () => {
expect(portalAPI).toBeInstanceOf(ApiClient);
expect(portalAPI).toHaveProperty('get');
expect(portalAPI).toHaveProperty('show');
expect(portalAPI).toHaveProperty('create');
expect(portalAPI).toHaveProperty('update');
expect(portalAPI).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,161 @@
import reportsAPI from '../reports';
import ApiClient from '../ApiClient';
describe('#Reports API', () => {
it('creates correct instance', () => {
expect(reportsAPI).toBeInstanceOf(ApiClient);
expect(reportsAPI.apiVersion).toBe('/api/v2');
expect(reportsAPI).toHaveProperty('get');
expect(reportsAPI).toHaveProperty('show');
expect(reportsAPI).toHaveProperty('create');
expect(reportsAPI).toHaveProperty('update');
expect(reportsAPI).toHaveProperty('delete');
expect(reportsAPI).toHaveProperty('getReports');
expect(reportsAPI).toHaveProperty('getSummary');
expect(reportsAPI).toHaveProperty('getAgentReports');
expect(reportsAPI).toHaveProperty('getLabelReports');
expect(reportsAPI).toHaveProperty('getInboxReports');
expect(reportsAPI).toHaveProperty('getTeamReports');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getAccountReports', () => {
reportsAPI.getReports({
metric: 'conversations_count',
from: 1621103400,
to: 1621621800,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports', {
params: {
metric: 'conversations_count',
since: 1621103400,
until: 1621621800,
type: 'account',
timezone_offset: -0,
},
});
});
it('#getAccountSummary', () => {
reportsAPI.getSummary(1621103400, 1621621800);
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports/summary', {
params: {
business_hours: undefined,
group_by: undefined,
id: undefined,
since: 1621103400,
timezone_offset: -0,
type: 'account',
until: 1621621800,
},
});
});
it('#getAgentReports', () => {
reportsAPI.getAgentReports({
from: 1621103400,
to: 1621621800,
businessHours: true,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports/agents', {
params: {
since: 1621103400,
until: 1621621800,
business_hours: true,
},
});
});
it('#getLabelReports', () => {
reportsAPI.getLabelReports({ from: 1621103400, to: 1621621800 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports/labels', {
params: {
since: 1621103400,
until: 1621621800,
},
});
});
it('#getInboxReports', () => {
reportsAPI.getInboxReports({ from: 1621103400, to: 1621621800 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports/inboxes', {
params: {
since: 1621103400,
until: 1621621800,
},
});
});
it('#getTeamReports', () => {
reportsAPI.getTeamReports({ from: 1621103400, to: 1621621800 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v2/reports/teams', {
params: {
since: 1621103400,
until: 1621621800,
},
});
});
it('#getBotMetrics', () => {
reportsAPI.getBotMetrics({ from: 1621103400, to: 1621621800 });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v2/reports/bot_metrics',
{
params: {
since: 1621103400,
until: 1621621800,
},
}
);
});
it('#getBotSummary', () => {
reportsAPI.getBotSummary({
from: 1621103400,
to: 1621621800,
groupBy: 'date',
businessHours: true,
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v2/reports/bot_summary',
{
params: {
since: 1621103400,
until: 1621621800,
type: 'account',
group_by: 'date',
business_hours: true,
},
}
);
});
it('#getConversationMetric', () => {
reportsAPI.getConversationMetric('account');
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v2/reports/conversations',
{
params: {
type: 'account',
page: 1,
},
}
);
});
});
});

View File

@@ -0,0 +1,134 @@
import searchAPI from '../search';
import ApiClient from '../ApiClient';
describe('#SearchAPI', () => {
it('creates correct instance', () => {
expect(searchAPI).toBeInstanceOf(ApiClient);
expect(searchAPI).toHaveProperty('get');
expect(searchAPI).toHaveProperty('contacts');
expect(searchAPI).toHaveProperty('conversations');
expect(searchAPI).toHaveProperty('messages');
expect(searchAPI).toHaveProperty('articles');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
get: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
vi.clearAllMocks();
});
it('#get', () => {
searchAPI.get({ q: 'test query' });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search', {
params: { q: 'test query' },
});
});
it('#contacts', () => {
searchAPI.contacts({ q: 'test', page: 1 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/contacts', {
params: { q: 'test', page: 1, since: undefined, until: undefined },
});
});
it('#contacts with date filters', () => {
searchAPI.contacts({
q: 'test',
page: 2,
since: 1700000000,
until: 1732000000,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/contacts', {
params: { q: 'test', page: 2, since: 1700000000, until: 1732000000 },
});
});
it('#conversations', () => {
searchAPI.conversations({ q: 'test', page: 1 });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/search/conversations',
{
params: { q: 'test', page: 1, since: undefined, until: undefined },
}
);
});
it('#conversations with date filters', () => {
searchAPI.conversations({
q: 'test',
page: 1,
since: 1700000000,
until: 1732000000,
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/search/conversations',
{
params: { q: 'test', page: 1, since: 1700000000, until: 1732000000 },
}
);
});
it('#messages', () => {
searchAPI.messages({ q: 'test', page: 1 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/messages', {
params: {
q: 'test',
page: 1,
since: undefined,
until: undefined,
from: undefined,
inbox_id: undefined,
},
});
});
it('#messages with all filters', () => {
searchAPI.messages({
q: 'test',
page: 1,
since: 1700000000,
until: 1732000000,
from: 'contact:42',
inboxId: 10,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/messages', {
params: {
q: 'test',
page: 1,
since: 1700000000,
until: 1732000000,
from: 'contact:42',
inbox_id: 10,
},
});
});
it('#articles', () => {
searchAPI.articles({ q: 'test', page: 1 });
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/articles', {
params: { q: 'test', page: 1, since: undefined, until: undefined },
});
});
it('#articles with date filters', () => {
searchAPI.articles({
q: 'test',
page: 2,
since: 1700000000,
until: 1732000000,
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/search/articles', {
params: { q: 'test', page: 2, since: 1700000000, until: 1732000000 },
});
});
});
});

View File

@@ -0,0 +1,104 @@
import SLAReportsAPI from '../slaReports';
import ApiClient from '../ApiClient';
describe('#SLAReports API', () => {
it('creates correct instance', () => {
expect(SLAReportsAPI).toBeInstanceOf(ApiClient);
expect(SLAReportsAPI.apiVersion).toBe('/api/v1');
expect(SLAReportsAPI).toHaveProperty('get');
expect(SLAReportsAPI).toHaveProperty('getMetrics');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#get', () => {
SLAReportsAPI.get({
page: 1,
from: 1622485800,
to: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
});
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/applied_slas', {
params: {
page: 1,
since: 1622485800,
until: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
},
});
});
it('#getMetrics', () => {
SLAReportsAPI.getMetrics({
from: 1622485800,
to: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/applied_slas/metrics',
{
params: {
since: 1622485800,
until: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
},
}
);
});
it('#download', () => {
SLAReportsAPI.download({
from: 1622485800,
to: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
});
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/applied_slas/download',
{
params: {
since: 1622485800,
until: 1623695400,
assigned_agent_id: 1,
inbox_id: 1,
team_id: 1,
sla_policy_id: 1,
label_list: ['label1'],
},
}
);
});
});
});

View File

@@ -0,0 +1,64 @@
import teamsAPI from '../teams';
import ApiClient from '../ApiClient';
describe('#TeamsAPI', () => {
it('creates correct instance', () => {
expect(teamsAPI).toBeInstanceOf(ApiClient);
expect(teamsAPI).toHaveProperty('get');
expect(teamsAPI).toHaveProperty('show');
expect(teamsAPI).toHaveProperty('create');
expect(teamsAPI).toHaveProperty('update');
expect(teamsAPI).toHaveProperty('delete');
expect(teamsAPI).toHaveProperty('getAgents');
expect(teamsAPI).toHaveProperty('addAgents');
expect(teamsAPI).toHaveProperty('updateAgents');
});
describe('API calls', () => {
const originalAxios = window.axios;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
get: vi.fn(() => Promise.resolve()),
patch: vi.fn(() => Promise.resolve()),
delete: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
});
afterEach(() => {
window.axios = originalAxios;
});
it('#getAgents', () => {
teamsAPI.getAgents({ teamId: 1 });
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/teams/1/team_members'
);
});
it('#addAgents', () => {
teamsAPI.addAgents({ teamId: 1, agentsList: { user_ids: [1, 10, 21] } });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/teams/1/team_members',
{
user_ids: { user_ids: [1, 10, 21] },
}
);
});
it('#updateAgents', () => {
const agentsList = { user_ids: [1, 10, 21] };
teamsAPI.updateAgents({
teamId: 1,
agentsList,
});
expect(axiosMock.patch).toHaveBeenCalledWith(
'/api/v1/teams/1/team_members',
{
user_ids: agentsList,
}
);
});
});
});

View File

@@ -0,0 +1,35 @@
import ApiClient from '../ApiClient';
import tiktokClient from '../channel/tiktokClient';
describe('#TiktokClient', () => {
it('creates correct instance', () => {
expect(tiktokClient).toBeInstanceOf(ApiClient);
expect(tiktokClient).toHaveProperty('generateAuthorization');
});
describe('#generateAuthorization', () => {
const originalAxios = window.axios;
const originalPathname = window.location.pathname;
const axiosMock = {
post: vi.fn(() => Promise.resolve()),
};
beforeEach(() => {
window.axios = axiosMock;
window.history.pushState({}, '', '/app/accounts/1/settings');
});
afterEach(() => {
window.axios = originalAxios;
window.history.pushState({}, '', originalPathname);
});
it('posts to the authorization endpoint', () => {
tiktokClient.generateAuthorization({ state: 'test-state' });
expect(axiosMock.post).toHaveBeenCalledWith(
'/api/v1/accounts/1/tiktok/authorization',
{ state: 'test-state' }
);
});
});
});

View File

@@ -0,0 +1,13 @@
import userNotificationSettings from '../userNotificationSettings';
import ApiClient from '../ApiClient';
describe('#AgentAPI', () => {
it('creates correct instance', () => {
expect(userNotificationSettings).toBeInstanceOf(ApiClient);
expect(userNotificationSettings).toHaveProperty('get');
expect(userNotificationSettings).toHaveProperty('show');
expect(userNotificationSettings).toHaveProperty('create');
expect(userNotificationSettings).toHaveProperty('update');
expect(userNotificationSettings).toHaveProperty('delete');
});
});

View File

@@ -0,0 +1,13 @@
import webhooksAPI from '../webhooks';
import ApiClient from '../ApiClient';
describe('#webhooksAPI', () => {
it('creates correct instance', () => {
expect(webhooksAPI).toBeInstanceOf(ApiClient);
expect(webhooksAPI).toHaveProperty('get');
expect(webhooksAPI).toHaveProperty('show');
expect(webhooksAPI).toHaveProperty('create');
expect(webhooksAPI).toHaveProperty('update');
expect(webhooksAPI).toHaveProperty('delete');
});
});