From 8577e17dde8d5cfd7df5fcb87f775a558fe090cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sadjow=20Le=C3=A3o?= Date: Tue, 13 Oct 2026 21:06:14 -0300 Subject: [PATCH] test: consolidate utm helper tests into one suite --- test/unit.test.ts | 121 ---------------------------- test/unit/utm.test.ts | 157 ------------------------------------- test/utm.test.ts | 178 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 278 deletions(-) delete mode 100644 test/unit.test.ts delete mode 100644 test/unit/utm.test.ts create mode 100644 test/utm.test.ts diff --git a/test/unit.test.ts b/test/unit.test.ts deleted file mode 100644 index ab427ca..0000000 --- a/test/unit.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { ref, type Ref } from 'vue' -import type { DataObject } from 'nuxt-utm' -import { describe, it, expect, beforeEach } from 'vitest' -import { isRepeatedEntry, readLocalData, urlHasUtmParams, getUtmParams } from './../src/runtime/utm' - -global.localStorage = (() => { - let store: Record = {} - - return { - getItem: (key: string): string | null => store[key] ?? null, - setItem: (key: string, value: string): void => { - store[key] = value.toString() - }, - removeItem: (key: string): void => { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete store[key] - }, - clear: (): void => { - store = {} - }, - key: (): string | null => '', - length: Object.keys(store).length, - } -})() - -describe('readLocalData function', () => { - beforeEach(() => { - localStorage.clear() - }) - it('Returns empty array if local storage is empty', () => { - expect(readLocalData('nuxt-utm-test')).toEqual([]) - }) - - it('Returns an array with objects if local storage has data', () => { - localStorage.setItem('nuxt-utm-test', `[${utmItem}]`) - expect(readLocalData('nuxt-utm-test')).toEqual([JSON.parse(utmItem)]) - }) -}) - -describe('urlHasUtmParams function', () => { - it('Returns false if there are no utm values', () => { - const locationQueryMock = {} - expect(urlHasUtmParams(locationQueryMock)).toBeFalsy() - }) - - it('Returns true if at least one utm value exists', () => { - const locationQueryMock = { utm_source: 'test_source' } - expect(urlHasUtmParams(locationQueryMock)).toBeTruthy() - }) -}) - -describe('getUtmParams function', () => { - it('Returns the correct utm values', () => { - const locationQueryMock = { - utm_source: 'test_source', - utm_medium: 'test_medium', - utm_term: 'test_term', - utm_content: 'test_content', - } - expect(getUtmParams(locationQueryMock)).toEqual({ - utm_source: 'test_source', - utm_medium: 'test_medium', - utm_term: 'test_term', - utm_content: 'test_content', - }) - }) - - it('Returns undefined values when no UTM params are present', () => { - const locationQueryMock = {} - expect(getUtmParams(locationQueryMock)).toEqual({ - utm_source: undefined, - utm_medium: undefined, - utm_campaign: undefined, - utm_term: undefined, - utm_content: undefined, - }) - }) -}) - -describe('isRepeatedEntry function', () => { - let data: Ref - let newUtmItem: DataObject - beforeEach(() => { - data = ref(JSON.parse(`[${utmItem}]`)) - newUtmItem = JSON.parse(utmItem) - }) - - it('Returns true if the utm params and the session already exists in local storage', () => { - expect(isRepeatedEntry(data, newUtmItem)).toBeTruthy() - }) - it('Returns false if the utm params are the same but the session is different', () => { - newUtmItem.sessionId = 'New Session' - expect(isRepeatedEntry(data, newUtmItem)).toBeFalsy() - }) - it('Returns false if the utm params are different but the session is the same', () => { - newUtmItem.utmParams.utm_content = 'New UTM content' - expect(isRepeatedEntry(data, newUtmItem)).toBeFalsy() - }) -}) - -const utmItem = `{ - "timestamp": "2023-11-02T10:11:17.219Z", - "utmParams": { - "utm_source": "test_source", - "utm_medium": "test_medium", - "utm_campaign": "test_campaign", - "utm_term": "test_term", - "utm_content": "test_content" - }, - "additionalInfo": { - "referrer": "http://localhost:3000/?utm_source=test_source&utm_medium=test_medium&utm_campaign=test_campaign&utm_term=test_term&utm_content=test_content", - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", - "language": "en-GB", - "landingPageUrl": "http://localhost:3000/", - "screen": { - "width": 1728, - "height": 1117 - } - }, - "sessionId": "beai1gx7dg" -}` diff --git a/test/unit/utm.test.ts b/test/unit/utm.test.ts deleted file mode 100644 index 9c6cbf9..0000000 --- a/test/unit/utm.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { describe, it, expect } from 'vitest' -import type { LocationQuery } from 'vue-router' -import type { GCLIDParams } from 'nuxt-utm' -import { getGCLID } from '../../src/runtime/utm' - -describe('getGCLID', () => { - it('should return GCLID and gad_source when both are present in query', () => { - const query: LocationQuery = { - gclid: 'testGclid123', - gad_source: 'testGadSourceABC', - } - const expected: GCLIDParams = { - gclid: 'testGclid123', - gad_source: 'testGadSourceABC', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should return only gclid when gad_source is not present', () => { - const query: LocationQuery = { - gclid: 'testGclid123', - } - const expected: GCLIDParams = { - gclid: 'testGclid123', - gad_source: undefined, - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should return only gad_source when gclid is not present', () => { - const query: LocationQuery = { - gad_source: 'testGadSourceABC', - } - const expected: GCLIDParams = { - gclid: undefined, - gad_source: 'testGadSourceABC', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should return undefined for both when neither gclid nor gad_source is present', () => { - const query: LocationQuery = {} - const expected: GCLIDParams = { - gclid: undefined, - gad_source: undefined, - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should return empty strings if query parameters are empty strings', () => { - const query: LocationQuery = { - gclid: '', - gad_source: '', - } - const expected: GCLIDParams = { - gclid: '', - gad_source: '', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle gclid present and gad_source as empty string', () => { - const query: LocationQuery = { - gclid: 'testGclid123', - gad_source: '', - } - const expected: GCLIDParams = { - gclid: 'testGclid123', - gad_source: '', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle gad_source present and gclid as empty string', () => { - const query: LocationQuery = { - gclid: '', - gad_source: 'testGadSourceABC', - } - const expected: GCLIDParams = { - gclid: '', - gad_source: 'testGadSourceABC', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle query parameters with special characters', () => { - const query: LocationQuery = { - gclid: 'gclid-123_abc!@#', - gad_source: 'gad_source-XYZ*%^', - } - const expected: GCLIDParams = { - gclid: 'gclid-123_abc!@#', - gad_source: 'gad_source-XYZ*%^', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle query parameters that are numbers (as strings)', () => { - const query: LocationQuery = { - gclid: '12345', - gad_source: '67890', - } - const expected: GCLIDParams = { - gclid: '12345', - gad_source: '67890', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle null values for query parameters', () => { - const query: LocationQuery = { - gclid: null, - gad_source: null, - } - const expected: GCLIDParams = { - gclid: undefined, - gad_source: undefined, - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle one param as null and other present', () => { - const query: LocationQuery = { - gclid: 'testGclid123', - gad_source: null, - } - const expected: GCLIDParams = { - gclid: 'testGclid123', - gad_source: undefined, - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should convert array query parameters to comma-separated strings', () => { - const query: LocationQuery = { - gclid: ['testGclid123', 'anotherGclid'], - gad_source: ['testGadSourceABC', 'anotherGadSource'], - } - const expected: GCLIDParams = { - gclid: 'testGclid123,anotherGclid', - gad_source: 'testGadSourceABC,anotherGadSource', - } - expect(getGCLID(query)).toEqual(expected) - }) - - it('should handle mixed types of query parameters (string and array)', () => { - const query: LocationQuery = { - gclid: 'testGclid123', - gad_source: ['testGadSourceABC', 'anotherGadSource'], - } - const expected: GCLIDParams = { - gclid: 'testGclid123', - gad_source: 'testGadSourceABC,anotherGadSource', - } - expect(getGCLID(query)).toEqual(expected) - }) -}) diff --git a/test/utm.test.ts b/test/utm.test.ts new file mode 100644 index 0000000..83cebff --- /dev/null +++ b/test/utm.test.ts @@ -0,0 +1,178 @@ +import { ref } from 'vue' +import { describe, expect, it } from 'vitest' +import type { LocationQuery } from 'vue-router' +import type { DataObject, GCLIDParams } from '../src/runtime/types' +import { createStorage } from '../src/runtime/storage' +import { + getGCLID, + getUtmParams, + isRepeatedEntry, + readLocalData, + urlHasUtmParams, +} from '../src/runtime/utm' + +const entry: DataObject = { + timestamp: '2023-11-02T10:11:17.219Z', + utmParams: { + utm_source: 'test_source', + utm_medium: 'test_medium', + utm_campaign: 'test_campaign', + utm_term: 'test_term', + utm_content: 'test_content', + }, + additionalInfo: { + referrer: 'http://localhost:3000/?utm_source=test_source', + userAgent: 'test', + language: 'en-GB', + landingPageUrl: 'http://localhost:3000/', + screen: { width: 1728, height: 1117 }, + }, + sessionId: 'beai1gx7dg', +} + +const storageWith = (items: Record) => + createStorage(() => ({ getItem: (key: string) => items[key] ?? null }) as unknown as Storage) + +describe('readLocalData', () => { + it('returns an empty history when nothing is stored', () => { + expect(readLocalData('nuxt-utm-test', storageWith({}))).toEqual([]) + }) + + it('returns the entries stored under the key', () => { + const storage = storageWith({ 'nuxt-utm-test': JSON.stringify([entry]) }) + expect(readLocalData('nuxt-utm-test', storage)).toEqual([entry]) + }) +}) + +describe('urlHasUtmParams', () => { + it('returns false without UTM parameters', () => { + expect(urlHasUtmParams({})).toBe(false) + }) + + it('returns true when at least one UTM parameter is present', () => { + expect(urlHasUtmParams({ utm_source: 'test_source' })).toBe(true) + }) +}) + +describe('getUtmParams', () => { + it('reads the UTM parameters from the query', () => { + const query = { + utm_source: 'test_source', + utm_medium: 'test_medium', + utm_term: 'test_term', + utm_content: 'test_content', + } + expect(getUtmParams(query)).toEqual(query) + }) + + it('returns undefined values when no UTM parameters are present', () => { + expect(getUtmParams({})).toEqual({ + utm_source: undefined, + utm_medium: undefined, + utm_campaign: undefined, + utm_term: undefined, + utm_content: undefined, + }) + }) +}) + +interface GCLIDCase { + name: string + query: LocationQuery + expected: GCLIDParams +} + +describe('getGCLID', () => { + it.each([ + { + name: 'both parameters', + query: { gclid: 'testGclid123', gad_source: 'testGadSourceABC' }, + expected: { gclid: 'testGclid123', gad_source: 'testGadSourceABC' }, + }, + { + name: 'gclid alone', + query: { gclid: 'testGclid123' }, + expected: { gclid: 'testGclid123', gad_source: undefined }, + }, + { + name: 'gad_source alone', + query: { gad_source: 'testGadSourceABC' }, + expected: { gclid: undefined, gad_source: 'testGadSourceABC' }, + }, + { + name: 'a query without either parameter', + query: {}, + expected: { gclid: undefined, gad_source: undefined }, + }, + { + name: 'empty strings', + query: { gclid: '', gad_source: '' }, + expected: { gclid: '', gad_source: '' }, + }, + { + name: 'gclid with an empty gad_source', + query: { gclid: 'testGclid123', gad_source: '' }, + expected: { gclid: 'testGclid123', gad_source: '' }, + }, + { + name: 'gad_source with an empty gclid', + query: { gclid: '', gad_source: 'testGadSourceABC' }, + expected: { gclid: '', gad_source: 'testGadSourceABC' }, + }, + { + name: 'special characters', + query: { gclid: 'gclid-123_abc!@#', gad_source: 'gad_source-XYZ*%^' }, + expected: { gclid: 'gclid-123_abc!@#', gad_source: 'gad_source-XYZ*%^' }, + }, + { + name: 'numeric strings', + query: { gclid: '12345', gad_source: '67890' }, + expected: { gclid: '12345', gad_source: '67890' }, + }, + { + name: 'null values as undefined', + query: { gclid: null, gad_source: null }, + expected: { gclid: undefined, gad_source: undefined }, + }, + { + name: 'gclid with a null gad_source', + query: { gclid: 'testGclid123', gad_source: null }, + expected: { gclid: 'testGclid123', gad_source: undefined }, + }, + { + name: 'repeated parameters as comma-separated strings', + query: { + gclid: ['testGclid123', 'anotherGclid'], + gad_source: ['testGadSourceABC', 'anotherGadSource'], + }, + expected: { + gclid: 'testGclid123,anotherGclid', + gad_source: 'testGadSourceABC,anotherGadSource', + }, + }, + { + name: 'a single and a repeated parameter', + query: { gclid: 'testGclid123', gad_source: ['testGadSourceABC', 'anotherGadSource'] }, + expected: { gclid: 'testGclid123', gad_source: 'testGadSourceABC,anotherGadSource' }, + }, + ])('reads $name', ({ query, expected }) => { + expect(getGCLID(query)).toEqual(expected) + }) +}) + +describe('isRepeatedEntry', () => { + const history = ref([entry]) + + it('detects the same campaign in the same session', () => { + expect(isRepeatedEntry(history, { ...entry })).toBe(true) + }) + + it('treats the same campaign in a new session as a new entry', () => { + expect(isRepeatedEntry(history, { ...entry, sessionId: 'new-session' })).toBe(false) + }) + + it('treats changed UTM parameters in the same session as a new entry', () => { + const utmParams = { ...entry.utmParams, utm_content: 'new-content' } + expect(isRepeatedEntry(history, { ...entry, utmParams })).toBe(false) + }) +})