Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(test): more completion tests #279

Merged
merged 1 commit into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion server/src/e2e/suite/BaseTestSuite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ export abstract class BaseTestSuite {
await activate()
}

public workingDir(): string {
return path.join(__dirname, "../../../test-workspace/")
}

public async setup(): Promise<void> {
this.testFilePath = path.join(__dirname, "../../../test-workspace/test.tact")
this.testFilePath = path.join(this.workingDir(), "test.tact")
const testDir = path.dirname(this.testFilePath)
await fs.promises.mkdir(testDir, {recursive: true})
await fs.promises.writeFile(this.testFilePath, "")
Expand Down
10 changes: 10 additions & 0 deletions server/src/e2e/suite/completion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as assert from "node:assert"
import {BaseTestSuite} from "./BaseTestSuite"
import type {TestCase} from "./TestParser"
import {CompletionItem} from "vscode"
import * as path from "node:path"
import * as fs from "node:fs"

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

protected runTest(testFile: string, testCase: TestCase): void {
test(`Completion: ${testCase.name}`, async () => {
if (testFile.includes("import")) {
const filePath = path.join(this.workingDir(), "other.tact")
await fs.promises.writeFile(filePath, "")

const additionalDoc = await vscode.workspace.openTextDocument(filePath)
await vscode.languages.setTextDocumentLanguage(additionalDoc, "tact")
}

const completions = await this.getCompletions(testCase.input, ".")

const items = completions.map(item => {
Expand Down
47 changes: 39 additions & 8 deletions server/src/e2e/suite/completionSelect.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as vscode from "vscode"
import {CompletionItem, Position} from "vscode"
import * as assert from "node:assert"
import {BaseTestSuite} from "./BaseTestSuite"
import type {TestCase} from "./TestParser"
import {CompletionItem} from "vscode"

suite("Completion Test Suite", () => {
const testSuite = new (class extends BaseTestSuite {
Expand All @@ -25,20 +25,20 @@ suite("Completion Test Suite", () => {
position,
)

const line = this.document.lineAt(position.line)
const textBeforeCursor = line.text.slice(0, position.character)
const textBeforeCursor = this.findWordBeforeCursor(position)

// Filtering items to match better completion for this test
let items = completions.items.filter(item => {
const items = completions.items.filter(item => {
const label = typeof item.label === "object" ? item.label.label : item.label
return label.includes(textBeforeCursor.trim())
})

if (completions.items.length <= 0) {
if (completions.items.length === 0) {
throw new Error("No completions available for this test")
}

if (items.length <= 0) {
items = completions.items
return completions.items[0]
}

return items[0]
Expand Down Expand Up @@ -76,20 +76,51 @@ suite("Completion Test Suite", () => {
test(`Completion Select: ${testCase.name}`, async () => {
const completion = await this.getFilteredCompletion(testCase.input)
await this.applyCompletionItem(completion)

const cursor = this.editor.selection.active
const editorText = this.document.getText()
const editorTextWithCursor = this.insertCursor(editorText, cursor)

const expected = testCase.expected

if (BaseTestSuite.UPDATE_SNAPSHOTS) {
this.updates.push({
filePath: testFile,
testName: testCase.name,
actual: editorText,
actual: editorTextWithCursor,
})
} else {
assert.deepStrictEqual(editorText, expected)
assert.deepStrictEqual(editorTextWithCursor, expected)
}
})
}

protected findWordBeforeCursor(position: Position): string {
const line = this.document.lineAt(position.line)
const textBeforeCursor = line.text.slice(0, position.character)

const letterRe = new RegExp(/[a-z]/i)

for (let i = textBeforeCursor.length; i >= 0; i--) {
const symbol = textBeforeCursor[i]
if (!letterRe.test(symbol)) {
return textBeforeCursor.slice(i + 1, line.text.length)
}
}

return line.text
}

protected insertCursor(text: string, position: Position): string {
const lines = text.split(/\r?\n/)
if (position.line >= lines.length) return text

const line = lines[position.line]
lines[position.line] =
line.slice(0, position.character) + "<caret>" + line.slice(position.character)

return lines.join("\n")
}
})()

suiteSetup(async function () {
Expand Down
14 changes: 14 additions & 0 deletions server/src/e2e/suite/testcases/completion/imports.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
========================================================================
Completion for empty import
========================================================================
import "<caret>";
------------------------------------------------------------------------
16 ./other.tact
18 @stdlib/

========================================================================
Completion for current dir
========================================================================
import "./<caret>";
------------------------------------------------------------------------
16 other.tact
10 changes: 10 additions & 0 deletions server/src/e2e/suite/testcases/completion/structs.test
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,13 @@ fun test() {
14 try-catch
14 until
14 while

========================================================================
Completion in struct
========================================================================
struct Foo {
<caret>
}
------------------------------------------------------------------------
0 Foo
0 struct
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Global complete Contract
========================================================================
contract<caret>
------------------------------------------------------------------------
contract Name {}
contract Name<caret> {}
115 changes: 115 additions & 0 deletions server/src/e2e/suite/testcases/completionSelect/functions.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
========================================================================
Completion for function without parameters
========================================================================
primitive Int;

fun foo() {}

fun test() {
foo<caret>
}
------------------------------------------------------------------------
primitive Int;

fun foo() {}

fun test() {
foo()<caret>;
}

========================================================================
Completion for function with parameters
========================================================================
primitive Int;

fun foo(value: Int) {}

fun test() {
foo<caret>
}
------------------------------------------------------------------------
primitive Int;

fun foo(value: Int) {}

fun test() {
foo(<caret>);
}

========================================================================
Completion for function before ()
========================================================================
primitive Int;

fun foo(value: Int) {}

fun test() {
fo<caret>();
}
------------------------------------------------------------------------
primitive Int;

fun foo(value: Int) {}

fun test() {
foo<caret>();
}

========================================================================
Completion for function before ;
========================================================================
primitive Int;

fun foo() {}

fun test() {
foo<caret>;
}
------------------------------------------------------------------------
primitive Int;

fun foo() {}

fun test() {
foo()<caret>;
}

========================================================================
Completion for function inside expression
========================================================================
primitive Int;

fun foo() {}

fun test() {
let a = fo<caret>
}
------------------------------------------------------------------------
primitive Int;

fun foo() {}

fun test() {
let a = foo()<caret>
}

========================================================================
Completion for function inside expression 2
========================================================================
primitive Int;

fun foo(): Int { return 0; }
fun bar(a: Int) {}

fun test() {
bar(fo<caret>);
}
------------------------------------------------------------------------
primitive Int;

fun foo(): Int { return 0; }
fun bar(a: Int) {}

fun test() {
bar(foo()<caret>);
}
68 changes: 68 additions & 0 deletions server/src/e2e/suite/testcases/completionSelect/initOf.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
========================================================================
initOf completion
========================================================================
primitive Int;

contract Foo {
value: Int;

fun foo() {
initO<caret>
}
}
------------------------------------------------------------------------
primitive Int;

contract Foo {
value: Int;

fun foo() {
initOf <caret>()
}
}

========================================================================
initOf name completion before ()
========================================================================
primitive Int;

contract Foo {
value: Int;

fun foo() {
initOf <caret>
}
}
------------------------------------------------------------------------
primitive Int;

contract Foo {
value: Int;

fun foo() {
initOf Foo()<caret>
}
}

========================================================================
initOf name completion before ()
========================================================================
primitive Int;

contract Foo {
value: Int;

fun foo() {
initOf <caret>()
}
}
------------------------------------------------------------------------
primitive Int;

contract Foo {
value: Int;

fun foo() {
initOf Foo()<caret>
}
}
22 changes: 22 additions & 0 deletions server/src/e2e/suite/testcases/completionSelect/self.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
========================================================================
Completion for contract field
========================================================================
primitive Int;

contract Foo {
value: Int;

fun foo() {
value<caret>
}
}
------------------------------------------------------------------------
primitive Int;

contract Foo {
value: Int;

fun foo() {
self.value<caret>
}
}
Loading