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

test: Add tests for signatureHelp #253

Merged
merged 10 commits into from
Feb 17, 2025
63 changes: 63 additions & 0 deletions server/src/e2e/suite/signatures.test.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call it signatureHelp.test.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Renamed

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as vscode from "vscode"
import * as assert from "node:assert"
import {BaseTestSuite} from "./BaseTestSuite"
import type {TestCase} from "./TestParser"

suite("Signatures Test Suite", () => {
const testSuite = new (class extends BaseTestSuite {
public async getSignature(input: string): Promise<vscode.SignatureHelp> {
const textWithoutCaret = input.replace("<caret>", "")
await this.replaceDocumentText(textWithoutCaret)

const caretIndex = input.indexOf("<caret>")
if (caretIndex === -1) {
throw new Error("No <caret> marker found in input")
}

const position = this.document.positionAt(caretIndex)
this.editor.selection = new vscode.Selection(position, position)
this.editor.revealRange(new vscode.Range(position, position))

return vscode.commands.executeCommand<vscode.SignatureHelp>(
"vscode.executeSignatureHelpProvider",
this.document.uri,
position,
)
}

protected runTest(testFile: string, testCase: TestCase): void {
test(`Signature: ${testCase.name}`, async () => {
const signature = await this.getSignature(testCase.input)
const items = signature.signatures.map(item => {
const label = item.label
if (item.activeParameter !== undefined) {
const activeParamLabel = item.parameters[item.activeParameter]?.label ?? ""
return `${activeParamLabel.toString()}\n${label}`
}
return ""
})
const expected = testCase.expected.split("\n").filter((line: string) => line !== "")
if (BaseTestSuite.UPDATE_SNAPSHOTS) {
this.updates.push({
filePath: testFile,
testName: testCase.name,
actual: items.join("\n"),
})
} else {
assert.deepStrictEqual(items.sort(), expected.sort())
}
})
}
})()

suiteSetup(async function () {
this.timeout(10_000)
await testSuite.suiteSetup()
})

setup(async () => testSuite.setup())
teardown(async () => testSuite.teardown())
suiteTeardown(() => testSuite.suiteTeardown())

testSuite.runTestsFromDirectory("signatures")
})
279 changes: 279 additions & 0 deletions server/src/e2e/suite/testcases/signatures/contract.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
========================================================================
Basic Function with Multiple Parameters
========================================================================
primitive Int;
primitive String;

struct User {
first_name: String;
last_name: String;
age: Int;
}

contract Foo {

fun bar(a: Int, b: String, c: User) {
return a + 42;
}

init() {
self.bar(1000, <caret>);
}
}
------------------------------------------------------------------------
b: String
fun bar(a: Int, b: String, c: User)

========================================================================
Basic Function with Multiple Parameters - 2
========================================================================
primitive Int;
primitive String;

struct User {
name: String;
age: Int;
}

contract Foo {
fun baz(user: User, action: String, value: Int) {
// ...
}

init() {
self.baz(user, "update", <caret>);
}
}
------------------------------------------------------------------------
value: Int
fun baz(user: User, action: String, value: Int)

========================================================================
Function Overloading
========================================================================
primitive Int;
primitive String;

contract Foo {
fun add(a: Int, b: Int): Int {
return a + b;
}

fun add(a: String, b: String): String {
return a + b;
}

init() {
self.add("hello", <caret>);
}
}
------------------------------------------------------------------------
b: Int
fun add(a: Int, b: Int)

========================================================================
Nested Function Calls
========================================================================
primitive Int;
primitive String;

contract Foo {
fun multiply(a: Int, b: Int): Int {
return a * b;
}

fun calculate(x: Int, y: Int, z: Int): Int {
return x + self.multiply(y, z);
}

init() {
self.calculate(10, <caret>);
}
}
------------------------------------------------------------------------
y: Int
fun calculate(x: Int, y: Int, z: Int)

========================================================================
Function with Optional Parameters
========================================================================
primitive Int;

contract Foo {
fun sum(a: Int, b: Int = 10, c: Int = 20): Int {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tact doesn't support this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

return a + b + c;
}

init() {
self.sum(5, <caret>);
}
}
------------------------------------------------------------------------
b: Int
fun sum(a: Int, b: Int, c: Int)

========================================================================
Default Parameter Values
========================================================================
primitive Int;

contract Foo {
fun configure(a: Int, b: Int = 42, c: Int = 100): Int {
return a + b + c;
}

init() {
self.configure(10, <caret>);
}
}
------------------------------------------------------------------------
b: Int
fun configure(a: Int, b: Int, c: Int)

========================================================================
Chained Function Calls
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nested :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Updated

========================================================================
primitive Int;

contract Foo {
fun double(x: Int): Int {
return x * 2;
}

fun triple(x: Int): Int {
return x * 3;
}

init() {
self.double(self.triple(<caret>));
}
}
------------------------------------------------------------------------
x: Int
fun triple(x: Int)

========================================================================
Promt first arg while second is filled
========================================================================
primitive Int;

contract Foo {
fun add(a: Int, b: Int): Int {
return a + b;
}

init() {
self.add(<caret>, 2);
}
}
------------------------------------------------------------------------
a: Int
fun add(a: Int, b: Int)

========================================================================
Map with Complex Key Types
========================================================================
primitive Int;
primitive String;

struct Key {
id: Int;
name: String;
}

contract Foo {
fun processComplexMap(map: Map<Key, Int>) {
// ...
}

init() {
let key = Key { id: 1, name: "Test" };
let map = emptyMap();
self.processComplexMap(<caret>);
}
}
------------------------------------------------------------------------
map: Map
fun processComplexMap(map: Map)

========================================================================
Set Map (Key)
========================================================================
primitive Int;
extends mutates fun set(self: map<K, V>, key: K, val: V);

contract A {
init() {
let fizz: map<Int, Int> = emptyMap();

fizz.set(<caret>)
}
}
------------------------------------------------------------------------
key: K
fun set(self: map<K, V>, key: K, val: V)

========================================================================
Set Map (Value)
========================================================================
primitive Int;
extends mutates fun set(self: map<K, V>, key: K, val: V);

contract A {
init() {
let fizz: map<Int, Int> = emptyMap();

fizz.set(42, <caret>)
}
}
------------------------------------------------------------------------
val: V
fun set(self: map<K, V>, key: K, val: V)

========================================================================
Get value from Map
========================================================================
primitive Int;
extends fun get(self: map<K, V>, key: K): V?;
contract A {
init() {
let fizz: map<Int, Int> = emptyMap();

fizz.get(<caret>);
}
}
------------------------------------------------------------------------
key: K
fun get(self: map<K, V>, key: K)

========================================================================
Replace value map by key (caret on key)
========================================================================
primitive Int;
extends mutates fun replace(self: map<K, V>, key: K, val: V): Bool;
contract A {
init() {
let fizz: map<Int, Int> = emptyMap();

fizz.replace(<caret>)
}
}
------------------------------------------------------------------------
key: K
fun replace(self: map<K, V>, key: K, val: V)

========================================================================
Replace value map by key (caret on value)
========================================================================
primitive Int;
extends mutates fun replace(self: map<K, V>, key: K, val: V): Bool;
contract A {
init() {
let fizz: map<Int, Int> = emptyMap();

fizz.replace(42, <caret>)
}
}
------------------------------------------------------------------------
val: V
fun replace(self: map<K, V>, key: K, val: V)
Loading