Skip to content

Commit 9b8451d

Browse files
authored
testing: fix text messages being shown as terminal output (microsoft#185945)
TestMessages should not be treated as terminal output like `appendOutput`. They were incorrectly kept in the same implementation when we added terminal support. Fixes microsoft#185778
1 parent a201c73 commit 9b8451d

File tree

1 file changed

+88
-37
lines changed

1 file changed

+88
-37
lines changed

src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts

Lines changed: 88 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import 'vs/css!./testingOutputPeek';
3434
import { ICodeEditor, IDiffEditorConstructionOptions, isCodeEditor } from 'vs/editor/browser/editorBrowser';
3535
import { EditorAction2 } from 'vs/editor/browser/editorExtensions';
3636
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
37+
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
3738
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
3839
import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
3940
import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
@@ -729,7 +730,8 @@ class TestResultsViewContent extends Disposable {
729730
this.contentProviders = [
730731
this._register(this.instantiationService.createInstance(DiffContentProvider, this.editor, messageContainer)),
731732
this._register(this.instantiationService.createInstance(MarkdownTestMessagePeek, messageContainer)),
732-
this._register(this.instantiationService.createInstance(PlainTextMessagePeek, messageContainer, isInPeekView)),
733+
this._register(this.instantiationService.createInstance(TerminalMessagePeek, messageContainer, isInPeekView)),
734+
this._register(this.instantiationService.createInstance(PlainTextMessagePeek, this.editor, messageContainer)),
733735
];
734736

735737
const treeContainer = dom.append(containerElement, dom.$('.test-output-peek-tree'));
@@ -1157,8 +1159,67 @@ class MarkdownTestMessagePeek extends Disposable implements IPeekOutputRenderer
11571159
}
11581160
}
11591161

1160-
11611162
class PlainTextMessagePeek extends Disposable implements IPeekOutputRenderer {
1163+
private readonly widget = this._register(new MutableDisposable<CodeEditorWidget>());
1164+
private readonly model = this._register(new MutableDisposable());
1165+
private dimension?: dom.IDimension;
1166+
1167+
constructor(
1168+
private readonly editor: ICodeEditor | undefined,
1169+
private readonly container: HTMLElement,
1170+
@IInstantiationService private readonly instantiationService: IInstantiationService,
1171+
@ITextModelService private readonly modelService: ITextModelService,
1172+
) {
1173+
super();
1174+
}
1175+
1176+
public async update(subject: InspectSubject) {
1177+
if (!(subject instanceof MessageSubject)) {
1178+
return this.clear();
1179+
}
1180+
1181+
const message = subject.messages[subject.messageIndex];
1182+
if (isDiffable(message) || typeof message.message !== 'string') {
1183+
return this.clear();
1184+
}
1185+
1186+
1187+
const modelRef = this.model.value = await this.modelService.createModelReference(subject.messageUri);
1188+
if (!this.widget.value) {
1189+
this.widget.value = this.editor ? this.instantiationService.createInstance(
1190+
EmbeddedCodeEditorWidget,
1191+
this.container,
1192+
commonEditorOptions,
1193+
{},
1194+
this.editor,
1195+
) : this.instantiationService.createInstance(
1196+
CodeEditorWidget,
1197+
this.container,
1198+
commonEditorOptions,
1199+
{ isSimpleWidget: true }
1200+
);
1201+
1202+
if (this.dimension) {
1203+
this.widget.value.layout(this.dimension);
1204+
}
1205+
}
1206+
1207+
this.widget.value.setModel(modelRef.object.textEditorModel);
1208+
this.widget.value.updateOptions(commonEditorOptions);
1209+
}
1210+
1211+
private clear() {
1212+
this.model.clear();
1213+
this.widget.clear();
1214+
}
1215+
1216+
public layout(dimensions: dom.IDimension) {
1217+
this.dimension = dimensions;
1218+
this.widget.value?.layout(dimensions);
1219+
}
1220+
}
1221+
1222+
class TerminalMessagePeek extends Disposable implements IPeekOutputRenderer {
11621223
private dimensions?: dom.IDimension;
11631224
private readonly terminalCwd = this._register(new MutableObservableValue<string>(''));
11641225

@@ -1224,46 +1285,36 @@ class PlainTextMessagePeek extends Disposable implements IPeekOutputRenderer {
12241285

12251286
public async update(subject: InspectSubject) {
12261287
this.outputDataListener.clear();
1288+
if (!(subject instanceof TaskSubject)) {
1289+
return this.clear();
1290+
}
12271291

1228-
if (subject instanceof MessageSubject) {
1229-
const message = subject.messages[subject.messageIndex];
1230-
if (isDiffable(message) || typeof message.message !== 'string') {
1231-
return this.clear();
1232-
}
1233-
1234-
this.updateCwd(subject.test.uri);
1235-
const terminal = await this.makeTerminal();
1236-
terminal.write(message.message);
1237-
this.layoutTerminal(terminal);
1238-
this.attachTerminalToDom(terminal);
1239-
} else {
1240-
const result = this.resultService.getResult(subject.resultId);
1241-
const task = result?.tasks[subject.taskIndex];
1242-
if (!task) {
1243-
return this.clear();
1244-
}
1292+
const result = this.resultService.getResult(subject.resultId);
1293+
const task = result?.tasks[subject.taskIndex];
1294+
if (!task) {
1295+
return this.clear();
1296+
}
12451297

1246-
// Update the cwd and use the first test to try to hint at the correct cwd,
1247-
// but often this will fall back to the first workspace folder.
1248-
this.updateCwd(Iterable.find(result.tests, t => !!t.item.uri)?.item.uri);
1298+
// Update the cwd and use the first test to try to hint at the correct cwd,
1299+
// but often this will fall back to the first workspace folder.
1300+
this.updateCwd(Iterable.find(result.tests, t => !!t.item.uri)?.item.uri);
12491301

1250-
const terminal = await this.makeTerminal();
1251-
if (result instanceof LiveTestResult) {
1252-
let hadData = false;
1253-
for (const buffer of task.output.buffers) {
1254-
hadData ||= buffer.byteLength > 0;
1255-
terminal.write(buffer.buffer);
1256-
}
1257-
if (!hadData && !task.running) {
1258-
this.writeNotice(terminal, localize('runNoOutout', 'The test run did not record any output.'));
1259-
}
1260-
} else {
1261-
this.writeNotice(terminal, localize('runNoOutputForPast', 'Test output is only available for new test runs.'));
1302+
const terminal = await this.makeTerminal();
1303+
if (result instanceof LiveTestResult) {
1304+
let hadData = false;
1305+
for (const buffer of task.output.buffers) {
1306+
hadData ||= buffer.byteLength > 0;
1307+
terminal.write(buffer.buffer);
12621308
}
1263-
1264-
this.attachTerminalToDom(terminal);
1265-
this.outputDataListener.value = task.output.onDidWriteData(e => terminal.write(e.buffer));
1309+
if (!hadData && !task.running) {
1310+
this.writeNotice(terminal, localize('runNoOutout', 'The test run did not record any output.'));
1311+
}
1312+
} else {
1313+
this.writeNotice(terminal, localize('runNoOutputForPast', 'Test output is only available for new test runs.'));
12661314
}
1315+
1316+
this.attachTerminalToDom(terminal);
1317+
this.outputDataListener.value = task.output.onDidWriteData(e => terminal.write(e.buffer));
12671318
}
12681319

12691320
private updateCwd(testUri?: URI) {

0 commit comments

Comments
 (0)