Skip to content

Commit e24b761

Browse files
h9jianggopherbot
authored andcommitted
extension/test: add test for interactive refactoring
Since the gopls pre-release candidate is available, vscode-go can now introduce test against the interactive refactoring. For golang/go#76331 Change-Id: If71a3c65c4aec6eea4dd65c1c583789ca684bb33 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/778580 Reviewed-by: Madeline Kalil <mkalil@google.com> Auto-Submit: Hongxiang Jiang <hxjiang@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent 41ee1e7 commit e24b761

4 files changed

Lines changed: 137 additions & 0 deletions

File tree

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
/*---------------------------------------------------------
3+
* Copyright 2026 The Go Authors. All rights reserved.
4+
* Licensed under the MIT License. See LICENSE in the project root for license information.
5+
*--------------------------------------------------------*/
6+
7+
import assert from 'assert';
8+
import path = require('path');
9+
import sinon = require('sinon');
10+
import vscode = require('vscode');
11+
import { Env } from './goplsTestEnv.utils';
12+
import { updateGoVarsFromConfig } from '../../src/goInstallTools';
13+
14+
suite('Interactive Refactoring', function () {
15+
this.timeout(30000);
16+
17+
let document: vscode.TextDocument;
18+
const sandbox = sinon.createSandbox();
19+
const projectDir = path.join(__dirname, '..', '..', '..');
20+
const testdataDir = path.join(projectDir, 'test', 'testdata', 'interactive');
21+
const env = new Env();
22+
23+
this.afterEach(function () {
24+
env.flushTrace(this.currentTest?.state === 'failed');
25+
sandbox.restore();
26+
});
27+
28+
suiteSetup(async () => {
29+
await updateGoVarsFromConfig({});
30+
const uri = vscode.Uri.file(path.join(testdataDir, 'interactive.go'));
31+
await env.startGopls(uri.fsPath, undefined, testdataDir);
32+
document = await vscode.workspace.openTextDocument(uri);
33+
});
34+
35+
suiteTeardown(async () => {
36+
await env.teardown();
37+
});
38+
39+
test('Add struct tags', async () => {
40+
const editor = await vscode.window.showTextDocument(document);
41+
42+
// type Foo struct {
43+
// Foo string //@loc(editor.selection, "Foo string")
44+
// }
45+
editor.selection = new vscode.Selection(3, 1, 3, 11);
46+
47+
const codeActions = await vscode.commands.executeCommand<vscode.CodeAction[]>(
48+
'vscode.executeCodeActionProvider',
49+
document.uri,
50+
editor.selection
51+
);
52+
53+
const action = codeActions.find((a) => a.kind?.value === 'refactor.rewrite.addTags');
54+
55+
assert.ok(action, 'Add struct tags code action not found');
56+
assert.ok(action.command, 'Code action has no command');
57+
58+
const inputBoxStub = sandbox.stub(vscode.window, 'showInputBox');
59+
const quickPickStub = sandbox.stub(vscode.window, 'showQuickPick');
60+
61+
// First attempt fails because of invalid tags.
62+
inputBoxStub.onFirstCall().resolves('json,x x,html'); // invalid, space not allowed in a tag "x x"
63+
quickPickStub.onFirstCall().resolves({ value: 'camelcase', label: 'camelCase' } as any);
64+
65+
// Second attempt succeeds. vscode-go will ask the second question regardless.
66+
inputBoxStub.onSecondCall().resolves('json,xml');
67+
quickPickStub.onSecondCall().resolves({ value: 'camelcase', label: 'camelCase' } as any);
68+
69+
// Trigger the command. The middleware handles the interactive handshake
70+
// with gopls, collects answers via our stubs, and executes the refactoring.
71+
await vscode.commands.executeCommand(action.command.command, ...action.command.arguments!);
72+
73+
const docText = document.getText();
74+
assert.match(docText, /Foo string `json:"foo" xml:"foo"`/);
75+
});
76+
77+
test('Stub methods', async () => {
78+
const editor = await vscode.window.showTextDocument(document);
79+
80+
// type Foo struct {
81+
// Foo string //@loc(editor.selection, "Foo string")
82+
// }
83+
editor.selection = new vscode.Selection(3, 1, 3, 11);
84+
85+
const codeActions = await vscode.commands.executeCommand<vscode.CodeAction[]>(
86+
'vscode.executeCodeActionProvider',
87+
document.uri,
88+
editor.selection
89+
);
90+
91+
const action = codeActions.find((a) => a.kind?.value === 'refactor.rewrite.implementInterface');
92+
assert.ok(action, 'Stub methods code action not found');
93+
assert.ok(action.command, 'Stub methods code action has no command');
94+
95+
sandbox.stub(vscode.window, 'createQuickPick').returns({
96+
// In production, `onDidAccept` registers a callback that waits for a
97+
// user's click.
98+
// In this test, we simulate an immediate user selection by invoking the
99+
// callback instantly and mocking the chosen value via `selectedItems`.
100+
onDidAccept: (cb: () => void) => cb(),
101+
selectedItems: [{ label: 'net.Error', value: 'net.Error' }],
102+
// The following are fake properties, place holders for
103+
// production code to overwrite.
104+
title: '',
105+
placeholder: '',
106+
matchOnDescription: true,
107+
onDidChangeValue: sinon.fake(),
108+
onDidHide: sinon.fake(),
109+
show: sinon.fake(),
110+
hide: sinon.fake(),
111+
dispose: sinon.fake()
112+
} as any);
113+
114+
// Trigger the command. The middleware handles the interactive handshake
115+
// with gopls, collects answers via our stubs, and executes the refactoring.
116+
await vscode.commands.executeCommand(action.command.command, ...action.command.arguments!);
117+
118+
const docText = document.getText();
119+
120+
assert.match(docText, /func \(f \*Foo\) Error\(\) string/);
121+
assert.match(docText, /func \(f \*Foo\) Temporary\(\) bool/);
122+
assert.match(docText, /func \(f \*Foo\) Timeout\(\) bool/);
123+
});
124+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package interactive
2+
3+
import "net"
4+
5+
var _ net.Error
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/microsoft/vscode-go/gofixtures/interactive
2+
3+
go 1.18
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package interactive
2+
3+
type Foo struct {
4+
Foo string
5+
}

0 commit comments

Comments
 (0)