Skip to content

Commit acb5b01

Browse files
committed
Add schedule tests
1 parent afe83c2 commit acb5b01

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import { describe, it, expect, assert, vi } from "vitest";
2+
import { actor, setup } from "@/mod";
3+
import { setupTest } from "@/test/mod";
4+
import type { Alarm } from "@/actor/schedule";
5+
6+
describe("Actor scheduling", () => {
7+
// Increase timeout for scheduling tests
8+
it("should schedule and execute events after specified duration", async () => {
9+
const events: string[] = [];
10+
11+
const testActor = actor({
12+
state: {
13+
events: [] as string[],
14+
done: false
15+
},
16+
actions: {
17+
scheduleEvents: async (c) => {
18+
await c.schedule.after(100, "recordEvent", "event1");
19+
await c.schedule.after(200, "recordEvent", "event2");
20+
},
21+
recordEvent: (c, event: string) => {
22+
events.push(event);
23+
if (events.length === 2) {
24+
c.state.done = true;
25+
}
26+
},
27+
isDone: (c) => c.state.done
28+
}
29+
});
30+
31+
const app = setup({
32+
actors: { testActor }
33+
});
34+
35+
const { client } = await setupTest(app);
36+
const instance = await client.testActor.get();
37+
38+
await instance.scheduleEvents();
39+
40+
// Advance time to trigger both events
41+
await vi.advanceTimersByTimeAsync(250);
42+
43+
expect(events).toEqual(["event1", "event2"]);
44+
});
45+
46+
it("should schedule events at specific timestamps", async () => {
47+
const events: string[] = [];
48+
49+
const testActor = actor({
50+
state: {
51+
events: [] as string[],
52+
done: false
53+
},
54+
actions: {
55+
scheduleEvents: async (c) => {
56+
const now = Date.now();
57+
await c.schedule.at(now + 100, "recordEvent", "event1");
58+
await c.schedule.at(now + 200, "recordEvent", "event2");
59+
},
60+
recordEvent: (c, event: string) => {
61+
events.push(event);
62+
if (events.length === 2) {
63+
c.state.done = true;
64+
}
65+
},
66+
isDone: (c) => c.state.done
67+
}
68+
});
69+
70+
const app = setup({
71+
actors: { testActor }
72+
});
73+
74+
const { client } = await setupTest(app);
75+
const instance = await client.testActor.get();
76+
77+
await instance.scheduleEvents();
78+
79+
// Advance time to trigger both events
80+
await vi.advanceTimersByTimeAsync(250);
81+
82+
expect(events).toEqual(["event1", "event2"]);
83+
});
84+
85+
it("should allow canceling scheduled events", async () => {
86+
const events: string[] = [];
87+
let eventId2: string;
88+
89+
const testActor = actor({
90+
state: {
91+
events: [] as string[],
92+
done: false
93+
},
94+
actions: {
95+
scheduleEvents: async (c) => {
96+
await c.schedule.after(100, "recordEvent", "event1");
97+
eventId2 = await c.schedule.after(200, "recordEvent", "event2");
98+
},
99+
cancelEvent: async (c) => {
100+
await c.schedule.cancel(eventId2);
101+
},
102+
recordEvent: (c, event: string) => {
103+
events.push(event);
104+
},
105+
isDone: (c) => c.state.done
106+
}
107+
});
108+
109+
const app = setup({
110+
actors: { testActor }
111+
});
112+
113+
const { client } = await setupTest(app);
114+
const instance = await client.testActor.get();
115+
116+
await instance.scheduleEvents();
117+
await instance.cancelEvent();
118+
119+
// Advance time to trigger all events except the cancelled one
120+
await vi.advanceTimersByTimeAsync(700);
121+
122+
expect(events).toEqual(["event1"]);
123+
});
124+
125+
it("should list all scheduled events", async () => {
126+
const testActor = actor({
127+
state: {
128+
scheduledEvents: null as readonly Alarm[] | null
129+
},
130+
actions: {
131+
scheduleAndList: async (c) => {
132+
await c.schedule.after(1000, "doSomething");
133+
await c.schedule.after(2000, "doSomething");
134+
c.state.scheduledEvents = await c.schedule.list();
135+
},
136+
getScheduledEvents: (c) => c.state.scheduledEvents,
137+
doSomething: () => { }
138+
}
139+
});
140+
141+
const app = setup({
142+
actors: { testActor }
143+
});
144+
145+
const { client } = await setupTest(app);
146+
const instance = await client.testActor.get();
147+
148+
const now = Date.now();
149+
await instance.scheduleAndList();
150+
const scheduledEvents = await instance.getScheduledEvents();
151+
152+
expect(scheduledEvents).toHaveLength(2);
153+
assert(scheduledEvents, "scheduledEvents should not be null");
154+
expect(scheduledEvents[0].triggersAt).toBeGreaterThan(now);
155+
expect(scheduledEvents[1].triggersAt).toBeGreaterThan(scheduledEvents[0].triggersAt);
156+
});
157+
158+
it("should get details of a specific scheduled event", async () => {
159+
const testActor = actor({
160+
state: {
161+
eventDetails: null as Alarm | null,
162+
eventId: "" as string
163+
},
164+
actions: {
165+
scheduleAndGet: async (c) => {
166+
c.state.eventId = await c.schedule.after(1000, "doSomething", "arg1", 42);
167+
const details = await c.schedule.get(c.state.eventId);
168+
c.state.eventDetails = details || null;
169+
},
170+
getEventDetails: (c) => ({
171+
details: c.state.eventDetails,
172+
id: c.state.eventId
173+
}),
174+
doSomething: () => { }
175+
}
176+
});
177+
178+
const app = setup({
179+
actors: { testActor }
180+
});
181+
182+
const { client } = await setupTest(app);
183+
const instance = await client.testActor.get();
184+
185+
const now = Date.now();
186+
await instance.scheduleAndGet();
187+
const { details: eventDetails, id: eventId } = await instance.getEventDetails();
188+
189+
expect(eventDetails).toBeDefined();
190+
expect(eventDetails?.id).toBe(eventId);
191+
expect(eventDetails?.fn).toBe("doSomething");
192+
expect(eventDetails?.args).toEqual(["arg1", 42]);
193+
expect(eventDetails?.triggersAt).toBeGreaterThan(now);
194+
expect(eventDetails?.createdAt).toBeLessThanOrEqual(now);
195+
});
196+
});

0 commit comments

Comments
 (0)