Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
1681 lines
62 KiB
TypeScript
1681 lines
62 KiB
TypeScript
import { faker } from '@faker-js/faker';
|
|
import type { ILivechatVisitor, IOmnichannelRoom } from '@rocket.chat/core-typings';
|
|
import { expect } from 'chai';
|
|
import { before, describe, it, after } from 'mocha';
|
|
import type { Response } from 'supertest';
|
|
|
|
import { getCredentials, api, request, credentials } from '../../../data/api-data';
|
|
import { createCustomField, deleteCustomField } from '../../../data/livechat/custom-fields';
|
|
import {
|
|
makeAgentAvailable,
|
|
createAgent,
|
|
createLivechatRoom,
|
|
createVisitor,
|
|
startANewLivechatRoomAndTakeIt,
|
|
closeOmnichannelRoom,
|
|
createVisitorWithCustomData,
|
|
sendAgentMessage,
|
|
sendMessage,
|
|
} from '../../../data/livechat/rooms';
|
|
import { getRandomVisitorToken } from '../../../data/livechat/users';
|
|
import { getLivechatVisitorByToken } from '../../../data/livechat/visitor';
|
|
import {
|
|
updatePermission,
|
|
updateSetting,
|
|
removePermissionFromAllRoles,
|
|
restorePermissionToRoles,
|
|
updateEESetting,
|
|
} from '../../../data/permissions.helper';
|
|
import { adminUsername } from '../../../data/user';
|
|
import { IS_EE } from '../../../e2e/config/constants';
|
|
|
|
const getLicenseInfo = (loadValues = false) => {
|
|
return request.get(api('licenses.info')).set(credentials).query({ loadValues }).expect(200);
|
|
};
|
|
|
|
describe('LIVECHAT - visitors', () => {
|
|
let visitor: ILivechatVisitor;
|
|
|
|
before((done) => getCredentials(done));
|
|
|
|
before(async () => {
|
|
await updateSetting('Livechat_enabled', true);
|
|
await updatePermission('view-livechat-manager', ['admin']);
|
|
await updateEESetting('Livechat_Require_Contact_Verification', 'never');
|
|
await createAgent();
|
|
await makeAgentAvailable();
|
|
visitor = await createVisitor();
|
|
});
|
|
|
|
describe('livechat/visitor', () => {
|
|
it('should fail if no "visitor" key is passed as body parameter', async () => {
|
|
const { body } = await request.post(api('livechat/visitor')).send({});
|
|
expect(body).to.have.property('success', false);
|
|
});
|
|
it('should fail if visitor.token is not present', async () => {
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: {} });
|
|
expect(body).to.have.property('success', false);
|
|
});
|
|
it('should fail when token is an empty string', async () => {
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token: '' } });
|
|
expect(body).to.have.property('success', false);
|
|
});
|
|
it('should create a visitor', async () => {
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token: 'test' } });
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', 'test');
|
|
|
|
// Ensure all new visitors are created as online :)
|
|
expect(body.visitor).to.have.property('status', 'online');
|
|
});
|
|
it('should create a visitor with provided extra information', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const phone = new Date().getTime().toString();
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token, phone } });
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.have.property('phone');
|
|
expect(body.visitor.phone[0].phoneNumber).to.equal(phone);
|
|
});
|
|
it('should save customFields when passed', async () => {
|
|
const customFieldName = `new_custom_field_${Date.now()}`;
|
|
const token = `${new Date().getTime()}-test`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: customFieldName,
|
|
label: customFieldName,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'Not a real address :)', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.have.property('livechatData');
|
|
expect(body.visitor.livechatData).to.have.property(customFieldName, 'Not a real address :)');
|
|
});
|
|
it('should update a current visitor when phone is same', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const token2 = `${new Date().getTime()}-test2`;
|
|
const phone = new Date().getTime().toString();
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token, phone } });
|
|
expect(body).to.have.property('success', true);
|
|
|
|
const { body: body2 } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: token2,
|
|
phone,
|
|
},
|
|
});
|
|
|
|
expect(body2).to.have.property('success', true);
|
|
expect(body2).to.have.property('visitor');
|
|
|
|
// Same visitor won't update the token
|
|
expect(body2.visitor).to.have.property('token', token);
|
|
expect(body2.visitor).to.have.property('phone');
|
|
expect(body2.visitor.phone[0].phoneNumber).to.equal(phone);
|
|
});
|
|
|
|
it('should update a visitor custom fields when customFields key is provided', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const customFieldName = `new_custom_field_${Date.now()}`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: customFieldName,
|
|
label: customFieldName,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'Not a real address :)', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.have.property('livechatData');
|
|
expect(body.visitor.livechatData).to.have.property(customFieldName, 'Not a real address :)');
|
|
});
|
|
|
|
it('should not update a custom field when it does not exists', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const customFieldName = `new_custom_field_${Date.now()}`;
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'Not a real address :)', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.not.have.property('livechatData');
|
|
});
|
|
|
|
it('should not update a custom field when the scope of it is not visitor', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const customFieldName = `new_custom_field_${Date.now()}`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: customFieldName,
|
|
label: customFieldName,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'room',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'Not a real address :)', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.not.have.property('livechatData');
|
|
});
|
|
|
|
it('should not update a custom field when the overwrite flag is false', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const customFieldName = `new_custom_field_${Date.now()}`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: customFieldName,
|
|
label: customFieldName,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'Not a real address :)', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token,
|
|
customFields: [{ key: customFieldName, value: 'This should not change!', overwrite: false }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
expect(body.visitor).to.have.property('livechatData');
|
|
expect(body.visitor.livechatData).to.have.property(customFieldName, 'Not a real address :)');
|
|
});
|
|
|
|
it('should not validate required custom fields if no custom fields are provided', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const customFieldName = `required_custom_field`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: customFieldName,
|
|
label: customFieldName,
|
|
defaultValue: 'default_value',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
required: true,
|
|
});
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token } });
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
await deleteCustomField(customFieldName);
|
|
});
|
|
|
|
it('should fail if provided custom fields but are missing required ones', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
const optionalCustomFieldName = `optional_custom_field`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: optionalCustomFieldName,
|
|
label: optionalCustomFieldName,
|
|
defaultValue: 'default_value',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
required: false,
|
|
});
|
|
const requiredCustomFieldName = `required_custom_field`;
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: requiredCustomFieldName,
|
|
label: requiredCustomFieldName,
|
|
defaultValue: 'default_value',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
required: true,
|
|
});
|
|
const { body } = await request
|
|
.post(api('livechat/visitor'))
|
|
.send({ visitor: { token, customFields: [{ key: optionalCustomFieldName, value: 'test', overwrite: true }] } });
|
|
expect(body).to.have.property('success', false);
|
|
expect(body).to.have.property('error');
|
|
expect(body.error).to.be.equal(`Missing required custom fields: required_custom_field`);
|
|
await Promise.all([deleteCustomField(optionalCustomFieldName), deleteCustomField(requiredCustomFieldName)]);
|
|
});
|
|
|
|
describe('special cases', () => {
|
|
before(async () => {
|
|
await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', true);
|
|
});
|
|
after(async () => {
|
|
await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', false);
|
|
});
|
|
|
|
it('should allow to create a visitor without passing connectionData when GDPR setting is enabled', async () => {
|
|
const token = `${new Date().getTime()}-test`;
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({ visitor: { token } });
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body).to.have.property('visitor');
|
|
expect(body.visitor).to.have.property('token', token);
|
|
});
|
|
});
|
|
|
|
describe('visitor & contact custom fields', () => {
|
|
let visitor: ILivechatVisitor;
|
|
let room: IOmnichannelRoom;
|
|
const cf1 = `cf1-${Date.now()}_1`;
|
|
const cf2 = `cf2-${Date.now()}_2`;
|
|
const cf3 = `cf3-${Date.now()}_3`;
|
|
before(async () => {
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: cf1,
|
|
label: cf1,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: cf2,
|
|
label: cf2,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: cf3,
|
|
label: cf3,
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
});
|
|
after(async () => {
|
|
await Promise.all([deleteCustomField(cf1), deleteCustomField(cf2), deleteCustomField(cf3)]);
|
|
});
|
|
|
|
it('should update custom fields on the contact', async () => {
|
|
const visitor = await createVisitor();
|
|
const room = await createLivechatRoom(visitor.token);
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [{ key: cf1, value: 'test', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
|
|
await request
|
|
.get(api(`omnichannel/contacts.get`))
|
|
.set(credentials)
|
|
.query({ contactId: room.contactId })
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('customFields');
|
|
expect(res.body.contact.customFields).to.have.property(cf1, 'test');
|
|
});
|
|
await closeOmnichannelRoom(room!._id);
|
|
});
|
|
it('should update multiple custom fields on a contact after it already has custom fields added', async () => {
|
|
const visitor = await createVisitor();
|
|
const room = await createLivechatRoom(visitor.token);
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [{ key: cf1, value: 'test', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
|
|
const { body: body2 } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [
|
|
{ key: cf2, value: 'test', overwrite: true },
|
|
{ key: cf3, value: 'test', overwrite: false },
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(body2).to.have.property('success', true);
|
|
|
|
await request
|
|
.get(api(`omnichannel/contacts.get`))
|
|
.set(credentials)
|
|
.query({ contactId: room.contactId })
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('customFields');
|
|
expect(res.body.contact.customFields).to.have.property(cf1, 'test');
|
|
expect(res.body.contact.customFields).to.have.property(cf2, 'test');
|
|
expect(res.body.contact.customFields).to.have.property(cf3, 'test');
|
|
});
|
|
await closeOmnichannelRoom(room!._id);
|
|
});
|
|
it('should overwrite a custom field value when the flag is true', async () => {
|
|
const visitor = await createVisitor();
|
|
const room = await createLivechatRoom(visitor.token);
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [{ key: cf1, value: 'test', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
|
|
const { body: body2 } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [
|
|
{ key: cf1, value: 'new test', overwrite: true },
|
|
{ key: cf3, value: 'test', overwrite: false },
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(body2).to.have.property('success', true);
|
|
|
|
await request
|
|
.get(api(`omnichannel/contacts.get`))
|
|
.set(credentials)
|
|
.query({ contactId: room.contactId })
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('customFields');
|
|
expect(res.body.contact.customFields).to.have.property(cf1, 'new test');
|
|
expect(res.body.contact.customFields).to.have.property(cf3, 'test');
|
|
});
|
|
await closeOmnichannelRoom(room!._id);
|
|
});
|
|
it('should properly conflict a custom field when existing and overwrite is false', async () => {
|
|
visitor = await createVisitor();
|
|
room = await createLivechatRoom(visitor.token);
|
|
|
|
const { body } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [{ key: cf1, value: 'test', overwrite: true }],
|
|
},
|
|
});
|
|
|
|
expect(body).to.have.property('success', true);
|
|
|
|
const { body: body2 } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [
|
|
{ key: cf1, value: 'new test', overwrite: false },
|
|
{ key: cf2, value: 'test', overwrite: true },
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(body2).to.have.property('success', true);
|
|
|
|
await request
|
|
.get(api(`omnichannel/contacts.get`))
|
|
.set(credentials)
|
|
.query({ contactId: room.contactId })
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('customFields');
|
|
expect(res.body.contact.customFields).to.have.property(cf1, 'test');
|
|
expect(res.body.contact.customFields).to.have.property(cf2, 'test');
|
|
expect(res.body.contact.conflictingFields).to.be.an('array');
|
|
expect(res.body.contact.conflictingFields[0])
|
|
.to.be.an('object')
|
|
.that.is.deep.equal({
|
|
field: `customFields.${cf1}`,
|
|
value: 'new test',
|
|
});
|
|
});
|
|
});
|
|
it('should add more conflicts to a contact custom fields', async () => {
|
|
const { body: body2 } = await request.post(api('livechat/visitor')).send({
|
|
visitor: {
|
|
token: visitor.token,
|
|
customFields: [
|
|
{ key: cf1, value: 'new test 2', overwrite: false },
|
|
{ key: cf2, value: 'test', overwrite: true },
|
|
],
|
|
},
|
|
});
|
|
|
|
expect(body2).to.have.property('success', true);
|
|
|
|
await request
|
|
.get(api(`omnichannel/contacts.get`))
|
|
.set(credentials)
|
|
.query({ contactId: room.contactId })
|
|
.expect(200)
|
|
.expect((res) => {
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('customFields');
|
|
expect(res.body.contact.customFields).to.have.property(cf1, 'test');
|
|
expect(res.body.contact.customFields).to.have.property(cf2, 'test');
|
|
expect(res.body.contact.conflictingFields).to.be.an('array').with.lengthOf(2);
|
|
expect(res.body.contact.conflictingFields[0])
|
|
.to.be.an('object')
|
|
.that.is.deep.equal({
|
|
field: `customFields.${cf1}`,
|
|
value: 'new test',
|
|
});
|
|
expect(res.body.contact.conflictingFields[1])
|
|
.to.be.an('object')
|
|
.that.is.deep.equal({
|
|
field: `customFields.${cf1}`,
|
|
value: 'new test 2',
|
|
});
|
|
});
|
|
await closeOmnichannelRoom(room._id);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.info', () => {
|
|
it('should return an "unauthorized error" when the user does not have the necessary permission', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.info'))
|
|
.query({ visitorId: 'invalid' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('User does not have the permissions required for this action [error-unauthorized]');
|
|
});
|
|
});
|
|
it('should return an "visitor not found error" when the visitor doe snot exists', async () => {
|
|
await updatePermission('view-l-room', ['admin']);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.info'))
|
|
.query({ visitorId: 'invalid' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('visitor-not-found');
|
|
});
|
|
});
|
|
it('should return the visitor info', async () => {
|
|
await request
|
|
.get(api('livechat/visitors.info'))
|
|
.query({ visitorId: visitor._id })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.visitor._id).to.be.equal(visitor._id);
|
|
});
|
|
});
|
|
it('should not return the visitor token', async () => {
|
|
await request
|
|
.get(api('livechat/visitors.info'))
|
|
.query({ visitorId: visitor._id })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.visitor).to.not.have.property('token');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.pagesVisited', () => {
|
|
it('should return an "unauthorized error" when the user does not have the necessary permission', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.pagesVisited/room-id'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('User does not have the permissions required for this action [error-unauthorized]');
|
|
});
|
|
});
|
|
it('should return an "error" when the roomId param is not provided', async () => {
|
|
await updatePermission('view-l-room', ['admin']);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.pagesVisited/room-id'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
it('should return an array of pages', async () => {
|
|
await updatePermission('view-l-room', ['admin']);
|
|
const createdVisitor = await createVisitor();
|
|
const createdRoom = await createLivechatRoom(createdVisitor.token);
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.pagesVisited/${createdRoom._id}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.pages).to.be.an('array');
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.chatHistory/room/room-id/visitor/visitor-id', () => {
|
|
it('should return an "unauthorized error" when the user does not have the necessary permission', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.chatHistory/room/room-id/visitor/visitor-id'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('User does not have the permissions required for this action [error-unauthorized]');
|
|
});
|
|
});
|
|
it('should return an "error" when the roomId param is invalid', async () => {
|
|
await updatePermission('view-l-room', ['admin']);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.chatHistory/room/room-id/visitor/visitor-id'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
it('should return an array of chat history', async () => {
|
|
await updatePermission('view-l-room', ['admin']);
|
|
const createdVisitor = await createVisitor();
|
|
|
|
const createdRoom = await createLivechatRoom(createdVisitor.token);
|
|
await request
|
|
.get(api(`livechat/visitors.chatHistory/room/${createdRoom._id}/visitor/${createdVisitor._id}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body).to.have.property('offset');
|
|
expect(res.body).to.have.property('total');
|
|
expect(res.body).to.have.property('count');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitor/:token', () => {
|
|
// get
|
|
it("should return a 'invalid token' error when visitor with given token does not exist ", async () => {
|
|
await request
|
|
.get(api('livechat/visitor/invalid'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('[invalid-token]');
|
|
});
|
|
});
|
|
|
|
it('should return an error when the "token" query parameter is not valid', async () => {
|
|
await request
|
|
.get(api('livechat/visitor/invalid'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
|
|
it('should return a visitor when the query params is all valid', async () => {
|
|
await request
|
|
.get(api(`livechat/visitor/${visitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('visitor');
|
|
});
|
|
});
|
|
|
|
// delete
|
|
it("should return a 'invalid token' error when visitor with given token does not exist ", async () => {
|
|
await request
|
|
.delete(api('livechat/visitor/invalid'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('[invalid-token]');
|
|
});
|
|
});
|
|
|
|
it('should return an error when the "token" query parameter is not valid', async () => {
|
|
await request
|
|
.delete(api('livechat/visitor/invalid'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
|
|
it("should return a 'visitor-has-open-rooms' error when there are open rooms", async () => {
|
|
await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', false);
|
|
const createdVisitor = await createVisitor();
|
|
await createLivechatRoom(createdVisitor.token);
|
|
|
|
await request
|
|
.delete(api(`livechat/visitor/${createdVisitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal('Cannot remove visitors with opened rooms [visitor-has-open-rooms]');
|
|
});
|
|
});
|
|
|
|
it("should not return a 'visitor-has-open-rooms' when visitor has open rooms but GDPR is enabled", async () => {
|
|
await updateSetting('Livechat_Allow_collect_and_store_HTTP_header_informations', true);
|
|
const createdVisitor = await createVisitor();
|
|
await createLivechatRoom(createdVisitor.token);
|
|
|
|
await request
|
|
.delete(api(`livechat/visitor/${createdVisitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
});
|
|
|
|
it('should remove the rooms associated with the visitor if any', async () => {
|
|
const createdVisitor = await createVisitor();
|
|
const room = await createLivechatRoom(createdVisitor.token);
|
|
|
|
await request
|
|
.delete(api(`livechat/visitor/${createdVisitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
await request.get(api('livechat/room')).query({ rid: room._id }).set(credentials).expect(400);
|
|
});
|
|
|
|
it('should remove the contact associated with the visitor if any', async () => {
|
|
const createdVisitor = await createVisitor();
|
|
const room = await createLivechatRoom(createdVisitor.token);
|
|
|
|
await request
|
|
.delete(api(`livechat/visitor/${createdVisitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
await request.get(api(`omnichannel/contacts.get`)).set(credentials).query({ contactId: room.contactId }).expect(404);
|
|
});
|
|
|
|
it('should return a visitor when the query params is all valid', async () => {
|
|
const createdVisitor = await createVisitor();
|
|
await request
|
|
.delete(api(`livechat/visitor/${createdVisitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('visitor');
|
|
expect(res.body.visitor).to.have.property('_id');
|
|
expect(res.body.visitor).to.have.property('ts');
|
|
expect(res.body.visitor._id).to.be.equal(createdVisitor._id);
|
|
});
|
|
});
|
|
|
|
it('should not affect MAC count when a visitor is removed via GDPR', async () => {
|
|
const { visitor, room } = await startANewLivechatRoomAndTakeIt();
|
|
// agent should send a message on the room
|
|
await request
|
|
.post(api('chat.sendMessage'))
|
|
.set(credentials)
|
|
.send({
|
|
message: {
|
|
rid: room._id,
|
|
msg: 'test',
|
|
},
|
|
});
|
|
const { body: currentLicense } = await getLicenseInfo(true);
|
|
|
|
await request
|
|
.delete(api(`livechat/visitor/${visitor.token}`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
const { body: licenseAfterGdpr } = await getLicenseInfo(true);
|
|
|
|
expect(currentLicense.license).to.have.property('limits');
|
|
expect(currentLicense.license.limits).to.have.property('monthlyActiveContacts');
|
|
expect(currentLicense.license.limits.monthlyActiveContacts).to.have.property('value');
|
|
const currentLimit = currentLicense.license.limits.monthlyActiveContacts.value;
|
|
|
|
expect(licenseAfterGdpr.license).to.have.property('limits');
|
|
expect(licenseAfterGdpr.license.limits).to.have.property('monthlyActiveContacts');
|
|
expect(licenseAfterGdpr.license.limits.monthlyActiveContacts).to.have.property('value');
|
|
const limitAfterGdpr = licenseAfterGdpr.license.limits.monthlyActiveContacts.value;
|
|
|
|
expect(limitAfterGdpr).to.be.equal(currentLimit);
|
|
});
|
|
|
|
it("should return a 'error-removing-visitor' error when removeGuest's result is false", async () => {
|
|
await request
|
|
.delete(api('livechat/visitor/123'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.autocomplete', () => {
|
|
it('should return an error when the user doesnt have the right permissions', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
await request
|
|
.get(api('livechat/visitors.autocomplete'))
|
|
.set(credentials)
|
|
.query({ selector: 'invalid' })
|
|
.query({ selector: 'xxx' })
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403);
|
|
});
|
|
|
|
it('should return an error when the "selector" query parameter is not valid', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
await request
|
|
.get(api('livechat/visitors.autocomplete'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
expect(res.body.error).to.be.equal("must have required property 'selector' [invalid-params]");
|
|
});
|
|
});
|
|
|
|
it('should return an error if "selector" param is not JSON serializable', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
await request
|
|
.get(api('livechat/visitors.autocomplete'))
|
|
.query({ selector: '{invalid' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
|
|
it('should return a list of visitors when the query params is all valid', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
const createdVisitor = await createVisitor();
|
|
|
|
await request
|
|
.get(api('livechat/visitors.autocomplete'))
|
|
.query({ selector: JSON.stringify({ term: createdVisitor.name }) })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('items');
|
|
expect(res.body.items).to.be.an('array');
|
|
expect(res.body.items).to.have.length.of.at.least(1);
|
|
expect(res.body.items[0]).to.have.property('_id');
|
|
expect(res.body.items[0]).to.have.property('name');
|
|
|
|
const visitor = res.body.items.find((item: any) => item._id === createdVisitor._id);
|
|
expect(visitor).to.have.property('_id');
|
|
expect(visitor).to.have.property('name');
|
|
expect(visitor._id).to.be.equal(createdVisitor._id);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.searchChats/room/:roomId/visitor/:visitorId', () => {
|
|
it('should return an error when the user doesnt have the right permissions', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
await request
|
|
.get(api('livechat/visitors.searchChats/room/123/visitor/123'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(403);
|
|
});
|
|
|
|
it('should throw an error when the roomId is not valid', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
|
|
await request
|
|
.get(api('livechat/visitors.searchChats/room/invalid/visitor/123'))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
});
|
|
|
|
it('should return an empty array if the user is not the one serving the chat', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
await updateSetting('Livechat_Routing_Method', 'Manual_Selection');
|
|
const createdVisitor = await createVisitor();
|
|
const room = await createLivechatRoom(createdVisitor.token);
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${room._id}/visitor/123`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history).to.have.lengthOf(0);
|
|
});
|
|
});
|
|
|
|
it('should return an empty array if the visitorId doesnt correlate to room', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
await updateSetting('Livechat_Routing_Method', 'Manual_Selection');
|
|
const createdVisitor = await createVisitor();
|
|
const room = await createLivechatRoom(createdVisitor.token);
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${room._id}/visitor/123`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history).to.have.lengthOf(0);
|
|
});
|
|
});
|
|
|
|
it('should return a list of chats when the query params is all valid', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent', 'livechat-manager']);
|
|
await createAgent();
|
|
|
|
const {
|
|
room: { _id: roomId },
|
|
visitor: { _id: visitorId },
|
|
} = await startANewLivechatRoomAndTakeIt();
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${roomId}/visitor/${visitorId}?closedChatsOnly=false&servedChatsOnly=true`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history).to.have.length.of.at.least(1);
|
|
expect(res.body.history[0]).to.have.property('_id');
|
|
expect(res.body.history[0]).to.have.property('fname');
|
|
expect(res.body.history[0]).to.have.property('v');
|
|
});
|
|
});
|
|
|
|
it('should return a list of chats when filtered by ', async () => {
|
|
const {
|
|
room: { _id: roomId },
|
|
visitor: { _id: visitorId },
|
|
} = await startANewLivechatRoomAndTakeIt();
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${roomId}/visitor/${visitorId}?source=api&servedChatsOnly=true`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history).to.have.length.of.at.least(1);
|
|
expect(res.body.history[0]).to.have.property('_id');
|
|
expect(res.body.history[0]).to.have.property('fname');
|
|
expect(res.body.history[0]).to.have.property('v');
|
|
});
|
|
});
|
|
|
|
it('should return only closed chats when closedChatsOnly is true', async () => {
|
|
const {
|
|
room: { _id: roomId },
|
|
visitor: { _id: visitorId },
|
|
} = await startANewLivechatRoomAndTakeIt();
|
|
|
|
await closeOmnichannelRoom(roomId);
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${roomId}/visitor/${visitorId}?closedChatsOnly=true&servedChatsOnly=false`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history.find((chat: any) => chat._id === roomId)).to.be.an('object');
|
|
});
|
|
});
|
|
|
|
it('should return only served chats when servedChatsOnly is true', async () => {
|
|
const visitor = await createVisitor();
|
|
const room = await createLivechatRoom(visitor.token);
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${room._id}/visitor/${visitor._id}?closedChatsOnly=false&servedChatsOnly=true`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history.find((chat: any) => chat._id === room._id)).to.be.undefined;
|
|
});
|
|
});
|
|
|
|
it('should return closed rooms (served & unserved) when `closedChatsOnly` is true & `servedChatsOnly` is false', async () => {
|
|
const {
|
|
room: { _id: roomId },
|
|
visitor: { _id: visitorId, token },
|
|
} = await startANewLivechatRoomAndTakeIt();
|
|
await closeOmnichannelRoom(roomId);
|
|
const room2 = await createLivechatRoom(token);
|
|
await closeOmnichannelRoom(room2._id);
|
|
|
|
await request
|
|
.get(api(`livechat/visitors.searchChats/room/${roomId}/visitor/${visitorId}?closedChatsOnly=true&servedChatsOnly=false`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('history');
|
|
expect(res.body.history).to.be.an('array');
|
|
expect(res.body.history.find((chat: any) => chat._id === roomId)).to.be.an('object');
|
|
expect(res.body.history.find((chat: any) => chat._id === room2._id)).to.be.an('object');
|
|
});
|
|
});
|
|
|
|
it('should return all chats when both closed & served flags are false', async () => {
|
|
const visitor = await createVisitor();
|
|
const room = await createLivechatRoom(visitor.token);
|
|
await closeOmnichannelRoom(room._id);
|
|
const room2 = await createLivechatRoom(visitor.token);
|
|
await closeOmnichannelRoom(room2._id);
|
|
await createLivechatRoom(visitor.token);
|
|
|
|
const { body } = await request
|
|
.get(api(`livechat/visitors.searchChats/room/${room._id}/visitor/${visitor._id}?closedChatsOnly=false&servedChatsOnly=false`))
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200);
|
|
|
|
expect(body).to.have.property('success', true);
|
|
expect(body.count).to.be.equal(3);
|
|
expect(body.history.filter((chat: any) => !!chat.closedAt).length === 2).to.be.true;
|
|
expect(body.history.filter((chat: any) => !chat.closedAt).length === 1).to.be.true;
|
|
expect(body.total).to.be.equal(3);
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitor.status', () => {
|
|
it('should return an error if token is not present as body param', async () => {
|
|
const res = await request.post(api('livechat/visitor.status')).set(credentials).expect(400);
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should return an error if status is not present as body param', async () => {
|
|
const res = await request.post(api('livechat/visitor.status')).set(credentials).send({ token: '123' }).expect(400);
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should return an error if token is not a valid guest token', async () => {
|
|
const res = await request.post(api('livechat/visitor.status')).set(credentials).send({ token: '123', status: 'online' }).expect(400);
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should update visitor status if all things are valid', async () => {
|
|
const visitor = await createVisitor();
|
|
const res = await request
|
|
.post(api('livechat/visitor.status'))
|
|
.set(credentials)
|
|
.send({ token: visitor.token, status: 'online' })
|
|
.expect(200);
|
|
expect(res.body).to.have.property('success', true);
|
|
});
|
|
});
|
|
|
|
describe('GET [omnichannel/contact.search]', () => {
|
|
it('should fail if no email|phone|custom params are passed as query', async () => {
|
|
await request.get(api('omnichannel/contact.search')).set(credentials).expect('Content-Type', 'application/json').expect(400);
|
|
});
|
|
it('should fail if its trying to find by an empty string', async () => {
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ email: '' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
});
|
|
it('should fail if custom is passed but is not JSON serializable', async () => {
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: '{a":1}' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
});
|
|
it('should fail if custom is an empty object and no email|phone are provided', async () => {
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: '{}' })
|
|
.set(credentials)
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(400);
|
|
});
|
|
it('should find a contact by email', async () => {
|
|
const visitor = await createVisitor();
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ email: visitor.visitorEmails?.[0].address })
|
|
.set(credentials)
|
|
.send()
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('_id');
|
|
expect(res.body.contact).to.have.property('name');
|
|
expect(res.body.contact).to.have.property('username');
|
|
expect(res.body.contact).to.have.property('phone');
|
|
expect(res.body.contact).to.have.property('visitorEmails');
|
|
expect(res.body.contact._id).to.be.equal(visitor._id);
|
|
expect(res.body.contact.phone[0].phoneNumber).to.be.equal(visitor.phone?.[0].phoneNumber);
|
|
// done();
|
|
});
|
|
});
|
|
it('should find a contact by phone', async () => {
|
|
const visitor = await createVisitor();
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ phone: visitor.phone?.[0].phoneNumber })
|
|
.set(credentials)
|
|
.send()
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.have.property('_id');
|
|
expect(res.body.contact).to.have.property('name');
|
|
expect(res.body.contact).to.have.property('username');
|
|
expect(res.body.contact).to.have.property('phone');
|
|
expect(res.body.contact).to.have.property('visitorEmails');
|
|
expect(res.body.contact._id).to.be.equal(visitor._id);
|
|
expect(res.body.contact.phone[0].phoneNumber).to.be.equal(visitor.phone?.[0].phoneNumber);
|
|
});
|
|
});
|
|
it('should find a contact by custom field', async () => {
|
|
const cfID = 'address';
|
|
const cf = await createCustomField({
|
|
searchable: true,
|
|
field: 'address',
|
|
label: 'address',
|
|
defaultValue: 'test_default_address',
|
|
scope: 'visitor',
|
|
visibility: 'public',
|
|
regexp: '',
|
|
});
|
|
|
|
if (!cf) {
|
|
throw new Error('Custom field not created');
|
|
}
|
|
|
|
await createVisitor();
|
|
|
|
await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ address: 'Rocket.Chat' }) })
|
|
.set(credentials)
|
|
.send()
|
|
.expect('Content-Type', 'application/json')
|
|
.expect(200)
|
|
.expect((res: Response) => {
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.have.property('name');
|
|
expect(res.body.contact).to.have.property('username');
|
|
expect(res.body.contact).to.have.property('phone');
|
|
expect(res.body.contact).to.have.property('visitorEmails');
|
|
expect(res.body.contact.livechatData).to.have.property('address', 'Rocket.Chat street');
|
|
});
|
|
|
|
await deleteCustomField(cfID);
|
|
});
|
|
|
|
it('should return null if an invalid set of custom fields is passed and no other params are sent', async () => {
|
|
const res = await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ nope: 'nel' }) })
|
|
.set(credentials)
|
|
.send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.be.null;
|
|
});
|
|
|
|
it('should not break if more than 1 custom field are passed', async () => {
|
|
const res = await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ nope: 'nel', another: 'field' }) })
|
|
.set(credentials)
|
|
.send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.be.null;
|
|
});
|
|
|
|
it('should not break if bad things are passed as custom field keys', async () => {
|
|
const res = await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ $regex: 'nel' }) })
|
|
.set(credentials)
|
|
.send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.be.null;
|
|
});
|
|
|
|
it('should not break if bad things are passed as custom field keys 2', async () => {
|
|
const res = await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ '$regex: { very-bad }': 'nel' }) })
|
|
.set(credentials)
|
|
.send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.be.null;
|
|
});
|
|
|
|
it('should not break if bad things are passed as custom field values', async () => {
|
|
const res = await request
|
|
.get(api('omnichannel/contact.search'))
|
|
.query({ custom: JSON.stringify({ nope: '^((ab)*)+$' }) })
|
|
.set(credentials)
|
|
.send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.contact).to.be.null;
|
|
});
|
|
});
|
|
|
|
describe('livechat/visitors.search', () => {
|
|
it('should fail if user doesnt have view-l-room permission', async () => {
|
|
await updatePermission('view-l-room', []);
|
|
const res = await request.get(api('livechat/visitors.search')).query({ text: 'nel' }).set(credentials).send();
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should fail if term is not on query params', async () => {
|
|
await updatePermission('view-l-room', ['admin', 'livechat-agent']);
|
|
const res = await request.get(api(`livechat/visitors.search`)).set(credentials).send();
|
|
expect(res.body).to.have.property('success', false);
|
|
});
|
|
it('should not fail when term is an evil regex string', async () => {
|
|
const res = await request.get(api('livechat/visitors.search')).query({ term: '^((ab)*)+$' }).set(credentials).send();
|
|
expect(res.body).to.have.property('success', true);
|
|
});
|
|
it('should return a list of visitors when term is a valid string', async () => {
|
|
const visitor = await createVisitor();
|
|
|
|
const res = await request.get(api('livechat/visitors.search')).query({ term: visitor.name }).set(credentials).send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.visitors).to.be.an('array');
|
|
expect(res.body.visitors).to.have.lengthOf.greaterThan(0);
|
|
expect(res.body.visitors[0]).to.have.property('_id', visitor._id);
|
|
expect(res.body.visitors[0]).to.have.property('name', visitor.name);
|
|
expect(res.body.visitors[0]).to.have.property('username', visitor.username);
|
|
expect(res.body.visitors[0]).to.have.property('visitorEmails');
|
|
expect(res.body.visitors[0]).to.have.property('phone');
|
|
});
|
|
it('should return a list of visitors when term is an empty string', async () => {
|
|
const res = await request.get(api('livechat/visitors.search')).query({ term: '' }).set(credentials).send();
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body.visitors).to.be.an('array');
|
|
expect(res.body.visitors).to.have.lengthOf.greaterThan(0);
|
|
expect(res.body.visitors[0]).to.have.property('_id');
|
|
expect(res.body.visitors[0]).to.have.property('username');
|
|
expect(res.body.visitors[0]).to.have.property('name');
|
|
expect(res.body.visitors[0]).to.have.property('phone');
|
|
expect(res.body.visitors[0]).to.have.property('visitorEmails');
|
|
});
|
|
});
|
|
|
|
describe('omnichannel/contact', () => {
|
|
let contact: ILivechatVisitor;
|
|
it('should fail if user doesnt have view-l-room permission', async () => {
|
|
await removePermissionFromAllRoles('view-l-room');
|
|
const res = await request.get(api('omnichannel/contact')).query({ text: 'nel' }).set(credentials).send();
|
|
expect(res.body).to.have.property('success', false);
|
|
|
|
await restorePermissionToRoles('view-l-room');
|
|
});
|
|
it('should create a new contact', async () => {
|
|
const token = getRandomVisitorToken();
|
|
const res = await request.post(api('omnichannel/contact')).set(credentials).send({
|
|
name: faker.person.fullName(),
|
|
token,
|
|
});
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.be.an('string');
|
|
const contactId: string = res.body.contact;
|
|
|
|
contact = await getLivechatVisitorByToken(token);
|
|
expect(contact._id).to.equal(contactId);
|
|
});
|
|
it('should update an existing contact', async () => {
|
|
const name = faker.person.fullName();
|
|
const res = await request.post(api('omnichannel/contact')).set(credentials).send({
|
|
name,
|
|
token: contact.token,
|
|
});
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.be.an('string');
|
|
expect(res.body.contact).to.equal(contact._id);
|
|
|
|
contact = await getLivechatVisitorByToken(contact.token);
|
|
expect(contact.name).to.equal(name);
|
|
});
|
|
it('should change the contact name, email and phone', async () => {
|
|
const name = faker.person.fullName();
|
|
const email = faker.internet.email().toLowerCase();
|
|
const phone = faker.phone.number();
|
|
const res = await request.post(api('omnichannel/contact')).set(credentials).send({
|
|
name,
|
|
email,
|
|
phone,
|
|
token: contact.token,
|
|
});
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.be.an('string');
|
|
expect(res.body.contact).to.equal(contact._id);
|
|
|
|
contact = await getLivechatVisitorByToken(contact.token);
|
|
expect(contact.name).to.equal(name);
|
|
expect(contact.visitorEmails).to.be.an('array');
|
|
expect(contact.visitorEmails).to.have.lengthOf(1);
|
|
if (contact.visitorEmails?.[0]) {
|
|
expect(contact.visitorEmails[0].address).to.equal(email);
|
|
}
|
|
expect(contact.phone).to.be.an('array');
|
|
expect(contact.phone).to.have.lengthOf(1);
|
|
if (contact.phone?.[0]) {
|
|
expect(contact.phone[0].phoneNumber).to.equal(phone);
|
|
}
|
|
});
|
|
(IS_EE ? it : it.skip)('should change the contact manager', async () => {
|
|
const managerUsername = adminUsername;
|
|
|
|
const res = await request
|
|
.post(api('omnichannel/contact'))
|
|
.set(credentials)
|
|
.send({
|
|
contactManager: {
|
|
username: managerUsername,
|
|
},
|
|
token: contact.token,
|
|
name: contact.name,
|
|
});
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.be.an('string');
|
|
expect(res.body.contact).to.equal(contact._id);
|
|
|
|
contact = await getLivechatVisitorByToken(contact.token);
|
|
expect(contact.contactManager).to.be.an('object');
|
|
expect(contact.contactManager).to.have.property('username', managerUsername);
|
|
});
|
|
it('should change custom fields', async () => {
|
|
const cfName = faker.lorem.word();
|
|
await createCustomField({
|
|
searchable: true,
|
|
field: cfName,
|
|
label: cfName,
|
|
scope: 'visitor',
|
|
visibility: 'visible',
|
|
regexp: '',
|
|
});
|
|
|
|
const res = await request
|
|
.post(api('omnichannel/contact'))
|
|
.set(credentials)
|
|
.send({
|
|
token: contact.token,
|
|
name: contact.name,
|
|
customFields: {
|
|
[cfName]: 'test',
|
|
},
|
|
});
|
|
|
|
expect(res.body).to.have.property('success', true);
|
|
expect(res.body).to.have.property('contact');
|
|
expect(res.body.contact).to.be.an('string');
|
|
expect(res.body.contact).to.equal(contact._id);
|
|
|
|
contact = await getLivechatVisitorByToken(contact.token);
|
|
expect(contact).to.have.property('livechatData');
|
|
expect(contact.livechatData).to.have.property(cfName, 'test');
|
|
});
|
|
});
|
|
|
|
describe('lead capture', () => {
|
|
let visitor: ILivechatVisitor;
|
|
let room: IOmnichannelRoom;
|
|
|
|
before(async () => {
|
|
visitor = await createVisitorWithCustomData({
|
|
ignoreEmail: true,
|
|
ignorePhone: true,
|
|
});
|
|
room = await createLivechatRoom(visitor.token);
|
|
await createAgent();
|
|
});
|
|
after(async () => {
|
|
await closeOmnichannelRoom(room._id);
|
|
});
|
|
|
|
it('should capture the data matching the email regex and add it to the visitor', async () => {
|
|
await sendMessage(room._id, 'My email is random@email.com', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(1);
|
|
expect(visitor.visitorEmails?.[0].address).to.be.equal('random@email.com');
|
|
});
|
|
|
|
it('should capture more emails when the visitor sends the message', async () => {
|
|
await sendMessage(room._id, 'Another email is test@teste.com', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(2);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails).to.include('test@teste.com');
|
|
});
|
|
|
|
it('should capture multiple emails', async () => {
|
|
await sendMessage(room._id, 'My emails are test@123.com notest@1234.com', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(4);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails).to.include('test@123.com');
|
|
expect(emails).to.include('notest@1234.com');
|
|
});
|
|
|
|
it('should not add an email thats already registered', async () => {
|
|
await sendMessage(room._id, 'My email is test@123.com', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(4);
|
|
});
|
|
|
|
it('should not save emails the agent sends', async () => {
|
|
await sendAgentMessage(room._id, 'Confirming your email is test@12345.com?', credentials);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(4);
|
|
});
|
|
|
|
it('should save phone numbers matching the regex', async () => {
|
|
await sendMessage(room._id, 'My phone number is 12345678', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(1);
|
|
expect(visitor.phone?.[0].phoneNumber).to.be.equal('12345678');
|
|
});
|
|
|
|
it('should capture more phone numbers when the visitor sends the message', async () => {
|
|
await sendMessage(room._id, 'Another phone number is 87654321 87654323', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(3);
|
|
const phones = visitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones).to.include('87654321');
|
|
expect(phones).to.include('87654323');
|
|
});
|
|
|
|
it('should not add a phone number thats already registered', async () => {
|
|
await sendMessage(room._id, 'My phone number is 12345678', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(3);
|
|
});
|
|
|
|
it('should not save phone numbers the agent sends', async () => {
|
|
await sendAgentMessage(room._id, 'Confirming your phone number is 99999999?', credentials);
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(3);
|
|
});
|
|
|
|
it('should capture both phones & emails when sent on the same message', async () => {
|
|
await sendMessage(room._id, 'My email is zardw@asdf.com and my phone is 11223344', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(5);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails).to.include('zardw@asdf.com');
|
|
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(4);
|
|
const phones = visitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones).to.include('11223344');
|
|
});
|
|
|
|
describe('when settings are empty', () => {
|
|
before(async () => {
|
|
await updateSetting('Livechat_lead_phone_regex', '');
|
|
await updateSetting('Livechat_lead_email_regex', '');
|
|
});
|
|
|
|
after(async () => {
|
|
// reset settings
|
|
await updateSetting('Livechat_lead_email_regex', '\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,4}\\b');
|
|
await updateSetting(
|
|
'Livechat_lead_phone_regex',
|
|
'((?:\\([0-9]{1,3}\\)|[0-9]{2})[ \\-]*?[0-9]{4,5}(?:[\\-\\s\\_]{1,2})?[0-9]{4}(?:(?=[^0-9])|$)|[0-9]{4,5}(?:[\\-\\s\\_]{1,2})?[0-9]{4}(?:(?=[^0-9])|$))',
|
|
);
|
|
});
|
|
|
|
it('should not capture any email or phone no matter what the visitor sends', async () => {
|
|
await sendMessage(room._id, 'Now my email is this@shalnotpass.com', visitor.token);
|
|
|
|
await sendMessage(room._id, 'And my phone number is 55667788', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails || []).to.not.include('this@shalnotpass.com');
|
|
|
|
const phones = visitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones || []).to.not.include('55667788');
|
|
});
|
|
});
|
|
|
|
describe('when phone regex is broken', () => {
|
|
before(async () => {
|
|
await updateSetting('Livechat_lead_phone_regex', '(');
|
|
});
|
|
|
|
after(async () => {
|
|
// reset settings
|
|
await updateSetting(
|
|
'Livechat_lead_phone_regex',
|
|
'((?:\\([0-9]{1,3}\\)|[0-9]{2})[ \\-]*?[0-9]{4,5}(?:[\\-\\s\\_]{1,2})?[0-9]{4}(?:(?=[^0-9])|$)|[0-9]{4,5}(?:[\\-\\s\\_]{1,2})?[0-9]{4}(?:(?=[^0-9])|$))',
|
|
);
|
|
});
|
|
|
|
it('should capture email', async () => {
|
|
await sendMessage(room._id, 'Now my email is this@isok.com', visitor.token);
|
|
|
|
await sendMessage(room._id, 'And my phone number is 55667799', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
|
|
expect(visitor.visitorEmails).to.be.an('array');
|
|
expect(visitor.visitorEmails).to.have.lengthOf(6);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails).to.include('this@isok.com');
|
|
|
|
expect(visitor.phone).to.have.lengthOf(4);
|
|
const phones = visitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones || []).to.not.include('55667788');
|
|
});
|
|
});
|
|
|
|
describe('when email regex is broken', () => {
|
|
before(async () => {
|
|
await updateSetting('Livechat_lead_email_regex', '(');
|
|
});
|
|
|
|
after(async () => {
|
|
// reset settings
|
|
await updateSetting('Livechat_lead_email_regex', '\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,4}\\b');
|
|
});
|
|
|
|
it('should capture email', async () => {
|
|
await sendMessage(room._id, 'Now my email is this@shalnotpass.com', visitor.token);
|
|
|
|
await sendMessage(room._id, 'And my phone number is 98765432', visitor.token);
|
|
|
|
visitor = await getLivechatVisitorByToken(visitor.token);
|
|
|
|
expect(visitor.visitorEmails).to.have.lengthOf(6);
|
|
const emails = visitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails || []).to.not.include('this@shalnotpass.com');
|
|
|
|
expect(visitor.phone).to.be.an('array');
|
|
expect(visitor.phone).to.have.lengthOf(5);
|
|
const phones = visitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones).to.include('98765432');
|
|
});
|
|
});
|
|
|
|
describe('when the visitor has emails & phones already', () => {
|
|
let newVisitor: ILivechatVisitor;
|
|
let newRoom: IOmnichannelRoom;
|
|
before(async () => {
|
|
newVisitor = await createVisitor();
|
|
newRoom = await createLivechatRoom(newVisitor.token);
|
|
});
|
|
after(async () => {
|
|
await closeOmnichannelRoom(newRoom._id);
|
|
});
|
|
|
|
it('should capture new emails & phones and add them to the existing ones', async () => {
|
|
await sendMessage(newRoom._id, 'My email is 1234@12344.com and my phone is 11223344', newVisitor.token);
|
|
|
|
newVisitor = await getLivechatVisitorByToken(newVisitor.token);
|
|
expect(newVisitor.visitorEmails).to.be.an('array');
|
|
expect(newVisitor.visitorEmails).to.have.lengthOf(2);
|
|
const emails = newVisitor.visitorEmails?.map((e) => e.address);
|
|
expect(emails).to.include('1234@12344.com');
|
|
|
|
expect(newVisitor.phone).to.be.an('array');
|
|
expect(newVisitor.phone).to.have.lengthOf(2);
|
|
const phones = newVisitor.phone?.map((p) => p.phoneNumber);
|
|
expect(phones).to.include('11223344');
|
|
});
|
|
});
|
|
});
|
|
});
|