Weather
weather.test.js 56 lines
Files · 9
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556import { test, expect } from "bun:test";
import { Database } from "bun:sqlite";
import { readFileSync } from "node:fs";
import { setupWeather, saveWeather, loadWeather, conditionText, updateLocation } from "./weather.js";
import ddl from "./schema.js";
function mock() {
const db = new Database(":memory:");
db.exec("PRAGMA foreign_keys=ON");
const L = { db: {
exec: async (sql, params = []) => db.query(sql).run(...params),
query: async (sql, params = []) => db.query(sql).all(...params),
}};
return { db, L };
}
const payload = (date = "2026-10-17") => ({
current: { temperature_2m: 14, apparent_temperature: 12, relative_humidity_2m: 70,
wind_speed_10m: 18, weather_code: 61, precipitation: 1 },
daily: { time: [date], weather_code: [71], temperature_2m_max: [16],
temperature_2m_min: [-2], precipitation_sum: [4.2] },
});
test("weather stores forecasts by local date, restores UI data and replaces only the refreshed location", async () => {
expect(ddl).toBe(readFileSync(new URL("./schema.sql", import.meta.url), "utf8"));
const { db, L } = mock();
try {
await setupWeather(L);
await setupWeather(L);
await L.db.exec("INSERT INTO locations (name,lat,lon) VALUES ('London',51,0),('Tokyo',35,139)");
expect(await loadWeather(L, 1)).toBeNull();
await saveWeather(L, 1, payload());
await saveWeather(L, 2, payload());
await saveWeather(L, 1, payload("2026-10-18"));
const saved = await loadWeather(L, 1);
expect(saved.current).toMatchObject({ temperature_2m: 14, apparent_temperature: 12, condition: "Rain", precipitation: 1 });
expect(saved.daily.time).toEqual(["2026-10-18"]);
expect((await loadWeather(L, 2)).daily.time).toEqual(["2026-10-17"]);
expect(db.query("SELECT * FROM forecasts WHERE location_id=1").get()).toMatchObject({
date: "2026-10-18", condition: conditionText(71), temperature_max_c: 16, temperature_min_c: -2, precipitation_mm: 4.2,
});
expect(db.query("SELECT count(*) AS n FROM weather_log WHERE location_id=1").get().n).toBe(2);
const before = await loadWeather(L, 1);
await expect(saveWeather(L, 1, { current: payload().current })).rejects.toThrow("incomplete");
expect(await loadWeather(L, 1)).toEqual(before);
db.exec("CREATE TRIGGER fail_forecast BEFORE INSERT ON forecasts BEGIN SELECT RAISE(ABORT,'disk error'); END");
await expect(saveWeather(L, 1, payload())).rejects.toThrow("disk error");
expect(await loadWeather(L, 1)).toEqual(before);
const previous = { id: 1, name: "London", lat: 51, lon: 0 };
await updateLocation(L, previous, { name: "Home", lat: 51, lon: 0 });
expect(await loadWeather(L, 1)).toEqual(before);
await updateLocation(L, previous, { name: "New location", lat: 52, lon: 1 });
expect(await loadWeather(L, 1)).toBeNull();
expect(db.query("SELECT count(*) AS n FROM forecasts WHERE location_id=1").get().n).toBe(0);
expect((await loadWeather(L, 2)).daily.time).toEqual(["2026-10-17"]);
} finally { db.close(); }
});