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