Add query() tests with mocked API response

Tests transformation logic including:
- Feed item type assignment
- Hourly/daily limits
- Timestamp from context
- Unit conversion (metric/imperial)
- Priority assignment
- Unique ID generation

Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
2026-01-17 01:09:39 +00:00
parent ceb9dbd576
commit 850d1925b6

View File

@@ -1,10 +1,11 @@
import type { Context } from "@aris/core" import type { Context } from "@aris/core"
import { describe, expect, test } from "bun:test" import { describe, expect, mock, test } from "bun:test"
import fixture from "../fixtures/san-francisco.json" import fixture from "../fixtures/san-francisco.json"
import { WeatherKitDataSource, Units } from "./data-source" import { WeatherKitDataSource, Units } from "./data-source"
import { WeatherFeedItemType } from "./feed-items" import { WeatherFeedItemType } from "./feed-items"
import * as weatherkit from "./weatherkit"
const mockCredentials = { const mockCredentials = {
privateKey: "mock", privateKey: "mock",
@@ -101,3 +102,137 @@ describe("unit conversion", () => {
expect(Units.imperial).toBe("imperial") expect(Units.imperial).toBe("imperial")
}) })
}) })
describe("query() with mocked API", () => {
const mockFetchWeather = mock(() =>
Promise.resolve(fixture.response as weatherkit.WeatherKitResponse),
)
test("transforms API response into feed items", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource } = await import("./data-source")
const dataSource = new WeatherKitDataSource({ credentials: mockCredentials })
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const items = await dataSource.query(context)
expect(items.length).toBeGreaterThan(0)
expect(items.some((i) => i.type === WeatherFeedItemType.current)).toBe(true)
expect(items.some((i) => i.type === WeatherFeedItemType.hourly)).toBe(true)
expect(items.some((i) => i.type === WeatherFeedItemType.daily)).toBe(true)
})
test("applies hourly and daily limits", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource } = await import("./data-source")
const dataSource = new WeatherKitDataSource({
credentials: mockCredentials,
hourlyLimit: 3,
dailyLimit: 2,
})
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const items = await dataSource.query(context)
const hourlyItems = items.filter((i) => i.type === WeatherFeedItemType.hourly)
const dailyItems = items.filter((i) => i.type === WeatherFeedItemType.daily)
expect(hourlyItems.length).toBe(3)
expect(dailyItems.length).toBe(2)
})
test("sets timestamp from context.time", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource } = await import("./data-source")
const dataSource = new WeatherKitDataSource({ credentials: mockCredentials })
const queryTime = new Date("2026-01-17T12:00:00Z")
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
context.time = queryTime
const items = await dataSource.query(context)
for (const item of items) {
expect(item.timestamp).toEqual(queryTime)
}
})
test("converts temperatures to imperial", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource, Units } = await import("./data-source")
const dataSource = new WeatherKitDataSource({ credentials: mockCredentials })
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const metricItems = await dataSource.query(context, { units: Units.metric })
const imperialItems = await dataSource.query(context, { units: Units.imperial })
const metricCurrent = metricItems.find((i) => i.type === WeatherFeedItemType.current)
const imperialCurrent = imperialItems.find((i) => i.type === WeatherFeedItemType.current)
expect(metricCurrent).toBeDefined()
expect(imperialCurrent).toBeDefined()
// Imperial temp should be higher (F > C for typical weather temps)
const metricTemp = (metricCurrent!.data as { temperature: number }).temperature
const imperialTemp = (imperialCurrent!.data as { temperature: number }).temperature
// Verify conversion: F = C * 9/5 + 32
const expectedImperial = (metricTemp * 9) / 5 + 32
expect(imperialTemp).toBeCloseTo(expectedImperial, 2)
})
test("assigns priority based on weather conditions", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource } = await import("./data-source")
const dataSource = new WeatherKitDataSource({ credentials: mockCredentials })
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const items = await dataSource.query(context)
for (const item of items) {
expect(item.priority).toBeGreaterThanOrEqual(0)
expect(item.priority).toBeLessThanOrEqual(1)
}
const currentItem = items.find((i) => i.type === WeatherFeedItemType.current)
expect(currentItem).toBeDefined()
// Base priority for current is 0.5, may be adjusted for conditions
expect(currentItem!.priority).toBeGreaterThanOrEqual(0.5)
})
test("generates unique IDs for each item", async () => {
mock.module("./weatherkit", () => ({
...weatherkit,
fetchWeather: mockFetchWeather,
}))
const { WeatherKitDataSource } = await import("./data-source")
const dataSource = new WeatherKitDataSource({ credentials: mockCredentials })
const context = createMockContext({ lat: 37.7749, lng: -122.4194 })
const items = await dataSource.query(context)
const ids = items.map((i) => i.id)
const uniqueIds = new Set(ids)
expect(uniqueIds.size).toBe(ids.length)
})
})