ci: add detailed e2e tests & prebuilt node-pty (#188)

* ci: add detailed e2e tests

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* fix: e2e test command

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* ci: add link cmd to provide is command

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* build: drop node-pty for node-pty prebuilds

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* fix: ci issues / zsh config

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* ci: drop .only for testing

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* ci: add back other vms

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* fix: add cursor detection

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* test: add under test flag to status tests

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

* fix: use set shell for status check

Signed-off-by: Chapman Pendery <cpendery@vt.edu>

---------

Signed-off-by: Chapman Pendery <cpendery@vt.edu>
This commit is contained in:
Chapman Pendery
2024-03-06 10:10:51 -08:00
committed by GitHub
parent b1777aa909
commit b5075417dc
9 changed files with 1873 additions and 231 deletions
+32 -5
View File
@@ -9,26 +9,53 @@ jobs:
build:
strategy:
matrix:
os: ["windows-latest", "ubuntu-latest"]
version: [16, 18, 20]
os: ["macos-latest", "windows-latest", "ubuntu-latest"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Use Node.js 18.x
- name: Use Node.js ${{ matrix.version }}.x
uses: actions/setup-node@v3
with:
node-version: 18.x
node-version: ${{ matrix.version }}
- run: npm ci
- run: npm run lint
- name: setup zsh-autosuggestions
if: matrix.os != 'windows-latest'
- name: setup macOS shells
if: matrix.os == 'macos-latest'
shell: bash
run: |
brew install fish
brew install zsh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
echo "source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh" > ~/.zshrc
sudo chmod g-w /usr/local/share/zsh /usr/local/share/zsh/site-functions /usr/share/zsh
- name: setup linux shells
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt install fish zsh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
echo "source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh" > ~/.zshrc
sudo chmod -R 755 /usr/share/zsh/vendor-completions
sudo chown -R root:root /usr/share/zsh/vendor-completions
sudo chmod -R 755 /usr/share/zsh
sudo chown -R root:root /usr/share/zsh
- run: npm test
- run: npm run build
- run: npm link
- run: npm run test:e2e
+2 -1
View File
@@ -1,3 +1,4 @@
node_modules/
build/
t*.md
t*.md
.tui-test/
+1609 -221
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -4,7 +4,7 @@
"description": "IDE style command line auto complete",
"type": "module",
"engines": {
"node" : ">=16.6.0 <21.0.0"
"node": ">=16.6.0 <21.0.0"
},
"bin": {
"inshellisense": "./build/index.js",
@@ -20,6 +20,7 @@
"build": "tsc",
"dev": "node --loader ts-node/esm src/index.ts -V",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:e2e": "tui-test",
"lint": "eslint src/ --ext .ts,.tsx && prettier src/ --check",
"lint:fix": "eslint src/ --ext .ts,.tsx --fix && prettier src/ --write",
"debug": "node --inspect --loader ts-node/esm src/index.ts -V",
@@ -38,6 +39,8 @@
},
"homepage": "https://github.com/microsoft/inshellisense#readme",
"dependencies": {
"@homebridge/node-pty-prebuilt-multiarch": "^0.11.12",
"@microsoft/tui-test": "^0.0.1-rc.3",
"@withfig/autocomplete": "2.651.0",
"ajv": "^8.12.0",
"ansi-escapes": "^6.2.0",
@@ -45,7 +48,6 @@
"chalk": "^5.3.0",
"commander": "^11.0.0",
"find-process": "^1.4.7",
"node-pty": "^1.0.0",
"which": "^4.0.0",
"wrap-ansi": "^8.1.0",
"xterm-headless": "^5.3.0"
+1 -1
View File
@@ -44,7 +44,7 @@ __is_update_prompt() {
if [[ $ISTERM_TESTING == "1" ]]; then
__is_prior_prompt="> "
fi
PS1="%{$(__is_prompt_start)%}$PS1%{$(__is_prompt_end)%}"
PS1="%{$(__is_prompt_start)%}$__is_prior_prompt%{$(__is_prompt_end)%}"
}
__is_precmd() {
+7 -1
View File
@@ -7,7 +7,7 @@ import os from "node:os";
import path from "node:path";
import url from "node:url";
import pty, { IPty, IEvent } from "node-pty";
import pty, { IPty, IEvent } from "@homebridge/node-pty-prebuilt-multiarch";
import { Shell, userZdotdir, zdotdir } from "../utils/shell.js";
import { IsTermOscPs, IstermOscPt, IstermPromptStart, IstermPromptEnd } from "../utils/ansi.js";
import xterm from "xterm-headless";
@@ -80,6 +80,12 @@ export class ISTerm implements IPty {
};
this.onExit = this.#pty.onExit;
}
on(event: "data", listener: (data: string) => void): void;
on(event: "exit", listener: (exitCode: number, signal?: number | undefined) => void): void;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
on(_event: unknown, _listener: unknown): void {
throw new Error("Method not implemented as deprecated in node-pty.");
}
private _deserializeIsMessage(message: string): string {
return message.replaceAll(/\\(\\|x([0-9a-f]{2}))/gi, (_match: string, op: string, hex?: string) => (hex ? String.fromCharCode(parseInt(hex, 16)) : op));
+179
View File
@@ -0,0 +1,179 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { test, expect, Shell } from "@microsoft/tui-test";
import os from "node:os";
const windowsShells = [Shell.Cmd, Shell.Powershell, Shell.WindowsPowershell];
const unixShells = [Shell.Bash, Shell.Fish, Shell.Zsh];
const shells = os.platform() == "win32" ? windowsShells : unixShells;
shells.map((activeShell) => {
test.describe(`[${activeShell}]`, () => {
test.use({ program: { file: "is", args: ["-V", "-T", "-s", activeShell] } });
test("basic git suggestions", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("blame")).toBeVisible();
await expect(terminal.getByText("archive", { strict: false })).toHaveBgColor("7d56f4");
});
test("cursor up when at top of list", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toHaveBgColor("7d56f4");
terminal.keyUp();
await expect(terminal.getByText("archive", { strict: false })).toHaveBgColor("7d56f4");
});
test("move cursor backwards to hide suggestions", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.keyLeft();
await expect(terminal.getByText("archive", { strict: false })).not.toBeVisible();
});
test("cursor down when at top of list", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.keyDown(2);
await expect(terminal.getByText("repository")).toBeVisible();
await expect(terminal.getByText("commit")).toHaveBgColor("7d56f4");
await expect(terminal.getByText("archive", { strict: false })).not.toHaveBgColor("7d56f4");
});
test("scroll down a full page when at top of list", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.keyDown(5);
await expect(terminal.getByText("archive", { strict: false })).not.toBeVisible();
await expect(terminal.getByText("add")).toHaveBgColor("7d56f4");
});
// excluding cmd since it doesn't support CWD tracking
test.when(activeShell !== Shell.Cmd, "generator results lead suggestions", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("ls ");
await expect(terminal.getByText("📀", { strict: false })).toBeVisible();
});
test("tab completion", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.write("\t");
await expect(terminal.getByText("--format")).toBeVisible();
});
test("backspacing after accepting tab completion", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.write("\t");
await expect(terminal.getByText("--format")).toBeVisible();
terminal.keyBackspace(3);
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
});
test("suggestion cursor resets between views", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.keyDown(2);
await expect(terminal.getByText("repository")).toBeVisible();
await expect(terminal.getByText("commit")).toHaveBgColor("7d56f4");
terminal.keyBackspace(1);
await expect(terminal.getByText("repository")).not.toBeVisible();
terminal.write(" ");
await expect(terminal.getByText("archive", { strict: false })).toHaveBgColor("7d56f4");
});
test("ui on bottom of the screen", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.resize(80, 10);
terminal.write("\r".repeat(10));
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
});
test("command detection after command execution", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write(`echo "hello"\r`);
await expect(terminal.getByText("hello", { strict: false })).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
});
test("command detection after command execution", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write(`echo "hello"\r`);
await expect(terminal.getByText("hello", { strict: false })).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
});
test("suggestions clear after command execution", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("git ");
await expect(terminal.getByText("archive", { strict: false })).toBeVisible();
terminal.write("\r");
await expect(terminal.getByText("archive", { strict: false })).not.toBeVisible();
});
test("access history when no suggestions exist", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("clear");
await expect(terminal.getByText("clear")).toBeVisible();
terminal.write("\r");
await expect(terminal.getByText("clear")).not.toBeVisible();
terminal.keyUp();
await expect(terminal.getByText("clear")).toBeVisible();
});
test.when([Shell.Zsh, Shell.Powershell].includes(activeShell), "command detection with suggestions", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write(`dotnet add item\r`);
await expect(terminal.getByText("dotnet", { strict: false })).toBeVisible();
terminal.write("clear\r");
await expect(terminal.getByText("dotnet", { strict: false })).not.toBeVisible();
terminal.write("dotnet add ");
await expect(terminal.getByText("item")).toBeVisible();
await expect(terminal.getByText("package", { strict: false })).toBeVisible();
});
});
});
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { test, expect, Shell } from "@microsoft/tui-test";
import os from "node:os";
const shell = os.platform() == "darwin" ? Shell.Zsh : os.platform() == "linux" ? Shell.Bash : Shell.Powershell;
test.describe("status checks", () => {
test.describe("inside inshellisense session", () => {
test.use({ program: { file: "is", args: ["-T", "-s", shell] } });
test("current status", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("is -c\r");
await expect(terminal.getByText("live")).toBeVisible();
await expect(terminal.getByText("live")).toHaveFgColor(2);
});
});
test.describe("outside inshellisense session", () => {
test("current status", async ({ terminal }) => {
await expect(terminal.getByText("> ")).toBeVisible();
terminal.write("is -c\r");
await expect(terminal.getByText("not found")).toBeVisible();
await expect(terminal.getByText("not found")).toHaveFgColor(1);
});
});
});
+8
View File
@@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { defineConfig } from "@microsoft/tui-test";
export default defineConfig({
testMatch: "src/tests/ui/**/*.@(spec|test).?(c|m)[jt]s?(x)",
retries: 3,
});