import { beforeEach, describe, expect, it, vi } from 'vitest'; const { app, ActionCableConnector } = vi.hoisted(() => ({ app: { use: vi.fn(), directive: vi.fn(), mount: vi.fn(() => ({ $store: {} })), }, ActionCableConnector: vi.fn(), })); vi.mock('vue', () => ({ createApp: () => app })); vi.mock('vue-i18n', () => ({ createI18n: vi.fn() })); vi.mock('vue-dompurify-html', () => ({ default: {} })); vi.mock('../../widget/store', () => ({ default: {} })); vi.mock('../../widget/App.vue', () => ({ default: {} })); vi.mock('../../widget/helpers/actionCable', () => ({ default: ActionCableConnector, })); vi.mock('../../widget/i18n', () => ({ default: {} })); vi.mock('../../widget/router', () => ({ default: {} })); vi.mock('vue3-click-away', () => ({ directive: {} })); vi.mock('../../shared/helpers/HTMLSanitizer', () => ({ domPurifyConfig: {}, })); vi.mock('@formkit/vue', () => ({ plugin: {}, defaultConfig: vi.fn(), })); vi.mock('shared/helpers/Validators', () => ({ startsWithPlus: vi.fn(), isPhoneNumberValidWithDialCode: vi.fn(), })); describe('widget entrypoint', () => { beforeEach(() => { vi.resetModules(); vi.clearAllMocks(); delete window.WOOT_WIDGET; delete window.actionCable; window.chatwootPubsubToken = 'pubsub-token'; }); it('mounts and connects only once when load fires repeatedly', async () => { vi.spyOn(document, 'readyState', 'get').mockReturnValue('loading'); await import('../widget'); window.dispatchEvent(new Event('load')); window.dispatchEvent(new Event('load')); expect(app.mount).toHaveBeenCalledOnce(); expect(ActionCableConnector).toHaveBeenCalledOnce(); expect(ActionCableConnector).toHaveBeenCalledWith( window.WOOT_WIDGET, 'pubsub-token' ); }); });