Skip to content

Commit b4e72cc

Browse files
authored
feat(test): more completion tests (#279)
1 parent cdfbe2f commit b4e72cc

File tree

10 files changed

+381
-10
lines changed

10 files changed

+381
-10
lines changed

server/src/e2e/suite/BaseTestSuite.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ export abstract class BaseTestSuite {
2121
await activate()
2222
}
2323

24+
public workingDir(): string {
25+
return path.join(__dirname, "../../../test-workspace/")
26+
}
27+
2428
public async setup(): Promise<void> {
25-
this.testFilePath = path.join(__dirname, "../../../test-workspace/test.tact")
29+
this.testFilePath = path.join(this.workingDir(), "test.tact")
2630
const testDir = path.dirname(this.testFilePath)
2731
await fs.promises.mkdir(testDir, {recursive: true})
2832
await fs.promises.writeFile(this.testFilePath, "")

server/src/e2e/suite/completion.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as assert from "node:assert"
33
import {BaseTestSuite} from "./BaseTestSuite"
44
import type {TestCase} from "./TestParser"
55
import {CompletionItem} from "vscode"
6+
import * as path from "node:path"
7+
import * as fs from "node:fs"
68

79
suite("Completion Test Suite", () => {
810
const testSuite = new (class extends BaseTestSuite {
@@ -36,6 +38,14 @@ suite("Completion Test Suite", () => {
3638

3739
protected runTest(testFile: string, testCase: TestCase): void {
3840
test(`Completion: ${testCase.name}`, async () => {
41+
if (testFile.includes("import")) {
42+
const filePath = path.join(this.workingDir(), "other.tact")
43+
await fs.promises.writeFile(filePath, "")
44+
45+
const additionalDoc = await vscode.workspace.openTextDocument(filePath)
46+
await vscode.languages.setTextDocumentLanguage(additionalDoc, "tact")
47+
}
48+
3949
const completions = await this.getCompletions(testCase.input, ".")
4050

4151
const items = completions.map(item => {

server/src/e2e/suite/completionSelect.test.ts

+39-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as vscode from "vscode"
2+
import {CompletionItem, Position} from "vscode"
23
import * as assert from "node:assert"
34
import {BaseTestSuite} from "./BaseTestSuite"
45
import type {TestCase} from "./TestParser"
5-
import {CompletionItem} from "vscode"
66

77
suite("Completion Test Suite", () => {
88
const testSuite = new (class extends BaseTestSuite {
@@ -25,20 +25,20 @@ suite("Completion Test Suite", () => {
2525
position,
2626
)
2727

28-
const line = this.document.lineAt(position.line)
29-
const textBeforeCursor = line.text.slice(0, position.character)
28+
const textBeforeCursor = this.findWordBeforeCursor(position)
29+
3030
// Filtering items to match better completion for this test
31-
let items = completions.items.filter(item => {
31+
const items = completions.items.filter(item => {
3232
const label = typeof item.label === "object" ? item.label.label : item.label
3333
return label.includes(textBeforeCursor.trim())
3434
})
3535

36-
if (completions.items.length <= 0) {
36+
if (completions.items.length === 0) {
3737
throw new Error("No completions available for this test")
3838
}
3939

4040
if (items.length <= 0) {
41-
items = completions.items
41+
return completions.items[0]
4242
}
4343

4444
return items[0]
@@ -76,20 +76,51 @@ suite("Completion Test Suite", () => {
7676
test(`Completion Select: ${testCase.name}`, async () => {
7777
const completion = await this.getFilteredCompletion(testCase.input)
7878
await this.applyCompletionItem(completion)
79+
80+
const cursor = this.editor.selection.active
7981
const editorText = this.document.getText()
82+
const editorTextWithCursor = this.insertCursor(editorText, cursor)
83+
8084
const expected = testCase.expected
8185

8286
if (BaseTestSuite.UPDATE_SNAPSHOTS) {
8387
this.updates.push({
8488
filePath: testFile,
8589
testName: testCase.name,
86-
actual: editorText,
90+
actual: editorTextWithCursor,
8791
})
8892
} else {
89-
assert.deepStrictEqual(editorText, expected)
93+
assert.deepStrictEqual(editorTextWithCursor, expected)
9094
}
9195
})
9296
}
97+
98+
protected findWordBeforeCursor(position: Position): string {
99+
const line = this.document.lineAt(position.line)
100+
const textBeforeCursor = line.text.slice(0, position.character)
101+
102+
const letterRe = new RegExp(/[a-z]/i)
103+
104+
for (let i = textBeforeCursor.length; i >= 0; i--) {
105+
const symbol = textBeforeCursor[i]
106+
if (!letterRe.test(symbol)) {
107+
return textBeforeCursor.slice(i + 1, line.text.length)
108+
}
109+
}
110+
111+
return line.text
112+
}
113+
114+
protected insertCursor(text: string, position: Position): string {
115+
const lines = text.split(/\r?\n/)
116+
if (position.line >= lines.length) return text
117+
118+
const line = lines[position.line]
119+
lines[position.line] =
120+
line.slice(0, position.character) + "<caret>" + line.slice(position.character)
121+
122+
return lines.join("\n")
123+
}
93124
})()
94125

95126
suiteSetup(async function () {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
========================================================================
2+
Completion for empty import
3+
========================================================================
4+
import "<caret>";
5+
------------------------------------------------------------------------
6+
16 ./other.tact
7+
18 @stdlib/
8+
9+
========================================================================
10+
Completion for current dir
11+
========================================================================
12+
import "./<caret>";
13+
------------------------------------------------------------------------
14+
16 other.tact

server/src/e2e/suite/testcases/completion/structs.test

+10
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,13 @@ fun test() {
6161
14 try-catch
6262
14 until
6363
14 while
64+
65+
========================================================================
66+
Completion in struct
67+
========================================================================
68+
struct Foo {
69+
<caret>
70+
}
71+
------------------------------------------------------------------------
72+
0 Foo
73+
0 struct

server/src/e2e/suite/testcases/completionSelect/contract.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ Global complete Contract
33
========================================================================
44
contract<caret>
55
------------------------------------------------------------------------
6-
contract Name {}
6+
contract Name<caret> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
========================================================================
2+
Completion for function without parameters
3+
========================================================================
4+
primitive Int;
5+
6+
fun foo() {}
7+
8+
fun test() {
9+
foo<caret>
10+
}
11+
------------------------------------------------------------------------
12+
primitive Int;
13+
14+
fun foo() {}
15+
16+
fun test() {
17+
foo()<caret>;
18+
}
19+
20+
========================================================================
21+
Completion for function with parameters
22+
========================================================================
23+
primitive Int;
24+
25+
fun foo(value: Int) {}
26+
27+
fun test() {
28+
foo<caret>
29+
}
30+
------------------------------------------------------------------------
31+
primitive Int;
32+
33+
fun foo(value: Int) {}
34+
35+
fun test() {
36+
foo(<caret>);
37+
}
38+
39+
========================================================================
40+
Completion for function before ()
41+
========================================================================
42+
primitive Int;
43+
44+
fun foo(value: Int) {}
45+
46+
fun test() {
47+
fo<caret>();
48+
}
49+
------------------------------------------------------------------------
50+
primitive Int;
51+
52+
fun foo(value: Int) {}
53+
54+
fun test() {
55+
foo<caret>();
56+
}
57+
58+
========================================================================
59+
Completion for function before ;
60+
========================================================================
61+
primitive Int;
62+
63+
fun foo() {}
64+
65+
fun test() {
66+
foo<caret>;
67+
}
68+
------------------------------------------------------------------------
69+
primitive Int;
70+
71+
fun foo() {}
72+
73+
fun test() {
74+
foo()<caret>;
75+
}
76+
77+
========================================================================
78+
Completion for function inside expression
79+
========================================================================
80+
primitive Int;
81+
82+
fun foo() {}
83+
84+
fun test() {
85+
let a = fo<caret>
86+
}
87+
------------------------------------------------------------------------
88+
primitive Int;
89+
90+
fun foo() {}
91+
92+
fun test() {
93+
let a = foo()<caret>
94+
}
95+
96+
========================================================================
97+
Completion for function inside expression 2
98+
========================================================================
99+
primitive Int;
100+
101+
fun foo(): Int { return 0; }
102+
fun bar(a: Int) {}
103+
104+
fun test() {
105+
bar(fo<caret>);
106+
}
107+
------------------------------------------------------------------------
108+
primitive Int;
109+
110+
fun foo(): Int { return 0; }
111+
fun bar(a: Int) {}
112+
113+
fun test() {
114+
bar(foo()<caret>);
115+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
========================================================================
2+
initOf completion
3+
========================================================================
4+
primitive Int;
5+
6+
contract Foo {
7+
value: Int;
8+
9+
fun foo() {
10+
initO<caret>
11+
}
12+
}
13+
------------------------------------------------------------------------
14+
primitive Int;
15+
16+
contract Foo {
17+
value: Int;
18+
19+
fun foo() {
20+
initOf <caret>()
21+
}
22+
}
23+
24+
========================================================================
25+
initOf name completion before ()
26+
========================================================================
27+
primitive Int;
28+
29+
contract Foo {
30+
value: Int;
31+
32+
fun foo() {
33+
initOf <caret>
34+
}
35+
}
36+
------------------------------------------------------------------------
37+
primitive Int;
38+
39+
contract Foo {
40+
value: Int;
41+
42+
fun foo() {
43+
initOf Foo()<caret>
44+
}
45+
}
46+
47+
========================================================================
48+
initOf name completion before ()
49+
========================================================================
50+
primitive Int;
51+
52+
contract Foo {
53+
value: Int;
54+
55+
fun foo() {
56+
initOf <caret>()
57+
}
58+
}
59+
------------------------------------------------------------------------
60+
primitive Int;
61+
62+
contract Foo {
63+
value: Int;
64+
65+
fun foo() {
66+
initOf Foo()<caret>
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
========================================================================
2+
Completion for contract field
3+
========================================================================
4+
primitive Int;
5+
6+
contract Foo {
7+
value: Int;
8+
9+
fun foo() {
10+
value<caret>
11+
}
12+
}
13+
------------------------------------------------------------------------
14+
primitive Int;
15+
16+
contract Foo {
17+
value: Int;
18+
19+
fun foo() {
20+
self.value<caret>
21+
}
22+
}

0 commit comments

Comments
 (0)