test: add vitest

* feature(root): add vitest and some basic tests

* fix(test): after rebase + added referrars test and more sites

* fix(test): test broken after rebase

* fix(test): provide db url to make prisma happy

* fix tests
This commit is contained in:
Carl-Gerhard Lindesvärd
2025-06-06 19:14:18 +02:00
committed by GitHub
parent 09c83ddeb4
commit 5445d6309e
23 changed files with 1131 additions and 3133 deletions

View File

@@ -121,14 +121,36 @@ export async function incomingEvent(
// if timestamp is from the past we dont want to create a new session
if (uaInfo.isServer || isTimestampFromThePast) {
const event = profileId
const screenView = profileId
? await eventBuffer.getLastScreenView({
profileId,
projectId,
})
: null;
const payload = merge(omit(['properties'], event ?? {}), baseEvent);
const payload = {
...baseEvent,
deviceId: screenView?.deviceId ?? '',
sessionId: screenView?.sessionId ?? '',
referrer: screenView?.referrer ?? undefined,
referrerName: screenView?.referrerName ?? undefined,
referrerType: screenView?.referrerType ?? undefined,
path: screenView?.path ?? baseEvent.path,
os: screenView?.os ?? baseEvent.os,
osVersion: screenView?.osVersion ?? baseEvent.osVersion,
browserVersion: screenView?.browserVersion ?? baseEvent.browserVersion,
browser: screenView?.browser ?? baseEvent.browser,
device: screenView?.device ?? baseEvent.device,
brand: screenView?.brand ?? baseEvent.brand,
model: screenView?.model ?? baseEvent.model,
city: screenView?.city ?? baseEvent.city,
country: screenView?.country ?? baseEvent.country,
region: screenView?.region ?? baseEvent.region,
longitude: screenView?.longitude ?? baseEvent.longitude,
latitude: screenView?.latitude ?? baseEvent.latitude,
origin: screenView?.origin ?? baseEvent.origin,
};
return createEventAndNotify(
payload as IServiceEvent,
job.data.payload,
@@ -180,7 +202,9 @@ export async function incomingEvent(
const event = await createEventAndNotify(payload, job.data.payload, logger);
await createSessionEndJob({ payload });
if (!sessionEnd) {
await createSessionEndJob({ payload });
}
return event;
}

View File

@@ -1,351 +1,380 @@
// import { type Mock, beforeEach, describe, expect, it, mock } from 'bun:test';
// import { getTime, toISOString } from '@openpanel/common';
// import type { Job } from 'bullmq';
// import { SESSION_TIMEOUT, incomingEvent } from './events.incoming-event';
import { type IServiceEvent, createEvent } from '@openpanel/db';
import { eventBuffer } from '@openpanel/db';
import { sessionsQueue } from '@openpanel/queue';
import type { Job } from 'bullmq';
import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest';
import { incomingEvent } from './events.incoming-event';
// const projectId = 'test-project';
// const currentDeviceId = 'device-123';
// const previousDeviceId = 'device-456';
// const geo = {
// country: 'US',
// city: 'New York',
// region: 'NY',
// longitude: 0,
// latitude: 0,
// };
vi.mock('@openpanel/queue');
vi.mock('@openpanel/db', async () => {
const actual = await vi.importActual('@openpanel/db');
return {
...actual,
createEvent: vi.fn(),
getLastScreenView: vi.fn(),
checkNotificationRulesForEvent: vi.fn().mockResolvedValue(true),
eventBuffer: {
getLastScreenView: vi.fn(),
},
};
});
// const createEvent = mock(() => {});
// const getLastScreenViewFromProfileId = mock();
// // // Mock dependencies
// mock.module('@openpanel/db', () => ({
// createEvent,
// getLastScreenViewFromProfileId,
// }));
// 30 minutes
const SESSION_TIMEOUT = 30 * 60 * 1000;
const projectId = 'test-project';
const currentDeviceId = 'device-123';
const previousDeviceId = 'device-456';
const geo = {
country: 'US',
city: 'New York',
region: 'NY',
longitude: 0,
latitude: 0,
};
// const sessionsQueue = { add: mock(() => Promise.resolve({})) };
describe('incomingEvent', () => {
beforeEach(() => {
vi.clearAllMocks();
});
// const findJobByPrefix = mock();
it('should create a session start and an event', async () => {
const spySessionsQueueAdd = vi.spyOn(sessionsQueue, 'add');
const timestamp = new Date();
// Mock job data
const jobData = {
payload: {
geo,
event: {
name: 'test_event',
timestamp: timestamp.toISOString(),
properties: { __path: 'https://example.com/test' },
},
headers: {
'request-id': '123',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'openpanel-sdk-name': 'web',
'openpanel-sdk-version': '1.0.0',
},
projectId,
currentDeviceId,
previousDeviceId,
},
};
// mock.module('@openpanel/queue', () => ({
// sessionsQueue,
// findJobByPrefix,
// }));
const job = { data: jobData } as Job;
// const getRedisQueue = mock(() => ({
// keys: mock(() => Promise.resolve([])),
// }));
// Execute the job
await incomingEvent(job);
// mock.module('@openpanel/redis', () => ({
// getRedisQueue,
// }));
const event = {
name: 'test_event',
deviceId: currentDeviceId,
profileId: '',
sessionId: expect.stringMatching(
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
),
projectId,
properties: {
__hash: undefined,
__query: undefined,
__user_agent: jobData.payload.headers['user-agent'],
__reqId: jobData.payload.headers['request-id'],
},
createdAt: timestamp,
country: 'US',
city: 'New York',
region: 'NY',
longitude: 0,
latitude: 0,
os: 'Windows',
osVersion: '10',
browser: 'Chrome',
browserVersion: '91.0.4472.124',
device: 'desktop',
brand: undefined,
model: undefined,
duration: 0,
path: '/test',
origin: 'https://example.com',
referrer: '',
referrerName: '',
referrerType: 'unknown',
sdkName: jobData.payload.headers['openpanel-sdk-name'],
sdkVersion: jobData.payload.headers['openpanel-sdk-version'],
};
// describe('incomingEvent', () => {
// beforeEach(() => {
// createEvent.mockClear();
// findJobByPrefix.mockClear();
// sessionsQueue.add.mockClear();
// getLastScreenViewFromProfileId.mockClear();
// });
expect(spySessionsQueueAdd).toHaveBeenCalledWith(
'session',
{
type: 'createSessionEnd',
payload: expect.objectContaining(event),
},
{
delay: SESSION_TIMEOUT,
jobId: `sessionEnd:${projectId}:${currentDeviceId}`,
attempts: 3,
backoff: {
delay: 200,
type: 'exponential',
},
},
);
// it('should create a session start and an event', async () => {
// const timestamp = new Date();
// // Mock job data
// const jobData = {
// payload: {
// geo,
// event: {
// name: 'test_event',
// timestamp: timestamp.toISOString(),
// properties: { __path: 'https://example.com/test' },
// },
// headers: {
// 'user-agent':
// 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
// 'openpanel-sdk-name': 'web',
// 'openpanel-sdk-version': '1.0.0',
// },
// projectId,
// currentDeviceId,
// previousDeviceId,
// priority: true,
// },
// };
expect((createEvent as Mock).mock.calls[0]![0]).toStrictEqual({
...event,
createdAt: new Date(timestamp.getTime() - 100),
name: 'session_start',
});
expect((createEvent as Mock).mock.calls[1]).toMatchObject([event]);
});
// const job = { data: jobData } as Job;
it('should reuse existing session', async () => {
const spySessionsQueueAdd = vi.spyOn(sessionsQueue, 'add');
const spySessionsQueueGetJob = vi.spyOn(sessionsQueue, 'getJob');
// // Execute the job
// await incomingEvent(job);
const timestamp = new Date();
// Mock job data
const jobData = {
payload: {
geo,
event: {
name: 'test_event',
timestamp: timestamp.toISOString(),
properties: { __path: 'https://example.com/test' },
},
headers: {
'request-id': '123',
'user-agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'openpanel-sdk-name': 'web',
'openpanel-sdk-version': '1.0.0',
},
projectId,
currentDeviceId,
previousDeviceId,
},
};
// const event = {
// name: 'test_event',
// deviceId: currentDeviceId,
// // @ts-expect-error
// sessionId: createEvent.mock.calls[1][0].sessionId,
// profileId: '',
// projectId,
// properties: {
// __hash: undefined,
// __query: undefined,
// },
// createdAt: timestamp,
// country: 'US',
// city: 'New York',
// region: 'NY',
// longitude: 0,
// latitude: 0,
// os: 'Windows',
// osVersion: '10',
// browser: 'Chrome',
// browserVersion: '91.0.4472.124',
// device: 'desktop',
// brand: '',
// model: '',
// duration: 0,
// path: '/test',
// origin: 'https://example.com',
// referrer: '',
// referrerName: '',
// referrerType: 'unknown',
// sdkName: 'web',
// sdkVersion: '1.0.0',
// };
const job = { data: jobData } as Job;
// expect(sessionsQueue.add.mock.calls[0]).toMatchObject([
// 'session',
// {
// type: 'createSessionEnd',
// payload: event,
// },
// {
// delay: SESSION_TIMEOUT,
// jobId: `sessionEnd:${projectId}:${event.deviceId}:${timestamp.getTime()}`,
// },
// ]);
const changeDelay = vi.fn();
const updateData = vi.fn();
spySessionsQueueGetJob.mockResolvedValueOnce({
getState: vi.fn().mockResolvedValue('delayed'),
updateData,
changeDelay,
data: {
type: 'createSessionEnd',
payload: {
sessionId: 'session-123',
deviceId: currentDeviceId,
profileId: currentDeviceId,
projectId,
},
},
} as Partial<Job> as Job);
// Execute the job
await incomingEvent(job);
// // Assertions
// // Issue: https://github.com/oven-sh/bun/issues/10380
// // expect(createEvent).toHaveBeenCalledWith(...)
// expect(createEvent.mock.calls[0]).toMatchObject([
// {
// name: 'session_start',
// deviceId: currentDeviceId,
// sessionId: expect.stringMatching(
// /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
// ),
// profileId: '',
// projectId,
// properties: {
// __hash: undefined,
// __query: undefined,
// },
// createdAt: new Date(timestamp.getTime() - 100),
// country: 'US',
// city: 'New York',
// region: 'NY',
// longitude: 0,
// latitude: 0,
// os: 'Windows',
// osVersion: '10',
// browser: 'Chrome',
// browserVersion: '91.0.4472.124',
// device: 'desktop',
// brand: '',
// model: '',
// duration: 0,
// path: '/test',
// origin: 'https://example.com',
// referrer: '',
// referrerName: '',
// referrerType: 'unknown',
// sdkName: 'web',
// sdkVersion: '1.0.0',
// },
// ]);
// expect(createEvent.mock.calls[1]).toMatchObject([event]);
const event = {
name: 'test_event',
deviceId: currentDeviceId,
profileId: '',
sessionId: 'session-123',
projectId,
properties: {
__hash: undefined,
__query: undefined,
__user_agent: jobData.payload.headers['user-agent'],
__reqId: jobData.payload.headers['request-id'],
},
createdAt: timestamp,
country: 'US',
city: 'New York',
region: 'NY',
longitude: 0,
latitude: 0,
os: 'Windows',
osVersion: '10',
browser: 'Chrome',
browserVersion: '91.0.4472.124',
device: 'desktop',
brand: undefined,
model: undefined,
duration: 0,
path: '/test',
origin: 'https://example.com',
referrer: '',
referrerName: '',
referrerType: 'unknown',
sdkName: jobData.payload.headers['openpanel-sdk-name'],
sdkVersion: jobData.payload.headers['openpanel-sdk-version'],
};
// // Add more specific assertions based on the expected behavior
// });
expect(spySessionsQueueAdd).toHaveBeenCalledTimes(0);
expect(changeDelay).toHaveBeenCalledWith(SESSION_TIMEOUT);
expect(createEvent as Mock).toBeCalledTimes(1);
expect((createEvent as Mock).mock.calls[0]![0]).toStrictEqual(event);
});
// it('should reuse existing session', async () => {
// // Mock job data
// const jobData = {
// payload: {
// geo,
// event: {
// name: 'test_event',
// timestamp: new Date().toISOString(),
// properties: { __path: 'https://example.com/test' },
// },
// headers: {
// 'user-agent':
// 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
// 'openpanel-sdk-name': 'web',
// 'openpanel-sdk-version': '1.0.0',
// },
// projectId,
// currentDeviceId,
// previousDeviceId,
// priority: false,
// },
// };
// const changeDelay = mock();
// findJobByPrefix.mockReturnValueOnce({
// changeDelay,
// data: {
// type: 'createSessionEnd',
// payload: {
// sessionId: 'session-123',
// deviceId: currentDeviceId,
// profileId: currentDeviceId,
// projectId,
// },
// },
// });
it('should handle server events (with existing screen view)', async () => {
const timestamp = new Date();
const jobData = {
payload: {
geo,
event: {
name: 'server_event',
timestamp: timestamp.toISOString(),
properties: { custom_property: 'test_value' },
profileId: 'profile-123',
},
headers: {
'user-agent': 'OpenPanel Server/1.0',
'openpanel-sdk-name': 'server',
'openpanel-sdk-version': '1.0.0',
'request-id': '123',
},
projectId,
currentDeviceId: '',
previousDeviceId: '',
},
};
// const job = { data: jobData } as Job;
const job = { data: jobData } as Job;
// // Execute the job
// await incomingEvent(job);
const mockLastScreenView = {
deviceId: 'last-device-123',
sessionId: 'last-session-456',
country: 'CA',
city: 'Toronto',
region: 'ON',
os: 'iOS',
osVersion: '15.0',
browser: 'Safari',
browserVersion: '15.0',
device: 'mobile',
brand: 'Apple',
model: 'iPhone',
path: '/last-path',
origin: 'https://example.com',
referrer: 'https://google.com',
referrerName: 'Google',
referrerType: 'search',
};
// expect(changeDelay.mock.calls[0]).toMatchObject([SESSION_TIMEOUT]);
// Mock the eventBuffer.getLastScreenView method
vi.mocked(eventBuffer.getLastScreenView).mockResolvedValueOnce(
mockLastScreenView as IServiceEvent,
);
// // Assertions
// // Issue: https://github.com/oven-sh/bun/issues/10380
// // expect(createEvent).toHaveBeenCalledWith(...)
// expect(createEvent.mock.calls[0]).toMatchObject([
// {
// name: 'test_event',
// deviceId: currentDeviceId,
// profileId: '',
// sessionId: 'session-123',
// projectId,
// properties: {
// __hash: undefined,
// __query: undefined,
// },
// createdAt: expect.any(Date),
// country: 'US',
// city: 'New York',
// region: 'NY',
// longitude: 0,
// latitude: 0,
// os: 'Windows',
// osVersion: '10',
// browser: 'Chrome',
// browserVersion: '91.0.4472.124',
// device: 'desktop',
// brand: '',
// model: '',
// duration: 0,
// path: '/test',
// origin: 'https://example.com',
// referrer: '',
// referrerName: '',
// referrerType: 'unknown',
// sdkName: 'web',
// sdkVersion: '1.0.0',
// },
// ]);
await incomingEvent(job);
// // Add more specific assertions based on the expected behavior
// });
expect((createEvent as Mock).mock.calls[0]![0]).toStrictEqual({
name: 'server_event',
deviceId: 'last-device-123',
sessionId: 'last-session-456',
profileId: 'profile-123',
projectId,
properties: {
custom_property: 'test_value',
__user_agent: 'OpenPanel Server/1.0',
__reqId: '123',
__hash: undefined,
__query: undefined,
},
createdAt: timestamp,
country: 'CA',
city: 'Toronto',
region: 'ON',
longitude: 0,
latitude: 0,
os: 'iOS',
osVersion: '15.0',
browser: 'Safari',
browserVersion: '15.0',
device: 'mobile',
brand: 'Apple',
model: 'iPhone',
duration: 0,
path: '/last-path',
origin: 'https://example.com',
referrer: 'https://google.com',
referrerName: 'Google',
referrerType: 'search',
sdkName: 'server',
sdkVersion: '1.0.0',
});
// it('should handle server events', async () => {
// const timestamp = new Date();
// const jobData = {
// payload: {
// geo,
// event: {
// name: 'server_event',
// timestamp: timestamp.toISOString(),
// properties: { custom_property: 'test_value' },
// profileId: 'profile-123',
// },
// headers: {
// 'user-agent': 'OpenPanel Server/1.0',
// 'openpanel-sdk-name': 'server',
// 'openpanel-sdk-version': '1.0.0',
// },
// projectId,
// currentDeviceId: '',
// previousDeviceId: '',
// priority: true,
// },
// };
expect(sessionsQueue.add).not.toHaveBeenCalled();
});
// const job = { data: jobData } as Job;
it('should handle server events (without existing screen view)', async () => {
const timestamp = new Date();
const jobData = {
payload: {
geo,
event: {
name: 'server_event',
timestamp: timestamp.toISOString(),
properties: { custom_property: 'test_value' },
profileId: 'profile-123',
},
headers: {
'user-agent': 'OpenPanel Server/1.0',
'openpanel-sdk-name': 'server',
'openpanel-sdk-version': '1.0.0',
'request-id': '123',
},
projectId,
currentDeviceId: '',
previousDeviceId: '',
},
};
// const mockLastScreenView = {
// deviceId: 'last-device-123',
// sessionId: 'last-session-456',
// country: 'CA',
// city: 'Toronto',
// region: 'ON',
// os: 'iOS',
// osVersion: '15.0',
// browser: 'Safari',
// browserVersion: '15.0',
// device: 'mobile',
// brand: 'Apple',
// model: 'iPhone',
// path: '/last-path',
// origin: 'https://example.com',
// referrer: 'https://google.com',
// referrerName: 'Google',
// referrerType: 'search',
// };
const job = { data: jobData } as Job;
// getLastScreenViewFromProfileId.mockReturnValueOnce(mockLastScreenView);
// Mock getLastScreenView to return null
vi.mocked(eventBuffer.getLastScreenView).mockResolvedValueOnce(null);
// await incomingEvent(job);
await incomingEvent(job);
// // expect(getLastScreenViewFromProfileId).toHaveBeenCalledWith({
// // profileId: 'profile-123',
// // projectId,
// // });
expect((createEvent as Mock).mock.calls[0]![0]).toStrictEqual({
name: 'server_event',
deviceId: '',
sessionId: '',
profileId: 'profile-123',
projectId,
properties: {
custom_property: 'test_value',
__user_agent: 'OpenPanel Server/1.0',
__reqId: '123',
__hash: undefined,
__query: undefined,
},
createdAt: timestamp,
country: 'US',
city: 'New York',
region: 'NY',
longitude: 0,
latitude: 0,
os: '',
osVersion: '',
browser: '',
browserVersion: '',
device: 'server',
brand: '',
model: '',
duration: 0,
path: '',
origin: '',
referrer: undefined,
referrerName: undefined,
referrerType: undefined,
sdkName: 'server',
sdkVersion: '1.0.0',
});
// expect(createEvent.mock.calls[0]).toMatchObject([
// {
// name: 'server_event',
// deviceId: 'last-device-123',
// sessionId: 'last-session-456',
// profileId: 'profile-123',
// projectId,
// properties: {
// custom_property: 'test_value',
// user_agent: 'OpenPanel Server/1.0',
// },
// createdAt: timestamp,
// country: 'CA',
// city: 'Toronto',
// region: 'ON',
// longitude: 0,
// latitude: 0,
// os: 'iOS',
// osVersion: '15.0',
// browser: 'Safari',
// browserVersion: '15.0',
// device: 'mobile',
// brand: 'Apple',
// model: 'iPhone',
// duration: 0,
// path: '/last-path',
// origin: 'https://example.com',
// referrer: 'https://google.com',
// referrerName: 'Google',
// referrerType: 'search',
// sdkName: 'server',
// sdkVersion: '1.0.0',
// },
// ]);
// expect(sessionsQueue.add).not.toHaveBeenCalled();
// expect(findJobByPrefix).not.toHaveBeenCalled();
// });
// // Add more test cases for different scenarios:
// // - Server events
// // - Existing sessions
// // - Different priorities
// // - Error cases
// });
expect(sessionsQueue.add).not.toHaveBeenCalled();
});
});

View File

@@ -2663,8 +2663,8 @@ const referrers: Record<string, { type: string; name: string }> = {
'com.laurencedawson.reddit_sync': { type: 'social', name: 'Reddit' },
'com.laurencedawson.reddit_sync.pro': { type: 'social', name: 'Reddit' },
'viadeo.com': { type: 'social', name: 'Viadeo' },
'github.com': { type: 'social', name: 'GitHub' },
'stackoverflow.com': { type: 'social', name: 'StackOverflow' },
'github.com': { type: 'tech', name: 'GitHub' },
'stackoverflow.com': { type: 'tech', name: 'Stack Overflow' },
'gaiaonline.com': { type: 'social', name: 'Gaia Online' },
'stumbleupon.com': { type: 'social', name: 'StumbleUpon' },
'inci.sozlukspot.com': { type: 'social', name: 'Inci Sozluk' },
@@ -2680,5 +2680,38 @@ const referrers: Record<string, { type: string; name: string }> = {
'hyves.nl': { type: 'social', name: 'Hyves' },
'paper.li': { type: 'social', name: 'Paper.li' },
'moikrug.ru': { type: 'social', name: 'MoiKrug.ru' },
'zoom.us': { type: 'social', name: 'Zoom' },
'apple.com': { type: 'tech', name: 'Apple' },
'adobe.com': { type: 'tech', name: 'Adobe' },
'figma.com': { type: 'tech', name: 'Figma' },
'wix.com': { type: 'commerce', name: 'Wix' },
'gmail.com': { type: 'email', name: 'Gmail' },
'notion.so': { type: 'tech', name: 'Notion' },
'ebay.com': { type: 'commerce', name: 'eBay' },
'gitlab.com': { type: 'tech', name: 'GitLab' },
'slack.com': { type: 'social', name: 'Slack' },
'etsy.com': { type: 'commerce', name: 'Etsy' },
'bsky.app': { type: 'social', name: 'Bluesky' },
'twitch.tv': { type: 'content', name: 'Twitch' },
'dropbox.com': { type: 'tech', name: 'Dropbox' },
'outlook.com': { type: 'email', name: 'Outlook' },
'medium.com': { type: 'content', name: 'Medium' },
'paypal.com': { type: 'commerce', name: 'PayPal' },
'discord.com': { type: 'social', name: 'Discord' },
'stripe.com': { type: 'commerce', name: 'Stripe' },
'spotify.com': { type: 'content', name: 'Spotify' },
'netflix.com': { type: 'content', name: 'Netflix' },
'whatsapp.com': { type: 'social', name: 'WhatsApp' },
'shopify.com': { type: 'commerce', name: 'Shopify' },
'microsoft.com': { type: 'tech', name: 'Microsoft' },
'alibaba.com': { type: 'commerce', name: 'Alibaba' },
'telegram.org': { type: 'social', name: 'Telegram' },
'substack.com': { type: 'content', name: 'Substack' },
'salesforce.com': { type: 'tech', name: 'Salesforce' },
'wikipedia.org': { type: 'content', name: 'Wikipedia' },
'mastodon.social': { type: 'social', name: 'Mastodon' },
'office.com': { type: 'tech', name: 'Microsoft Office' },
'squarespace.com': { type: 'commerce', name: 'Squarespace' },
'teams.microsoft.com': { type: 'social', name: 'Microsoft Teams' },
} as const;
export default referrers;

View File

@@ -0,0 +1,117 @@
import { describe, expect, it } from 'vitest';
import { getReferrerWithQuery, parseReferrer } from './parse-referrer';
describe('parseReferrer', () => {
it('should handle undefined or empty URLs', () => {
expect(parseReferrer(undefined)).toEqual({
name: '',
type: 'unknown',
url: '',
});
expect(parseReferrer('')).toEqual({
name: '',
type: 'unknown',
url: '',
});
});
it('should parse valid referrer URLs', () => {
expect(parseReferrer('https://google.com/search?q=test')).toEqual({
name: 'Google',
type: 'search',
url: 'https://google.com/search?q=test',
});
});
it('should handle www prefix in hostnames', () => {
expect(parseReferrer('https://www.twitter.com/user')).toEqual({
name: 'Twitter',
type: 'social',
url: 'https://www.twitter.com/user',
});
expect(parseReferrer('https://twitter.com/user')).toEqual({
name: 'Twitter',
type: 'social',
url: 'https://twitter.com/user',
});
});
it('should handle unknown referrers', () => {
expect(parseReferrer('https://unknown-site.com')).toEqual({
name: '',
type: 'unknown',
url: 'https://unknown-site.com',
});
});
it('should handle invalid URLs', () => {
expect(parseReferrer('not-a-url')).toEqual({
name: '',
type: 'unknown',
url: 'not-a-url',
});
});
});
describe('getReferrerWithQuery', () => {
it('should handle undefined or empty query', () => {
expect(getReferrerWithQuery(undefined)).toBeNull();
expect(getReferrerWithQuery({})).toBeNull();
});
it('should parse utm_source parameter', () => {
expect(getReferrerWithQuery({ utm_source: 'google' })).toEqual({
name: 'Google',
type: 'unknown',
url: '',
});
});
it('should parse ref parameter', () => {
expect(getReferrerWithQuery({ ref: 'facebook' })).toEqual({
name: 'Facebook',
type: 'social',
url: '',
});
});
it('should parse utm_referrer parameter', () => {
expect(getReferrerWithQuery({ utm_referrer: 'twitter' })).toEqual({
name: 'Twitter',
type: 'social',
url: '',
});
});
it('should handle case-insensitive matching', () => {
expect(getReferrerWithQuery({ utm_source: 'GoOgLe' })).toEqual({
name: 'Google',
type: 'unknown',
url: '',
});
});
it('should handle unknown sources', () => {
expect(getReferrerWithQuery({ utm_source: 'unknown-source' })).toEqual({
name: 'unknown-source',
type: 'unknown',
url: '',
});
});
it('should prioritize utm_source over ref and utm_referrer', () => {
expect(
getReferrerWithQuery({
utm_source: 'google',
ref: 'facebook',
utm_referrer: 'twitter',
}),
).toEqual({
name: 'Google',
type: 'unknown',
url: '',
});
});
});

View File

@@ -76,7 +76,7 @@ export async function getSessionEnd({
sessionEnd.job.data.payload.deviceId;
const eventIsIdentified =
sessionEnd.job.data.payload.profileId !== profileId;
profileId && sessionEnd.job.data.payload.profileId !== profileId;
if (existingSessionIsAnonymous && eventIsIdentified) {
await sessionEnd.job.updateData({