-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathformatter-edge.test.ts
More file actions
174 lines (150 loc) · 7.86 KB
/
formatter-edge.test.ts
File metadata and controls
174 lines (150 loc) · 7.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import { describe, it, expect, vi } from "vitest";
import { WitFormatter } from "../src/formatter.js";
vi.mock("vscode", () => ({}));
describe("WitFormatter — edge cases", () => {
const formatter = new WitFormatter();
const defaultOptions = { insertSpaces: true, tabSize: 4 };
describe("empty and whitespace input", () => {
it("should handle empty string", () => {
expect(formatter.formatWitContent("", defaultOptions)).toBe("");
});
it("should preserve blank lines", () => {
const input = "\n\n\n";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("\n\n\n");
});
it("should handle single blank line", () => {
const input = "\n";
expect(formatter.formatWitContent(input, defaultOptions)).toBe("\n");
});
});
describe("tab indentation", () => {
it("should use tabs when insertSpaces is false", () => {
const input = "package foo:bar;\n\ninterface test {\nmy-func: func();\n}";
const result = formatter.formatWitContent(input, { insertSpaces: false, tabSize: 4 });
expect(result).toContain("\tmy-func: func();");
});
it("should respect tabSize setting", () => {
const input = "package foo:bar;\n\ninterface test {\nmy-func: func();\n}";
const result2 = formatter.formatWitContent(input, { insertSpaces: true, tabSize: 2 });
expect(result2).toContain(" my-func: func();");
const result4 = formatter.formatWitContent(input, { insertSpaces: true, tabSize: 4 });
expect(result4).toContain(" my-func: func();");
});
});
describe("nested structures", () => {
it("should handle deeply nested braces", () => {
const input =
"package foo:bar;\n\nworld my-world {\nexport run: func();\nimport log: func(msg: string);\n}";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain(" export run: func();");
expect(result).toContain(" import log: func(msg: string);");
});
it("should format resource with methods", () => {
const input =
"package foo:bar;\n\ninterface api {\nresource my-res {\nconstructor(name: string);\nget-name: func() -> string;\n}\n}";
const result = formatter.formatWitContent(input, defaultOptions);
// Resource body should be indented within interface
const lines = result.split("\n");
const constructorLine = lines.find((l: string) => l.includes("constructor"));
expect(constructorLine).toBeDefined();
expect(constructorLine!.startsWith(" ")).toBe(true); // 8 spaces (2 levels)
});
});
describe("comment handling", () => {
it("should preserve single-line comments at correct indentation", () => {
const input = "package foo:bar;\n\ninterface test {\n// A comment\nmy-func: func();\n}";
const result = formatter.formatWitContent(input, defaultOptions);
const lines = result.split("\n");
const commentLine = lines.find((l: string) => l.includes("// A comment"));
expect(commentLine).toBeDefined();
expect(commentLine!.startsWith(" ")).toBe(true);
});
it("should handle doc comments (///)", () => {
const input = "package foo:bar;\n\ninterface test {\n/// Doc comment\nmy-func: func();\n}";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain("/// Doc comment");
});
});
describe("type alias formatting", () => {
it("should format simple type aliases", () => {
const input = "type my-type = u32 ;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("type my-type = u32;");
});
it("should format type alias with complex type", () => {
const input = "type my-type = list<u8> ;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("type my-type = list<u8>;");
});
});
describe("use statement formatting", () => {
it("should format use statements", () => {
const input = "use my-interface.{type1, type2} ;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain("use my-interface");
expect(result.endsWith(";")).toBe(true);
});
it("should format use with as clause", () => {
const input = "use my-interface.{type1} as alias-name ;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain(" as ");
});
});
describe("function formatting edge cases", () => {
it("should format function with no parameters", () => {
const input = "my-func:func();";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("my-func: func();");
});
it("should format function with return type", () => {
const input = "my-func:func()->string;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("my-func: func() -> string;");
});
it("should format function with multiple parameters", () => {
const input = "my-func:func(a:u32,b:string)->bool;";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toBe("my-func: func(a: u32, b: string) -> bool;");
});
});
describe("enum and flags formatting", () => {
it("should format enum with cases", () => {
const input = "package foo:bar;\n\nenum my-enum {\ncase-a,\ncase-b,\n}";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain("enum my-enum {");
expect(result).toContain(" case-a,");
});
it("should format flags with members", () => {
const input = "package foo:bar;\n\nflags my-flags {\nflag-a,\nflag-b,\n}";
const result = formatter.formatWitContent(input, defaultOptions);
expect(result).toContain("flags my-flags {");
expect(result).toContain(" flag-a,");
});
});
describe("provideDocumentFormattingEdits", () => {
it("should return empty array when content is unchanged", () => {
const mockDocument = {
getText: () => "package foo:bar;",
positionAt: (offset: number) => ({ line: 0, character: offset }),
} as unknown as import("vscode").TextDocument;
const result = formatter.provideDocumentFormattingEdits(mockDocument, defaultOptions);
expect(result).toEqual([]);
});
});
describe("multiline function parameters", () => {
it("should indent continuation lines of func parameters", () => {
const input = "package foo:bar;\n\ninterface test {\nmy-func: func(\na: u32,\nb: string,\n) -> bool;\n}";
const result = formatter.formatWitContent(input, defaultOptions);
const lines = result.split("\n");
const paramLine = lines.find((l: string) => l.includes("a: u32"));
expect(paramLine).toBeDefined();
// Should be indented more than the func line
const funcLine = lines.find((l: string) => l.includes("my-func"));
expect(funcLine).toBeDefined();
const funcIndent = funcLine!.length - funcLine!.trimStart().length;
const paramIndent = paramLine!.length - paramLine!.trimStart().length;
expect(paramIndent).toBeGreaterThan(funcIndent);
});
});
});