diff --git a/backend/__tests__/services/customScriptSanitiser.test.js b/backend/__tests__/services/customScriptSanitiser.test.js new file mode 100644 index 00000000..e56ebb62 --- /dev/null +++ b/backend/__tests__/services/customScriptSanitiser.test.js @@ -0,0 +1,100 @@ +/** + * Tests for the custom-tracker HTML sanitiser (#663 Phase 1). + * + * The field accepts admin-pasted ``-style snippets for arbitrary + * trackers (Plausible / Matomo / Pirsch / GA4 / GoatCounter / Fathom / + * Cloudflare Web Analytics). We sanitise on save with a narrow allowlist + * tuned for tracker scripts — defence-in-depth, even though the field is + * admin-only. + */ + +const { sanitizeTrackerSnippet } = require('../../src/services/trackers/customScriptSanitiser'); + +describe('sanitizeTrackerSnippet (#663)', () => { + test('returns empty string for non-string / empty / whitespace input', () => { + expect(sanitizeTrackerSnippet(null)).toBe(''); + expect(sanitizeTrackerSnippet(undefined)).toBe(''); + expect(sanitizeTrackerSnippet(42)).toBe(''); + expect(sanitizeTrackerSnippet('')).toBe(''); + expect(sanitizeTrackerSnippet(' ')).toBe(''); + }); + + test('passes through a Plausible-style script tag with data-domain', () => { + const input = ''; + const out = sanitizeTrackerSnippet(input); + expect(out).toContain('src="https://plausible.io/js/script.js"'); + expect(out).toContain('data-domain="example.com"'); + expect(out).toContain('defer'); + }); + + test('passes through a Umami-style script with data-website-id', () => { + const input = ''; + const out = sanitizeTrackerSnippet(input); + expect(out).toContain('src="https://analytics.example.com/script.js"'); + expect(out).toContain('data-website-id="aaa-bbb-ccc"'); + }); + + test('passes through inline script body unchanged', () => { + const input = ''; + const out = sanitizeTrackerSnippet(input); + expect(out).toContain('window.GA = "x"'); + expect(out).toContain('console.log("init")'); + }); + + test('allows