Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/smoke/src/areas/terminal/terminal-shellIntegration.test.ts
3520 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Application, Terminal, SettingsEditor, TerminalCommandIdWithValue, TerminalCommandId } from '../../../../automation';
7
import { setTerminalTestSettings } from './terminal-helpers';
8
9
export function setup(options?: { skipSuite: boolean }) {
10
(options?.skipSuite ? describe.skip : describe)('Terminal Shell Integration', () => {
11
let terminal: Terminal;
12
let settingsEditor: SettingsEditor;
13
let app: Application;
14
// Acquire automation API
15
before(async function () {
16
app = this.app as Application;
17
terminal = app.workbench.terminal;
18
settingsEditor = app.workbench.settingsEditor;
19
});
20
21
afterEach(async function () {
22
await app.workbench.terminal.runCommand(TerminalCommandId.KillAll);
23
});
24
25
async function createShellIntegrationProfile() {
26
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, process.platform === 'win32' ? 'PowerShell' : 'bash');
27
}
28
29
// TODO: Some agents may not have pwsh installed?
30
(process.platform === 'win32' ? describe.skip : describe)(`Process-based tests`, function () {
31
before(async function () {
32
await setTerminalTestSettings(app, [['terminal.integrated.shellIntegration.enabled', 'true']]);
33
});
34
after(async function () {
35
await settingsEditor.clearUserSettings();
36
});
37
describe('Decorations', function () {
38
describe('Should show default icons', function () {
39
it('Placeholder', async () => {
40
await createShellIntegrationProfile();
41
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
42
});
43
it('Success', async () => {
44
await createShellIntegrationProfile();
45
await terminal.runCommandInTerminal(`echo "success"`);
46
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
47
});
48
it('Error', async () => {
49
await createShellIntegrationProfile();
50
await terminal.runCommandInTerminal(`false`);
51
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 1 });
52
});
53
});
54
describe('terminal.integrated.shellIntegration.decorationsEnabled should determine gutter and overview ruler decoration visibility', function () {
55
beforeEach(async () => {
56
await settingsEditor.clearUserSettings();
57
await setTerminalTestSettings(app, [['terminal.integrated.shellIntegration.enabled', 'true']]);
58
await createShellIntegrationProfile();
59
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
60
await terminal.runCommandInTerminal(`echo "foo"`);
61
await terminal.runCommandInTerminal(`bar`);
62
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
63
});
64
afterEach(async () => {
65
await app.workbench.terminal.runCommand(TerminalCommandId.KillAll);
66
});
67
it('never', async () => {
68
await settingsEditor.addUserSetting('terminal.integrated.shellIntegration.decorationsEnabled', '"never"');
69
await terminal.assertCommandDecorations({ placeholder: 0, success: 0, error: 0 }, undefined, 'never');
70
});
71
it('both', async () => {
72
await settingsEditor.addUserSetting('terminal.integrated.shellIntegration.decorationsEnabled', '"both"');
73
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 }, undefined, 'both');
74
});
75
it('gutter', async () => {
76
await settingsEditor.addUserSetting('terminal.integrated.shellIntegration.decorationsEnabled', '"gutter"');
77
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 }, undefined, 'gutter');
78
});
79
it('overviewRuler', async () => {
80
await settingsEditor.addUserSetting('terminal.integrated.shellIntegration.decorationsEnabled', '"overviewRuler"');
81
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 }, undefined, 'overviewRuler');
82
});
83
});
84
});
85
});
86
87
// These are integration tests that only test the UI side by simulating process writes.
88
// Because of this, they do not test the shell integration scripts, only what the scripts
89
// are expected to write.
90
describe('Write data-based tests', () => {
91
before(async function () {
92
await setTerminalTestSettings(app);
93
});
94
after(async function () {
95
await settingsEditor.clearUserSettings();
96
});
97
98
// Don't use beforeEach as that ignores the retry count, createEmptyTerminal has been
99
// flaky in the past
100
async function beforeEachSetup() {
101
// Use the simplest profile to get as little process interaction as possible
102
await terminal.createEmptyTerminal();
103
// Erase all content and reset cursor to top
104
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${csi('2J')}${csi('H')}`);
105
}
106
107
describe('VS Code sequences', () => {
108
it('should handle the simple case', async () => {
109
await beforeEachSetup();
110
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 0`);
111
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
112
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Success\\r\\n${vsc('D;0')}`);
113
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
114
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}exitcode 1`);
115
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
116
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${vsc('C')}Failure\\r\\n${vsc('D;1')}`);
117
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
118
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${vsc('A')}Prompt> ${vsc('B')}`);
119
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
120
});
121
});
122
describe('Final Term sequences', () => {
123
it('should handle the simple case', async () => {
124
await beforeEachSetup();
125
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 0`);
126
await terminal.assertCommandDecorations({ placeholder: 1, success: 0, error: 0 });
127
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Success\\r\\n${ft('D;0')}`);
128
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 0 });
129
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
130
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 0 });
131
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `\\r\\n${ft('C')}Failure\\r\\n${ft('D;1')}`);
132
await terminal.assertCommandDecorations({ placeholder: 0, success: 1, error: 1 });
133
await terminal.runCommandWithValue(TerminalCommandIdWithValue.WriteDataToTerminal, `${ft('A')}Prompt> ${ft('B')}exitcode 1`);
134
await terminal.assertCommandDecorations({ placeholder: 1, success: 1, error: 1 });
135
});
136
});
137
});
138
});
139
}
140
141
function ft(data: string) {
142
return setTextParams(`133;${data}`);
143
}
144
145
function vsc(data: string) {
146
return setTextParams(`633;${data}`);
147
}
148
149
function setTextParams(data: string) {
150
return osc(`${data}\\x07`);
151
}
152
153
function osc(data: string) {
154
return `\\x1b]${data}`;
155
}
156
157
function csi(data: string) {
158
return `\\x1b[${data}`;
159
}
160
161