import type { Props } from "@alloy-js/core";
import {
namekey,
NamePolicyContext,
refkey,
StatementList,
} from "@alloy-js/core";
import { describe, expect, it } from "vitest";
import * as ts from "../src/components/index.js";
import type { ParameterDescriptor } from "../src/components/index.js";
import { Reference } from "../src/components/Reference.js";
import { createTSNamePolicy } from "../src/name-policy.js";
import { TestFile } from "./utils.js";
it("declares interfaces", () => {
const res = (
);
expect(res).toRenderTo(`
interface Foo {}
`);
});
it("accepts export and default", () => {
const res = (
);
expect(res).toRenderTo(`
export default interface Foo {}
`);
});
it("creates extends", () => {
const res = (
);
expect(res).toRenderTo(`
interface Foo extends string {}
`);
});
it("can create members", () => {
const res = (
}
/>
);
expect(res).toRenderTo(`
interface Foo {
member: string;
circular: Foo;
[str: string]: number;
}
`);
});
it("can create optional members", () => {
const res = (
}
/>
);
expect(res).toRenderTo(`
interface Foo {
member: string;
circular?: Foo;
[str: string]: number;
}
`);
});
it("can create readonly members", () => {
const res = (
}
/>
);
expect(res).toRenderTo(`
interface Foo {
readonly member: string;
circular: Foo;
readonly [str: string]: number;
}
`);
});
it("can reference member", () => {
const ref = refkey("Foo");
const res = (
} />
);
expect(res).toRenderTo(`
interface Foo {
prop: string
}
interface Bar {
ref: Foo["prop"]
}
`);
});
describe("interface expressions", () => {
it("basic", () => {
const res = (
;
);
expect(res).toRenderTo(`
{
member: string;
}
`);
});
it("nested", () => {
const res = (
;
);
expect(res).toRenderTo(`
{
outer: {
inner: string;
}
}
`);
});
it("can reference member when nested in a declaration", () => {
const ref = refkey("Foo");
const res = (
} />
);
expect(res).toRenderTo(`
interface Foo {
outer: {
inner: string
}
}
interface Bar {
ref: Foo["outer"]["inner"]
}
`);
});
});
it("supports the naming policy", () => {
const policy = createTSNamePolicy();
const res = (
;
);
expect(res).toRenderTo(`
interface InterfaceName {
memberProperty: string;
}
`);
});
it("handles invalid identifier names", () => {
const res = (
;
);
expect(res).toRenderTo(`
{
"invalid-name": string;
}
`);
});
it("accepts type parameters by descriptors", () => {
const typeParams: ts.TypeParameterDescriptor[] = [
{ name: "T", refkey: refkey() },
{ name: "U", extends: "number", refkey: refkey() },
{ name: "V", default: "object", refkey: refkey() },
{ name: "W", extends: "string", default: '"test"', refkey: refkey() },
];
const res = (
;
;
;
;
);
expect(res).toRenderTo(`
interface Foo {
member: T;
member2: U;
member3: V;
member4: W;
}
`);
});
it("accepts type parameters with extends", () => {
const res = (
;
);
expect(res).toRenderTo(`
interface Foo extends Bar {
member: T;
}
`);
});
it("accepts type parameters children", () => {
const res = (
T, U extends number, V = object, W extends string = "test"
;
;
;
;
);
expect(res).toRenderTo(`
interface Foo {
member: T;
member2: U;
member3: V;
member4: W;
}
`);
});
it("takes namekeys for all its elements", () => {
const ifaceKey = namekey("Foo");
const TKey = namekey("T");
const memberKey = namekey("member");
const res = (
;
{ifaceKey};
{memberKey};
);
expect(res).toRenderTo(`
interface Foo {
member: T;
}
Foo;
Foo["member"];
`);
});
describe("method members", () => {
it("render basic", () => {
expect(
,
).toRenderTo(`
interface Foo {
foo(): void
}
`);
});
it("render in interface", () => {
expect(
,
).toRenderTo(`
interface Foo {
foo(): void
}
`);
});
it("can be an async function", () => {
expect(
,
).toRenderTo(`
interface Foo {
foo(): Promise
}
`);
});
it("can be an async function with returnType", () => {
expect(
,
).toRenderTo(`
interface Foo {
foo(): Promise
}
`);
});
it("can be an async function with returnType element", () => {
function Foo(_props?: Props) {
return <>Foo>;
}
expect(
} />
,
).toRenderTo(`
interface Foo {
foo(): Promise
}
`);
});
it("supports parameters by element", () => {
const decl = (
a, b
);
expect({decl}).toRenderTo(`
interface Foo {
foo(a, b): void
}
`);
});
it("supports type parameters by descriptor object", () => {
const decl = (
);
expect({decl}).toRenderTo(`
interface Foo {
foo(): void
}
`);
});
it("supports type parameters by descriptor array", () => {
const decl = (
);
expect({decl}).toRenderTo(`
interface Foo {
foo(): void
}
`);
});
it("supports type parameters by element", () => {
const decl = (
a, b
);
expect({decl}).toRenderTo(`
interface Foo {
foo(): void
}
`);
});
describe("symbols", () => {
it("create optional parameters", () => {
const paramDesc: ParameterDescriptor = {
name: "foo",
refkey: refkey(),
type: "any",
optional: true,
};
const decl = (
);
expect({decl}).toRenderTo(`
interface Foo {
foo(foo?: any): void
}
`);
});
});
});