-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlog.test.ts
More file actions
126 lines (113 loc) · 3.64 KB
/
Copy pathlog.test.ts
File metadata and controls
126 lines (113 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
__resetActivityEventLog,
appendEvent,
getAllEvents,
getEventsForOffer,
getEventsSince,
getLatestSeq,
onAppend,
} from './log';
import type { ActivityEventInput, OfferSnapshot } from './types';
const snapshot: OfferSnapshot = {
id: 'offer-a',
scenario_key: 'tracking',
_bucket: 'pending',
_createdAtMinutesAgo: 5,
_startedAtMinutesAgo: 5,
_lastCompletedAtMinutesAgo: null,
_eventCompletedAtMinutesAgo: [],
title: 'Seed',
icon_url: '',
images: { default: null, medium: null, large: null },
assets: { images: {}, video_url: null, screenshots: [] },
description: '',
secondary_description: '',
additional_information: '',
detailed_highlights: null,
supported_platforms: [],
offer_status: 'new',
payout: '1.00',
requirements: '',
redirect_url: '',
categories: [],
events: [],
support_url: null,
partner_slug: 'demo',
metric_value: null,
payout_boost_factor: null,
featured_copy: null,
user_offer_activity: { status: null },
offer_progress_state: null,
};
function created(offerId: string, overrides?: Partial<OfferSnapshot>): ActivityEventInput {
return {
kind: 'offer_created',
actor: { kind: 'system' },
offer_id: offerId,
payload: { ...snapshot, ...overrides, id: offerId },
};
}
beforeEach(() => {
__resetActivityEventLog();
});
describe('activity event log', () => {
it('starts empty after reset', () => {
expect(getAllEvents()).toEqual([]);
expect(getLatestSeq()).toBe(0);
});
it('assigns monotonically increasing seq on append', () => {
const first = appendEvent(created('offer-1'));
const second = appendEvent(created('offer-2'));
expect(first.seq).toBe(1);
expect(second.seq).toBe(2);
expect(getLatestSeq()).toBe(2);
});
it('stamps an ISO timestamp when not supplied', () => {
const event = appendEvent(created('offer-1'));
expect(event.at).toMatch(/^\d{4}-\d{2}-\d{2}T/);
});
it('preserves the caller-supplied `at` timestamp when given', () => {
const event = appendEvent({ ...created('offer-1'), at: '2026-01-01T00:00:00.000Z' });
expect(event.at).toBe('2026-01-01T00:00:00.000Z');
});
it('returns only events strictly after the supplied seq', () => {
appendEvent(created('offer-1'));
appendEvent(created('offer-2'));
appendEvent(created('offer-3'));
expect(getEventsSince(0).map((e) => e.seq)).toEqual([1, 2, 3]);
expect(getEventsSince(1).map((e) => e.seq)).toEqual([2, 3]);
expect(getEventsSince(3)).toEqual([]);
});
it('filters events by offer_id', () => {
appendEvent(created('offer-1'));
appendEvent(created('offer-2'));
appendEvent({
kind: 'offer_updated',
actor: { kind: 'system' },
offer_id: 'offer-1',
patch: { title: 'Renamed' },
});
const events = getEventsForOffer('offer-1');
expect(events.map((e) => e.kind)).toEqual(['offer_created', 'offer_updated']);
});
it('reset clears events and resets seq', () => {
appendEvent(created('offer-1'));
appendEvent(created('offer-2'));
__resetActivityEventLog();
expect(getAllEvents()).toEqual([]);
expect(getLatestSeq()).toBe(0);
const next = appendEvent(created('offer-3'));
expect(next.seq).toBe(1);
});
it('notifies onAppend listeners after each append', () => {
const listener = vi.fn();
const unsubscribe = onAppend(listener);
const event = appendEvent(created('offer-notify'));
expect(listener).toHaveBeenCalledTimes(1);
expect(listener.mock.calls[0][0]).toEqual(event);
unsubscribe();
appendEvent(created('offer-silent'));
expect(listener).toHaveBeenCalledTimes(1);
});
});