Files
chatwoot/app/javascript/dashboard/composables/spec/useInbox.spec.js
Muhsin Keloth b18341ea6e feat: Add QR codes for WhatsApp, Messenger, and Telegram on inbox finish page (#12257)
Added QR code generation for multiple messaging platforms on the inbox
finish setup page. So users can scan QR codes to instantly test their
newly created channels.

**Supported Platforms**

  - **WhatsApp**: QR code for `https://wa.me/{phone_number}`
    - Supports both WhatsApp Cloud and Twilio WhatsApp inboxes
  - **Facebook Messenger**: QR code for `https://m.me/{page_id}`
    - All Facebook page inboxes
  - **Telegram**: QR code for `https://t.me/{bot_name}`
    - All Telegram bot inboxes

**How to test the changes**
You can test these changes by navigating to this URL
`{BASE_URL}/app/accounts/{account_id}/settings/inboxes/new/{inbox_id}/finish`
and simply replacing the inbox ID with one you've already created.

**Preview**

<img width="2432" height="1474" alt="CleanShot 2025-08-21 at 15 40
59@2x"
src="https://github.com/user-attachments/assets/4226133b-9793-48ca-bf79-903b7e003ef3"
/>

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
2025-08-27 11:53:03 +05:30

278 lines
8.5 KiB
JavaScript

import { describe, it, expect, vi } from 'vitest';
import { defineComponent, h } from 'vue';
import { createStore } from 'vuex';
import { mount } from '@vue/test-utils';
import { useInbox } from '../useInbox';
import { INBOX_TYPES } from 'dashboard/helper/inbox';
vi.mock('dashboard/composables/store');
vi.mock('dashboard/composables/useTransformKeys');
// Mock the dependencies
const mockStore = createStore({
modules: {
conversations: {
namespaced: false,
getters: {
getSelectedChat: () => ({ inbox_id: 1 }),
},
},
inboxes: {
namespaced: true,
getters: {
getInboxById: () => id => {
const inboxes = {
1: {
id: 1,
channel_type: INBOX_TYPES.WHATSAPP,
provider: 'whatsapp_cloud',
},
2: { id: 2, channel_type: INBOX_TYPES.FB },
3: { id: 3, channel_type: INBOX_TYPES.TWILIO, medium: 'sms' },
4: { id: 4, channel_type: INBOX_TYPES.TWILIO, medium: 'whatsapp' },
5: {
id: 5,
channel_type: INBOX_TYPES.EMAIL,
provider: 'microsoft',
},
6: { id: 6, channel_type: INBOX_TYPES.EMAIL, provider: 'google' },
7: {
id: 7,
channel_type: INBOX_TYPES.WHATSAPP,
provider: 'default',
},
8: { id: 8, channel_type: INBOX_TYPES.TELEGRAM },
9: { id: 9, channel_type: INBOX_TYPES.LINE },
10: { id: 10, channel_type: INBOX_TYPES.WEB },
11: { id: 11, channel_type: INBOX_TYPES.API },
12: { id: 12, channel_type: INBOX_TYPES.SMS },
13: { id: 13, channel_type: INBOX_TYPES.INSTAGRAM },
14: { id: 14, channel_type: INBOX_TYPES.VOICE },
};
return inboxes[id] || null;
},
},
},
},
});
// Mock useMapGetter to return mock store getters
vi.mock('dashboard/composables/store', () => ({
useMapGetter: vi.fn(getter => {
if (getter === 'getSelectedChat') {
return { value: { inbox_id: 1 } };
}
if (getter === 'inboxes/getInboxById') {
return { value: mockStore.getters['inboxes/getInboxById'] };
}
return { value: null };
}),
}));
// Mock useCamelCase to return the data as-is for testing
vi.mock('dashboard/composables/useTransformKeys', () => ({
useCamelCase: vi.fn(data => ({
...data,
channelType: data?.channel_type,
})),
}));
describe('useInbox', () => {
const createTestComponent = inboxId =>
defineComponent({
setup() {
return useInbox(inboxId);
},
render() {
return h('div');
},
});
describe('with current chat context (no inboxId provided)', () => {
it('identifies WhatsApp Cloud channel correctly', () => {
const wrapper = mount(createTestComponent(), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(true);
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
});
it('returns correct inbox object', () => {
const wrapper = mount(createTestComponent(), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.inbox).toEqual({
id: 1,
channel_type: INBOX_TYPES.WHATSAPP,
provider: 'whatsapp_cloud',
channelType: INBOX_TYPES.WHATSAPP,
});
});
});
describe('with explicit inboxId provided', () => {
it('identifies Facebook inbox correctly', () => {
const wrapper = mount(createTestComponent(2), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAFacebookInbox).toBe(true);
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
});
it('identifies Twilio SMS channel correctly', () => {
const wrapper = mount(createTestComponent(3), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isATwilioChannel).toBe(true);
expect(wrapper.vm.isASmsInbox).toBe(true);
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
});
it('identifies Twilio WhatsApp channel correctly', () => {
const wrapper = mount(createTestComponent(4), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isATwilioChannel).toBe(true);
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
expect(wrapper.vm.isATwilioWhatsAppChannel).toBe(true);
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(false);
});
it('identifies Microsoft email inbox correctly', () => {
const wrapper = mount(createTestComponent(5), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAnEmailChannel).toBe(true);
expect(wrapper.vm.isAMicrosoftInbox).toBe(true);
expect(wrapper.vm.isAGoogleInbox).toBe(false);
});
it('identifies Google email inbox correctly', () => {
const wrapper = mount(createTestComponent(6), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAnEmailChannel).toBe(true);
expect(wrapper.vm.isAGoogleInbox).toBe(true);
expect(wrapper.vm.isAMicrosoftInbox).toBe(false);
});
it('identifies 360Dialog WhatsApp channel correctly', () => {
const wrapper = mount(createTestComponent(7), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.is360DialogWhatsAppChannel).toBe(true);
expect(wrapper.vm.isAWhatsAppChannel).toBe(true);
expect(wrapper.vm.isAWhatsAppCloudChannel).toBe(false);
});
it('identifies all other channel types correctly', () => {
// Test Telegram
let wrapper = mount(createTestComponent(8), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isATelegramChannel).toBe(true);
// Test Line
wrapper = mount(createTestComponent(9), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isALineChannel).toBe(true);
// Test Web Widget
wrapper = mount(createTestComponent(10), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAWebWidgetInbox).toBe(true);
// Test API
wrapper = mount(createTestComponent(11), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAPIInbox).toBe(true);
// Test SMS
wrapper = mount(createTestComponent(12), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isASmsInbox).toBe(true);
// Test Instagram
wrapper = mount(createTestComponent(13), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAnInstagramChannel).toBe(true);
// Test Voice
wrapper = mount(createTestComponent(14), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.isAVoiceChannel).toBe(true);
});
});
describe('edge cases', () => {
it('handles non-existent inbox ID gracefully', () => {
const wrapper = mount(createTestComponent(999), {
global: { plugins: [mockStore] },
});
// useCamelCase still processes null data, so we get an object with channelType: undefined
expect(wrapper.vm.inbox).toEqual({ channelType: undefined });
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
expect(wrapper.vm.isAFacebookInbox).toBe(false);
});
it('handles inbox with no data correctly', () => {
// The mock will return null for non-existent IDs, but useCamelCase processes it
const wrapper = mount(createTestComponent(999), {
global: { plugins: [mockStore] },
});
expect(wrapper.vm.inbox.channelType).toBeUndefined();
expect(wrapper.vm.isAWhatsAppChannel).toBe(false);
expect(wrapper.vm.isAFacebookInbox).toBe(false);
expect(wrapper.vm.isATelegramChannel).toBe(false);
});
});
describe('return object completeness', () => {
it('returns all expected properties', () => {
const wrapper = mount(createTestComponent(1), {
global: { plugins: [mockStore] },
});
const expectedProperties = [
'inbox',
'isAFacebookInbox',
'isALineChannel',
'isAPIInbox',
'isASmsInbox',
'isATelegramChannel',
'isATwilioChannel',
'isAWebWidgetInbox',
'isAWhatsAppChannel',
'isAMicrosoftInbox',
'isAGoogleInbox',
'isATwilioWhatsAppChannel',
'isAWhatsAppCloudChannel',
'is360DialogWhatsAppChannel',
'isAnEmailChannel',
'isAnInstagramChannel',
'isAVoiceChannel',
];
expectedProperties.forEach(prop => {
expect(wrapper.vm).toHaveProperty(prop);
});
});
});
});