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%
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