import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { JSDOM } from 'jsdom'; import { InitializationHelpers, openExternalLinksInNewTab, } from '../portalHelpers'; describe('InitializationHelpers.navigateToLocalePage', () => { let dom; let document; let window; beforeEach(() => { dom = new JSDOM( '
', { url: 'http://localhost/' } ); document = dom.window.document; window = dom.window; global.document = document; global.window = window; }); afterEach(() => { dom = null; document = null; window = null; delete global.document; delete global.window; }); it('sets up document event listener regardless of locale-switcher existence', () => { document.querySelector('.locale-switcher').remove(); const documentSpy = vi.spyOn(document, 'addEventListener'); InitializationHelpers.navigateToLocalePage(); expect(documentSpy).toHaveBeenCalledWith('change', expect.any(Function)); documentSpy.mockRestore(); }); it('adds document-level event listener to handle locale switching', () => { const documentSpy = vi.spyOn(document, 'addEventListener'); InitializationHelpers.navigateToLocalePage(); expect(documentSpy).toHaveBeenCalledWith('change', expect.any(Function)); documentSpy.mockRestore(); }); }); describe('openExternalLinksInNewTab', () => { let dom; let document; let window; beforeEach(() => { dom = new JSDOM( `
External Internal Custom CodeBold
`, { url: 'https://app.chatwoot.com/hc/article' } ); document = dom.window.document; window = dom.window; window.portalConfig = { customDomain: 'custom.domain.com', hostURL: 'app.chatwoot.com', }; global.document = document; global.window = window; }); afterEach(() => { dom = null; document = null; window = null; delete global.document; delete global.window; }); const simulateClick = selector => { const element = document.querySelector(selector); const event = new window.MouseEvent('click', { bubbles: true }); element.dispatchEvent(event); return element.closest('a') || element; }; it('opens external links in new tab', () => { openExternalLinksInNewTab(); const link = simulateClick('#external'); expect(link.target).toBe('_blank'); expect(link.rel).toBe('noopener noreferrer'); }); it('preserves internal links', () => { openExternalLinksInNewTab(); const internal = simulateClick('#internal'); const custom = simulateClick('#custom'); expect(internal.target).not.toBe('_blank'); expect(custom.target).not.toBe('_blank'); }); it('handles clicks on nested elements', () => { openExternalLinksInNewTab(); simulateClick('#nested code'); simulateClick('#nested strong'); const link = document.getElementById('nested'); expect(link.target).toBe('_blank'); expect(link.rel).toBe('noopener noreferrer'); }); it('handles links inside list items with strong tags', () => { openExternalLinksInNewTab(); // Click on the strong element inside the link in the list simulateClick('#list-link strong'); const link = document.getElementById('list-link'); expect(link.target).toBe('_blank'); expect(link.rel).toBe('noopener noreferrer'); }); it('opens external links in a new tab even if customDomain is empty', () => { window = dom.window; window.portalConfig = { hostURL: 'app.chatwoot.com', }; global.window = window; openExternalLinksInNewTab(); const link = simulateClick('#external'); const internal = simulateClick('#internal'); const custom = simulateClick('#custom'); expect(link.target).toBe('_blank'); expect(link.rel).toBe('noopener noreferrer'); expect(internal.target).not.toBe('_blank'); // this will be blank since the configs customDomain is empty // which is a fair expectation expect(custom.target).toBe('_blank'); }); it('opens external links in a new tab even if hostURL is empty', () => { window = dom.window; window.portalConfig = { customDomain: 'custom.domain.com', }; global.window = window; openExternalLinksInNewTab(); const link = simulateClick('#external'); const internal = simulateClick('#internal'); const custom = simulateClick('#custom'); expect(link.target).toBe('_blank'); expect(link.rel).toBe('noopener noreferrer'); expect(internal.target).not.toBe('_blank'); expect(custom.target).not.toBe('_blank'); }); });