Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/schema/pathwayTimeseries.v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@
"nuclear",
"biomass",
"hydro",
"geothermal",
"energyStorage",
Comment thread
jacobvjk marked this conversation as resolved.
"renewables",
"electricVehicles",
"hydrogenVehicles",
Expand Down Expand Up @@ -298,6 +300,7 @@
"then": {
"properties": {
"technology": {
"$comment": "Exactly the Power technology keys of src/utils/timeseriesTaxonomy.ts, which the plots and the CSV download look every row up in; pathwayTimeseries.v2.test.ts checks the two agree. Every value must also be in the all-sector enum above, because both lists apply to a Power row: `geothermal`, `battery` and `hydrogen` used to be listed here only, so they could never validate (#977). Storage is `energyStorage` (cookbook decision 0020), matching the `Energy storage` segment.",
"type": ["string", "null"],
"enum": [
"coal",
Expand All @@ -309,9 +312,8 @@
"solar",
"biomass",
"geothermal",
"hydrogen",
"energyStorage",
"renewables",
"battery",
"other",
null
]
Expand Down
48 changes: 48 additions & 0 deletions src/schema/pathwayTimeseries.v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,56 @@ import { describe, it, expect } from "vitest";
import timeseriesJson from "./pathwayTimeseries.v2.json" with { type: "json" };
import { commonSchemas } from "./common/index.ts";
import { validateFilesBySchema } from "../utils/validateData";
import { SECTORS_BY_KEY } from "../utils/timeseriesTaxonomy";
import ieaSteps from "../data/iea/IEA-STEPS-2024_timeseries.json" with { type: "json" };

/** The slice of the schema these assertions read. */
interface RowSchema {
properties: { technology: { enum: (string | null)[] } };
then: { properties: { technology: { enum: (string | null)[] } } };
}

const row = (
timeseriesJson as unknown as {
properties: { data: { items: RowSchema } };
}
).properties.data.items;
const allSectors = row.properties.technology.enum;
const power = row.then.properties.technology.enum;

describe("pathwayTimeseries.v2 Power technologies (#977)", () => {
it("are exactly the taxonomy's Power technology keys", () => {
// The plots and the CSV download look every row's technology up in the
// taxonomy, so the schema must not allow one it cannot resolve.
const taxonomy = Object.keys(SECTORS_BY_KEY.power.technologies ?? {});
expect(power.filter((t) => t !== null).sort()).toEqual(taxonomy.sort());
expect(power).toContain(null); // a sector-level row has no technology
});

it("are all in the all-sector enum too, since both lists apply", () => {
expect(power.filter((t) => !allSectors.includes(t))).toEqual([]);
});

const validate = (technology: string) => {
const doc = structuredClone(ieaSteps) as {
data: { technology: unknown }[];
};
doc.data = [{ ...doc.data[0], technology }];
return validateFilesBySchema(
[{ name: "row.json", data: doc }],
[timeseriesJson, ...commonSchemas],
);
};

it.each(["geothermal", "energyStorage"])("accepts a %s row", (technology) => {
expect(validate(technology).invalid).toEqual([]);
});

it.each(["battery", "hydrogen"])("rejects the retired %s", (technology) => {
expect(validate(technology).invalid).toHaveLength(1);
});
});

/** A real file with one field replaced, validated against the v2 schema. */
const validateWith = (over: Record<string, unknown>) =>
validateFilesBySchema(
Expand Down
2 changes: 2 additions & 0 deletions src/types/pathwayTimeseries.v2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ export interface PathwayTimeseriesV2 {
| "nuclear"
| "biomass"
| "hydro"
| "geothermal"
| "energyStorage"
| "renewables"
| "electricVehicles"
| "hydrogenVehicles"
Expand Down
Loading