/
languageServerFeatures.test.ts
167 lines (142 loc) · 5.93 KB
/
languageServerFeatures.test.ts
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
// @ts-ignore TS6133
import { expect } from "https://deno.land/x/expect@v0.2.6/mod.ts";
const test = Deno.test;
import { filePath } from "./languageServerFeatures.source.ts";
import { Project, Node, SyntaxKind } from "ts-morph";
import path from "path";
// The following tool is helpful for understanding the TypeScript AST associated with these tests:
// https://ts-ast-viewer.com/ (just copy the contents of languageServerFeatures.source into the viewer)
describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => {
// Compile file developmentEnvironment.source
const project = new Project({
tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"),
skipAddingFilesFromTsConfig: true,
});
const sourceFile = project.addSourceFileAtPath(filePath);
test("works for simple object properties", () => {
// Find usage of Test.f1 property
const instanceVariable =
sourceFile.getVariableDeclarationOrThrow("instanceOfTest");
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f1"
);
// Find definition of Test.f1 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of Test
expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
expect(parentOfProperty?.getName()).toEqual("Test");
});
test("works for first merged object properties", () => {
// Find usage of TestMerge.f1 property
const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
"instanceOfTestMerge"
);
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f1"
);
// Find definition of TestMerge.f1 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of Test
expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
expect(parentOfProperty?.getName()).toEqual("Test");
});
test("works for second merged object properties", () => {
// Find usage of TestMerge.f2 property
const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
"instanceOfTestMerge"
);
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f2"
);
// Find definition of TestMerge.f2 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of TestMerge
expect(definitionOfProperty?.getText()).toEqual(
"f2: z.string().optional()"
);
expect(parentOfProperty?.getName()).toEqual("TestMerge");
});
test("works for first unioned object properties", () => {
// Find usage of TestUnion.f1 property
const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
"instanceOfTestUnion"
);
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f1"
);
// Find definition of TestUnion.f1 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of Test
expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
expect(parentOfProperty?.getName()).toEqual("Test");
});
test("works for second unioned object properties", () => {
// Find usage of TestUnion.f2 property
const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
"instanceOfTestUnion"
);
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f2"
);
// Find definition of TestUnion.f2 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of TestUnion
expect(definitionOfProperty?.getText()).toEqual(
"f2: z.string().optional()"
);
expect(parentOfProperty?.getName()).toEqual("TestUnion");
});
test("works for partial objects", () => {
// Find usage of TestPartial.f1 property
const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
"instanceOfTestPartial"
);
const propertyBeingAssigned = getPropertyBeingAssigned(
instanceVariable,
"f1"
);
// Find definition of TestPartial.f1 property
const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
SyntaxKind.VariableDeclaration
);
// Assert that find definition returned the Zod definition of Test
expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
expect(parentOfProperty?.getName()).toEqual("Test");
});
});
const getPropertyBeingAssigned = (node: Node, name: string) => {
const propertyAssignment = node.forEachDescendant((descendent) =>
Node.isPropertyAssignment(descendent) && descendent.getName() == name
? descendent
: undefined
);
if (propertyAssignment == null)
fail(`Could not find property assignment with name ${name}`);
const propertyLiteral = propertyAssignment.getFirstDescendantByKind(
SyntaxKind.Identifier
);
if (propertyLiteral == null)
fail(`Could not find property literal with name ${name}`);
return propertyLiteral;
};