Skip to content

Commit

Permalink
Add an integration test of completions. (runem#232)
Browse files Browse the repository at this point in the history
* Add an integration test of completions.

* Clarify the completions fixture file

Also put the completion locations in a single, easier-to-update place in the code.

* Also open our test vscode to the fixtures dir

This way we can, in the future, add settings and such to a .vscode directory there.

Also makes debugging a bit nicer.

* Use path join more

Hoping to fix windows test

* Don't throw when failing to write to log file.
  • Loading branch information
rictic authored Feb 4, 2022
1 parent 88c989a commit da309c1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 3 deletions.
6 changes: 5 additions & 1 deletion packages/ts-lit-plugin/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ export class Logger extends DefaultLitAnalyzerLogger {
breakLength: 50,
maxArrayLength: 10
});
appendFileSync(this.logPath, `${prefix}${message}\n`);
try {
appendFileSync(this.logPath, `${prefix}${message}\n`);
} catch {
// ignore
}
this.tsLogger?.msg(`[ts-lit-plugin] ${message}`, level === LitAnalyzerLoggerLevel.ERROR ? tsServer.server.Msg.Err : tsServer.server.Msg.Info);
}
}
Expand Down
31 changes: 31 additions & 0 deletions packages/vscode-lit-plugin/src/test/fixtures/completions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Pretending this is the Lit html function
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const html: any;

/** An element to test autocomplete with. */
class CompleteMe extends HTMLElement {
/** Docs for prop 1. */
prop1 = "";
/** Docs for prop 2. */
prop2 = "";
/** Docs for prop 3. */
prop3 = "";
}
customElements.define("complete-me", CompleteMe);
declare global {
interface HTMLElementTagNameMap {
"complete-me": CompleteMe;
}
}

// These lines are used as a basis for testing completions, with hardcoded
// line and character offsets in the test file. So if you change this file,
// you'll likely need to update those offsets in ../simple-test.ts
html`
<complete-me
></complete-me>
<com
`;

export {};
5 changes: 3 additions & 2 deletions packages/vscode-lit-plugin/src/test/scripts/test-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import { runTests } from "@vscode/test-electron";
async function main() {
try {
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, "../../../");
const extensionDevelopmentPath = path.resolve(__dirname, "..", "..", "..");
// The path to the extension test runner script
const extensionTestsPath = path.resolve(__dirname, "./mocha-driver");

const fixturesDir = path.join(__dirname, "..", "..", "..", "src", "test", "fixtures");
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath });
await runTests({ extensionDevelopmentPath, extensionTestsPath, launchArgs: [fixturesDir] });
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
Expand Down
47 changes: 47 additions & 0 deletions packages/vscode-lit-plugin/src/test/simple-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,51 @@ suite("Extension Test Suite", () => {
["'my-element' has not been registered on HTMLElementTagNameMap"]
);
});

test("We generate completions", async () => {
const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(path.join(__dirname, "../../src/test/fixtures/completions.ts")));
const editor = await vscode.window.showTextDocument(doc);

const tagCompletionPosition = new vscode.Position(27, 8);
const propertyCompletionPosition = new vscode.Position(25, 6);

editor.selection = new vscode.Selection(tagCompletionPosition, tagCompletionPosition);

async function getCompletions(expected: string) {
for (let i = 0; i < 100; i++) {
const completions = await vscode.commands.executeCommand<vscode.CompletionList>(
"vscode.executeCompletionItemProvider",
doc.uri,
editor.selection.active
);
if (completions && completions.items.length > 0) {
for (const completion of completions.items) {
if (completion.label === expected) {
return completions.items;
}
}
}
// Is there a better way to wait for the ts server to be ready?
// Maybe we can listen for the event that displays and hides the "initializing TS/JS language features" message?
await new Promise(resolve => setTimeout(resolve, 100));
}
throw new Error("No completions found");
}

const elemCompletions = await getCompletions("complete-me");
const elemLabels = elemCompletions.map(c => c.label);
assert.ok(elemLabels.includes("complete-me"), `Expected to find completion 'complete-me' in completions: ${JSON.stringify(elemLabels)}`);

editor.selection = new vscode.Selection(propertyCompletionPosition, propertyCompletionPosition);
// type a '.' character
await editor.edit(editBuilder => {
editBuilder.insert(editor.selection.active, ".");
});

const propCompletions = await getCompletions(".prop1");
const propLabels = propCompletions.map(c => c.label);
assert.ok(propLabels.includes(".prop1"), `Expected to find completion '.prop1' in completions: ${JSON.stringify(propLabels)}`);
assert.ok(propLabels.includes(".prop2"), `Expected to find completion '.prop2' in completions: ${JSON.stringify(propLabels)}`);
assert.ok(propLabels.includes(".prop3"), `Expected to find completion '.prop3' in completions: ${JSON.stringify(propLabels)}`);
});
});

0 comments on commit da309c1

Please sign in to comment.