testing: allow toggling test output visibility
Also, just show outputs for the last test run.
This commit is contained in:
parent
76cbce4663
commit
4b80b4cd36
5 changed files with 100 additions and 44 deletions
|
@ -9,6 +9,7 @@ suite('Arrays', () => {
|
|||
test('findFirst', () => {
|
||||
const array = [1, 4, 5, 7, 55, 59, 60, 61, 64, 69];
|
||||
|
||||
console.log('hello');
|
||||
let idx = arrays.findFirstInSorted(array, e => e >= 0);
|
||||
assert.strictEqual(array[idx], 1);
|
||||
|
||||
|
@ -20,6 +21,7 @@ suite('Arrays', () => {
|
|||
|
||||
idx = arrays.findFirstInSorted(array, e => e >= 61);
|
||||
assert.strictEqual(array[idx], 61);
|
||||
console.log('world');
|
||||
|
||||
idx = arrays.findFirstInSorted(array, e => e >= 69);
|
||||
assert.strictEqual(array[idx], 69);
|
||||
|
@ -28,7 +30,7 @@ suite('Arrays', () => {
|
|||
assert.strictEqual(idx, array.length);
|
||||
|
||||
idx = arrays.findFirstInSorted([], e => e >= 0);
|
||||
assert.strictEqual(array[idx], 1);
|
||||
assert.strictEqual(array[idx], 3);
|
||||
});
|
||||
|
||||
test('quickSelect', () => {
|
||||
|
|
|
@ -1103,6 +1103,30 @@ export class OpenOutputPeek extends Action2 {
|
|||
}
|
||||
}
|
||||
|
||||
export class ToggleInlineTestOutput extends Action2 {
|
||||
public static readonly ID = 'testing.toggleInlineTestOutput';
|
||||
constructor() {
|
||||
super({
|
||||
id: ToggleInlineTestOutput.ID,
|
||||
title: localize('testing.toggleInlineTestOutput', "Toggle Inline Test Output"),
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_I),
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: TestingContextKeys.hasAnyResults.isEqualTo(true),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public async run(accessor: ServicesAccessor) {
|
||||
const testService = accessor.get(ITestService);
|
||||
testService.showInlineOutput.value = !testService.showInlineOutput.value;
|
||||
}
|
||||
}
|
||||
|
||||
export const allTestActions = [
|
||||
// todo: these are disabled until we figure out how we want autorun to work
|
||||
// AutoRunOffAction,
|
||||
|
@ -1136,5 +1160,6 @@ export const allTestActions = [
|
|||
TestingSortByStatusAction,
|
||||
TestingViewAsListAction,
|
||||
TestingViewAsTreeAction,
|
||||
ToggleInlineTestOutput,
|
||||
UnhideTestAction,
|
||||
];
|
||||
|
|
|
@ -38,6 +38,7 @@ import { IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMe
|
|||
import { isFailedState, maxPriority } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri';
|
||||
import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService';
|
||||
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { getContextForTestItem, ITestService, testsInFile } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
||||
|
@ -126,17 +127,12 @@ export class TestingDecorations extends Disposable implements IEditorContributio
|
|||
}
|
||||
}));
|
||||
|
||||
this._register(Event.any(this.results.onResultsChanged, this.testService.excluded.onTestExclusionsChanged)(() => {
|
||||
if (this.currentUri) {
|
||||
this.setDecorations(this.currentUri);
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.testService.onDidProcessDiff(() => {
|
||||
if (this.currentUri) {
|
||||
this.setDecorations(this.currentUri);
|
||||
}
|
||||
}));
|
||||
this._register(Event.any(
|
||||
this.results.onResultsChanged,
|
||||
this.testService.excluded.onTestExclusionsChanged,
|
||||
this.testService.showInlineOutput.onDidChange,
|
||||
this.testService.onDidProcessDiff,
|
||||
)(() => this.setDecorations(this.currentUri)));
|
||||
}
|
||||
|
||||
private attachModel(uri?: URI) {
|
||||
|
@ -165,45 +161,56 @@ export class TestingDecorations extends Disposable implements IEditorContributio
|
|||
this.setDecorations(uri);
|
||||
}
|
||||
|
||||
private setDecorations(uri: URI): void {
|
||||
private setDecorations(uri: URI | undefined): void {
|
||||
if (!uri) {
|
||||
this.clearDecorations();
|
||||
return;
|
||||
}
|
||||
|
||||
this.editor.changeDecorations(accessor => {
|
||||
const newDecorations: ITestDecoration[] = [];
|
||||
for (const test of this.testService.collection.all) {
|
||||
const stateLookup = this.results.getStateById(test.item.extId);
|
||||
if (test.item.range && test.item.uri?.toString() === uri.toString()) {
|
||||
const line = test.item.range.startLineNumber;
|
||||
const resultItem = stateLookup?.[1];
|
||||
const existing = newDecorations.findIndex(d => d instanceof RunTestDecoration && d.line === line);
|
||||
if (existing !== -1) {
|
||||
newDecorations[existing] = (newDecorations[existing] as RunTestDecoration).merge(test, resultItem);
|
||||
} else {
|
||||
newDecorations.push(this.instantiationService.createInstance(RunSingleTestDecoration, test, this.editor, stateLookup?.[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateLookup) {
|
||||
if (!test.item.range || test.item.uri?.toString() !== uri.toString()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const [result, stateItem] = stateLookup;
|
||||
if (stateItem.retired) {
|
||||
continue; // do not show decorations for outdated tests
|
||||
const stateLookup = this.results.getStateById(test.item.extId);
|
||||
const line = test.item.range.startLineNumber;
|
||||
const resultItem = stateLookup?.[1];
|
||||
const existing = newDecorations.findIndex(d => d instanceof RunTestDecoration && d.line === line);
|
||||
if (existing !== -1) {
|
||||
newDecorations[existing] = (newDecorations[existing] as RunTestDecoration).merge(test, resultItem);
|
||||
} else {
|
||||
newDecorations.push(this.instantiationService.createInstance(RunSingleTestDecoration, test, this.editor, stateLookup?.[1]));
|
||||
}
|
||||
}
|
||||
|
||||
const lastResult = this.results.results[0];
|
||||
if (this.testService.showInlineOutput.value && lastResult instanceof LiveTestResult) {
|
||||
for (const task of lastResult.tasks) {
|
||||
for (const m of task.otherMessages) {
|
||||
if (!this.invalidatedMessages.has(m) && hasValidLocation(uri, m)) {
|
||||
newDecorations.push(this.instantiationService.createInstance(TestMessageDecoration, m, uri, m.location, this.editor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let taskId = 0; taskId < stateItem.tasks.length; taskId++) {
|
||||
const state = stateItem.tasks[taskId];
|
||||
for (let i = 0; i < state.messages.length; i++) {
|
||||
const m = state.messages[i];
|
||||
if (!this.invalidatedMessages.has(m) && hasValidLocation(uri, m)) {
|
||||
const uri = m.type === TestMessageType.Info ? undefined : buildTestUri({
|
||||
type: TestUriType.ResultActualOutput,
|
||||
messageIndex: i,
|
||||
taskIndex: taskId,
|
||||
resultId: result.id,
|
||||
testExtId: stateItem.item.extId,
|
||||
});
|
||||
for (const test of lastResult.tests) {
|
||||
for (let taskId = 0; taskId < test.tasks.length; taskId++) {
|
||||
const state = test.tasks[taskId];
|
||||
for (let i = 0; i < state.messages.length; i++) {
|
||||
const m = state.messages[i];
|
||||
if (!this.invalidatedMessages.has(m) && hasValidLocation(uri, m)) {
|
||||
const uri = m.type === TestMessageType.Info ? undefined : buildTestUri({
|
||||
type: TestUriType.ResultActualOutput,
|
||||
messageIndex: i,
|
||||
taskIndex: taskId,
|
||||
resultId: lastResult.id,
|
||||
testExtId: test.item.extId,
|
||||
});
|
||||
|
||||
newDecorations.push(this.instantiationService.createInstance(TestMessageDecoration, m, uri, m.location, this.editor));
|
||||
newDecorations.push(this.instantiationService.createInstance(TestMessageDecoration, m, uri, m.location, this.editor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +225,10 @@ export class TestingDecorations extends Disposable implements IEditorContributio
|
|||
}
|
||||
|
||||
private clearDecorations(): void {
|
||||
if (!this.lastDecorations.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editor.changeDecorations(accessor => {
|
||||
for (const decoration of this.lastDecorations) {
|
||||
accessor.removeDecoration(decoration.id);
|
||||
|
|
|
@ -7,11 +7,11 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
|||
import { Event } from 'vs/base/common/event';
|
||||
import * as extpath from 'vs/base/common/extpath';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { MarshalledId } from 'vs/base/common/marshalling';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { IObservableValue, MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { AbstractIncrementalTestCollection, IncrementalTestCollectionItem, InternalTestItem, ITestItemContext, ITestTagDisplayInfo, ResolvedTestRunRequest, RunTestForControllerRequest, TestItemExpandState, TestRunProfileBitset, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
|
@ -225,6 +225,11 @@ export interface ITestService {
|
|||
*/
|
||||
readonly onDidProcessDiff: Event<TestsDiff>;
|
||||
|
||||
/**
|
||||
* Whether inline editor decorations should be visible.
|
||||
*/
|
||||
readonly showInlineOutput: MutableObservableValue<boolean>;
|
||||
|
||||
/**
|
||||
* Registers an interface that runs tests for the given provider ID.
|
||||
*/
|
||||
|
|
|
@ -11,8 +11,11 @@ import { localize } from 'vs/nls';
|
|||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { MainThreadTestCollection } from 'vs/workbench/contrib/testing/common/mainThreadTestCollection';
|
||||
import { MutableObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
|
||||
import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue';
|
||||
import { ResolvedTestRunRequest, TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestExclusions } from 'vs/workbench/contrib/testing/common/testExclusions';
|
||||
import { TestId } from 'vs/workbench/contrib/testing/common/testId';
|
||||
|
@ -55,9 +58,19 @@ export class TestService extends Disposable implements ITestService {
|
|||
*/
|
||||
public readonly excluded: TestExclusions;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public readonly showInlineOutput = MutableObservableValue.stored(new StoredValue<boolean>({
|
||||
key: 'inlineTestOutputVisible',
|
||||
scope: StorageScope.WORKSPACE,
|
||||
target: StorageTarget.USER
|
||||
}, this.storage), true);
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IStorageService private readonly storage: IStorageService,
|
||||
@ITestProfileService private readonly testProfiles: ITestProfileService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ITestResultService private readonly testResults: ITestResultService,
|
||||
|
|
Loading…
Reference in a new issue