mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-20 17:11:17 +00:00
163 lines
4.5 KiB
TypeScript
163 lines
4.5 KiB
TypeScript
|
|
import { describe, expect, mock, test } from "bun:test"
|
||
|
|
|
||
|
|
import { LocationService } from "../location/service.ts"
|
||
|
|
import { FeedEngineService } from "./service.ts"
|
||
|
|
|
||
|
|
describe("FeedEngineService", () => {
|
||
|
|
test("engineForUser creates engine on first call", () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const engine = service.engineForUser("user-1")
|
||
|
|
|
||
|
|
expect(engine).toBeDefined()
|
||
|
|
})
|
||
|
|
|
||
|
|
test("engineForUser returns same engine for same user", () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const engine1 = service.engineForUser("user-1")
|
||
|
|
const engine2 = service.engineForUser("user-1")
|
||
|
|
|
||
|
|
expect(engine1).toBe(engine2)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("engineForUser returns different engines for different users", () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const engine1 = service.engineForUser("user-1")
|
||
|
|
const engine2 = service.engineForUser("user-2")
|
||
|
|
|
||
|
|
expect(engine1).not.toBe(engine2)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("engineForUser registers sources from all providers", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const engine = service.engineForUser("user-1")
|
||
|
|
const result = await engine.refresh()
|
||
|
|
|
||
|
|
expect(result.errors).toHaveLength(0)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("engineForUser works with empty providers array", async () => {
|
||
|
|
const service = new FeedEngineService([])
|
||
|
|
|
||
|
|
const engine = service.engineForUser("user-1")
|
||
|
|
const result = await engine.refresh()
|
||
|
|
|
||
|
|
expect(result.errors).toHaveLength(0)
|
||
|
|
expect(result.items).toHaveLength(0)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("refresh returns feed result", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const result = await service.refresh("user-1")
|
||
|
|
|
||
|
|
expect(result).toHaveProperty("context")
|
||
|
|
expect(result).toHaveProperty("items")
|
||
|
|
expect(result).toHaveProperty("errors")
|
||
|
|
expect(result.context.time).toBeInstanceOf(Date)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("refresh uses location from LocationService", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
const location = {
|
||
|
|
lat: 51.5074,
|
||
|
|
lng: -0.1278,
|
||
|
|
accuracy: 10,
|
||
|
|
timestamp: new Date(),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create engine first, then update location
|
||
|
|
service.engineForUser("user-1")
|
||
|
|
locationService.updateUserLocation("user-1", location)
|
||
|
|
|
||
|
|
const result = await service.refresh("user-1")
|
||
|
|
|
||
|
|
expect(result.context.location).toEqual(location)
|
||
|
|
})
|
||
|
|
|
||
|
|
test("subscribe receives updates", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
const callback = mock()
|
||
|
|
|
||
|
|
service.subscribe("user-1", callback)
|
||
|
|
|
||
|
|
// Push location to trigger update
|
||
|
|
locationService.updateUserLocation("user-1", {
|
||
|
|
lat: 51.5074,
|
||
|
|
lng: -0.1278,
|
||
|
|
accuracy: 10,
|
||
|
|
timestamp: new Date(),
|
||
|
|
})
|
||
|
|
|
||
|
|
// Wait for async update propagation
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10))
|
||
|
|
|
||
|
|
expect(callback).toHaveBeenCalled()
|
||
|
|
})
|
||
|
|
|
||
|
|
test("subscribe returns unsubscribe function", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
const callback = mock()
|
||
|
|
|
||
|
|
const unsubscribe = service.subscribe("user-1", callback)
|
||
|
|
|
||
|
|
unsubscribe()
|
||
|
|
|
||
|
|
locationService.updateUserLocation("user-1", {
|
||
|
|
lat: 51.5074,
|
||
|
|
lng: -0.1278,
|
||
|
|
accuracy: 10,
|
||
|
|
timestamp: new Date(),
|
||
|
|
})
|
||
|
|
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10))
|
||
|
|
|
||
|
|
expect(callback).not.toHaveBeenCalled()
|
||
|
|
})
|
||
|
|
|
||
|
|
test("removeUser stops engine and removes it", async () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
const callback = mock()
|
||
|
|
|
||
|
|
service.subscribe("user-1", callback)
|
||
|
|
|
||
|
|
service.removeUser("user-1")
|
||
|
|
|
||
|
|
// Push location - should not trigger update since engine is stopped
|
||
|
|
locationService.feedSourceForUser("user-1")
|
||
|
|
locationService.updateUserLocation("user-1", {
|
||
|
|
lat: 51.5074,
|
||
|
|
lng: -0.1278,
|
||
|
|
accuracy: 10,
|
||
|
|
timestamp: new Date(),
|
||
|
|
})
|
||
|
|
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 10))
|
||
|
|
|
||
|
|
expect(callback).not.toHaveBeenCalled()
|
||
|
|
})
|
||
|
|
|
||
|
|
test("removeUser allows new engine to be created", () => {
|
||
|
|
const locationService = new LocationService()
|
||
|
|
const service = new FeedEngineService([locationService])
|
||
|
|
|
||
|
|
const engine1 = service.engineForUser("user-1")
|
||
|
|
service.removeUser("user-1")
|
||
|
|
const engine2 = service.engineForUser("user-1")
|
||
|
|
|
||
|
|
expect(engine1).not.toBe(engine2)
|
||
|
|
})
|
||
|
|
})
|