add terminal editor and tab smoke tests (#137393)

* Add a bunch of tests

* tweak tests

* add profile tests, now breaking (no profiles showing up)

* uncomment tests

* update expected

* fix test

* merge

* all passing

* bunch of improvements

* improve readability

* all should be passing and cleaned up

* all passing

* fix #137243 and clean-up

* remove .only

* fix #137247

* get rid of enum

* see if this fixes timing issue

* use keybinding for show terminal instead

* remove delay, implement better accept function

* get rid of unneeded index

* try something else

* wait for empty editor to be active

* remove .only

* decrease redundancy in names

* re-add xterm selector

* try something else

* undo change that broke things worse

* add terminal-tabs test

* all tabs tests passing locally

* kill all

* await before running each

* fix tests

* remove .only

* try waiting for focused xterm

* remove .only

* clean up

* 🧹

* fix profiles tests by using this.app.props

* revert to use default shell

* re-add conditional

* Get tests passing on WebKit

On WebKit the smoke tests were failing because the quick pick was
triggering a focus event on the terminal after the blur event had
already happened, this caused the view service to think the terminal
was still focused when it wasn't. The fix was to reset the context key
also in IViewsService.closeView.

* Safari -> WebKit

* Prefer arrow functions

* remove beforeEach timeout

* add timeouts to contributed profile tests

* add terminal editor tests, fix #137377

* add a bunch of tests

* refactor

* get rid of profile specific command

* more polish

* refactor getTabs -> assertTerminalGroups

* fix failing test

* more polish

* remove .only

* add assertSingleTab

* remove unused import

* fix error

* fix more failures

* more changes

* fix almost all except for plus button

* fix failing plus button test

* all passing

* modify error that gets thrown

* modify error message again

* remove unused wildcard/ ANY_NAME, fix icon code

* fix icon code

* large refactor, improvements

* finish polish

* 1 failing

* get test to pass

Co-authored-by: Daniel Imms <2193314+Tyriar@users.noreply.github.com>
This commit is contained in:
Megan Rogge
2021-11-18 15:11:40 -08:00
committed by GitHub
parent 15f1721061
commit f66bc86da8
7 changed files with 246 additions and 148 deletions
@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ParsedArgs } from 'minimist';
import { Terminal, TerminalCommandId, TerminalCommandIdWithValue } from '../../../../automation/out';
import { afterSuite, beforeSuite } from '../../utils';
export function setup(opts: ParsedArgs) {
describe('Terminal Editors', () => {
let terminal: Terminal;
beforeSuite(opts);
afterSuite(opts);
before(function () {
terminal = this.app.workbench.terminal;
});
afterEach(async () => {
await terminal.runCommand(TerminalCommandId.KillAll);
});
it('should update color of the tab', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
const color = 'Cyan';
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeColor, color);
await terminal.assertSingleTab({ color }, true);
});
it('should update icon of the tab', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
const icon = 'symbol-method';
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeIcon, icon);
await terminal.assertSingleTab({ icon }, true);
});
it('should rename the tab', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
const name = 'my terminal name';
await terminal.runCommandWithValue(TerminalCommandIdWithValue.Rename, name);
await terminal.assertSingleTab({ name }, true);
});
it('should show the panel when the terminal is moved there and close the editor', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.runCommand(TerminalCommandId.MoveToPanel);
await terminal.assertSingleTab({});
});
it('should open a terminal in a new group for open to the side', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.runCommand(TerminalCommandId.SplitEditor);
await terminal.assertEditorGroupCount(2);
});
it('should open a terminal in a new group when the split button is pressed', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.clickSplitButton();
await terminal.assertEditorGroupCount(2);
});
it('should create new terminals in the active editor group via command', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.assertEditorGroupCount(1);
});
it('should create new terminals in the active editor group via plus button', async () => {
await terminal.runCommand(TerminalCommandId.CreateNewEditor);
await terminal.clickPlusButton();
await terminal.assertEditorGroupCount(1);
});
});
}
@@ -3,31 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ok } from 'assert';
import { ParsedArgs } from 'minimist';
import { Code, Terminal } from '../../../../automation';
import { Terminal, TerminalCommandId, TerminalCommandIdWithValue } from '../../../../automation';
import { afterSuite, beforeSuite } from '../../utils';
const ContributedProfileName = `JavaScript Debug Terminal`;
const CONTRIBUTED_PROFILE_NAME = `JavaScript Debug Terminal`;
const ANY_PROFILE_NAME = '^((?!JavaScript Debug Terminal).)*$';
export function setup(opts: ParsedArgs) {
describe('Terminal Profiles', () => {
let code: Code;
let terminal: Terminal;
const enum TerminalCommandId {
Split = 'workbench.action.terminal.split',
KillAll = 'workbench.action.terminal.killAll',
Show = 'workbench.action.terminal.toggleTerminal',
CreateNew = 'workbench.action.terminal.new',
NewWithProfile = 'workbench.action.terminal.newWithProfile',
SelectDefaultProfile = 'workbench.action.terminal.selectDefaultShell'
}
beforeSuite(opts);
afterSuite(opts);
before(function () {
code = this.app.code;
terminal = this.app.workbench.terminal;
});
@@ -37,73 +27,56 @@ export function setup(opts: ParsedArgs) {
it('should launch the default profile', async () => {
await terminal.runCommand(TerminalCommandId.Show);
// TODO: Use getSingleTabLabel? Share logic with getTabLabel?
await code.waitForElement('.single-terminal-tab', e => e ? !e.textContent.endsWith(ContributedProfileName) : false);
await terminal.assertSingleTab({ name: ANY_PROFILE_NAME });
});
it.skip('should set the default profile to a contributed one', async () => {
await terminal.runProfileCommand(TerminalCommandId.SelectDefaultProfile, true);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SelectDefaultProfile, CONTRIBUTED_PROFILE_NAME);
await terminal.runCommand(TerminalCommandId.CreateNew);
await code.waitForElement('.single-terminal-tab', e => e ? e.textContent.endsWith(ContributedProfileName) : false);
await terminal.assertSingleTab({ name: CONTRIBUTED_PROFILE_NAME });
});
it.skip('should use the default contributed profile on panel open and for splitting', async () => {
await terminal.runProfileCommand(TerminalCommandId.SelectDefaultProfile, true);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SelectDefaultProfile, CONTRIBUTED_PROFILE_NAME);
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Split);
const tabs = await terminal.getTabLabels(2);
console.log('DEBUG: tabs', tabs);
ok(tabs[0].startsWith('┌') && tabs[0].endsWith(ContributedProfileName));
ok(tabs[1].startsWith('└') && tabs[1].endsWith(ContributedProfileName));
await terminal.assertTerminalGroups([[{ name: CONTRIBUTED_PROFILE_NAME }, { name: CONTRIBUTED_PROFILE_NAME }]]);
});
it('should set the default profile', async () => {
await terminal.runProfileCommand(TerminalCommandId.SelectDefaultProfile, undefined);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.SelectDefaultProfile);
await terminal.runCommand(TerminalCommandId.CreateNew);
await code.waitForElement('.single-terminal-tab', e => e ? !e.textContent.endsWith(ContributedProfileName) : false);
await terminal.assertSingleTab({ name: ANY_PROFILE_NAME });
});
it('should use the default profile on panel open and for splitting', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await code.waitForElement('.single-terminal-tab', e => e ? !e.textContent.endsWith(ContributedProfileName) : false);
await terminal.assertSingleTab({ name: ANY_PROFILE_NAME });
await terminal.runCommand(TerminalCommandId.Split);
const tabs = await terminal.getTabLabels(2, true);
ok(tabs[0].startsWith('┌') && !tabs[0].endsWith(ContributedProfileName));
ok(tabs[1].startsWith('└') && !tabs[1].endsWith(ContributedProfileName));
});
it('clicking the plus button should create a terminal and display the tabs view showing no split decorations', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await code.waitAndClick('li.action-item.monaco-dropdown-with-primary > div.action-container.menu-entry > a');
const tabLabels = await terminal.getTabLabels(2);
ok(!tabLabels[0].startsWith('┌') && !tabLabels[1].startsWith('└'));
await terminal.assertTerminalGroups([[{}, {}]]);
});
it('createWithProfile command should create a terminal with a profile', async () => {
await terminal.runProfileCommand(TerminalCommandId.NewWithProfile);
await code.waitForElement('.single-terminal-tab', e => e ? !e.textContent.endsWith(ContributedProfileName) : false);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile);
await terminal.assertSingleTab({ name: ANY_PROFILE_NAME });
});
it.skip('createWithProfile command should create a terminal with a contributed profile', async () => {
await terminal.runProfileCommand(TerminalCommandId.NewWithProfile, true);
await code.waitForElement('.single-terminal-tab', e => e ? e.textContent.endsWith(ContributedProfileName) : false);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, CONTRIBUTED_PROFILE_NAME);
await terminal.assertSingleTab({ name: CONTRIBUTED_PROFILE_NAME });
});
it('createWithProfile command should create a split terminal with a profile', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runProfileCommand(TerminalCommandId.NewWithProfile, undefined, true);
const tabs = await terminal.getTabLabels(2, true);
ok(tabs[0].startsWith('┌') && !tabs[0].endsWith(ContributedProfileName));
ok(tabs[1].startsWith('└') && !tabs[1].endsWith(ContributedProfileName));
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, undefined, true);
await terminal.assertTerminalGroups([[{}, {}]]);
});
it.skip('createWithProfile command should create a split terminal with a contributed profile', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await code.waitForElement('.single-terminal-tab', e => e ? !e.textContent.endsWith(ContributedProfileName) : false);
await terminal.runProfileCommand(TerminalCommandId.NewWithProfile, true, true);
const tabs = await terminal.getTabLabels(2, true);
ok(tabs[0].startsWith('┌') && !tabs[0].endsWith(ContributedProfileName));
ok(tabs[1].startsWith('└') && tabs[1].endsWith(ContributedProfileName));
await terminal.assertSingleTab({});
await terminal.runCommandWithValue(TerminalCommandIdWithValue.NewWithProfile, CONTRIBUTED_PROFILE_NAME, true);
await terminal.assertTerminalGroups([[{ name: ANY_PROFILE_NAME }, { name: CONTRIBUTED_PROFILE_NAME }]]);
});
});
}
@@ -3,35 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ok } from 'assert';
import { ParsedArgs } from 'minimist';
import { Code, Terminal } from '../../../../automation/out';
import { Terminal, TerminalCommandId, TerminalCommandIdWithValue } from '../../../../automation/out';
import { afterSuite, beforeSuite } from '../../utils';
export function setup(opts: ParsedArgs) {
// TODO: Re-enable when stable
describe.skip('Terminal Tabs', () => {
let code: Code;
describe('Terminal Tabs', () => {
let terminal: Terminal;
// TODO: Move into automation/terminal
const enum TerminalCommandId {
Rename = 'workbench.action.terminal.rename',
ChangeColor = 'workbench.action.terminal.changeColor',
ChangeIcon = 'workbench.action.terminal.changeIcon',
Split = 'workbench.action.terminal.split',
KillAll = 'workbench.action.terminal.killAll',
Unsplit = 'workbench.action.terminal.unsplit',
Join = 'workbench.action.terminal.join',
Show = 'workbench.action.terminal.toggleTerminal',
CreateNew = 'workbench.action.terminal.new'
}
beforeSuite(opts);
afterSuite(opts);
before(function () {
code = this.app.code;
terminal = this.app.workbench.terminal;
});
@@ -41,99 +25,99 @@ export function setup(opts: ParsedArgs) {
it('clicking the plus button should create a terminal and display the tabs view showing no split decorations', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await code.waitAndClick('li.action-item.monaco-dropdown-with-primary > div.action-container.menu-entry > a');
const tabLabels = await terminal.getTabLabels(2);
ok(!tabLabels[0].startsWith('┌') && !tabLabels[1].startsWith('└'));
await terminal.runCommand(TerminalCommandId.CreateNew);
await terminal.clickPlusButton();
await terminal.assertTerminalGroups([[{}], [{}]]);
});
it('should update color of the single tab', async () => {
await terminal.runCommand(TerminalCommandId.Show);
const color = 'Cyan';
await terminal.runCommand(TerminalCommandId.ChangeColor, color);
const singleTab = await code.waitForElement('.single-terminal-tab');
ok(singleTab.className.includes(`terminal-icon-terminal_ansi${color}`));
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeColor, color);
await terminal.assertSingleTab({ color });
});
it('should update color of the tab in the tabs list', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Split);
const tabs = await terminal.getTabLabels(2);
ok(tabs[0].startsWith('┌'));
ok(tabs[1].startsWith('└'));
const color = 'Cyan';
await terminal.runCommand(TerminalCommandId.ChangeColor, color);
await code.waitForElement(`.terminal-tabs-entry .terminal-icon-terminal_ansi${color}`);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeColor, color);
await terminal.assertTerminalGroups([[{}, { color }]]);
});
it('should update icon of the single tab', async () => {
await terminal.runCommand(TerminalCommandId.Show);
const icon = 'symbol-method';
await terminal.runCommand(TerminalCommandId.ChangeIcon, icon);
await code.waitForElement(`.single-terminal-tab .codicon-${icon}`);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeIcon, icon);
await terminal.assertSingleTab({ icon });
});
it('should update icon of the tab in the tabs list', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Split);
const tabs = await terminal.getTabLabels(2);
ok(tabs[0].startsWith('┌'));
ok(tabs[1].startsWith('└'));
const icon = 'symbol-method';
await terminal.runCommand(TerminalCommandId.ChangeIcon, icon);
await code.waitForElement(`.terminal-tabs-entry .codicon-${icon}`);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.ChangeIcon, icon);
await terminal.assertTerminalGroups([[{}, { icon }]]);
});
it('should rename the single tab', async () => {
await terminal.runCommand(TerminalCommandId.Show);
const name = 'my terminal name';
await terminal.runCommand(TerminalCommandId.Rename, name);
await code.waitForElement('.single-terminal-tab', e => e ? e?.textContent.includes(name) : false);
await terminal.runCommandWithValue(TerminalCommandIdWithValue.Rename, name);
await terminal.assertSingleTab({ name });
});
it('should rename the tab in the tabs list', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Split);
const name = 'my terminal name';
await terminal.runCommand(TerminalCommandId.Rename, name);
await terminal.getTabLabels(2, true, t => t.some(element => element.textContent.includes(name)));
await terminal.runCommandWithValue(TerminalCommandIdWithValue.Rename, name);
await terminal.assertTerminalGroups([[{}, { name }]]);
});
it('should create a split terminal when single tab is alt clicked', async () => {
await terminal.runCommand(TerminalCommandId.Show);
const page = await terminal.getPage();
page.keyboard.down('Alt');
await code.waitAndClick('.single-terminal-tab');
await terminal.clickSingleTab();
page.keyboard.up('Alt');
await terminal.getTabLabels(2, true);
await terminal.assertTerminalGroups([[{}, {}]]);
});
it('should do nothing when join tabs is run with only one terminal', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Join);
await code.waitForElement('.single-terminal-tab');
await terminal.assertSingleTab({});
});
it('should join tabs when more than one terminal', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.CreateNew);
await terminal.runCommand(TerminalCommandId.Join);
await terminal.getTabLabels(2, true);
await terminal.assertTerminalGroups([[{}, {}]]);
});
it('should do nothing when unsplit tabs called with no splits', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.CreateNew);
await terminal.getTabLabels(2, false);
await terminal.assertTerminalGroups([[{}], [{}]]);
await terminal.runCommand(TerminalCommandId.Unsplit);
await terminal.getTabLabels(2, false);
await terminal.assertTerminalGroups([[{}], [{}]]);
});
it('should unsplit tabs', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.runCommand(TerminalCommandId.Split);
await terminal.getTabLabels(2, true);
await terminal.assertTerminalGroups([[{}, {}]]);
await terminal.runCommand(TerminalCommandId.Unsplit);
await terminal.getTabLabels(2, false, t => t.every(label => !label.textContent.startsWith('┌') && !label.textContent.startsWith('└')));
await terminal.assertTerminalGroups([[{}], [{}]]);
});
it('should move the terminal to the editor area', async () => {
await terminal.runCommand(TerminalCommandId.Show);
await terminal.assertSingleTab({});
await terminal.runCommand(TerminalCommandId.MoveToEditor);
await terminal.assertEditorGroupCount(1);
});
});
}
+2
View File
@@ -29,6 +29,7 @@ import { setup as setupLocalizationTests } from './areas/workbench/localization.
import { setup as setupLaunchTests } from './areas/workbench/launch.test';
import { setup as setupTerminalProfileTests } from './areas/terminal/terminal-profiles.test';
import { setup as setupTerminalTabsTests } from './areas/terminal/terminal-tabs.test';
import { setup as setupTerminalEditorsTests } from './areas/terminal/terminal-editors.test';
const testDataPath = path.join(os.tmpdir(), 'vscsmoke');
if (fs.existsSync(testDataPath)) {
@@ -362,4 +363,5 @@ describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => {
// TODO: Enable terminal tests for non-web
if (opts.web) { setupTerminalProfileTests(opts); }
if (opts.web) { setupTerminalTabsTests(opts); }
if (opts.web) { setupTerminalEditorsTests(opts); }
});