import { describe, it } from "@std/testing/bdd";
import { assertStringIncludes } from "@std/assert";
import { StaticCacheFS } from "@commontools/static";
import { transformSource } from "../utils.ts";
const staticCache = new StaticCacheFS();
const commontools = await staticCache.getText("types/commontools.d.ts");
const SOURCE = `///
import { h, recipe, UI, ifElse, NAME } from "commontools";
interface Charm {
id: string;
[key: string]: string | undefined;
}
interface State {
charms: Charm[];
defaultName: string;
}
export default recipe("CharmList", (state) => {
return {
[UI]: (
{state.charms.map((charm: any, index: number) => (
-
{index + 1}
{charm[NAME] || state.defaultName}
))}
{ifElse(!state.charms.length, No charms
, Loaded charms
)}
),
};
});
`;
describe("OpaqueRef map callbacks", () => {
it("derives map callback parameters and unary negations", async () => {
const output = await transformSource(SOURCE, {
types: { "commontools.d.ts": commontools },
});
// Map callback should be transformed to recipe with schema for captured defaultName
assertStringIncludes(
output,
"__ctHelpers.recipe({",
);
// Check for correct parameter destructuring
assertStringIncludes(
output,
"({ element: charm, index, params: { state } }) =>",
);
assertStringIncludes(
output,
"state: {\n defaultName: state.defaultName\n }",
);
// Index parameter still gets derive wrapping for the arithmetic operation
assertStringIncludes(
output,
`__ctHelpers.derive({
type: "object",
properties: {
index: {
type: "number"
}
},
required: ["index"]
} as const satisfies __ctHelpers.JSONSchema, {
type: "number"
} as const satisfies __ctHelpers.JSONSchema, { index: index }, ({ index }) => index + 1)`,
);
// element[NAME] || defaultName - since right side is not JSX, wraps whole expression in derive
// (unless optimization only applies when right side is expensive like JSX)
assertStringIncludes(
output,
"({ charm, state }) => charm[NAME] || state.defaultName",
);
// ifElse still gets derive for the negation and preserves callback body
assertStringIncludes(
output,
"({ state }) => !state.charms.length",
);
});
});