Skip to content
Draft
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
275 changes: 266 additions & 9 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion website/.cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"*.svg",
"src/content/forms/",
"cache/",
".docs/"
".docs/",
"public/mockServiceWorker.js"
],
"dictionaryDefinitions": [],
"dictionaries": [],
Expand Down Expand Up @@ -46,6 +47,7 @@
"tspconfig",
"typespec",
"underrepresents",
"underserved",
"USCDI",
"rescope",
"rescoped",
Expand Down
3 changes: 3 additions & 0 deletions website/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ dist/
node_modules/
public/openapi/*openapi*.yaml

# Generated by `msw init` — vendored MSW worker script, not ours to format
public/mockServiceWorker.js

# Generated cache files
cache/
166 changes: 166 additions & 0 deletions website/__tests__/lib/mock/opportunities-fixtures.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { describe, it, expect } from "vitest";
import {
CANONICAL_OPPORTUNITY_ID,
OPPORTUNITY_FIXTURES,
RESERVED_MISSING_OPPORTUNITY_ID,
SUPPORTED_VERSIONS,
isSupportedVersion,
shapeOpportunityForVersion,
getById,
allForVersion,
type Opportunity,
} from "@/lib/mock/opportunities/fixtures";

const STATUS_VALUES = ["forecasted", "open", "closed", "custom"];

describe("OPPORTUNITY_FIXTURES", () => {
it("contains between 8 and 12 detail-shaped records", () => {
expect(OPPORTUNITY_FIXTURES.length).toBeGreaterThanOrEqual(8);
expect(OPPORTUNITY_FIXTURES.length).toBeLessThanOrEqual(12);
});

// Swagger UI pre-fills the `oppId` box with the specs' `Types.uuid` example.
// If no fixture carries that id, the first Execute a visitor runs — with the
// field untouched — answers 404 instead of the documented record.
it("carries the id the specs publish as their uuid example", () => {
const canonical = getById(CANONICAL_OPPORTUNITY_ID);

expect(canonical).toBeDefined();
expect(canonical!.title).toBe("Small business grant program");
expect(canonical!.description).toBe(
"This program provides funding to small businesses to help them grow and create jobs",
);
expect(canonical!.status).toEqual({
value: "open",
description: "The opportunity is currently accepting applications",
});
expect(canonical!.funding?.totalAmountAvailable).toEqual({
amount: "1000000.00",
currency: "USD",
});
});

it("sorts the documented example first under the list endpoint's default ordering", () => {
const newestFirst = [...OPPORTUNITY_FIXTURES].sort(
(a, b) =>
new Date(b.lastModifiedAt).getTime() -
new Date(a.lastModifiedAt).getTime(),
);

expect(newestFirst[0].id).toBe(CANONICAL_OPPORTUNITY_ID);
});

it("leaves the reserved 404 id absent from the fixture set", () => {
expect(getById(RESERVED_MISSING_OPPORTUNITY_ID)).toBeUndefined();
});

it("gives every record the OpportunityBase-emitted shape", () => {
for (const opp of OPPORTUNITY_FIXTURES) {
expect(typeof opp.id).toBe("string");
expect(typeof opp.title).toBe("string");
expect(typeof opp.description).toBe("string");
expect(typeof opp.createdAt).toBe("string");
expect(typeof opp.lastModifiedAt).toBe("string");

expect(typeof opp.status).toBe("object");
expect(STATUS_VALUES).toContain(opp.status.value);

expect(opp.funding).toBeDefined();
const amounts = [
opp.funding?.totalAmountAvailable,
opp.funding?.minAwardAmount,
opp.funding?.maxAwardAmount,
].filter(Boolean);
expect(amounts.length).toBeGreaterThan(0);
expect(typeof amounts[0]?.amount).toBe("string");
expect(typeof amounts[0]?.currency).toBe("string");

expect(opp.keyDates?.closeDate).toBeDefined();
}
});

it("includes all four status values, and 'custom' records carry a customValue", () => {
const values = OPPORTUNITY_FIXTURES.map((opp) => opp.status.value);
for (const status of STATUS_VALUES) {
expect(values).toContain(status);
}

const customRecords = OPPORTUNITY_FIXTURES.filter(
(opp) => opp.status.value === "custom",
);
expect(customRecords.length).toBeGreaterThan(0);
for (const opp of customRecords) {
expect(typeof opp.status.customValue).toBe("string");
}
});
});

describe("shapeOpportunityForVersion", () => {
const detailRecord = OPPORTUNITY_FIXTURES.find(
(opp) => Boolean(opp.competitions) && Boolean(opp.acceptedApplicantTypes),
) as Opportunity;

it("strips v0.2+-only fields for v0.1 detail records", () => {
expect(detailRecord).toBeDefined();

const shaped = shapeOpportunityForVersion(detailRecord, "0.1.0", "detail");

expect(shaped).not.toHaveProperty("competitions");
expect(shaped).not.toHaveProperty("acceptedApplicantTypes");
});

it("retains acceptedApplicantTypes and competitions for v0.2 detail records", () => {
const shaped = shapeOpportunityForVersion(detailRecord, "0.2.0", "detail");

expect(shaped).toHaveProperty("acceptedApplicantTypes");
expect(shaped).toHaveProperty("competitions");
});

it("never includes competitions on a v0.3 list-variant record", () => {
const shaped = shapeOpportunityForVersion(detailRecord, "0.3.0", "list");

expect(shaped).not.toHaveProperty("competitions");
});

it("allForVersion('0.1.0') strips acceptedApplicantTypes/competitions from every record", () => {
const shaped = allForVersion("0.1.0");

for (const opp of shaped) {
expect(opp).not.toHaveProperty("acceptedApplicantTypes");
expect(opp).not.toHaveProperty("competitions");
}
});

it("allForVersion('0.3.0') returns the same number of (list-shaped) records", () => {
const shaped = allForVersion("0.3.0");

expect(shaped.length).toBe(OPPORTUNITY_FIXTURES.length);
});
});

describe("getById", () => {
it("has unique ids across the fixture set", () => {
const ids = OPPORTUNITY_FIXTURES.map((opp) => opp.id);
expect(new Set(ids).size).toBe(ids.length);
});

it("resolves the STEM Education Grant Program seeded from the mock API server", () => {
const opp = getById("573525f2-8e15-4405-83fb-e6523511d893");

expect(opp?.title).toBe("STEM Education Grant Program");
});

it("returns undefined for an unknown id", () => {
expect(getById("does-not-exist")).toBeUndefined();
});
});

describe("isSupportedVersion", () => {
it.each(SUPPORTED_VERSIONS)("accepts the supported version %s", (version) => {
expect(isSupportedVersion(version)).toBe(true);
});

it("rejects a version the fixture cannot shape", () => {
expect(isSupportedVersion("0.4.0")).toBe(false);
});
});
Loading
Loading