import {
List,
namekey,
Output,
refkey,
render,
StatementList,
} from "@alloy-js/core";
import { describe, expect, it } from "vitest";
import * as ts from "../src/components/index.js";
import { TestFile } from "./utils.js";
it("declares classes", () => {
const res = (
);
expect(res).toRenderTo(`
class Foo {}
`);
});
it("accepts export and default", () => {
const res = (
);
expect(res).toRenderTo(`
export default class Foo {}
`);
});
it("creates extends", () => {
const res = (
);
expect(res).toRenderTo(`
class Foo extends string {}
`);
});
it("creates implements", () => {
const res = (
);
expect(res).toRenderTo(`
class Foo implements SomeInterface {}
`);
});
it("creates implements with multiple", () => {
const res = (
);
expect(res).toRenderTo(`
class Foo implements SomeInterface, OtherInterface {}
`);
});
it("creates implements with extends", () => {
const res = (
);
expect(res).toRenderTo(`
class Foo extends string implements SomeInterface {}
`);
});
it("takes namekeys for all elements", () => {
const res = (
);
expect(res).toRenderTo(`
class foo {
myField;
myMethod() {};
}
`);
});
describe("instance members", () => {
it("can be created", () => {
const res = (
12
);
expect(res).toRenderTo(`
class Foo {
one;
public two;
private three;
protected four;
five: number;
six: number = 12;
#seven;
}
`);
});
it("can be referenced", () => {
const one = refkey();
const privateOne = refkey();
const res = (
1
{one} + 1
1
{privateOne} + 1
);
expect(res).toRenderTo(`
class Foo {
one = 1;
two = this.one + 1;
#one = 1;
three = this.#one + 1;
}
`);
});
it("cannot be referenced outside the class", () => {
const one = refkey();
expect(() => {
render(
1
{one}
,
{ insertFinalNewLine: false },
);
}).toThrow(
/Cannot reference instance member 'one' without an instance of 'Foo'/,
);
});
it("cannot be referenced outside the class when protected", () => {
const one = refkey();
expect(() => {
render(
1
{one}
,
{ insertFinalNewLine: false },
);
}).toThrow(
/Cannot reference instance member 'one' without an instance of 'Foo'/,
);
});
it("cannot be referenced outside the class when private", () => {
const one = refkey();
expect(() => {
render(
1
{one}
,
{ insertFinalNewLine: false },
);
}).toThrow(
/Cannot reference instance member 'one' without an instance of 'Foo'/,
);
});
it("works with invalid identifier names", () => {
const one = refkey();
const res = (
1
{one} + 1
);
expect(res).toRenderTo(`
class Foo {
"o-n-e" = 1;
"t-w-o" = this["o-n-e"] + 1;
}
`);
});
it("doesn't conflict with variables outside the class", () => {
const rk = refkey();
const res = (
1;
2;
1
{rk} + 1
);
expect(res).toRenderTo(`
const one = 1;
const two = 2;
class Foo {
one = 1;
two() {
this.one + 1
};
}
`);
});
it("doesn't conflict with imports from other files", () => {
const rk1 = refkey();
const rk2 = refkey();
expect(
,
).toRenderTo({
"decl.ts": `
export const one = 1;
export const two = 2;
`,
"ref.ts": `
import { one, two } from "./decl.js";
class Foo {
one = one;
two() {
two
};
}
`,
});
});
});
describe("static members", () => {
it("renders", () => {
const one = refkey();
const res = (
1
2
);
expect(res).toRenderTo(`
class Foo {
static one = 1;
static #two = 2;
}
`);
});
it("can be referenced", () => {
const one = refkey();
const two = refkey();
const res = (
1
2
return {two};
{one};
);
expect(res).toRenderTo(`
class Foo {
static one = 1;
static #two = 2;
getTwo() {
return Foo.#two;
};
}
Foo.one;
`);
});
it("cannot be referenced outside the class when private", () => {
const two = refkey();
expect(() =>
render(
2
{two};
,
{ insertFinalNewLine: false },
),
).toThrow(/Cannot reference/);
});
});
describe("instance methods", () => {
it("renders", () => {
const one = refkey();
const a = refkey();
const b = refkey();
const res = (
{one} = {a} + {b};
);
expect(res).toRenderTo(`
class Foo {
one() {}
public two() {}
private three() {}
protected four() {}
five(a: string, b: string) {}
six(a: number, b: number): number {
this.one = a + b;
}
#seven() {}
}
`);
});
});
it("renders a class with docs for the class and its members", () => {
const res = (
123
;
return 123;
);
expect(res).toRenderTo(`
/**
* This is a class documentation
*/
class Foo {
/**
* This is a field documentation
*/
bar = 123;
/**
* This is a method documentation
*/
baz() {
return 123;
}
}
`);
});
it("renders a method with parameter docs", () => {
const res = (
);
expect(res).toRenderTo(
`
class Foo {
/**
* Method documentation
*
* @param {number} a - Parameter a doc
* @param {string} b - Line 1 for b.
* This is a long description that
* should continue in the next line.
*/
bar(a: number, b: string): void {}
}
`,
{ printWidth: 40 },
);
});