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 } `); }); }); });