feat: implement proper remote event checking for sync

This commit is contained in:
2026-07-13 16:03:27 +09:30
parent 34c536c2d8
commit fdf941b968
10 changed files with 772 additions and 21 deletions
@@ -5,8 +5,12 @@ global.fetch = mockFetch as typeof fetch;
import {
deleteOutlookCalendarEvent,
listGoogleSyncedEvents,
listOutlookSyncedEvents,
upsertOutlookCalendarEvent,
} from "@/seqta/utils/calendarSync/remoteEvents";
import { BSPLUS_GOOGLE_CALENDAR_EVENT_PROP } from "@/config/googleCalendar";
import { BSPLUS_OUTLOOK_CALENDAR_EVENT_CATEGORY } from "@/config/outlookCalendar";
describe("outlook calendar remote events", () => {
beforeEach(() => {
@@ -28,4 +32,101 @@ describe("outlook calendar remote events", () => {
await expect(deleteOutlookCalendarEvent("token", "evt-1")).resolves.toBeUndefined();
});
it("lists Outlook synced events and paginates", async () => {
mockFetch
.mockResolvedValueOnce(
new Response(
JSON.stringify({
value: [
{
id: "o1",
subject: "Math",
body: { content: "Synced by BetterSEQTA+\nKey: https://school.seqta.com.au:cal:1" },
start: { dateTime: "2026-07-13T09:00:00", timeZone: "UTC" },
end: { dateTime: "2026-07-13T10:00:00", timeZone: "UTC" },
categories: [BSPLUS_OUTLOOK_CALENDAR_EVENT_CATEGORY],
},
],
"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/calendarView?$skiptoken=2",
}),
{ status: 200 },
),
)
.mockResolvedValueOnce(
new Response(
JSON.stringify({
value: [
{
id: "o2",
subject: "English",
body: { content: "Synced by BetterSEQTA+\nKey: https://school.seqta.com.au:cal:2" },
start: { dateTime: "2026-07-14T09:00:00", timeZone: "UTC" },
end: { dateTime: "2026-07-14T10:00:00", timeZone: "UTC" },
categories: [BSPLUS_OUTLOOK_CALENDAR_EVENT_CATEGORY],
},
],
}),
{ status: 200 },
),
);
const events = await listOutlookSyncedEvents("token", {
from: "2026-07-13",
until: "2026-07-20",
});
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({
id: "o1",
seqtaKey: "https://school.seqta.com.au:cal:1",
});
expect(mockFetch).toHaveBeenCalledTimes(2);
});
});
describe("google calendar remote list", () => {
beforeEach(() => {
mockFetch.mockReset();
});
it("lists Google synced events using private extended properties", async () => {
mockFetch.mockResolvedValueOnce(
new Response(
JSON.stringify({
items: [
{
id: "g1",
summary: "Math",
description: "Synced by BetterSEQTA+",
start: { dateTime: "2026-07-13T09:00:00", timeZone: "UTC" },
end: { dateTime: "2026-07-13T10:00:00", timeZone: "UTC" },
extendedProperties: {
private: { [BSPLUS_GOOGLE_CALENDAR_EVENT_PROP]: "https://school.seqta.com.au:cal:1" },
},
},
{
id: "g-skip",
summary: "Unrelated",
start: { dateTime: "2026-07-13T11:00:00", timeZone: "UTC" },
end: { dateTime: "2026-07-13T12:00:00", timeZone: "UTC" },
},
],
}),
{ status: 200 },
),
);
const events = await listGoogleSyncedEvents("token", "cal-id", {
from: "2026-07-13",
until: "2026-07-20",
});
expect(events).toHaveLength(1);
expect(events[0]).toMatchObject({
id: "g1",
seqtaKey: "https://school.seqta.com.au:cal:1",
date: "2026-07-13",
});
});
});