mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-05 21:48:03 +00:00
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>
278 lines
8.5 KiB
JavaScript
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);
|
|
});
|
|
});
|
|
});
|
|
});
|