Skip to content

Commit e6f8786

Browse files
committed
Move node-pty tests
1 parent 3685e65 commit e6f8786

2 files changed

Lines changed: 100 additions & 0 deletions

File tree

packages/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"moduleNameMapper": {
2525
"^.+\\.(s?css|png|svg)$": "<rootDir>/../scripts/dummy.js",
2626
"@coder/ide/src/fill/evaluation": "<rootDir>/ide/src/fill/evaluation",
27+
"@coder/ide/src/fill/client": "<rootDir>/ide/src/fill/client",
2728
"@coder/(.*)/test": "<rootDir>/$1/test",
2829
"@coder/(.*)": "<rootDir>/$1/src"
2930
},
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { IPty } from "node-pty";
2+
import { createClient } from "@coder/protocol/test";
3+
4+
const client = createClient();
5+
jest.mock("../../ide/src/fill/client", () => ({ client }));
6+
const pty = require("../src/fill/node-pty") as typeof import("node-pty");
7+
8+
describe("node-pty", () => {
9+
/**
10+
* Returns a function that when called returns a promise that resolves with
11+
* the next chunk of data from the process.
12+
*/
13+
const promisifyData = (proc: IPty): (() => Promise<string>) => {
14+
// Use a persistent callback instead of creating it in the promise since
15+
// otherwise we could lose data that comes in while no promise is listening.
16+
let onData: (() => void) | undefined;
17+
let buffer: string | undefined;
18+
proc.on("data", (data) => {
19+
// Remove everything that isn't a letter, number, or $ to avoid issues
20+
// with ANSI escape codes printing inside the test output.
21+
buffer = (buffer || "") + data.toString().replace(/[^a-zA-Z0-9$]/g, "");
22+
if (onData) {
23+
onData();
24+
}
25+
});
26+
27+
return (): Promise<string> => new Promise((resolve): void => {
28+
onData = (): void => {
29+
if (typeof buffer !== "undefined") {
30+
const data = buffer;
31+
buffer = undefined;
32+
onData = undefined;
33+
resolve(data);
34+
}
35+
};
36+
onData();
37+
});
38+
};
39+
40+
it("should create shell", async () => {
41+
// Setting the config file to something that shouldn't exist so the test
42+
// isn't affected by custom configuration.
43+
const proc = pty.spawn("/bin/bash", ["--rcfile", "/tmp/test/nope/should/not/exist"], {
44+
cols: 100,
45+
rows: 10,
46+
});
47+
48+
const getData = promisifyData(proc);
49+
50+
// First it outputs @hostname:cwd
51+
expect((await getData()).length).toBeGreaterThan(1);
52+
53+
// Then it seems to overwrite that with a shorter prompt in the format of
54+
// [hostname@user]$
55+
expect((await getData())).toContain("$");
56+
57+
proc.kill();
58+
59+
await new Promise((resolve): void => {
60+
proc.on("exit", resolve);
61+
});
62+
});
63+
64+
it("should resize", async () => {
65+
// Requires the `tput lines` cmd to be available.
66+
// Setting the config file to something that shouldn't exist so the test
67+
// isn't affected by custom configuration.
68+
const proc = pty.spawn("/bin/bash", ["--rcfile", "/tmp/test/nope/should/not/exist"], {
69+
cols: 10,
70+
rows: 10,
71+
});
72+
73+
const getData = promisifyData(proc);
74+
75+
// We've already tested these first two bits of output; see shell test.
76+
await getData();
77+
await getData();
78+
79+
proc.write("tput lines\n");
80+
expect(await getData()).toContain("tput");
81+
82+
expect((await getData()).trim()).toContain("10");
83+
proc.resize(10, 50);
84+
85+
// The prompt again.
86+
await getData();
87+
await getData();
88+
89+
proc.write("tput lines\n");
90+
expect(await getData()).toContain("tput");
91+
92+
expect((await getData())).toContain("50");
93+
94+
proc.kill();
95+
await new Promise((resolve): void => {
96+
proc.on("exit", resolve);
97+
});
98+
});
99+
});

0 commit comments

Comments
 (0)