SPB Git

spb/earth-now Public License

earth-now.co — real-time planetary dashboard: live world metrics modeled, not streamed.

TypeScript 93% Shell 2.3% SQL 1.4% JavaScript 1.3% Dockerfile 1.2% CSS 0.8%
3.1 KB · 75 lines typescript
Raw Blame History
1/**2 * earth-now.co3 * Author:  Simon-Pierre Boucher4 * Contact: contact@spboucher.ai5 * File:    apps/ingest/test/runners.test.ts6 * Purpose: End-to-end run functions (fetch → archive → parse → summary) with fixture-backed fakes, no network7 */89import { existsSync, mkdtempSync, readdirSync, readFileSync } from "node:fs";10import { tmpdir } from "node:os";11import { join } from "node:path";12import { afterEach, beforeEach, describe, expect, it } from "vitest";13import type { FetchLike } from "../src/fetch-like";14import { KNOWN_SOURCE_IDS, runSource } from "../src/runners";1516const fixture = (name: string): string =>17  readFileSync(new URL(`./fixtures/${name}`, import.meta.url), "utf8");1819let previousRawDir: string | undefined;2021beforeEach(() => {22  previousRawDir = process.env.RAW_ARCHIVE_DIR;23  process.env.RAW_ARCHIVE_DIR = mkdtempSync(join(tmpdir(), "earth-now-runners-"));24});2526afterEach(() => {27  if (previousRawDir === undefined) delete process.env.RAW_ARCHIVE_DIR;28  else process.env.RAW_ARCHIVE_DIR = previousRawDir;29});3031describe("runSource", () => {32  it("knows exactly the declared sources", () => {33    expect([...KNOWN_SOURCE_IDS]).toEqual(["usgs_fdsn", "noaa_gml_mlo"]);34  });3536  it("rejects unknown source ids listing the known ones", async () => {37    await expect(runSource("nope")).rejects.toThrow(/Unknown source 'nope'.*usgs_fdsn/);38  });3940  it("usgs_fdsn: fetches, archives the raw payload and summarizes one observation", async () => {41    const body = fixture("usgs_count_sample.json");42    const fetchImpl: FetchLike = async () => ({ ok: true, status: 200, text: async () => body });4344    const summary = await runSource("usgs_fdsn", fetchImpl);45    expect(summary.sourceId).toBe("usgs_fdsn");46    expect(summary.observationCount).toBe(1);47    expect(summary.first?.value).toBe(132);48    expect(existsSync(summary.rawPath)).toBe(true);49    expect(readFileSync(summary.rawPath, "utf8")).toBe(body);50    expect(existsSync(`${summary.rawPath}.sha256`)).toBe(true);51  });5253  it("noaa_gml_mlo: fetches, archives and summarizes the monthly series", async () => {54    const body = fixture("co2_mm_mlo_sample.txt");55    const fetchImpl: FetchLike = async () => ({ ok: true, status: 200, text: async () => body });5657    const summary = await runSource("noaa_gml_mlo", fetchImpl);58    expect(summary.observationCount).toBe(15);59    expect(summary.first?.time).toBe("2024-01-15T00:00:00.000Z");60    expect(summary.last?.value).toBe(429.64);61    expect(readFileSync(summary.rawPath, "utf8")).toBe(body);62  });6364  it("noaa_gml_mlo: still archives the raw payload even when parsing fails (truncated file)", async () => {65    const body = fixture("co2_mm_mlo_truncated.txt");66    const fetchImpl: FetchLike = async () => ({ ok: true, status: 200, text: async () => body });6768    await expect(runSource("noaa_gml_mlo", fetchImpl)).rejects.toThrow(/truncated/);69    // The raw bytes were archived before parsing — nothing ingested is ever lost.70    const archivedDir = join(process.env.RAW_ARCHIVE_DIR ?? "", "noaa_gml_mlo");71    expect(existsSync(archivedDir)).toBe(true);72    expect(readdirSync(archivedDir).some((f) => f.endsWith(".raw"))).toBe(true);73  });74});75