UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

434 lines (345 loc) 13 kB
import '@testing-library/jest-dom' import { axe, toHaveNoViolations } from 'jest-axe' import { fireEvent } from '@testing-library/dom' import { vi } from 'vitest' import { createElementTest, BaseTestConfig } from '../../tests/test-framework' import { CustomElementFor } from '../../tests/component-registry' import './consent' expect.extend(toHaveNoViolations) export interface ConsentTestConfig extends BaseTestConfig { devMode?: boolean googleAnalyticsId?: string hotjarId?: string cookieDomain?: string cookieSecure?: string // Using string to match the component's string attributes cookieExpiryDays?: string triggerType?: string triggerText?: string i18nLanguage?: string } // Use shared framework export const createConsentTest = async (config: ConsentTestConfig = {}) => { const { container, element } = await createElementTest< CustomElementFor<'pkt-consent'>, ConsentTestConfig >('pkt-consent', config) return { container, consent: element, } } // Cleanup after each test afterEach(() => { document.body.innerHTML = '' // Clean up any injected scripts const existingScript = document.querySelector('#oslo-consent-script') if (existingScript) { existingScript.remove() } const existingStyles = document.querySelector('#oslo-consent-styles') if (existingStyles) { existingStyles.remove() } // Clean up global variables delete window.cookieBanner_googleAnalyticsId ;(window as any).cookieBanner_hotjarId = undefined ;(window as any).cookieBanner_devMode = undefined ;(window as any).cookieBanner_cookieDomain = undefined ;(window as any).cookieBanner_cookieSecure = undefined ;(window as any).cookieBanner_cookieExpiryDays = undefined ;(window as any).cookieBanner = undefined ;(window as any).__cookieEvents = undefined }) describe('PktConsent', () => { describe('Rendering and basic functionality', () => { test('renders without errors', async () => { const { consent } = await createConsentTest() expect(consent).toBeInTheDocument() await consent.updateComplete expect(consent).toBeTruthy() }) test('renders with default trigger type as button', async () => { const { consent } = await createConsentTest() await consent.updateComplete expect(consent.triggerType).toBe('button') const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() }) test('renders with custom trigger text', async () => { const customText = 'Custom consent settings' const { consent } = await createConsentTest({ triggerText: customText, }) await consent.updateComplete expect(consent.triggerText).toBe(customText) const button = consent.querySelector('pkt-button') expect(button?.textContent?.trim()).toBe(customText) }) }) describe('Properties and attributes', () => { test('applies default properties correctly', async () => { const { consent } = await createConsentTest() await consent.updateComplete expect(consent.devMode).toBe(false) expect(consent.triggerType).toBe('button') expect(consent.i18nLanguage).toBe('nb') expect(consent.hotjarId).toBe(null) expect(consent.googleAnalyticsId).toBe(null) expect(consent.cookieDomain).toBe(null) expect(consent.cookieSecure).toBe(null) expect(consent.cookieExpiryDays).toBe(null) }) test('sets dev mode correctly', async () => { const { consent } = await createConsentTest({ devMode: true, }) await consent.updateComplete expect(consent.devMode).toBe(true) }) test('sets analytics IDs correctly', async () => { const googleId = 'GA-123456789' const hotjarId = 'HJ-987654321' const { consent } = await createConsentTest({ googleAnalyticsId: googleId, hotjarId: hotjarId, }) await consent.updateComplete expect(consent.googleAnalyticsId).toBe(googleId) expect(consent.hotjarId).toBe(hotjarId) }) test('sets cookie configuration correctly', async () => { const domain = '.example.com' const secure = 'true' const expiryDays = '365' const { consent } = await createConsentTest({ cookieDomain: domain, cookieSecure: secure, cookieExpiryDays: expiryDays, }) await consent.updateComplete expect(consent.cookieDomain).toBe(domain) expect(consent.cookieSecure).toBe(secure) expect(consent.cookieExpiryDays).toBe(expiryDays) }) test('sets language correctly', async () => { const { consent } = await createConsentTest({ i18nLanguage: 'en', }) await consent.updateComplete expect(consent.i18nLanguage).toBe('en') }) }) describe('Trigger types', () => { test('renders as button trigger type', async () => { const { consent } = await createConsentTest({ triggerType: 'button', }) await consent.updateComplete expect(consent.triggerType).toBe('button') const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() expect(button?.getAttribute('skin')).toBe(null) // Default button }) test('renders as link trigger type', async () => { const { consent } = await createConsentTest({ triggerType: 'link', }) expect(consent.triggerType).toBe('link') const link = consent.querySelector('a.pkt-link') expect(link).toBeInTheDocument() expect(link?.getAttribute('href')).toBe('#') }) test('renders as footer link trigger type', async () => { const { consent } = await createConsentTest({ triggerType: 'footerlink', }) expect(consent.triggerType).toBe('footerlink') const footerLink = consent.querySelector('a.pkt-footer__link') expect(footerLink).toBeInTheDocument() const icon = footerLink?.querySelector('pkt-icon') expect(icon).toBeInTheDocument() expect(icon?.getAttribute('name')).toBe('chevron-right') }) test('renders as icon trigger type', async () => { const { consent } = await createConsentTest({ triggerType: 'icon', }) expect(consent.triggerType).toBe('icon') const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() expect(button?.getAttribute('skin')).toBe('tertiary') expect(button?.getAttribute('variant')).toBe('icon-only') expect(button?.getAttribute('iconName')).toBe('cookie') }) }) describe('Event handling', () => { beforeEach(() => { // Mock the entire window.cookieBanner object Object.defineProperty(window, 'cookieBanner', { value: { cookieConsent: { validateConsentCookie: vi.fn().mockResolvedValue(true), getConsentCookie: vi.fn().mockReturnValue('mock-cookie'), }, openCookieModal: vi.fn(), }, writable: true, }) // Mock window.__cookieEvents Object.defineProperty(window, '__cookieEvents', { value: { on: vi.fn(), off: vi.fn(), }, writable: true, }) // Use fake timers to control setTimeout vi.useFakeTimers() }) afterEach(() => { // Clean up mocks and timers vi.useRealTimers() ;(window as any).cookieBanner = undefined ;(window as any).__cookieEvents = undefined }) test('handles click event on button trigger', async () => { const { consent } = await createConsentTest() const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() fireEvent.click(button!) // Fast-forward time to trigger setTimeout vi.runAllTimers() expect(window.cookieBanner.openCookieModal).toHaveBeenCalled() }) test('handles click event on link trigger', async () => { const { consent } = await createConsentTest({ triggerType: 'link', }) const link = consent.querySelector('a.pkt-link') expect(link).toBeInTheDocument() fireEvent.click(link!) // Fast-forward time to trigger setTimeout vi.runAllTimers() expect(window.cookieBanner.openCookieModal).toHaveBeenCalled() }) test('dispatches toggle-consent event', async () => { const { consent } = await createConsentTest() let eventFired = false let eventDetail: any = null consent.addEventListener('toggle-consent', (e: Event) => { eventFired = true eventDetail = (e as CustomEvent).detail }) // Mock consent data const mockConsent = { value: JSON.stringify({ items: [ { name: 'analytics', consent: true }, { name: 'marketing', consent: false }, ], }), } consent.emitCookieConsents(mockConsent) expect(eventFired).toBe(true) expect(eventDetail).toEqual({ analytics: true, marketing: false, }) }) }) describe('Utility methods', () => { test('returnJsonOrObject handles JSON strings', async () => { const { consent } = await createConsentTest() const jsonString = '{"test": "value"}' const result = consent.returnJsonOrObject(jsonString) expect(result).toEqual({ test: 'value' }) }) test('returnJsonOrObject handles non-JSON objects', async () => { const { consent } = await createConsentTest() const nonJsonObject = { test: 'value' } const result = consent.returnJsonOrObject(nonJsonObject) expect(result).toEqual(nonJsonObject) }) test('returnJsonOrObject handles invalid JSON gracefully', async () => { const { consent } = await createConsentTest() const invalidJson = 'invalid json string' const result = consent.returnJsonOrObject(invalidJson) expect(result).toBe(invalidJson) }) }) describe('Accessibility', () => { test('button trigger is accessible', async () => { const { container, consent } = await createConsentTest({ triggerText: 'Cookie settings', }) const results = await axe(container) expect(results).toHaveNoViolations() const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() expect(button?.textContent?.trim()).toBe('Cookie settings') }) test('link trigger is accessible', async () => { const { container, consent } = await createConsentTest({ triggerType: 'link', triggerText: 'Cookie settings', }) const results = await axe(container) expect(results).toHaveNoViolations() const link = consent.querySelector('a') expect(link).toBeInTheDocument() expect(link?.textContent?.trim()).toBe('Cookie settings') }) test('footer link trigger is accessible', async () => { const { container, consent } = await createConsentTest({ triggerType: 'footerlink', triggerText: 'Cookie settings', }) const results = await axe(container) expect(results).toHaveNoViolations() const link = consent.querySelector('a.pkt-footer__link') expect(link).toBeInTheDocument() expect(link?.textContent?.trim()).toContain('Cookie settings') }) test('icon trigger is accessible', async () => { const { container, consent } = await createConsentTest({ triggerType: 'icon', triggerText: 'Cookie settings', }) const results = await axe(container) expect(results).toHaveNoViolations() const button = consent.querySelector('pkt-button') expect(button).toBeInTheDocument() expect(button?.textContent?.trim()).toContain('Cookie settings') }) }) describe('Integration and lifecycle', () => { test('sets global variables on firstUpdated', async () => { const googleId = 'GA-123456789' const hotjarId = 'HJ-987654321' await createConsentTest({ devMode: true, googleAnalyticsId: googleId, hotjarId: hotjarId, cookieDomain: '.test.com', }) expect(window.cookieBanner_googleAnalyticsId).toBe(googleId) expect(window.cookieBanner_hotjarId).toBe(hotjarId) expect(window.cookieBanner_devMode).toBe(true) expect(window.cookieBanner_cookieDomain).toBe('.test.com') }) test('cleans up event listeners on disconnect', async () => { const { consent } = await createConsentTest() // Mock the event system window.__cookieEvents = { on: vi.fn(), off: vi.fn(), } // Set up a handler const mockHandler = vi.fn() consent['_cookieEventHandler'] = mockHandler // Disconnect the component consent.disconnectedCallback() expect(window.__cookieEvents.off).toHaveBeenCalledWith('CookieManager.setCookie', mockHandler) }) }) })