diff --git a/package-lock.json b/package-lock.json index 2624c89bb..ce125425f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,6 +72,7 @@ "@emotion/server": "^11.10.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^12.0.0", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.1.1", "axe-testcafe": "^1.1.0", "css-loader": "^7.1.1", @@ -5059,6 +5060,36 @@ "react-dom": "<18.0.0" } }, + "node_modules/@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, "node_modules/@testing-library/react/node_modules/@testing-library/dom": { "version": "8.20.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", @@ -19674,6 +19705,22 @@ "react": "17.0.2" } }, + "node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-error-overlay": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", diff --git a/package.json b/package.json index 8f15e9b4f..53afc0a16 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "@emotion/server": "^11.10.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^12.0.0", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.1.1", "axe-testcafe": "^1.1.0", "css-loader": "^7.1.1", diff --git a/src/components/Matomo/__tests__/MatomoTracker.test.js b/src/components/Matomo/__tests__/MatomoTracker.test.js new file mode 100644 index 000000000..2a058860f --- /dev/null +++ b/src/components/Matomo/__tests__/MatomoTracker.test.js @@ -0,0 +1,96 @@ +/* eslint-disable no-underscore-dangle */ +import MatomoTracker from '../MatomoTracker'; +import { TRACK_TYPES } from '../constants'; + +const MOCK_URL_BASE = 'https://www.test.fi/'; +const MOCK_TRACKER_URL = 'https://www.test.fi/matomo.php'; + +describe('MatomoTracker', () => { + beforeEach(() => { + window._paq = []; + }); + + it('should initialise window._paq', () => { + // eslint-disable-next-line no-new + new MatomoTracker({ + urlBase: MOCK_URL_BASE, + siteId: 'test123', + srcUrl: 'test.js', + enabled: true, + configurations: { + foo: 'bar', + testArray: ['testArrayItem1', 'testArrayItem2'], + testNoValue: undefined, + }, + }); + + expect(window._paq).toEqual([ + ['setTrackerUrl', MOCK_TRACKER_URL], + ['setSiteId', 'test123'], + ['foo', 'bar'], + ['testArray', 'testArrayItem1', 'testArrayItem2'], + ['testNoValue'], + ['enableLinkTracking', true], + ]); + }); + + it('should throw error if urlBase missing', () => { + expect( + () => new MatomoTracker({ siteId: 'test123' }), + ).toThrowError(); + }); + + it('should throw error if siteId missing', () => { + expect( + () => new MatomoTracker({ + urlBase: 'http://www.test.fi', + }), + ).toThrowError(); + }); + + it('should track page view', () => { + const tracker = new MatomoTracker({ + urlBase: MOCK_URL_BASE, + siteId: 'test123', + srcUrl: 'test.js', + enabled: true, + configurations: {}, + }); + + tracker.trackPageView(); + + expect(window._paq).toEqual([ + ['setTrackerUrl', MOCK_TRACKER_URL], + ['setSiteId', 'test123'], + ['enableLinkTracking', true], + ['setCustomUrl', window.location.href], + ['setDocumentTitle', ''], + [TRACK_TYPES.TRACK_VIEW], + ]); + }); + + it('should track custom event', () => { + const tracker = new MatomoTracker({ + urlBase: MOCK_URL_BASE, + siteId: 'test123', + srcUrl: 'test.js', + enabled: true, + configurations: {}, + }); + + tracker.track({ + data: ['event', 'click', 'button'], + documentTitle: 'Custom Event', + href: 'https://www.test.fi/custom-event', + }); + + expect(window._paq).toEqual([ + ['setTrackerUrl', MOCK_TRACKER_URL], + ['setSiteId', 'test123'], + ['enableLinkTracking', true], + ['setCustomUrl', 'https://www.test.fi/custom-event'], + ['setDocumentTitle', 'Custom Event'], + ['event', 'click', 'button'], + ]); + }); +}); diff --git a/src/components/Matomo/__tests__/matomo-context.test.js b/src/components/Matomo/__tests__/matomo-context.test.js new file mode 100644 index 000000000..a3f16667e --- /dev/null +++ b/src/components/Matomo/__tests__/matomo-context.test.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +import { MatomoProvider } from '../matomo-context'; + +describe('matomo-context', () => { + it('renders children with provided value', () => { + const value = 'test value'; + + const { getByText } = render( + +
Test Component
+
, + ); + + expect(getByText('Test Component')).toBeInTheDocument(); + }); +}); diff --git a/src/components/Matomo/hooks/__tests__/useMatomo.test.js b/src/components/Matomo/hooks/__tests__/useMatomo.test.js new file mode 100644 index 000000000..6faf14af5 --- /dev/null +++ b/src/components/Matomo/hooks/__tests__/useMatomo.test.js @@ -0,0 +1,68 @@ +import React, { useEffect } from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { render } from '@testing-library/react'; + +import MatomoContext, { MatomoProvider } from '../../matomo-context'; +import * as MatomoTracker from '../../MatomoTracker'; +import useMatomo from '../useMatomo'; + +const MOCK_URL = 'https://www.hel.fi'; + +describe('useMatomo', () => { + it('should return trackPageView function', () => { + const trackPageView = jest.fn(); + const instance = { trackPageView }; + + const wrapper = ({ children }) => ( + + {children} + + ); + + const { result } = renderHook(() => useMatomo(), { wrapper }); + + expect(result.current.trackPageView).toBeDefined(); + }); + + function MockedComponent() { + const { trackPageView } = useMatomo(); + + useEffect(() => { + trackPageView({ href: MOCK_URL }); + }, [trackPageView]); + + return
MockedComponent
; + } + + it('should trackPageView', () => { + const trackPageViewMock = jest.fn(); + + jest.spyOn(MatomoTracker, 'default').mockImplementation(() => ({ + trackPageView: trackPageViewMock, + })); + + // eslint-disable-next-line new-cap + const instance = new MatomoTracker.default({ + urlBase: MOCK_URL, + siteId: 'test123', + srcUrl: 'test.js', + enabled: true, + }); + + function MockProvider() { + return ( + + + + ); + } + + expect(MatomoTracker.default).toHaveBeenCalled(); + + render(); + + expect(trackPageViewMock).toHaveBeenCalledWith({ + href: MOCK_URL, + }); + }); +});