@codingame/monaco-vscode-testing-service-override 3.2.3 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -8
- package/testing.js +5 -4
- package/external/rollup-plugin-styles/dist/runtime/inject-css.js +0 -3
- package/external/tslib/tslib.es6.js +0 -11
- package/vscode/src/vs/workbench/contrib/testing/browser/codeCoverageDecorations.js +0 -567
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/display.js +0 -3
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/index.js +0 -83
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/listProjection.js +0 -186
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/testItemContextOverlay.js +0 -18
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/testingObjectTree.js +0 -46
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/testingViewState.js +0 -17
- package/vscode/src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.js +0 -225
- package/vscode/src/vs/workbench/contrib/testing/browser/icons.js +0 -174
- package/vscode/src/vs/workbench/contrib/testing/browser/media/testing.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageBars.js +0 -227
- package/vscode/src/vs/workbench/contrib/testing/browser/testCoverageView.js +0 -545
- package/vscode/src/vs/workbench/contrib/testing/browser/testExplorerActions.js +0 -1662
- package/vscode/src/vs/workbench/contrib/testing/browser/testing.contribution.js +0 -219
- package/vscode/src/vs/workbench/contrib/testing/browser/testingDecorations.js +0 -970
- package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerFilter.js +0 -236
- package/vscode/src/vs/workbench/contrib/testing/browser/testingExplorerView.js +0 -1227
- package/vscode/src/vs/workbench/contrib/testing/browser/testingOutputPeek.css.js +0 -6
- package/vscode/src/vs/workbench/contrib/testing/browser/testingOutputPeek.js +0 -2091
- package/vscode/src/vs/workbench/contrib/testing/browser/testingProgressUiService.js +0 -142
- package/vscode/src/vs/workbench/contrib/testing/browser/testingViewPaneContainer.js +0 -47
- package/vscode/src/vs/workbench/contrib/testing/browser/theme.js +0 -259
- package/vscode/src/vs/workbench/contrib/testing/common/configuration.js +0 -273
- package/vscode/src/vs/workbench/contrib/testing/common/constants.js +0 -59
- package/vscode/src/vs/workbench/contrib/testing/common/mainThreadTestCollection.js +0 -129
- package/vscode/src/vs/workbench/contrib/testing/common/testExclusions.js +0 -48
- package/vscode/src/vs/workbench/contrib/testing/common/testServiceImpl.js +0 -296
- package/vscode/src/vs/workbench/contrib/testing/common/testingContentProvider.js +0 -125
- package/vscode/src/vs/workbench/contrib/testing/common/testingUri.js +0 -67
|
@@ -1,2091 +0,0 @@
|
|
|
1
|
-
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
|
|
2
|
-
import { append, $, reset, Dimension, scheduleAtNextAnimationFrame, getWindow } from 'vscode/vscode/vs/base/browser/dom';
|
|
3
|
-
import { renderStringAsPlaintext } from 'vscode/vscode/vs/base/browser/markdownRenderer';
|
|
4
|
-
import { ActionBar } from 'vscode/vscode/vs/base/browser/ui/actionbar/actionbar';
|
|
5
|
-
import { alert } from 'vscode/vscode/vs/base/browser/ui/aria/aria';
|
|
6
|
-
import { renderLabelWithIcons } from 'vscode/vscode/vs/base/browser/ui/iconLabel/iconLabels';
|
|
7
|
-
import { DomScrollableElement } from 'vscode/vscode/vs/base/browser/ui/scrollbar/scrollableElement';
|
|
8
|
-
import { SplitView, Sizing } from 'vscode/vscode/vs/base/browser/ui/splitview/splitview';
|
|
9
|
-
import { Separator, Action } from 'vscode/vscode/vs/base/common/actions';
|
|
10
|
-
import { Limiter, Delayer, RunOnceScheduler } from 'vscode/vscode/vs/base/common/async';
|
|
11
|
-
import { Codicon } from 'vscode/vscode/vs/base/common/codicons';
|
|
12
|
-
import { Color } from 'vscode/vscode/vs/base/common/color';
|
|
13
|
-
import { Emitter, Event } from 'vscode/vscode/vs/base/common/event';
|
|
14
|
-
import { stripIcons } from 'vscode/vscode/vs/base/common/iconLabels';
|
|
15
|
-
import { Iterable } from 'vscode/vscode/vs/base/common/iterator';
|
|
16
|
-
import { Lazy } from 'vscode/vscode/vs/base/common/lazy';
|
|
17
|
-
import { DisposableStore, Disposable, MutableDisposable, toDisposable, combinedDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
18
|
-
import { count } from 'vscode/vscode/vs/base/common/strings';
|
|
19
|
-
import { ThemeIcon } from 'vscode/vscode/vs/base/common/themables';
|
|
20
|
-
import { isDefined } from 'vscode/vscode/vs/base/common/types';
|
|
21
|
-
import './testingOutputPeek.css.js';
|
|
22
|
-
import { isCodeEditor } from 'vscode/vscode/vs/editor/browser/editorBrowser';
|
|
23
|
-
import { EditorAction2 } from 'vscode/vscode/vs/editor/browser/editorExtensions';
|
|
24
|
-
import { ICodeEditorService } from 'vscode/vscode/vs/editor/browser/services/codeEditorService';
|
|
25
|
-
import { CodeEditorWidget } from 'vscode/vscode/vs/editor/browser/widget/codeEditorWidget';
|
|
26
|
-
import { DiffEditorWidget } from 'vscode/vscode/vs/editor/browser/widget/diffEditor/diffEditorWidget';
|
|
27
|
-
import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vscode/vscode/vs/editor/browser/widget/embeddedCodeEditorWidget';
|
|
28
|
-
import { Range } from 'vscode/vscode/vs/editor/common/core/range';
|
|
29
|
-
import { EditorContextKeys } from 'vscode/vscode/vs/editor/common/editorContextKeys';
|
|
30
|
-
import { ITextModelService } from 'vscode/vscode/vs/editor/common/services/resolverService';
|
|
31
|
-
import { MarkdownRenderer } from 'vscode/vscode/vs/editor/browser/widget/markdownRenderer/browser/markdownRenderer';
|
|
32
|
-
import { PeekViewWidget, peekViewTitleForeground, peekViewTitleInfoForeground, IPeekViewService, peekViewResultsBackground } from 'vscode/vscode/vs/editor/contrib/peekView/browser/peekView';
|
|
33
|
-
import { localizeWithPath, localize2WithPath } from 'vscode/vscode/vs/nls';
|
|
34
|
-
import { Categories } from 'vscode/vscode/vs/platform/action/common/actionCommonCategories';
|
|
35
|
-
import { FloatingClickMenu } from 'vscode/vscode/vs/platform/actions/browser/floatingMenu';
|
|
36
|
-
import { MenuEntryActionViewItem, createAndFillInActionBarActions } from 'vscode/vscode/vs/platform/actions/browser/menuEntryActionViewItem';
|
|
37
|
-
import { MenuItemAction, Action2, MenuId, IMenuService } from 'vscode/vscode/vs/platform/actions/common/actions';
|
|
38
|
-
import { ICommandService } from 'vscode/vscode/vs/platform/commands/common/commands';
|
|
39
|
-
import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration';
|
|
40
|
-
import { ContextKeyExpr, IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
|
|
41
|
-
import { IContextMenuService } from 'vscode/vscode/vs/platform/contextview/browser/contextView';
|
|
42
|
-
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
|
|
43
|
-
import { ServiceCollection } from 'vscode/vscode/vs/platform/instantiation/common/serviceCollection';
|
|
44
|
-
import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding';
|
|
45
|
-
import { WorkbenchCompressibleObjectTree } from 'vscode/vscode/vs/platform/list/browser/listService';
|
|
46
|
-
import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
|
|
47
|
-
import { IOpenerService } from 'vscode/vscode/vs/platform/opener/common/opener';
|
|
48
|
-
import { IProgressService } from 'vscode/vscode/vs/platform/progress/common/progress';
|
|
49
|
-
import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
|
|
50
|
-
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
|
|
51
|
-
import { TerminalCapabilityStore } from 'vscode/vscode/vs/platform/terminal/common/capabilities/terminalCapabilityStore';
|
|
52
|
-
import { formatMessageForTerminal } from 'vscode/vscode/vs/platform/terminal/common/terminalStrings';
|
|
53
|
-
import { editorBackground } from 'vscode/vscode/vs/platform/theme/common/colorRegistry';
|
|
54
|
-
import { widgetClose } from 'vscode/vscode/vs/platform/theme/common/iconRegistry';
|
|
55
|
-
import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
|
|
56
|
-
import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace';
|
|
57
|
-
import { ViewPane } from 'vscode/vscode/vs/workbench/browser/parts/views/viewPane';
|
|
58
|
-
import { EditorModel } from 'vscode/vscode/vs/workbench/common/editor/editorModel';
|
|
59
|
-
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vscode/vscode/vs/workbench/common/theme';
|
|
60
|
-
import { IViewDescriptorService } from 'vscode/vscode/vs/workbench/common/views';
|
|
61
|
-
import { IViewsService } from 'vscode/vscode/vs/workbench/services/views/common/viewsService';
|
|
62
|
-
import { DetachedProcessInfo } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/detachedTerminal';
|
|
63
|
-
import { ITerminalService } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/terminal';
|
|
64
|
-
import { getXtermScaledDimensions } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal';
|
|
65
|
-
import { TERMINAL_BACKGROUND_COLOR } from 'vscode/vscode/vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
|
66
|
-
import { getTestItemContextOverlay } from './explorerProjections/testItemContextOverlay.js';
|
|
67
|
-
import { testingStatesToIcons, testingRunIcon, testingDebugIcon, testingCoverageReport } from './icons.js';
|
|
68
|
-
import { testingPeekBorder, testingMessagePeekBorder, testingPeekHeaderBackground, testingPeekMessageHeaderBackground } from './theme.js';
|
|
69
|
-
import { getTestingConfiguration } from '../common/configuration.js';
|
|
70
|
-
import { MutableObservableValue, staticObservableValue } from 'vscode/vscode/vs/workbench/contrib/testing/common/observableValue';
|
|
71
|
-
import { StoredValue } from 'vscode/vscode/vs/workbench/contrib/testing/common/storedValue';
|
|
72
|
-
import { ITestCoverageService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testCoverageService';
|
|
73
|
-
import { ITestExplorerFilterState } from 'vscode/vscode/vs/workbench/contrib/testing/common/testExplorerFilterState';
|
|
74
|
-
import { ITestProfileService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testProfileService';
|
|
75
|
-
import { resultItemParents, LiveTestResult, maxCountPriority } from 'vscode/vscode/vs/workbench/contrib/testing/common/testResult';
|
|
76
|
-
import { ITestResultService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testResultService';
|
|
77
|
-
import { ITestService } from 'vscode/vscode/vs/workbench/contrib/testing/common/testService';
|
|
78
|
-
import { ITestMessage, getMarkId } from 'vscode/vscode/vs/workbench/contrib/testing/common/testTypes';
|
|
79
|
-
import { TestingContextKeys } from 'vscode/vscode/vs/workbench/contrib/testing/common/testingContextKeys';
|
|
80
|
-
import { ITestingPeekOpener } from 'vscode/vscode/vs/workbench/contrib/testing/common/testingPeekOpener';
|
|
81
|
-
import { isFailedState, cmpPriority } from 'vscode/vscode/vs/workbench/contrib/testing/common/testingStates';
|
|
82
|
-
import { parseTestUri, buildTestUri } from '../common/testingUri.js';
|
|
83
|
-
import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
|
|
84
|
-
import { autorun } from 'vscode/vscode/vs/base/common/observableInternal/autorun';
|
|
85
|
-
|
|
86
|
-
var TestingOutputPeekController_1, TestResultsViewContent_1, TestResultsPeek_1, TestRunElementRenderer_1;
|
|
87
|
-
class MessageSubject {
|
|
88
|
-
get isDiffable() {
|
|
89
|
-
return this.message.type === 0 && isDiffable(this.message);
|
|
90
|
-
}
|
|
91
|
-
get contextValue() {
|
|
92
|
-
return this.message.type === 0 ? this.message.contextValue : undefined;
|
|
93
|
-
}
|
|
94
|
-
get context() {
|
|
95
|
-
return {
|
|
96
|
-
$mid: 18 ,
|
|
97
|
-
extId: this.test.extId,
|
|
98
|
-
message: ITestMessage.serialize(this.message),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
constructor(result, test, taskIndex, messageIndex) {
|
|
102
|
-
this.result = result;
|
|
103
|
-
this.taskIndex = taskIndex;
|
|
104
|
-
this.messageIndex = messageIndex;
|
|
105
|
-
this.test = test.item;
|
|
106
|
-
const messages = test.tasks[taskIndex].messages;
|
|
107
|
-
this.messageIndex = messageIndex;
|
|
108
|
-
const parts = { messageIndex, resultId: result.id, taskIndex, testExtId: test.item.extId };
|
|
109
|
-
this.expectedUri = buildTestUri({ ...parts, type: 4 });
|
|
110
|
-
this.actualUri = buildTestUri({ ...parts, type: 3 });
|
|
111
|
-
this.messageUri = buildTestUri({ ...parts, type: 2 });
|
|
112
|
-
const message = this.message = messages[this.messageIndex];
|
|
113
|
-
this.revealLocation = message.location ?? (test.item.uri && test.item.range ? { uri: test.item.uri, range: Range.lift(test.item.range) } : undefined);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
class TaskSubject {
|
|
117
|
-
constructor(result, taskIndex) {
|
|
118
|
-
this.result = result;
|
|
119
|
-
this.taskIndex = taskIndex;
|
|
120
|
-
this.outputUri = buildTestUri({ resultId: result.id, taskIndex, type: 0 });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
class TestOutputSubject {
|
|
124
|
-
constructor(result, taskIndex, test) {
|
|
125
|
-
this.result = result;
|
|
126
|
-
this.taskIndex = taskIndex;
|
|
127
|
-
this.test = test;
|
|
128
|
-
this.outputUri = buildTestUri({ resultId: this.result.id, taskIndex: this.taskIndex, testExtId: this.test.item.extId, type: 1 });
|
|
129
|
-
this.task = result.tasks[this.taskIndex];
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const equalsSubject = (a, b) => ((a instanceof MessageSubject && b instanceof MessageSubject && a.message === b.message) ||
|
|
133
|
-
(a instanceof TaskSubject && b instanceof TaskSubject && a.result === b.result && a.taskIndex === b.taskIndex) ||
|
|
134
|
-
(a instanceof TestOutputSubject && b instanceof TestOutputSubject && a.test === b.test && a.taskIndex === b.taskIndex));
|
|
135
|
-
function* allMessages(results) {
|
|
136
|
-
for (const result of results) {
|
|
137
|
-
for (const test of result.tests) {
|
|
138
|
-
for (let taskIndex = 0; taskIndex < test.tasks.length; taskIndex++) {
|
|
139
|
-
for (let messageIndex = 0; messageIndex < test.tasks[taskIndex].messages.length; messageIndex++) {
|
|
140
|
-
yield { result, test, taskIndex, messageIndex };
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
let TestingPeekOpener = class TestingPeekOpener extends Disposable {
|
|
147
|
-
constructor(configuration, editorService, codeEditorService, testResults, testService, storageService, viewsService, commandService, notificationService) {
|
|
148
|
-
super();
|
|
149
|
-
this.configuration = configuration;
|
|
150
|
-
this.editorService = editorService;
|
|
151
|
-
this.codeEditorService = codeEditorService;
|
|
152
|
-
this.testResults = testResults;
|
|
153
|
-
this.testService = testService;
|
|
154
|
-
this.storageService = storageService;
|
|
155
|
-
this.viewsService = viewsService;
|
|
156
|
-
this.commandService = commandService;
|
|
157
|
-
this.notificationService = notificationService;
|
|
158
|
-
this.historyVisible = MutableObservableValue.stored(this._register(( new StoredValue({
|
|
159
|
-
key: 'testHistoryVisibleInPeek',
|
|
160
|
-
scope: 0 ,
|
|
161
|
-
target: 0 ,
|
|
162
|
-
}, this.storageService))), false);
|
|
163
|
-
this._register(testResults.onTestChanged(this.openPeekOnFailure, this));
|
|
164
|
-
}
|
|
165
|
-
async open() {
|
|
166
|
-
let uri;
|
|
167
|
-
const active = this.editorService.activeTextEditorControl;
|
|
168
|
-
if (isCodeEditor(active) && active.getModel()?.uri) {
|
|
169
|
-
const modelUri = active.getModel()?.uri;
|
|
170
|
-
if (modelUri) {
|
|
171
|
-
uri = await this.getFileCandidateMessage(modelUri, active.getPosition());
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (!uri) {
|
|
175
|
-
uri = this.lastUri;
|
|
176
|
-
}
|
|
177
|
-
if (!uri) {
|
|
178
|
-
uri = this.getAnyCandidateMessage();
|
|
179
|
-
}
|
|
180
|
-
if (!uri) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
return this.showPeekFromUri(uri);
|
|
184
|
-
}
|
|
185
|
-
tryPeekFirstError(result, test, options) {
|
|
186
|
-
const candidate = this.getFailedCandidateMessage(test);
|
|
187
|
-
if (!candidate) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
this.showPeekFromUri({
|
|
191
|
-
type: 2 ,
|
|
192
|
-
documentUri: candidate.location.uri,
|
|
193
|
-
taskIndex: candidate.taskId,
|
|
194
|
-
messageIndex: candidate.index,
|
|
195
|
-
resultId: result.id,
|
|
196
|
-
testExtId: test.item.extId,
|
|
197
|
-
}, undefined, { selection: candidate.location.range, selectionRevealType: 3 , ...options });
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
peekUri(uri, options = {}) {
|
|
201
|
-
const parsed = parseTestUri(uri);
|
|
202
|
-
const result = parsed && this.testResults.getResult(parsed.resultId);
|
|
203
|
-
if (!parsed || !result || !('testExtId' in parsed)) {
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
if (!('messageIndex' in parsed)) {
|
|
207
|
-
return false;
|
|
208
|
-
}
|
|
209
|
-
const message = result.getStateById(parsed.testExtId)?.tasks[parsed.taskIndex].messages[parsed.messageIndex];
|
|
210
|
-
if (!message?.location) {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
this.showPeekFromUri({
|
|
214
|
-
type: 2 ,
|
|
215
|
-
documentUri: message.location.uri,
|
|
216
|
-
taskIndex: parsed.taskIndex,
|
|
217
|
-
messageIndex: parsed.messageIndex,
|
|
218
|
-
resultId: result.id,
|
|
219
|
-
testExtId: parsed.testExtId,
|
|
220
|
-
}, options.inEditor, { selection: message.location.range, ...options.options });
|
|
221
|
-
return true;
|
|
222
|
-
}
|
|
223
|
-
closeAllPeeks() {
|
|
224
|
-
for (const editor of this.codeEditorService.listCodeEditors()) {
|
|
225
|
-
TestingOutputPeekController.get(editor)?.removePeek();
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
openCurrentInEditor() {
|
|
229
|
-
const current = this.getActiveControl();
|
|
230
|
-
if (!current) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
const options = { pinned: false, revealIfOpened: true };
|
|
234
|
-
if (current instanceof TaskSubject || current instanceof TestOutputSubject) {
|
|
235
|
-
this.editorService.openEditor({ resource: current.outputUri, options });
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (current instanceof TestOutputSubject) {
|
|
239
|
-
this.editorService.openEditor({ resource: current.outputUri, options });
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
const message = current.message;
|
|
243
|
-
if (current.isDiffable) {
|
|
244
|
-
this.editorService.openEditor({
|
|
245
|
-
original: { resource: current.expectedUri },
|
|
246
|
-
modified: { resource: current.actualUri },
|
|
247
|
-
options,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
else if (typeof message.message === 'string') {
|
|
251
|
-
this.editorService.openEditor({ resource: current.messageUri, options });
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
this.commandService.executeCommand('markdown.showPreview', current.messageUri).catch(err => {
|
|
255
|
-
this.notificationService.error(( localizeWithPath(
|
|
256
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
257
|
-
'testing.markdownPeekError',
|
|
258
|
-
'Could not open markdown preview: {0}.\n\nPlease make sure the markdown extension is enabled.',
|
|
259
|
-
err.message
|
|
260
|
-
)));
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
getActiveControl() {
|
|
265
|
-
const editor = getPeekedEditorFromFocus(this.codeEditorService);
|
|
266
|
-
const controller = editor && TestingOutputPeekController.get(editor);
|
|
267
|
-
return controller?.subject ?? this.viewsService.getActiveViewWithId("workbench.panel.testResults.view" )?.subject;
|
|
268
|
-
}
|
|
269
|
-
async showPeekFromUri(uri, editor, options) {
|
|
270
|
-
if (isCodeEditor(editor)) {
|
|
271
|
-
this.lastUri = uri;
|
|
272
|
-
TestingOutputPeekController.get(editor)?.show(buildTestUri(this.lastUri));
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
const pane = await this.editorService.openEditor({
|
|
276
|
-
resource: uri.documentUri,
|
|
277
|
-
options: { revealIfOpened: true, ...options }
|
|
278
|
-
});
|
|
279
|
-
const control = pane?.getControl();
|
|
280
|
-
if (!isCodeEditor(control)) {
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
this.lastUri = uri;
|
|
284
|
-
TestingOutputPeekController.get(control)?.show(buildTestUri(this.lastUri));
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
openPeekOnFailure(evt) {
|
|
288
|
-
if (evt.reason !== 1 ) {
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
const candidate = this.getFailedCandidateMessage(evt.item);
|
|
292
|
-
if (!candidate) {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
if (evt.result.request.continuous && !getTestingConfiguration(this.configuration, "testing.automaticallyOpenPeekViewDuringAutoRun" )) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const editors = this.codeEditorService.listCodeEditors();
|
|
299
|
-
const cfg = getTestingConfiguration(this.configuration, "testing.automaticallyOpenPeekView" );
|
|
300
|
-
switch (cfg) {
|
|
301
|
-
case "failureInVisibleDocument" : {
|
|
302
|
-
const editorUris = ( new Set(( editors.map(e => e.getModel()?.uri.toString()))));
|
|
303
|
-
if (!( Iterable.some(resultItemParents(evt.result, evt.item), i => i.item.uri && ( editorUris.has(( i.item.uri.toString())))))) {
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
case "failureAnywhere" :
|
|
309
|
-
break;
|
|
310
|
-
default:
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
const controllers = ( editors.map(TestingOutputPeekController.get));
|
|
314
|
-
if (( controllers.some(c => c?.subject))) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
this.tryPeekFirstError(evt.result, evt.item);
|
|
318
|
-
}
|
|
319
|
-
async getFileCandidateMessage(uri, position) {
|
|
320
|
-
let best;
|
|
321
|
-
let bestDistance = Infinity;
|
|
322
|
-
const demandedUriStr = ( uri.toString());
|
|
323
|
-
for (const test of this.testService.collection.all) {
|
|
324
|
-
const result = this.testResults.getStateById(test.item.extId);
|
|
325
|
-
if (!result) {
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
mapFindTestMessage(result[1], (_task, message, messageIndex, taskIndex) => {
|
|
329
|
-
if (message.type !== 0 || !message.location || ( message.location.uri.toString()) !== demandedUriStr) {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
const distance = position ? Math.abs(position.lineNumber - message.location.range.startLineNumber) : 0;
|
|
333
|
-
if (!best || distance <= bestDistance) {
|
|
334
|
-
bestDistance = distance;
|
|
335
|
-
best = {
|
|
336
|
-
type: 2 ,
|
|
337
|
-
testExtId: result[1].item.extId,
|
|
338
|
-
resultId: result[0].id,
|
|
339
|
-
taskIndex,
|
|
340
|
-
messageIndex,
|
|
341
|
-
documentUri: uri,
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
return best;
|
|
347
|
-
}
|
|
348
|
-
getAnyCandidateMessage() {
|
|
349
|
-
const seen = ( new Set());
|
|
350
|
-
for (const result of this.testResults.results) {
|
|
351
|
-
for (const test of result.tests) {
|
|
352
|
-
if (( seen.has(test.item.extId))) {
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
seen.add(test.item.extId);
|
|
356
|
-
const found = mapFindTestMessage(test, (task, message, messageIndex, taskIndex) => (message.location && {
|
|
357
|
-
type: 2 ,
|
|
358
|
-
testExtId: test.item.extId,
|
|
359
|
-
resultId: result.id,
|
|
360
|
-
taskIndex,
|
|
361
|
-
messageIndex,
|
|
362
|
-
documentUri: message.location.uri,
|
|
363
|
-
}));
|
|
364
|
-
if (found) {
|
|
365
|
-
return found;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return undefined;
|
|
370
|
-
}
|
|
371
|
-
getFailedCandidateMessage(test) {
|
|
372
|
-
const fallbackLocation = test.item.uri && test.item.range
|
|
373
|
-
? { uri: test.item.uri, range: test.item.range }
|
|
374
|
-
: undefined;
|
|
375
|
-
let best;
|
|
376
|
-
mapFindTestMessage(test, (task, message, messageIndex, taskId) => {
|
|
377
|
-
const location = message.location || fallbackLocation;
|
|
378
|
-
if (!isFailedState(task.state) || !location) {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (best && message.type !== 0 ) {
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
best = { taskId, index: messageIndex, message, location };
|
|
385
|
-
});
|
|
386
|
-
return best;
|
|
387
|
-
}
|
|
388
|
-
};
|
|
389
|
-
TestingPeekOpener = ( __decorate([
|
|
390
|
-
( __param(0, IConfigurationService)),
|
|
391
|
-
( __param(1, IEditorService)),
|
|
392
|
-
( __param(2, ICodeEditorService)),
|
|
393
|
-
( __param(3, ITestResultService)),
|
|
394
|
-
( __param(4, ITestService)),
|
|
395
|
-
( __param(5, IStorageService)),
|
|
396
|
-
( __param(6, IViewsService)),
|
|
397
|
-
( __param(7, ICommandService)),
|
|
398
|
-
( __param(8, INotificationService))
|
|
399
|
-
], TestingPeekOpener));
|
|
400
|
-
const mapFindTestMessage = (test, fn) => {
|
|
401
|
-
for (let taskIndex = 0; taskIndex < test.tasks.length; taskIndex++) {
|
|
402
|
-
const task = test.tasks[taskIndex];
|
|
403
|
-
for (let messageIndex = 0; messageIndex < task.messages.length; messageIndex++) {
|
|
404
|
-
const r = fn(task, task.messages[messageIndex], messageIndex, taskIndex);
|
|
405
|
-
if (r !== undefined) {
|
|
406
|
-
return r;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return undefined;
|
|
411
|
-
};
|
|
412
|
-
let TestingOutputPeekController = TestingOutputPeekController_1 = class TestingOutputPeekController extends Disposable {
|
|
413
|
-
static get(editor) {
|
|
414
|
-
return editor.getContribution("editor.contrib.testingOutputPeek" );
|
|
415
|
-
}
|
|
416
|
-
get subject() {
|
|
417
|
-
return this.peek.value?.current;
|
|
418
|
-
}
|
|
419
|
-
constructor(editor, codeEditorService, instantiationService, testResults, contextKeyService) {
|
|
420
|
-
super();
|
|
421
|
-
this.editor = editor;
|
|
422
|
-
this.codeEditorService = codeEditorService;
|
|
423
|
-
this.instantiationService = instantiationService;
|
|
424
|
-
this.testResults = testResults;
|
|
425
|
-
this.peek = this._register(( new MutableDisposable()));
|
|
426
|
-
this.visible = TestingContextKeys.isPeekVisible.bindTo(contextKeyService);
|
|
427
|
-
this._register(editor.onDidChangeModel(() => this.peek.clear()));
|
|
428
|
-
this._register(testResults.onResultsChanged(this.closePeekOnCertainResultEvents, this));
|
|
429
|
-
this._register(testResults.onTestChanged(this.closePeekOnTestChange, this));
|
|
430
|
-
}
|
|
431
|
-
toggle(uri) {
|
|
432
|
-
if (this.currentPeekUri?.toString() === ( uri.toString())) {
|
|
433
|
-
this.peek.clear();
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
this.show(uri);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
async show(uri) {
|
|
440
|
-
const subject = this.retrieveTest(uri);
|
|
441
|
-
if (!subject) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
if (!this.peek.value) {
|
|
445
|
-
this.peek.value = this.instantiationService.createInstance(TestResultsPeek, this.editor);
|
|
446
|
-
this.peek.value.onDidClose(() => {
|
|
447
|
-
this.visible.set(false);
|
|
448
|
-
this.currentPeekUri = undefined;
|
|
449
|
-
this.peek.value = undefined;
|
|
450
|
-
});
|
|
451
|
-
this.visible.set(true);
|
|
452
|
-
this.peek.value.create();
|
|
453
|
-
}
|
|
454
|
-
if (subject instanceof MessageSubject) {
|
|
455
|
-
alert(renderStringAsPlaintext(subject.message.message));
|
|
456
|
-
}
|
|
457
|
-
this.peek.value.setModel(subject);
|
|
458
|
-
this.currentPeekUri = uri;
|
|
459
|
-
}
|
|
460
|
-
async openAndShow(uri) {
|
|
461
|
-
const subject = this.retrieveTest(uri);
|
|
462
|
-
if (!subject) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
if (!subject.revealLocation || ( subject.revealLocation.uri.toString()) === this.editor.getModel()?.uri.toString()) {
|
|
466
|
-
return this.show(uri);
|
|
467
|
-
}
|
|
468
|
-
const otherEditor = await this.codeEditorService.openCodeEditor({
|
|
469
|
-
resource: subject.revealLocation.uri,
|
|
470
|
-
options: { pinned: false, revealIfOpened: true }
|
|
471
|
-
}, this.editor);
|
|
472
|
-
if (otherEditor) {
|
|
473
|
-
TestingOutputPeekController_1.get(otherEditor)?.removePeek();
|
|
474
|
-
return TestingOutputPeekController_1.get(otherEditor)?.show(uri);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
removePeek() {
|
|
478
|
-
this.peek.clear();
|
|
479
|
-
}
|
|
480
|
-
next() {
|
|
481
|
-
const subject = this.peek.value?.current;
|
|
482
|
-
if (!subject) {
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
let found = false;
|
|
486
|
-
for (const { messageIndex, taskIndex, result, test } of allMessages(this.testResults.results)) {
|
|
487
|
-
if (subject instanceof TaskSubject && result.id === subject.result.id) {
|
|
488
|
-
found = true;
|
|
489
|
-
}
|
|
490
|
-
if (found) {
|
|
491
|
-
this.openAndShow(buildTestUri({
|
|
492
|
-
type: 2 ,
|
|
493
|
-
messageIndex,
|
|
494
|
-
taskIndex,
|
|
495
|
-
resultId: result.id,
|
|
496
|
-
testExtId: test.item.extId
|
|
497
|
-
}));
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
if (subject instanceof TestOutputSubject && subject.test.item.extId === test.item.extId && subject.taskIndex === taskIndex && subject.result.id === result.id) {
|
|
501
|
-
found = true;
|
|
502
|
-
}
|
|
503
|
-
if (subject instanceof MessageSubject && subject.test.extId === test.item.extId && subject.messageIndex === messageIndex && subject.taskIndex === taskIndex && subject.result.id === result.id) {
|
|
504
|
-
found = true;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
previous() {
|
|
509
|
-
const subject = this.peek.value?.current;
|
|
510
|
-
if (!subject) {
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
let previous;
|
|
514
|
-
for (const m of allMessages(this.testResults.results)) {
|
|
515
|
-
if (subject instanceof TaskSubject) {
|
|
516
|
-
if (m.result.id === subject.result.id) {
|
|
517
|
-
break;
|
|
518
|
-
}
|
|
519
|
-
continue;
|
|
520
|
-
}
|
|
521
|
-
if (subject instanceof TestOutputSubject) {
|
|
522
|
-
if (m.test.item.extId === subject.test.item.extId && m.result.id === subject.result.id && m.taskIndex === subject.taskIndex) {
|
|
523
|
-
break;
|
|
524
|
-
}
|
|
525
|
-
continue;
|
|
526
|
-
}
|
|
527
|
-
if (subject.test.extId === m.test.item.extId && subject.messageIndex === m.messageIndex && subject.taskIndex === m.taskIndex && subject.result.id === m.result.id) {
|
|
528
|
-
break;
|
|
529
|
-
}
|
|
530
|
-
previous = m;
|
|
531
|
-
}
|
|
532
|
-
if (previous) {
|
|
533
|
-
this.openAndShow(buildTestUri({
|
|
534
|
-
type: 2 ,
|
|
535
|
-
messageIndex: previous.messageIndex,
|
|
536
|
-
taskIndex: previous.taskIndex,
|
|
537
|
-
resultId: previous.result.id,
|
|
538
|
-
testExtId: previous.test.item.extId
|
|
539
|
-
}));
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
removeIfPeekingForTest(testId) {
|
|
543
|
-
const c = this.peek.value?.current;
|
|
544
|
-
if (c && c instanceof MessageSubject && c.test.extId === testId) {
|
|
545
|
-
this.peek.clear();
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
closePeekOnTestChange(evt) {
|
|
549
|
-
if (evt.reason !== 1 || evt.previousState === evt.item.ownComputedState) {
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
this.removeIfPeekingForTest(evt.item.item.extId);
|
|
553
|
-
}
|
|
554
|
-
closePeekOnCertainResultEvents(evt) {
|
|
555
|
-
if ('started' in evt) {
|
|
556
|
-
this.peek.clear();
|
|
557
|
-
}
|
|
558
|
-
if ('removed' in evt && this.testResults.results.length === 0) {
|
|
559
|
-
this.peek.clear();
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
retrieveTest(uri) {
|
|
563
|
-
const parts = parseTestUri(uri);
|
|
564
|
-
if (!parts) {
|
|
565
|
-
return undefined;
|
|
566
|
-
}
|
|
567
|
-
const result = this.testResults.results.find(r => r.id === parts.resultId);
|
|
568
|
-
if (!result) {
|
|
569
|
-
return;
|
|
570
|
-
}
|
|
571
|
-
if (parts.type === 0 ) {
|
|
572
|
-
return ( new TaskSubject(result, parts.taskIndex));
|
|
573
|
-
}
|
|
574
|
-
if (parts.type === 1 ) {
|
|
575
|
-
const test = result.getStateById(parts.testExtId);
|
|
576
|
-
if (!test) {
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
return ( new TestOutputSubject(result, parts.taskIndex, test));
|
|
580
|
-
}
|
|
581
|
-
const { testExtId, taskIndex, messageIndex } = parts;
|
|
582
|
-
const test = result?.getStateById(testExtId);
|
|
583
|
-
if (!test || !test.tasks[parts.taskIndex]) {
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
return ( new MessageSubject(result, test, taskIndex, messageIndex));
|
|
587
|
-
}
|
|
588
|
-
};
|
|
589
|
-
TestingOutputPeekController = TestingOutputPeekController_1 = ( __decorate([
|
|
590
|
-
( __param(1, ICodeEditorService)),
|
|
591
|
-
( __param(2, IInstantiationService)),
|
|
592
|
-
( __param(3, ITestResultService)),
|
|
593
|
-
( __param(4, IContextKeyService))
|
|
594
|
-
], TestingOutputPeekController));
|
|
595
|
-
let TestResultsViewContent = class TestResultsViewContent extends Disposable {
|
|
596
|
-
static { TestResultsViewContent_1 = this; }
|
|
597
|
-
constructor(editor, options, instantiationService, modelService, contextKeyService) {
|
|
598
|
-
super();
|
|
599
|
-
this.editor = editor;
|
|
600
|
-
this.options = options;
|
|
601
|
-
this.instantiationService = instantiationService;
|
|
602
|
-
this.modelService = modelService;
|
|
603
|
-
this.contextKeyService = contextKeyService;
|
|
604
|
-
this.didReveal = this._register(( new Emitter()));
|
|
605
|
-
this.currentSubjectStore = this._register(( new DisposableStore()));
|
|
606
|
-
this.contentProvidersUpdateLimiter = this._register(( new Limiter(1)));
|
|
607
|
-
}
|
|
608
|
-
fillBody(containerElement) {
|
|
609
|
-
const initialSpitWidth = TestResultsViewContent_1.lastSplitWidth;
|
|
610
|
-
this.splitView = ( new SplitView(containerElement, { orientation: 1 }));
|
|
611
|
-
const { historyVisible, showRevealLocationOnMessages } = this.options;
|
|
612
|
-
const isInPeekView = this.editor !== undefined;
|
|
613
|
-
const messageContainer = this.messageContainer = append(containerElement, $('.test-output-peek-message-container'));
|
|
614
|
-
this.contentProviders = [
|
|
615
|
-
this._register(this.instantiationService.createInstance(DiffContentProvider, this.editor, messageContainer)),
|
|
616
|
-
this._register(this.instantiationService.createInstance(MarkdownTestMessagePeek, messageContainer)),
|
|
617
|
-
this._register(this.instantiationService.createInstance(TerminalMessagePeek, messageContainer, isInPeekView)),
|
|
618
|
-
this._register(this.instantiationService.createInstance(PlainTextMessagePeek, this.editor, messageContainer)),
|
|
619
|
-
];
|
|
620
|
-
this.messageContextKeyService = this._register(this.contextKeyService.createScoped(this.messageContainer));
|
|
621
|
-
this.contextKeyTestMessage = TestingContextKeys.testMessageContext.bindTo(this.messageContextKeyService);
|
|
622
|
-
this.contextKeyResultOutdated = TestingContextKeys.testResultOutdated.bindTo(this.messageContextKeyService);
|
|
623
|
-
const treeContainer = append(containerElement, $('.test-output-peek-tree'));
|
|
624
|
-
const tree = this._register(this.instantiationService.createInstance(OutputPeekTree, treeContainer, this.didReveal.event, { showRevealLocationOnMessages, locationForProgress: this.options.locationForProgress }));
|
|
625
|
-
this.onDidRequestReveal = tree.onDidRequestReview;
|
|
626
|
-
this.splitView.addView({
|
|
627
|
-
onDidChange: Event.None,
|
|
628
|
-
element: messageContainer,
|
|
629
|
-
minimumSize: 200,
|
|
630
|
-
maximumSize: Number.MAX_VALUE,
|
|
631
|
-
layout: width => {
|
|
632
|
-
TestResultsViewContent_1.lastSplitWidth = width;
|
|
633
|
-
if (this.dimension) {
|
|
634
|
-
for (const provider of this.contentProviders) {
|
|
635
|
-
provider.layout({ height: this.dimension.height, width });
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
},
|
|
639
|
-
}, Sizing.Distribute);
|
|
640
|
-
this.splitView.addView({
|
|
641
|
-
onDidChange: Event.None,
|
|
642
|
-
element: treeContainer,
|
|
643
|
-
minimumSize: 100,
|
|
644
|
-
maximumSize: Number.MAX_VALUE,
|
|
645
|
-
layout: width => {
|
|
646
|
-
if (this.dimension) {
|
|
647
|
-
tree.layout(this.dimension.height, width);
|
|
648
|
-
}
|
|
649
|
-
},
|
|
650
|
-
}, Sizing.Distribute);
|
|
651
|
-
const historyViewIndex = 1;
|
|
652
|
-
this.splitView.setViewVisible(historyViewIndex, historyVisible.value);
|
|
653
|
-
this._register(historyVisible.onDidChange(visible => {
|
|
654
|
-
this.splitView.setViewVisible(historyViewIndex, visible);
|
|
655
|
-
}));
|
|
656
|
-
if (initialSpitWidth) {
|
|
657
|
-
queueMicrotask(() => this.splitView.resizeView(0, initialSpitWidth));
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
reveal(opts) {
|
|
661
|
-
this.didReveal.fire(opts);
|
|
662
|
-
if (this.current && equalsSubject(this.current, opts.subject)) {
|
|
663
|
-
return Promise.resolve();
|
|
664
|
-
}
|
|
665
|
-
this.current = opts.subject;
|
|
666
|
-
return this.contentProvidersUpdateLimiter.queue(async () => {
|
|
667
|
-
await Promise.all(( this.contentProviders.map(p => p.update(opts.subject))));
|
|
668
|
-
this.currentSubjectStore.clear();
|
|
669
|
-
this.populateFloatingClick(opts.subject);
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
populateFloatingClick(subject) {
|
|
673
|
-
if (!(subject instanceof MessageSubject)) {
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
this.currentSubjectStore.add(toDisposable(() => {
|
|
677
|
-
this.contextKeyResultOutdated.reset();
|
|
678
|
-
this.contextKeyTestMessage.reset();
|
|
679
|
-
}));
|
|
680
|
-
this.contextKeyTestMessage.set(subject.contextValue || '');
|
|
681
|
-
if (subject.result instanceof LiveTestResult) {
|
|
682
|
-
this.contextKeyResultOutdated.set(subject.result.getStateById(subject.test.extId)?.retired ?? false);
|
|
683
|
-
this.currentSubjectStore.add(subject.result.onChange(ev => {
|
|
684
|
-
if (ev.item.item.extId === subject.test.extId) {
|
|
685
|
-
this.contextKeyResultOutdated.set(ev.item.retired ?? false);
|
|
686
|
-
}
|
|
687
|
-
}));
|
|
688
|
-
}
|
|
689
|
-
else {
|
|
690
|
-
this.contextKeyResultOutdated.set(true);
|
|
691
|
-
}
|
|
692
|
-
this.currentSubjectStore.add(this.instantiationService
|
|
693
|
-
.createChild(( new ServiceCollection([IContextKeyService, this.messageContextKeyService])))
|
|
694
|
-
.createInstance(FloatingClickMenu, {
|
|
695
|
-
container: this.messageContainer,
|
|
696
|
-
menuId: MenuId.TestMessageContent,
|
|
697
|
-
getActionArg: () => subject.context,
|
|
698
|
-
}));
|
|
699
|
-
}
|
|
700
|
-
onLayoutBody(height, width) {
|
|
701
|
-
this.dimension = new Dimension(width, height);
|
|
702
|
-
this.splitView.layout(width);
|
|
703
|
-
}
|
|
704
|
-
onWidth(width) {
|
|
705
|
-
this.splitView.layout(width);
|
|
706
|
-
}
|
|
707
|
-
};
|
|
708
|
-
TestResultsViewContent = TestResultsViewContent_1 = ( __decorate([
|
|
709
|
-
( __param(2, IInstantiationService)),
|
|
710
|
-
( __param(3, ITextModelService)),
|
|
711
|
-
( __param(4, IContextKeyService))
|
|
712
|
-
], TestResultsViewContent));
|
|
713
|
-
let TestResultsPeek = class TestResultsPeek extends PeekViewWidget {
|
|
714
|
-
static { TestResultsPeek_1 = this; }
|
|
715
|
-
constructor(editor, themeService, peekViewService, testingPeek, contextKeyService, menuService, instantiationService, modelService) {
|
|
716
|
-
super(editor, { showFrame: true, frameWidth: 1, showArrow: true, isResizeable: true, isAccessible: true, className: 'test-output-peek' }, instantiationService);
|
|
717
|
-
this.themeService = themeService;
|
|
718
|
-
this.testingPeek = testingPeek;
|
|
719
|
-
this.contextKeyService = contextKeyService;
|
|
720
|
-
this.menuService = menuService;
|
|
721
|
-
this.modelService = modelService;
|
|
722
|
-
this.visibilityChange = this._disposables.add(( new Emitter()));
|
|
723
|
-
this._disposables.add(themeService.onDidColorThemeChange(this.applyTheme, this));
|
|
724
|
-
this._disposables.add(this.onDidClose(() => this.visibilityChange.fire(false)));
|
|
725
|
-
peekViewService.addExclusiveWidget(editor, this);
|
|
726
|
-
}
|
|
727
|
-
applyTheme() {
|
|
728
|
-
const theme = this.themeService.getColorTheme();
|
|
729
|
-
const isError = this.current instanceof MessageSubject && this.current.message.type === 0 ;
|
|
730
|
-
const borderColor = (isError ? theme.getColor(testingPeekBorder) : theme.getColor(testingMessagePeekBorder)) || Color.transparent;
|
|
731
|
-
const headerBg = (isError ? theme.getColor(testingPeekHeaderBackground) : theme.getColor(testingPeekMessageHeaderBackground)) || Color.transparent;
|
|
732
|
-
const editorBg = theme.getColor(editorBackground);
|
|
733
|
-
this.style({
|
|
734
|
-
arrowColor: borderColor,
|
|
735
|
-
frameColor: borderColor,
|
|
736
|
-
headerBackgroundColor: editorBg && headerBg ? headerBg.makeOpaque(editorBg) : headerBg,
|
|
737
|
-
primaryHeadingColor: theme.getColor(peekViewTitleForeground),
|
|
738
|
-
secondaryHeadingColor: theme.getColor(peekViewTitleInfoForeground)
|
|
739
|
-
});
|
|
740
|
-
}
|
|
741
|
-
_fillContainer(container) {
|
|
742
|
-
if (!this.scopedContextKeyService) {
|
|
743
|
-
this.scopedContextKeyService = this._disposables.add(this.contextKeyService.createScoped(container));
|
|
744
|
-
TestingContextKeys.isInPeek.bindTo(this.scopedContextKeyService).set(true);
|
|
745
|
-
const instaService = this.instantiationService.createChild(( new ServiceCollection([IContextKeyService, this.scopedContextKeyService])));
|
|
746
|
-
this.content = this._disposables.add(instaService.createInstance(TestResultsViewContent, this.editor, { historyVisible: this.testingPeek.historyVisible, showRevealLocationOnMessages: false, locationForProgress: "workbench.panel.testResults.view" }));
|
|
747
|
-
}
|
|
748
|
-
super._fillContainer(container);
|
|
749
|
-
}
|
|
750
|
-
_fillHead(container) {
|
|
751
|
-
super._fillHead(container);
|
|
752
|
-
const actions = [];
|
|
753
|
-
const menu = this.menuService.createMenu(MenuId.TestPeekTitle, this.contextKeyService);
|
|
754
|
-
createAndFillInActionBarActions(menu, undefined, actions);
|
|
755
|
-
this._actionbarWidget.push(actions, { label: false, icon: true, index: 0 });
|
|
756
|
-
menu.dispose();
|
|
757
|
-
}
|
|
758
|
-
_fillBody(containerElement) {
|
|
759
|
-
this.content.fillBody(containerElement);
|
|
760
|
-
this.content.onDidRequestReveal(sub => {
|
|
761
|
-
TestingOutputPeekController.get(this.editor)?.show(sub instanceof MessageSubject
|
|
762
|
-
? sub.messageUri
|
|
763
|
-
: sub.outputUri);
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
setModel(subject) {
|
|
767
|
-
if (subject instanceof TaskSubject || subject instanceof TestOutputSubject) {
|
|
768
|
-
this.current = subject;
|
|
769
|
-
return this.showInPlace(subject);
|
|
770
|
-
}
|
|
771
|
-
const message = subject.message;
|
|
772
|
-
const previous = this.current;
|
|
773
|
-
if (!subject.revealLocation && !previous) {
|
|
774
|
-
return Promise.resolve();
|
|
775
|
-
}
|
|
776
|
-
this.current = subject;
|
|
777
|
-
if (!subject.revealLocation) {
|
|
778
|
-
return this.showInPlace(subject);
|
|
779
|
-
}
|
|
780
|
-
this.show(subject.revealLocation.range, TestResultsPeek_1.lastHeightInLines || hintMessagePeekHeight(message));
|
|
781
|
-
const startPosition = subject.revealLocation.range.getStartPosition();
|
|
782
|
-
this.editor.revealRangeNearTopIfOutsideViewport(Range.fromPositions(startPosition), 0 );
|
|
783
|
-
return this.showInPlace(subject);
|
|
784
|
-
}
|
|
785
|
-
async showInPlace(subject) {
|
|
786
|
-
if (subject instanceof MessageSubject) {
|
|
787
|
-
const message = subject.message;
|
|
788
|
-
this.setTitle(firstLine(renderStringAsPlaintext(message.message)), stripIcons(subject.test.label));
|
|
789
|
-
}
|
|
790
|
-
else {
|
|
791
|
-
this.setTitle(( localizeWithPath(
|
|
792
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
793
|
-
'testOutputTitle',
|
|
794
|
-
'Test Output'
|
|
795
|
-
)));
|
|
796
|
-
}
|
|
797
|
-
this.applyTheme();
|
|
798
|
-
await this.content.reveal({ subject: subject, preserveFocus: false });
|
|
799
|
-
}
|
|
800
|
-
_relayout(newHeightInLines) {
|
|
801
|
-
super._relayout(newHeightInLines);
|
|
802
|
-
TestResultsPeek_1.lastHeightInLines = newHeightInLines;
|
|
803
|
-
}
|
|
804
|
-
_doLayoutBody(height, width) {
|
|
805
|
-
super._doLayoutBody(height, width);
|
|
806
|
-
this.content.onLayoutBody(height, width);
|
|
807
|
-
}
|
|
808
|
-
_onWidth(width) {
|
|
809
|
-
super._onWidth(width);
|
|
810
|
-
if (this.dimension) {
|
|
811
|
-
this.dimension = new Dimension(width, this.dimension.height);
|
|
812
|
-
}
|
|
813
|
-
this.content.onWidth(width);
|
|
814
|
-
}
|
|
815
|
-
};
|
|
816
|
-
TestResultsPeek = TestResultsPeek_1 = ( __decorate([
|
|
817
|
-
( __param(1, IThemeService)),
|
|
818
|
-
( __param(2, IPeekViewService)),
|
|
819
|
-
( __param(3, ITestingPeekOpener)),
|
|
820
|
-
( __param(4, IContextKeyService)),
|
|
821
|
-
( __param(5, IMenuService)),
|
|
822
|
-
( __param(6, IInstantiationService)),
|
|
823
|
-
( __param(7, ITextModelService))
|
|
824
|
-
], TestResultsPeek));
|
|
825
|
-
let TestResultsView = class TestResultsView extends ViewPane {
|
|
826
|
-
constructor(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService, resultService) {
|
|
827
|
-
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
|
828
|
-
this.resultService = resultService;
|
|
829
|
-
this.content = ( new Lazy(
|
|
830
|
-
() => this._register(this.instantiationService.createInstance(TestResultsViewContent, undefined, {
|
|
831
|
-
historyVisible: staticObservableValue(true),
|
|
832
|
-
showRevealLocationOnMessages: true,
|
|
833
|
-
locationForProgress: "workbench.view.testing" ,
|
|
834
|
-
}))
|
|
835
|
-
));
|
|
836
|
-
}
|
|
837
|
-
get subject() {
|
|
838
|
-
return this.content.rawValue?.current;
|
|
839
|
-
}
|
|
840
|
-
showLatestRun(preserveFocus = false) {
|
|
841
|
-
const result = this.resultService.results.find(r => r.tasks.length);
|
|
842
|
-
if (!result) {
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
this.content.rawValue?.reveal({ preserveFocus, subject: ( new TaskSubject(result, 0)) });
|
|
846
|
-
}
|
|
847
|
-
renderBody(container) {
|
|
848
|
-
super.renderBody(container);
|
|
849
|
-
if (this.isBodyVisible()) {
|
|
850
|
-
this.renderContent(container);
|
|
851
|
-
}
|
|
852
|
-
else {
|
|
853
|
-
this._register(Event.once(Event.filter(this.onDidChangeBodyVisibility, Boolean))(() => this.renderContent(container)));
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
layoutBody(height, width) {
|
|
857
|
-
super.layoutBody(height, width);
|
|
858
|
-
this.content.rawValue?.onLayoutBody(height, width);
|
|
859
|
-
}
|
|
860
|
-
renderContent(container) {
|
|
861
|
-
const content = this.content.value;
|
|
862
|
-
content.fillBody(container);
|
|
863
|
-
content.onDidRequestReveal(subject => content.reveal({ preserveFocus: true, subject }));
|
|
864
|
-
const [lastResult] = this.resultService.results;
|
|
865
|
-
if (lastResult && lastResult.tasks.length) {
|
|
866
|
-
content.reveal({ preserveFocus: true, subject: ( new TaskSubject(lastResult, 0)) });
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
TestResultsView = ( __decorate([
|
|
871
|
-
( __param(1, IKeybindingService)),
|
|
872
|
-
( __param(2, IContextMenuService)),
|
|
873
|
-
( __param(3, IConfigurationService)),
|
|
874
|
-
( __param(4, IContextKeyService)),
|
|
875
|
-
( __param(5, IViewDescriptorService)),
|
|
876
|
-
( __param(6, IInstantiationService)),
|
|
877
|
-
( __param(7, IOpenerService)),
|
|
878
|
-
( __param(8, IThemeService)),
|
|
879
|
-
( __param(9, ITelemetryService)),
|
|
880
|
-
( __param(10, ITestResultService))
|
|
881
|
-
], TestResultsView));
|
|
882
|
-
const commonEditorOptions = {
|
|
883
|
-
scrollBeyondLastLine: false,
|
|
884
|
-
links: true,
|
|
885
|
-
lineNumbers: 'off',
|
|
886
|
-
scrollbar: {
|
|
887
|
-
verticalScrollbarSize: 14,
|
|
888
|
-
horizontal: 'auto',
|
|
889
|
-
useShadows: true,
|
|
890
|
-
verticalHasArrows: false,
|
|
891
|
-
horizontalHasArrows: false,
|
|
892
|
-
alwaysConsumeMouseWheel: false
|
|
893
|
-
},
|
|
894
|
-
fixedOverflowWidgets: true,
|
|
895
|
-
readOnly: true,
|
|
896
|
-
minimap: {
|
|
897
|
-
enabled: false
|
|
898
|
-
},
|
|
899
|
-
wordWrap: 'on',
|
|
900
|
-
};
|
|
901
|
-
const diffEditorOptions = {
|
|
902
|
-
...commonEditorOptions,
|
|
903
|
-
enableSplitViewResizing: true,
|
|
904
|
-
isInEmbeddedEditor: true,
|
|
905
|
-
renderOverviewRuler: false,
|
|
906
|
-
ignoreTrimWhitespace: false,
|
|
907
|
-
renderSideBySide: true,
|
|
908
|
-
useInlineViewWhenSpaceIsLimited: false,
|
|
909
|
-
originalAriaLabel: ( localizeWithPath(
|
|
910
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
911
|
-
'testingOutputExpected',
|
|
912
|
-
'Expected result'
|
|
913
|
-
)),
|
|
914
|
-
modifiedAriaLabel: ( localizeWithPath(
|
|
915
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
916
|
-
'testingOutputActual',
|
|
917
|
-
'Actual result'
|
|
918
|
-
)),
|
|
919
|
-
diffAlgorithm: 'advanced',
|
|
920
|
-
};
|
|
921
|
-
const isDiffable = (message) => message.type === 0 && message.actual !== undefined && message.expected !== undefined;
|
|
922
|
-
let DiffContentProvider = class DiffContentProvider extends Disposable {
|
|
923
|
-
constructor(editor, container, instantiationService, modelService) {
|
|
924
|
-
super();
|
|
925
|
-
this.editor = editor;
|
|
926
|
-
this.container = container;
|
|
927
|
-
this.instantiationService = instantiationService;
|
|
928
|
-
this.modelService = modelService;
|
|
929
|
-
this.widget = this._register(( new MutableDisposable()));
|
|
930
|
-
this.model = this._register(( new MutableDisposable()));
|
|
931
|
-
}
|
|
932
|
-
async update(subject) {
|
|
933
|
-
if (!(subject instanceof MessageSubject)) {
|
|
934
|
-
return this.clear();
|
|
935
|
-
}
|
|
936
|
-
const message = subject.message;
|
|
937
|
-
if (!isDiffable(message)) {
|
|
938
|
-
return this.clear();
|
|
939
|
-
}
|
|
940
|
-
const [original, modified] = await Promise.all([
|
|
941
|
-
this.modelService.createModelReference(subject.expectedUri),
|
|
942
|
-
this.modelService.createModelReference(subject.actualUri),
|
|
943
|
-
]);
|
|
944
|
-
const model = this.model.value = ( new SimpleDiffEditorModel(original, modified));
|
|
945
|
-
if (!this.widget.value) {
|
|
946
|
-
this.widget.value = this.editor ? this.instantiationService.createInstance(EmbeddedDiffEditorWidget, this.container, diffEditorOptions, {}, this.editor) : this.instantiationService.createInstance(DiffEditorWidget, this.container, diffEditorOptions, {});
|
|
947
|
-
if (this.dimension) {
|
|
948
|
-
this.widget.value.layout(this.dimension);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
this.widget.value.setModel(model);
|
|
952
|
-
this.widget.value.updateOptions(this.getOptions(isMultiline(message.expected) || isMultiline(message.actual)));
|
|
953
|
-
}
|
|
954
|
-
clear() {
|
|
955
|
-
this.model.clear();
|
|
956
|
-
this.widget.clear();
|
|
957
|
-
}
|
|
958
|
-
layout(dimensions) {
|
|
959
|
-
this.dimension = dimensions;
|
|
960
|
-
this.widget.value?.layout(dimensions);
|
|
961
|
-
}
|
|
962
|
-
getOptions(isMultiline) {
|
|
963
|
-
return isMultiline
|
|
964
|
-
? { ...diffEditorOptions, lineNumbers: 'on' }
|
|
965
|
-
: { ...diffEditorOptions, lineNumbers: 'off' };
|
|
966
|
-
}
|
|
967
|
-
};
|
|
968
|
-
DiffContentProvider = ( __decorate([
|
|
969
|
-
( __param(2, IInstantiationService)),
|
|
970
|
-
( __param(3, ITextModelService))
|
|
971
|
-
], DiffContentProvider));
|
|
972
|
-
class ScrollableMarkdownMessage extends Disposable {
|
|
973
|
-
constructor(container, markdown, message) {
|
|
974
|
-
super();
|
|
975
|
-
const rendered = this._register(markdown.render(message, {}));
|
|
976
|
-
rendered.element.style.height = '100%';
|
|
977
|
-
rendered.element.style.userSelect = 'text';
|
|
978
|
-
container.appendChild(rendered.element);
|
|
979
|
-
this.element = rendered.element;
|
|
980
|
-
this.scrollable = this._register(( new DomScrollableElement(rendered.element, {
|
|
981
|
-
className: 'preview-text',
|
|
982
|
-
})));
|
|
983
|
-
container.appendChild(this.scrollable.getDomNode());
|
|
984
|
-
this._register(toDisposable(() => {
|
|
985
|
-
container.removeChild(this.scrollable.getDomNode());
|
|
986
|
-
}));
|
|
987
|
-
this.scrollable.scanDomNode();
|
|
988
|
-
}
|
|
989
|
-
layout(height, width) {
|
|
990
|
-
this.scrollable.setScrollDimensions({
|
|
991
|
-
width: width - 32,
|
|
992
|
-
height: height - 16,
|
|
993
|
-
scrollWidth: this.element.scrollWidth,
|
|
994
|
-
scrollHeight: this.element.scrollHeight
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
let MarkdownTestMessagePeek = class MarkdownTestMessagePeek extends Disposable {
|
|
999
|
-
constructor(container, instantiationService) {
|
|
1000
|
-
super();
|
|
1001
|
-
this.container = container;
|
|
1002
|
-
this.instantiationService = instantiationService;
|
|
1003
|
-
this.markdown = ( new Lazy(
|
|
1004
|
-
() => this._register(this.instantiationService.createInstance(MarkdownRenderer, {}))
|
|
1005
|
-
));
|
|
1006
|
-
this.textPreview = this._register(( new MutableDisposable()));
|
|
1007
|
-
}
|
|
1008
|
-
update(subject) {
|
|
1009
|
-
if (!(subject instanceof MessageSubject)) {
|
|
1010
|
-
return this.textPreview.clear();
|
|
1011
|
-
}
|
|
1012
|
-
const message = subject.message;
|
|
1013
|
-
if (isDiffable(message) || typeof message.message === 'string') {
|
|
1014
|
-
return this.textPreview.clear();
|
|
1015
|
-
}
|
|
1016
|
-
this.textPreview.value = ( new ScrollableMarkdownMessage(this.container, this.markdown.value, message.message));
|
|
1017
|
-
}
|
|
1018
|
-
layout(dimension) {
|
|
1019
|
-
this.textPreview.value?.layout(dimension.height, dimension.width);
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1022
|
-
MarkdownTestMessagePeek = ( __decorate([
|
|
1023
|
-
( __param(1, IInstantiationService))
|
|
1024
|
-
], MarkdownTestMessagePeek));
|
|
1025
|
-
let PlainTextMessagePeek = class PlainTextMessagePeek extends Disposable {
|
|
1026
|
-
constructor(editor, container, instantiationService, modelService) {
|
|
1027
|
-
super();
|
|
1028
|
-
this.editor = editor;
|
|
1029
|
-
this.container = container;
|
|
1030
|
-
this.instantiationService = instantiationService;
|
|
1031
|
-
this.modelService = modelService;
|
|
1032
|
-
this.widget = this._register(( new MutableDisposable()));
|
|
1033
|
-
this.model = this._register(( new MutableDisposable()));
|
|
1034
|
-
}
|
|
1035
|
-
async update(subject) {
|
|
1036
|
-
if (!(subject instanceof MessageSubject)) {
|
|
1037
|
-
return this.clear();
|
|
1038
|
-
}
|
|
1039
|
-
const message = subject.message;
|
|
1040
|
-
if (isDiffable(message) || message.type === 1 || typeof message.message !== 'string') {
|
|
1041
|
-
return this.clear();
|
|
1042
|
-
}
|
|
1043
|
-
const modelRef = this.model.value = await this.modelService.createModelReference(subject.messageUri);
|
|
1044
|
-
if (!this.widget.value) {
|
|
1045
|
-
this.widget.value = this.editor ? this.instantiationService.createInstance(EmbeddedCodeEditorWidget, this.container, commonEditorOptions, {}, this.editor) : this.instantiationService.createInstance(CodeEditorWidget, this.container, commonEditorOptions, { isSimpleWidget: true });
|
|
1046
|
-
if (this.dimension) {
|
|
1047
|
-
this.widget.value.layout(this.dimension);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
this.widget.value.setModel(modelRef.object.textEditorModel);
|
|
1051
|
-
this.widget.value.updateOptions(commonEditorOptions);
|
|
1052
|
-
}
|
|
1053
|
-
clear() {
|
|
1054
|
-
this.model.clear();
|
|
1055
|
-
this.widget.clear();
|
|
1056
|
-
}
|
|
1057
|
-
layout(dimensions) {
|
|
1058
|
-
this.dimension = dimensions;
|
|
1059
|
-
this.widget.value?.layout(dimensions);
|
|
1060
|
-
}
|
|
1061
|
-
};
|
|
1062
|
-
PlainTextMessagePeek = ( __decorate([
|
|
1063
|
-
( __param(2, IInstantiationService)),
|
|
1064
|
-
( __param(3, ITextModelService))
|
|
1065
|
-
], PlainTextMessagePeek));
|
|
1066
|
-
let TerminalMessagePeek = class TerminalMessagePeek extends Disposable {
|
|
1067
|
-
constructor(container, isInPeekView, terminalService, viewDescriptorService, workspaceContext) {
|
|
1068
|
-
super();
|
|
1069
|
-
this.container = container;
|
|
1070
|
-
this.isInPeekView = isInPeekView;
|
|
1071
|
-
this.terminalService = terminalService;
|
|
1072
|
-
this.viewDescriptorService = viewDescriptorService;
|
|
1073
|
-
this.workspaceContext = workspaceContext;
|
|
1074
|
-
this.terminalCwd = this._register(( new MutableObservableValue('')));
|
|
1075
|
-
this.xtermLayoutDelayer = this._register(( new Delayer(50)));
|
|
1076
|
-
this.terminal = this._register(( new MutableDisposable()));
|
|
1077
|
-
this.outputDataListener = this._register(( new MutableDisposable()));
|
|
1078
|
-
}
|
|
1079
|
-
async makeTerminal() {
|
|
1080
|
-
const prev = this.terminal.value;
|
|
1081
|
-
if (prev) {
|
|
1082
|
-
prev.xterm.clearBuffer();
|
|
1083
|
-
prev.xterm.clearSearchDecorations();
|
|
1084
|
-
prev.xterm.write(`\x1b[2J\x1b[0;0H`);
|
|
1085
|
-
return prev;
|
|
1086
|
-
}
|
|
1087
|
-
const capabilities = ( new TerminalCapabilityStore());
|
|
1088
|
-
const cwd = this.terminalCwd;
|
|
1089
|
-
capabilities.add(0 , {
|
|
1090
|
-
type: 0 ,
|
|
1091
|
-
get cwds() { return [cwd.value]; },
|
|
1092
|
-
onDidChangeCwd: cwd.onDidChange,
|
|
1093
|
-
getCwd: () => cwd.value,
|
|
1094
|
-
updateCwd: () => { },
|
|
1095
|
-
});
|
|
1096
|
-
return this.terminal.value = await this.terminalService.createDetachedTerminal({
|
|
1097
|
-
rows: 10,
|
|
1098
|
-
cols: 80,
|
|
1099
|
-
readonly: true,
|
|
1100
|
-
capabilities,
|
|
1101
|
-
processInfo: ( new DetachedProcessInfo({ initialCwd: cwd.value })),
|
|
1102
|
-
colorProvider: {
|
|
1103
|
-
getBackgroundColor: theme => {
|
|
1104
|
-
const terminalBackground = theme.getColor(TERMINAL_BACKGROUND_COLOR);
|
|
1105
|
-
if (terminalBackground) {
|
|
1106
|
-
return terminalBackground;
|
|
1107
|
-
}
|
|
1108
|
-
if (this.isInPeekView) {
|
|
1109
|
-
return theme.getColor(peekViewResultsBackground);
|
|
1110
|
-
}
|
|
1111
|
-
const location = this.viewDescriptorService.getViewLocationById("workbench.panel.testResults.view" );
|
|
1112
|
-
return location === 1
|
|
1113
|
-
? theme.getColor(PANEL_BACKGROUND)
|
|
1114
|
-
: theme.getColor(SIDE_BAR_BACKGROUND);
|
|
1115
|
-
},
|
|
1116
|
-
}
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
async update(subject) {
|
|
1120
|
-
this.outputDataListener.clear();
|
|
1121
|
-
if (subject instanceof TaskSubject) {
|
|
1122
|
-
await this.updateForTaskSubject(subject);
|
|
1123
|
-
}
|
|
1124
|
-
else if (subject instanceof TestOutputSubject || ((subject instanceof MessageSubject && subject.message.type === 1) )) {
|
|
1125
|
-
await this.updateForTestSubject(subject);
|
|
1126
|
-
}
|
|
1127
|
-
else {
|
|
1128
|
-
this.clear();
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
async updateForTestSubject(subject) {
|
|
1132
|
-
const that = this;
|
|
1133
|
-
const testItem = subject instanceof TestOutputSubject ? subject.test.item : subject.test;
|
|
1134
|
-
const terminal = await this.updateGenerically({
|
|
1135
|
-
subject,
|
|
1136
|
-
noOutputMessage: ( localizeWithPath(
|
|
1137
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1138
|
-
'caseNoOutput',
|
|
1139
|
-
'The test case did not report any output.'
|
|
1140
|
-
)),
|
|
1141
|
-
getTarget: result => result?.tasks[subject.taskIndex].output,
|
|
1142
|
-
*doInitialWrite(output, results) {
|
|
1143
|
-
that.updateCwd(testItem.uri);
|
|
1144
|
-
const state = subject instanceof TestOutputSubject ? subject.test : results.getStateById(testItem.extId);
|
|
1145
|
-
if (!state) {
|
|
1146
|
-
return;
|
|
1147
|
-
}
|
|
1148
|
-
for (const message of state.tasks[subject.taskIndex].messages) {
|
|
1149
|
-
if (message.type === 1 ) {
|
|
1150
|
-
yield* output.getRangeIter(message.offset, message.length);
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
},
|
|
1154
|
-
doListenForMoreData: (output, result, write) => result.onChange(e => {
|
|
1155
|
-
if (e.reason === 2 && e.item.item.extId === testItem.extId && e.message.type === 1 ) {
|
|
1156
|
-
for (const chunk of output.getRangeIter(e.message.offset, e.message.length)) {
|
|
1157
|
-
write(chunk.buffer);
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
}),
|
|
1161
|
-
});
|
|
1162
|
-
if (subject instanceof MessageSubject && subject.message.type === 1 && subject.message.marker !== undefined) {
|
|
1163
|
-
terminal?.xterm.selectMarkedRange(getMarkId(subject.message.marker, true), getMarkId(subject.message.marker, false), true);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
updateForTaskSubject(subject) {
|
|
1167
|
-
return this.updateGenerically({
|
|
1168
|
-
subject,
|
|
1169
|
-
noOutputMessage: ( localizeWithPath(
|
|
1170
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1171
|
-
'runNoOutput',
|
|
1172
|
-
'The test run did not record any output.'
|
|
1173
|
-
)),
|
|
1174
|
-
getTarget: result => result?.tasks[subject.taskIndex],
|
|
1175
|
-
doInitialWrite: (task, result) => {
|
|
1176
|
-
this.updateCwd(Iterable.find(result.tests, t => !!t.item.uri)?.item.uri);
|
|
1177
|
-
return task.output.buffers;
|
|
1178
|
-
},
|
|
1179
|
-
doListenForMoreData: (task, _result, write) => task.output.onDidWriteData(e => write(e.buffer)),
|
|
1180
|
-
});
|
|
1181
|
-
}
|
|
1182
|
-
async updateGenerically(opts) {
|
|
1183
|
-
const result = opts.subject.result;
|
|
1184
|
-
const target = opts.getTarget(result);
|
|
1185
|
-
if (!target) {
|
|
1186
|
-
return this.clear();
|
|
1187
|
-
}
|
|
1188
|
-
const terminal = await this.makeTerminal();
|
|
1189
|
-
let didWriteData = false;
|
|
1190
|
-
const pendingWrites = ( new MutableObservableValue(0));
|
|
1191
|
-
if (result instanceof LiveTestResult) {
|
|
1192
|
-
for (const chunk of opts.doInitialWrite(target, result)) {
|
|
1193
|
-
didWriteData ||= chunk.byteLength > 0;
|
|
1194
|
-
pendingWrites.value++;
|
|
1195
|
-
terminal.xterm.write(chunk.buffer, () => pendingWrites.value--);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
else {
|
|
1199
|
-
didWriteData = true;
|
|
1200
|
-
this.writeNotice(terminal, ( localizeWithPath(
|
|
1201
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1202
|
-
'runNoOutputForPast',
|
|
1203
|
-
'Test output is only available for new test runs.'
|
|
1204
|
-
)));
|
|
1205
|
-
}
|
|
1206
|
-
this.attachTerminalToDom(terminal);
|
|
1207
|
-
this.outputDataListener.clear();
|
|
1208
|
-
if (result instanceof LiveTestResult && !result.completedAt) {
|
|
1209
|
-
const l1 = result.onComplete(() => {
|
|
1210
|
-
if (!didWriteData) {
|
|
1211
|
-
this.writeNotice(terminal, opts.noOutputMessage);
|
|
1212
|
-
}
|
|
1213
|
-
});
|
|
1214
|
-
const l2 = opts.doListenForMoreData(target, result, data => {
|
|
1215
|
-
terminal.xterm.write(data);
|
|
1216
|
-
didWriteData ||= data.byteLength > 0;
|
|
1217
|
-
});
|
|
1218
|
-
this.outputDataListener.value = combinedDisposable(l1, l2);
|
|
1219
|
-
}
|
|
1220
|
-
if (!this.outputDataListener.value && !didWriteData) {
|
|
1221
|
-
this.writeNotice(terminal, opts.noOutputMessage);
|
|
1222
|
-
}
|
|
1223
|
-
if (pendingWrites.value > 0) {
|
|
1224
|
-
await ( new Promise(resolve => {
|
|
1225
|
-
const l = pendingWrites.onDidChange(() => {
|
|
1226
|
-
if (pendingWrites.value === 0) {
|
|
1227
|
-
l.dispose();
|
|
1228
|
-
resolve();
|
|
1229
|
-
}
|
|
1230
|
-
});
|
|
1231
|
-
}));
|
|
1232
|
-
}
|
|
1233
|
-
return terminal;
|
|
1234
|
-
}
|
|
1235
|
-
updateCwd(testUri) {
|
|
1236
|
-
const wf = (testUri && this.workspaceContext.getWorkspaceFolder(testUri))
|
|
1237
|
-
|| this.workspaceContext.getWorkspace().folders[0];
|
|
1238
|
-
if (wf) {
|
|
1239
|
-
this.terminalCwd.value = wf.uri.fsPath;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
writeNotice(terminal, str) {
|
|
1243
|
-
terminal.xterm.write(formatMessageForTerminal(str));
|
|
1244
|
-
}
|
|
1245
|
-
attachTerminalToDom(terminal) {
|
|
1246
|
-
terminal.xterm.write('\x1b[?25l');
|
|
1247
|
-
scheduleAtNextAnimationFrame(getWindow(this.container), () => this.layoutTerminal(terminal));
|
|
1248
|
-
terminal.attachToElement(this.container, { enableGpu: false });
|
|
1249
|
-
}
|
|
1250
|
-
clear() {
|
|
1251
|
-
this.outputDataListener.clear();
|
|
1252
|
-
this.xtermLayoutDelayer.cancel();
|
|
1253
|
-
this.terminal.clear();
|
|
1254
|
-
}
|
|
1255
|
-
layout(dimensions) {
|
|
1256
|
-
this.dimensions = dimensions;
|
|
1257
|
-
if (this.terminal.value) {
|
|
1258
|
-
this.layoutTerminal(this.terminal.value, dimensions.width, dimensions.height);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
layoutTerminal({ xterm }, width = this.dimensions?.width ?? this.container.clientWidth, height = this.dimensions?.height ?? this.container.clientHeight) {
|
|
1262
|
-
width -= 10 + 20;
|
|
1263
|
-
this.xtermLayoutDelayer.trigger(() => {
|
|
1264
|
-
const scaled = getXtermScaledDimensions(getWindow(this.container), xterm.getFont(), width, height);
|
|
1265
|
-
if (scaled) {
|
|
1266
|
-
xterm.resize(scaled.cols, scaled.rows);
|
|
1267
|
-
}
|
|
1268
|
-
});
|
|
1269
|
-
}
|
|
1270
|
-
};
|
|
1271
|
-
TerminalMessagePeek = ( __decorate([
|
|
1272
|
-
( __param(2, ITerminalService)),
|
|
1273
|
-
( __param(3, IViewDescriptorService)),
|
|
1274
|
-
( __param(4, IWorkspaceContextService))
|
|
1275
|
-
], TerminalMessagePeek));
|
|
1276
|
-
const hintMessagePeekHeight = (msg) => {
|
|
1277
|
-
const msgHeight = isDiffable(msg)
|
|
1278
|
-
? Math.max(hintPeekStrHeight(msg.actual), hintPeekStrHeight(msg.expected))
|
|
1279
|
-
: hintPeekStrHeight(typeof msg.message === 'string' ? msg.message : msg.message.value);
|
|
1280
|
-
return msgHeight + 8;
|
|
1281
|
-
};
|
|
1282
|
-
const firstLine = (str) => {
|
|
1283
|
-
const index = str.indexOf('\n');
|
|
1284
|
-
return index === -1 ? str : str.slice(0, index);
|
|
1285
|
-
};
|
|
1286
|
-
const isMultiline = (str) => !!str && str.includes('\n');
|
|
1287
|
-
const hintPeekStrHeight = (str) => Math.min(count(str, '\n'), 24);
|
|
1288
|
-
class SimpleDiffEditorModel extends EditorModel {
|
|
1289
|
-
constructor(_original, _modified) {
|
|
1290
|
-
super();
|
|
1291
|
-
this._original = _original;
|
|
1292
|
-
this._modified = _modified;
|
|
1293
|
-
this.original = this._original.object.textEditorModel;
|
|
1294
|
-
this.modified = this._modified.object.textEditorModel;
|
|
1295
|
-
}
|
|
1296
|
-
dispose() {
|
|
1297
|
-
super.dispose();
|
|
1298
|
-
this._original.dispose();
|
|
1299
|
-
this._modified.dispose();
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
function getOuterEditorFromDiffEditor(codeEditorService) {
|
|
1303
|
-
const diffEditors = codeEditorService.listDiffEditors();
|
|
1304
|
-
for (const diffEditor of diffEditors) {
|
|
1305
|
-
if (diffEditor.hasTextFocus() && diffEditor instanceof EmbeddedDiffEditorWidget) {
|
|
1306
|
-
return diffEditor.getParentEditor();
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
return null;
|
|
1310
|
-
}
|
|
1311
|
-
class CloseTestPeek extends EditorAction2 {
|
|
1312
|
-
constructor() {
|
|
1313
|
-
super({
|
|
1314
|
-
id: 'editor.closeTestPeek',
|
|
1315
|
-
title: ( localizeWithPath('vs/workbench/contrib/testing/browser/testingOutputPeek', 'close', 'Close')),
|
|
1316
|
-
icon: Codicon.close,
|
|
1317
|
-
precondition: ( ContextKeyExpr.or(TestingContextKeys.isInPeek, TestingContextKeys.isPeekVisible)),
|
|
1318
|
-
keybinding: {
|
|
1319
|
-
weight: 100 - 101,
|
|
1320
|
-
primary: 9 ,
|
|
1321
|
-
when: ContextKeyExpr.not('config.editor.stablePeek')
|
|
1322
|
-
}
|
|
1323
|
-
});
|
|
1324
|
-
}
|
|
1325
|
-
runEditorCommand(accessor, editor) {
|
|
1326
|
-
const parent = getPeekedEditorFromFocus(accessor.get(ICodeEditorService));
|
|
1327
|
-
TestingOutputPeekController.get(parent ?? editor)?.removePeek();
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
class TestResultElement {
|
|
1331
|
-
get icon() {
|
|
1332
|
-
return testingStatesToIcons.get(this.value.completedAt === undefined
|
|
1333
|
-
? 2
|
|
1334
|
-
: maxCountPriority(this.value.counts));
|
|
1335
|
-
}
|
|
1336
|
-
constructor(value) {
|
|
1337
|
-
this.value = value;
|
|
1338
|
-
this.changeEmitter = ( new Emitter());
|
|
1339
|
-
this.onDidChange = this.changeEmitter.event;
|
|
1340
|
-
this.type = 'result';
|
|
1341
|
-
this.context = this.value.id;
|
|
1342
|
-
this.id = this.value.id;
|
|
1343
|
-
this.label = this.value.name;
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
const openCoverageLabel = ( localizeWithPath(
|
|
1347
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1348
|
-
'openTestCoverage',
|
|
1349
|
-
'View Test Coverage'
|
|
1350
|
-
));
|
|
1351
|
-
const closeCoverageLabel = ( localizeWithPath(
|
|
1352
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1353
|
-
'closeTestCoverage',
|
|
1354
|
-
'Close Test Coverage'
|
|
1355
|
-
));
|
|
1356
|
-
class CoverageElement {
|
|
1357
|
-
get label() {
|
|
1358
|
-
return this.isOpen ? closeCoverageLabel : openCoverageLabel;
|
|
1359
|
-
}
|
|
1360
|
-
get icon() {
|
|
1361
|
-
return this.isOpen ? widgetClose : testingCoverageReport;
|
|
1362
|
-
}
|
|
1363
|
-
get isOpen() {
|
|
1364
|
-
return this.coverageService.selected.get()?.fromTaskId === this.task.id;
|
|
1365
|
-
}
|
|
1366
|
-
constructor(results, task, coverageService) {
|
|
1367
|
-
this.results = results;
|
|
1368
|
-
this.task = task;
|
|
1369
|
-
this.coverageService = coverageService;
|
|
1370
|
-
this.type = 'coverage';
|
|
1371
|
-
this.id = `coverage-${this.results.id}/${this.task.id}`;
|
|
1372
|
-
this.onDidChange = Event.fromObservableLight(coverageService.selected);
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
class TestCaseElement {
|
|
1376
|
-
get onDidChange() {
|
|
1377
|
-
if (!(this.results instanceof LiveTestResult)) {
|
|
1378
|
-
return Event.None;
|
|
1379
|
-
}
|
|
1380
|
-
return Event.filter(this.results.onChange, e => e.item.item.extId === this.test.item.extId);
|
|
1381
|
-
}
|
|
1382
|
-
get state() {
|
|
1383
|
-
return this.test.tasks[this.taskIndex].state;
|
|
1384
|
-
}
|
|
1385
|
-
get label() {
|
|
1386
|
-
return this.test.item.label;
|
|
1387
|
-
}
|
|
1388
|
-
get labelWithIcons() {
|
|
1389
|
-
return renderLabelWithIcons(this.label);
|
|
1390
|
-
}
|
|
1391
|
-
get icon() {
|
|
1392
|
-
return testingStatesToIcons.get(this.state);
|
|
1393
|
-
}
|
|
1394
|
-
get outputSubject() {
|
|
1395
|
-
return ( new TestOutputSubject(this.results, this.taskIndex, this.test));
|
|
1396
|
-
}
|
|
1397
|
-
constructor(results, test, taskIndex) {
|
|
1398
|
-
this.results = results;
|
|
1399
|
-
this.test = test;
|
|
1400
|
-
this.taskIndex = taskIndex;
|
|
1401
|
-
this.type = 'test';
|
|
1402
|
-
this.context = this.test.item.extId;
|
|
1403
|
-
this.id = `${this.results.id}/${this.test.item.extId}`;
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
class TaskElement {
|
|
1407
|
-
get icon() {
|
|
1408
|
-
return this.results.tasks[this.index].running ? testingStatesToIcons.get(2 ) : undefined;
|
|
1409
|
-
}
|
|
1410
|
-
constructor(results, task, index) {
|
|
1411
|
-
this.results = results;
|
|
1412
|
-
this.task = task;
|
|
1413
|
-
this.index = index;
|
|
1414
|
-
this.changeEmitter = ( new Emitter());
|
|
1415
|
-
this.onDidChange = this.changeEmitter.event;
|
|
1416
|
-
this.type = 'task';
|
|
1417
|
-
this.itemsCache = ( new CreationCache());
|
|
1418
|
-
this.id = `${results.id}/${index}`;
|
|
1419
|
-
this.task = results.tasks[index];
|
|
1420
|
-
this.context = String(index);
|
|
1421
|
-
this.label = this.task.name ?? ( localizeWithPath(
|
|
1422
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1423
|
-
'testUnnamedTask',
|
|
1424
|
-
'Unnamed Task'
|
|
1425
|
-
));
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
class TestMessageElement {
|
|
1429
|
-
get onDidChange() {
|
|
1430
|
-
if (!(this.result instanceof LiveTestResult)) {
|
|
1431
|
-
return Event.None;
|
|
1432
|
-
}
|
|
1433
|
-
return Event.filter(this.result.onChange, e => e.item.item.extId === this.test.item.extId);
|
|
1434
|
-
}
|
|
1435
|
-
get context() {
|
|
1436
|
-
return {
|
|
1437
|
-
$mid: 18 ,
|
|
1438
|
-
extId: this.test.item.extId,
|
|
1439
|
-
message: ITestMessage.serialize(this.message),
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1442
|
-
constructor(result, test, taskIndex, messageIndex) {
|
|
1443
|
-
this.result = result;
|
|
1444
|
-
this.test = test;
|
|
1445
|
-
this.taskIndex = taskIndex;
|
|
1446
|
-
this.messageIndex = messageIndex;
|
|
1447
|
-
this.type = 'message';
|
|
1448
|
-
const m = this.message = test.tasks[taskIndex].messages[messageIndex];
|
|
1449
|
-
this.location = m.location;
|
|
1450
|
-
this.contextValue = m.type === 0 ? m.contextValue : undefined;
|
|
1451
|
-
this.uri = buildTestUri({
|
|
1452
|
-
type: 2 ,
|
|
1453
|
-
messageIndex,
|
|
1454
|
-
resultId: result.id,
|
|
1455
|
-
taskIndex,
|
|
1456
|
-
testExtId: test.item.extId
|
|
1457
|
-
});
|
|
1458
|
-
this.id = ( this.uri.toString());
|
|
1459
|
-
const asPlaintext = renderStringAsPlaintext(m.message);
|
|
1460
|
-
const lines = count(asPlaintext.trimEnd(), '\n');
|
|
1461
|
-
this.label = firstLine(asPlaintext);
|
|
1462
|
-
if (lines > 0) {
|
|
1463
|
-
this.description = lines > 1
|
|
1464
|
-
? ( localizeWithPath(
|
|
1465
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1466
|
-
'messageMoreLinesN',
|
|
1467
|
-
'+ {0} more lines',
|
|
1468
|
-
lines
|
|
1469
|
-
))
|
|
1470
|
-
: ( localizeWithPath(
|
|
1471
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1472
|
-
'messageMoreLines1',
|
|
1473
|
-
'+ 1 more line'
|
|
1474
|
-
));
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
let OutputPeekTree = class OutputPeekTree extends Disposable {
|
|
1479
|
-
constructor(container, onDidReveal, options, contextMenuService, results, instantiationService, explorerFilter, coverageService, progressService) {
|
|
1480
|
-
super();
|
|
1481
|
-
this.contextMenuService = contextMenuService;
|
|
1482
|
-
this.disposed = false;
|
|
1483
|
-
this.requestReveal = this._register(( new Emitter()));
|
|
1484
|
-
this.onDidRequestReview = this.requestReveal.event;
|
|
1485
|
-
this.treeActions = instantiationService.createInstance(TreeActionsProvider, options.showRevealLocationOnMessages, this.requestReveal);
|
|
1486
|
-
const diffIdentityProvider = {
|
|
1487
|
-
getId(e) {
|
|
1488
|
-
return e.id;
|
|
1489
|
-
}
|
|
1490
|
-
};
|
|
1491
|
-
this.tree = this._register(instantiationService.createInstance(WorkbenchCompressibleObjectTree, 'Test Output Peek', container, {
|
|
1492
|
-
getHeight: () => 22,
|
|
1493
|
-
getTemplateId: () => TestRunElementRenderer.ID,
|
|
1494
|
-
}, [instantiationService.createInstance(TestRunElementRenderer, this.treeActions)], {
|
|
1495
|
-
compressionEnabled: true,
|
|
1496
|
-
hideTwistiesOfChildlessElements: true,
|
|
1497
|
-
identityProvider: diffIdentityProvider,
|
|
1498
|
-
sorter: {
|
|
1499
|
-
compare(a, b) {
|
|
1500
|
-
if (a instanceof TestCaseElement && b instanceof TestCaseElement) {
|
|
1501
|
-
return cmpPriority(a.state, b.state);
|
|
1502
|
-
}
|
|
1503
|
-
return 0;
|
|
1504
|
-
},
|
|
1505
|
-
},
|
|
1506
|
-
accessibilityProvider: {
|
|
1507
|
-
getAriaLabel(element) {
|
|
1508
|
-
return element.ariaLabel || element.label;
|
|
1509
|
-
},
|
|
1510
|
-
getWidgetAriaLabel() {
|
|
1511
|
-
return ( localizeWithPath(
|
|
1512
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1513
|
-
'testingPeekLabel',
|
|
1514
|
-
'Test Result Messages'
|
|
1515
|
-
));
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
}));
|
|
1519
|
-
const cc = ( new CreationCache());
|
|
1520
|
-
const getTaskChildren = (taskElem) => {
|
|
1521
|
-
const { results, index, itemsCache, task } = taskElem;
|
|
1522
|
-
const tests = Iterable.filter(results.tests, test => test.tasks[index].state >= 2 || test.tasks[index].messages.length > 0);
|
|
1523
|
-
let result = ( Iterable.map(tests, test => ({
|
|
1524
|
-
element: itemsCache.getOrCreate(test, () => ( new TestCaseElement(results, test, index))),
|
|
1525
|
-
incompressible: true,
|
|
1526
|
-
children: getTestChildren(results, test, index),
|
|
1527
|
-
})));
|
|
1528
|
-
if (task.coverage.get()) {
|
|
1529
|
-
result = Iterable.concat(Iterable.single({
|
|
1530
|
-
element: ( new CoverageElement(results, task, coverageService)),
|
|
1531
|
-
}), result);
|
|
1532
|
-
}
|
|
1533
|
-
return result;
|
|
1534
|
-
};
|
|
1535
|
-
const getTestChildren = (result, test, taskIndex) => {
|
|
1536
|
-
return ( test.tasks[taskIndex].messages
|
|
1537
|
-
.map((m, messageIndex) => m.type === 0
|
|
1538
|
-
? { element: cc.getOrCreate(m, () => ( new TestMessageElement(result, test, taskIndex, messageIndex))), incompressible: false }
|
|
1539
|
-
: undefined))
|
|
1540
|
-
.filter(isDefined);
|
|
1541
|
-
};
|
|
1542
|
-
const getResultChildren = (result) => {
|
|
1543
|
-
return ( result.tasks.map((task, taskIndex) => {
|
|
1544
|
-
const taskElem = cc.getOrCreate(task, () => ( new TaskElement(result, task, taskIndex)));
|
|
1545
|
-
return ({
|
|
1546
|
-
element: taskElem,
|
|
1547
|
-
incompressible: false,
|
|
1548
|
-
children: getTaskChildren(taskElem),
|
|
1549
|
-
});
|
|
1550
|
-
}));
|
|
1551
|
-
};
|
|
1552
|
-
const getRootChildren = () => ( results.results.map(result => {
|
|
1553
|
-
const element = cc.getOrCreate(result, () => ( new TestResultElement(result)));
|
|
1554
|
-
return {
|
|
1555
|
-
element,
|
|
1556
|
-
incompressible: true,
|
|
1557
|
-
collapsed: this.tree.hasElement(element) ? this.tree.isCollapsed(element) : true,
|
|
1558
|
-
children: getResultChildren(result)
|
|
1559
|
-
};
|
|
1560
|
-
}));
|
|
1561
|
-
const taskChildrenToUpdate = ( new Set());
|
|
1562
|
-
const taskChildrenUpdate = this._register(( new RunOnceScheduler(() => {
|
|
1563
|
-
for (const taskNode of taskChildrenToUpdate) {
|
|
1564
|
-
if (this.tree.hasElement(taskNode)) {
|
|
1565
|
-
this.tree.setChildren(taskNode, getTaskChildren(taskNode), { diffIdentityProvider });
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
taskChildrenToUpdate.clear();
|
|
1569
|
-
}, 300)));
|
|
1570
|
-
const queueTaskChildrenUpdate = (taskNode) => {
|
|
1571
|
-
taskChildrenToUpdate.add(taskNode);
|
|
1572
|
-
if (!taskChildrenUpdate.isScheduled()) {
|
|
1573
|
-
taskChildrenUpdate.schedule();
|
|
1574
|
-
}
|
|
1575
|
-
};
|
|
1576
|
-
const attachToResults = (result) => {
|
|
1577
|
-
const resultNode = cc.get(result);
|
|
1578
|
-
const disposable = ( new DisposableStore());
|
|
1579
|
-
disposable.add(result.onNewTask(i => {
|
|
1580
|
-
if (result.tasks.length === 1) {
|
|
1581
|
-
this.requestReveal.fire(( new TaskSubject(result, 0)));
|
|
1582
|
-
}
|
|
1583
|
-
if (this.tree.hasElement(resultNode)) {
|
|
1584
|
-
this.tree.setChildren(resultNode, getResultChildren(result), { diffIdentityProvider });
|
|
1585
|
-
}
|
|
1586
|
-
const task = result.tasks[i];
|
|
1587
|
-
disposable.add(autorun(reader => {
|
|
1588
|
-
task.coverage.read(reader);
|
|
1589
|
-
queueTaskChildrenUpdate(cc.get(task));
|
|
1590
|
-
}));
|
|
1591
|
-
}));
|
|
1592
|
-
disposable.add(result.onEndTask(index => {
|
|
1593
|
-
cc.get(result.tasks[index])?.changeEmitter.fire();
|
|
1594
|
-
}));
|
|
1595
|
-
disposable.add(result.onChange(e => {
|
|
1596
|
-
for (const [index, task] of result.tasks.entries()) {
|
|
1597
|
-
const taskNode = cc.get(task);
|
|
1598
|
-
if (!this.tree.hasElement(taskNode)) {
|
|
1599
|
-
continue;
|
|
1600
|
-
}
|
|
1601
|
-
const itemNode = taskNode.itemsCache.get(e.item);
|
|
1602
|
-
if (itemNode && this.tree.hasElement(itemNode)) {
|
|
1603
|
-
if (e.reason === 2 && e.message.type === 0 ) {
|
|
1604
|
-
this.tree.setChildren(itemNode, getTestChildren(result, e.item, index), { diffIdentityProvider });
|
|
1605
|
-
}
|
|
1606
|
-
return;
|
|
1607
|
-
}
|
|
1608
|
-
queueTaskChildrenUpdate(taskNode);
|
|
1609
|
-
}
|
|
1610
|
-
}));
|
|
1611
|
-
disposable.add(result.onComplete(() => {
|
|
1612
|
-
resultNode.changeEmitter.fire();
|
|
1613
|
-
disposable.dispose();
|
|
1614
|
-
}));
|
|
1615
|
-
return resultNode;
|
|
1616
|
-
};
|
|
1617
|
-
this._register(results.onResultsChanged(e => {
|
|
1618
|
-
if (this.disposed) {
|
|
1619
|
-
return;
|
|
1620
|
-
}
|
|
1621
|
-
if ('completed' in e) {
|
|
1622
|
-
cc.get(e.completed)?.changeEmitter.fire();
|
|
1623
|
-
return;
|
|
1624
|
-
}
|
|
1625
|
-
this.tree.setChildren(null, getRootChildren(), { diffIdentityProvider });
|
|
1626
|
-
if ('started' in e) {
|
|
1627
|
-
for (const child of this.tree.getNode(null).children) {
|
|
1628
|
-
this.tree.collapse(child.element, false);
|
|
1629
|
-
}
|
|
1630
|
-
this.tree.expand(attachToResults(e.started), true);
|
|
1631
|
-
}
|
|
1632
|
-
}));
|
|
1633
|
-
const revealItem = (element, preserveFocus) => {
|
|
1634
|
-
this.tree.setFocus([element]);
|
|
1635
|
-
this.tree.setSelection([element]);
|
|
1636
|
-
if (!preserveFocus) {
|
|
1637
|
-
this.tree.domFocus();
|
|
1638
|
-
}
|
|
1639
|
-
};
|
|
1640
|
-
this._register(onDidReveal(async ({ subject, preserveFocus = false }) => {
|
|
1641
|
-
if (subject instanceof TaskSubject) {
|
|
1642
|
-
const resultItem = this.tree.getNode(null).children.find(c => {
|
|
1643
|
-
if (c.element instanceof TaskElement) {
|
|
1644
|
-
return c.element.results.id === subject.result.id && c.element.index === subject.taskIndex;
|
|
1645
|
-
}
|
|
1646
|
-
if (c.element instanceof TestResultElement) {
|
|
1647
|
-
return c.element.id === subject.result.id;
|
|
1648
|
-
}
|
|
1649
|
-
return false;
|
|
1650
|
-
});
|
|
1651
|
-
if (resultItem) {
|
|
1652
|
-
revealItem(resultItem.element, preserveFocus);
|
|
1653
|
-
}
|
|
1654
|
-
return;
|
|
1655
|
-
}
|
|
1656
|
-
const revealElement = subject instanceof TestOutputSubject
|
|
1657
|
-
? cc.get(subject.task)?.itemsCache.get(subject.test)
|
|
1658
|
-
: cc.get(subject.message);
|
|
1659
|
-
if (!revealElement || !this.tree.hasElement(revealElement)) {
|
|
1660
|
-
return;
|
|
1661
|
-
}
|
|
1662
|
-
const parents = [];
|
|
1663
|
-
for (let parent = this.tree.getParentElement(revealElement); parent; parent = this.tree.getParentElement(parent)) {
|
|
1664
|
-
parents.unshift(parent);
|
|
1665
|
-
}
|
|
1666
|
-
for (const parent of parents) {
|
|
1667
|
-
this.tree.expand(parent);
|
|
1668
|
-
}
|
|
1669
|
-
if (this.tree.getRelativeTop(revealElement) === null) {
|
|
1670
|
-
this.tree.reveal(revealElement, 0.5);
|
|
1671
|
-
}
|
|
1672
|
-
revealItem(revealElement, preserveFocus);
|
|
1673
|
-
}));
|
|
1674
|
-
this._register(this.tree.onDidOpen(async (e) => {
|
|
1675
|
-
if (e.element instanceof TestMessageElement) {
|
|
1676
|
-
this.requestReveal.fire(( new MessageSubject(
|
|
1677
|
-
e.element.result,
|
|
1678
|
-
e.element.test,
|
|
1679
|
-
e.element.taskIndex,
|
|
1680
|
-
e.element.messageIndex
|
|
1681
|
-
)));
|
|
1682
|
-
}
|
|
1683
|
-
else if (e.element instanceof TestCaseElement) {
|
|
1684
|
-
const t = e.element;
|
|
1685
|
-
const message = mapFindTestMessage(e.element.test, (_t, _m, mesasgeIndex, taskIndex) => ( new MessageSubject(t.results, t.test, taskIndex, mesasgeIndex)));
|
|
1686
|
-
this.requestReveal.fire(message || ( new TestOutputSubject(t.results, 0, t.test)));
|
|
1687
|
-
}
|
|
1688
|
-
else if (e.element instanceof CoverageElement) {
|
|
1689
|
-
const task = e.element.task;
|
|
1690
|
-
if (e.element.isOpen) {
|
|
1691
|
-
return coverageService.closeCoverage();
|
|
1692
|
-
}
|
|
1693
|
-
progressService.withProgress({ location: options.locationForProgress }, () => coverageService.openCoverage(task, true));
|
|
1694
|
-
}
|
|
1695
|
-
}));
|
|
1696
|
-
this._register(this.tree.onDidChangeSelection(evt => {
|
|
1697
|
-
for (const element of evt.elements) {
|
|
1698
|
-
if (element && 'test' in element) {
|
|
1699
|
-
explorerFilter.reveal.value = element.test.item.extId;
|
|
1700
|
-
break;
|
|
1701
|
-
}
|
|
1702
|
-
}
|
|
1703
|
-
}));
|
|
1704
|
-
this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
|
|
1705
|
-
this.tree.setChildren(null, getRootChildren());
|
|
1706
|
-
for (const result of results.results) {
|
|
1707
|
-
if (!result.completedAt && result instanceof LiveTestResult) {
|
|
1708
|
-
attachToResults(result);
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
}
|
|
1712
|
-
layout(height, width) {
|
|
1713
|
-
this.tree.layout(height, width);
|
|
1714
|
-
}
|
|
1715
|
-
onContextMenu(evt) {
|
|
1716
|
-
if (!evt.element) {
|
|
1717
|
-
return;
|
|
1718
|
-
}
|
|
1719
|
-
const actions = this.treeActions.provideActionBar(evt.element);
|
|
1720
|
-
this.contextMenuService.showContextMenu({
|
|
1721
|
-
getAnchor: () => evt.anchor,
|
|
1722
|
-
getActions: () => actions.secondary.length
|
|
1723
|
-
? [...actions.primary, ( new Separator()), ...actions.secondary]
|
|
1724
|
-
: actions.primary,
|
|
1725
|
-
getActionsContext: () => evt.element?.context
|
|
1726
|
-
});
|
|
1727
|
-
}
|
|
1728
|
-
dispose() {
|
|
1729
|
-
super.dispose();
|
|
1730
|
-
this.disposed = true;
|
|
1731
|
-
}
|
|
1732
|
-
};
|
|
1733
|
-
OutputPeekTree = ( __decorate([
|
|
1734
|
-
( __param(3, IContextMenuService)),
|
|
1735
|
-
( __param(4, ITestResultService)),
|
|
1736
|
-
( __param(5, IInstantiationService)),
|
|
1737
|
-
( __param(6, ITestExplorerFilterState)),
|
|
1738
|
-
( __param(7, ITestCoverageService)),
|
|
1739
|
-
( __param(8, IProgressService))
|
|
1740
|
-
], OutputPeekTree));
|
|
1741
|
-
let TestRunElementRenderer = class TestRunElementRenderer {
|
|
1742
|
-
static { TestRunElementRenderer_1 = this; }
|
|
1743
|
-
static { this.ID = 'testRunElementRenderer'; }
|
|
1744
|
-
constructor(treeActions, instantiationService) {
|
|
1745
|
-
this.treeActions = treeActions;
|
|
1746
|
-
this.instantiationService = instantiationService;
|
|
1747
|
-
this.templateId = TestRunElementRenderer_1.ID;
|
|
1748
|
-
}
|
|
1749
|
-
renderCompressedElements(node, _index, templateData) {
|
|
1750
|
-
const chain = node.element.elements;
|
|
1751
|
-
const lastElement = chain[chain.length - 1];
|
|
1752
|
-
if ((lastElement instanceof TaskElement || lastElement instanceof TestMessageElement) && chain.length >= 2) {
|
|
1753
|
-
this.doRender(chain[chain.length - 2], templateData, lastElement);
|
|
1754
|
-
}
|
|
1755
|
-
else {
|
|
1756
|
-
this.doRender(lastElement, templateData);
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
renderTemplate(container) {
|
|
1760
|
-
const templateDisposable = ( new DisposableStore());
|
|
1761
|
-
const wrapper = append(container, $('.test-peek-item'));
|
|
1762
|
-
const icon = append(wrapper, $('.state'));
|
|
1763
|
-
const label = append(wrapper, $('.name'));
|
|
1764
|
-
const actionBar = ( new ActionBar(wrapper, {
|
|
1765
|
-
actionViewItemProvider: action => action instanceof MenuItemAction
|
|
1766
|
-
? this.instantiationService.createInstance(MenuEntryActionViewItem, action, undefined)
|
|
1767
|
-
: undefined
|
|
1768
|
-
}));
|
|
1769
|
-
const elementDisposable = ( new DisposableStore());
|
|
1770
|
-
templateDisposable.add(elementDisposable);
|
|
1771
|
-
templateDisposable.add(actionBar);
|
|
1772
|
-
return {
|
|
1773
|
-
icon,
|
|
1774
|
-
label,
|
|
1775
|
-
actionBar,
|
|
1776
|
-
elementDisposable,
|
|
1777
|
-
templateDisposable,
|
|
1778
|
-
};
|
|
1779
|
-
}
|
|
1780
|
-
renderElement(element, _index, templateData) {
|
|
1781
|
-
this.doRender(element.element, templateData);
|
|
1782
|
-
}
|
|
1783
|
-
disposeTemplate(templateData) {
|
|
1784
|
-
templateData.templateDisposable.dispose();
|
|
1785
|
-
}
|
|
1786
|
-
doRender(element, templateData, subjectElement) {
|
|
1787
|
-
templateData.elementDisposable.clear();
|
|
1788
|
-
templateData.elementDisposable.add(element.onDidChange(() => this.doRender(element, templateData, subjectElement)));
|
|
1789
|
-
this.doRenderInner(element, templateData, subjectElement);
|
|
1790
|
-
}
|
|
1791
|
-
doRenderInner(element, templateData, subjectElement) {
|
|
1792
|
-
let { label, labelWithIcons, description } = element;
|
|
1793
|
-
if (subjectElement instanceof TestMessageElement) {
|
|
1794
|
-
description = subjectElement.label;
|
|
1795
|
-
}
|
|
1796
|
-
const descriptionElement = description ? $('span.test-label-description', {}, description) : '';
|
|
1797
|
-
if (labelWithIcons) {
|
|
1798
|
-
reset(templateData.label, ...labelWithIcons, descriptionElement);
|
|
1799
|
-
}
|
|
1800
|
-
else {
|
|
1801
|
-
reset(templateData.label, label, descriptionElement);
|
|
1802
|
-
}
|
|
1803
|
-
const icon = element.icon;
|
|
1804
|
-
templateData.icon.className = `computed-state ${icon ? ThemeIcon.asClassName(icon) : ''}`;
|
|
1805
|
-
const actions = this.treeActions.provideActionBar(element);
|
|
1806
|
-
templateData.actionBar.clear();
|
|
1807
|
-
templateData.actionBar.context = element.context;
|
|
1808
|
-
templateData.actionBar.push(actions.primary, { icon: true, label: false });
|
|
1809
|
-
}
|
|
1810
|
-
};
|
|
1811
|
-
TestRunElementRenderer = TestRunElementRenderer_1 = ( __decorate([
|
|
1812
|
-
( __param(1, IInstantiationService))
|
|
1813
|
-
], TestRunElementRenderer));
|
|
1814
|
-
let TreeActionsProvider = class TreeActionsProvider {
|
|
1815
|
-
constructor(showRevealLocationOnMessages, requestReveal, contextKeyService, menuService, commandService, testProfileService, editorService) {
|
|
1816
|
-
this.showRevealLocationOnMessages = showRevealLocationOnMessages;
|
|
1817
|
-
this.requestReveal = requestReveal;
|
|
1818
|
-
this.contextKeyService = contextKeyService;
|
|
1819
|
-
this.menuService = menuService;
|
|
1820
|
-
this.commandService = commandService;
|
|
1821
|
-
this.testProfileService = testProfileService;
|
|
1822
|
-
this.editorService = editorService;
|
|
1823
|
-
}
|
|
1824
|
-
provideActionBar(element) {
|
|
1825
|
-
const test = element instanceof TestCaseElement ? element.test : undefined;
|
|
1826
|
-
const capabilities = test ? this.testProfileService.capabilitiesForTest(test) : 0;
|
|
1827
|
-
const contextKeys = [
|
|
1828
|
-
['peek', "editor.contrib.testingOutputPeek" ],
|
|
1829
|
-
[TestingContextKeys.peekItemType.key, element.type],
|
|
1830
|
-
];
|
|
1831
|
-
let id = MenuId.TestPeekElement;
|
|
1832
|
-
const primary = [];
|
|
1833
|
-
const secondary = [];
|
|
1834
|
-
if (element instanceof TaskElement) {
|
|
1835
|
-
primary.push(( new Action('testing.outputPeek.showResultOutput', ( localizeWithPath(
|
|
1836
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1837
|
-
'testing.showResultOutput',
|
|
1838
|
-
"Show Result Output"
|
|
1839
|
-
)), ThemeIcon.asClassName(Codicon.terminal), undefined, () => this.requestReveal.fire(( new TaskSubject(element.results, element.index))))));
|
|
1840
|
-
}
|
|
1841
|
-
if (element instanceof TestResultElement) {
|
|
1842
|
-
if (element.value.tasks.length === 1) {
|
|
1843
|
-
primary.push(( new Action('testing.outputPeek.showResultOutput', ( localizeWithPath(
|
|
1844
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1845
|
-
'testing.showResultOutput',
|
|
1846
|
-
"Show Result Output"
|
|
1847
|
-
)), ThemeIcon.asClassName(Codicon.terminal), undefined, () => this.requestReveal.fire(( new TaskSubject(element.value, 0))))));
|
|
1848
|
-
}
|
|
1849
|
-
primary.push(( new Action('testing.outputPeek.reRunLastRun', ( localizeWithPath(
|
|
1850
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1851
|
-
'testing.reRunLastRun',
|
|
1852
|
-
"Rerun Test Run"
|
|
1853
|
-
)), ThemeIcon.asClassName(testingRunIcon), undefined, () => this.commandService.executeCommand('testing.reRunLastRun', element.value.id))));
|
|
1854
|
-
if (capabilities & 4 ) {
|
|
1855
|
-
primary.push(( new Action('testing.outputPeek.debugLastRun', ( localizeWithPath(
|
|
1856
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1857
|
-
'testing.debugLastRun',
|
|
1858
|
-
"Debug Test Run"
|
|
1859
|
-
)), ThemeIcon.asClassName(testingDebugIcon), undefined, () => this.commandService.executeCommand('testing.debugLastRun', element.value.id))));
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
if (element instanceof TestCaseElement || element instanceof TestMessageElement) {
|
|
1863
|
-
contextKeys.push([TestingContextKeys.testResultOutdated.key, element.test.retired], ...getTestItemContextOverlay(element.test, capabilities));
|
|
1864
|
-
}
|
|
1865
|
-
if (element instanceof TestCaseElement) {
|
|
1866
|
-
const extId = element.test.item.extId;
|
|
1867
|
-
if (( element.test.tasks[element.taskIndex].messages.some(m => m.type === 1 ))) {
|
|
1868
|
-
primary.push(( new Action('testing.outputPeek.showResultOutput', ( localizeWithPath(
|
|
1869
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1870
|
-
'testing.showResultOutput',
|
|
1871
|
-
"Show Result Output"
|
|
1872
|
-
)), ThemeIcon.asClassName(Codicon.terminal), undefined, () => this.requestReveal.fire(element.outputSubject))));
|
|
1873
|
-
}
|
|
1874
|
-
secondary.push(( new Action('testing.outputPeek.revealInExplorer', ( localizeWithPath(
|
|
1875
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1876
|
-
'testing.revealInExplorer',
|
|
1877
|
-
"Reveal in Test Explorer"
|
|
1878
|
-
)), ThemeIcon.asClassName(Codicon.listTree), undefined, () => this.commandService.executeCommand('_revealTestInExplorer', extId))));
|
|
1879
|
-
if (capabilities & 2 ) {
|
|
1880
|
-
primary.push(( new Action('testing.outputPeek.runTest', ( localizeWithPath(
|
|
1881
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1882
|
-
'run test',
|
|
1883
|
-
'Run Test'
|
|
1884
|
-
)), ThemeIcon.asClassName(testingRunIcon), undefined, () => this.commandService.executeCommand('vscode.runTestsById', 2 , extId))));
|
|
1885
|
-
}
|
|
1886
|
-
if (capabilities & 4 ) {
|
|
1887
|
-
primary.push(( new Action('testing.outputPeek.debugTest', ( localizeWithPath(
|
|
1888
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1889
|
-
'debug test',
|
|
1890
|
-
'Debug Test'
|
|
1891
|
-
)), ThemeIcon.asClassName(testingDebugIcon), undefined, () => this.commandService.executeCommand('vscode.runTestsById', 4 , extId))));
|
|
1892
|
-
}
|
|
1893
|
-
primary.push(( new Action('testing.outputPeek.goToFile', ( localizeWithPath(
|
|
1894
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1895
|
-
'testing.goToFile',
|
|
1896
|
-
"Go to Source"
|
|
1897
|
-
)), ThemeIcon.asClassName(Codicon.goToFile), undefined, () => this.commandService.executeCommand('vscode.revealTest', extId))));
|
|
1898
|
-
}
|
|
1899
|
-
if (element instanceof TestMessageElement) {
|
|
1900
|
-
id = MenuId.TestMessageContext;
|
|
1901
|
-
contextKeys.push([TestingContextKeys.testMessageContext.key, element.contextValue]);
|
|
1902
|
-
if (this.showRevealLocationOnMessages && element.location) {
|
|
1903
|
-
primary.push(( new Action('testing.outputPeek.goToError', ( localizeWithPath(
|
|
1904
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1905
|
-
'testing.goToError',
|
|
1906
|
-
"Go to Source"
|
|
1907
|
-
)), ThemeIcon.asClassName(Codicon.goToFile), undefined, () => this.editorService.openEditor({
|
|
1908
|
-
resource: element.location.uri,
|
|
1909
|
-
options: {
|
|
1910
|
-
selection: element.location.range,
|
|
1911
|
-
preserveFocus: true,
|
|
1912
|
-
}
|
|
1913
|
-
}))));
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
const contextOverlay = this.contextKeyService.createOverlay(contextKeys);
|
|
1917
|
-
const result = { primary, secondary };
|
|
1918
|
-
const menu = this.menuService.createMenu(id, contextOverlay);
|
|
1919
|
-
try {
|
|
1920
|
-
createAndFillInActionBarActions(menu, { arg: element.context }, result, 'inline');
|
|
1921
|
-
return result;
|
|
1922
|
-
}
|
|
1923
|
-
finally {
|
|
1924
|
-
menu.dispose();
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
};
|
|
1928
|
-
TreeActionsProvider = ( __decorate([
|
|
1929
|
-
( __param(2, IContextKeyService)),
|
|
1930
|
-
( __param(3, IMenuService)),
|
|
1931
|
-
( __param(4, ICommandService)),
|
|
1932
|
-
( __param(5, ITestProfileService)),
|
|
1933
|
-
( __param(6, IEditorService))
|
|
1934
|
-
], TreeActionsProvider));
|
|
1935
|
-
const navWhen = ( ContextKeyExpr.and(EditorContextKeys.focus, TestingContextKeys.isPeekVisible));
|
|
1936
|
-
const getPeekedEditorFromFocus = (codeEditorService) => {
|
|
1937
|
-
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
|
|
1938
|
-
return editor && getPeekedEditor(codeEditorService, editor);
|
|
1939
|
-
};
|
|
1940
|
-
const getPeekedEditor = (codeEditorService, editor) => {
|
|
1941
|
-
if (TestingOutputPeekController.get(editor)?.subject) {
|
|
1942
|
-
return editor;
|
|
1943
|
-
}
|
|
1944
|
-
if (editor instanceof EmbeddedCodeEditorWidget) {
|
|
1945
|
-
return editor.getParentEditor();
|
|
1946
|
-
}
|
|
1947
|
-
const outer = getOuterEditorFromDiffEditor(codeEditorService);
|
|
1948
|
-
if (outer) {
|
|
1949
|
-
return outer;
|
|
1950
|
-
}
|
|
1951
|
-
return editor;
|
|
1952
|
-
};
|
|
1953
|
-
class GoToNextMessageAction extends Action2 {
|
|
1954
|
-
static { this.ID = 'testing.goToNextMessage'; }
|
|
1955
|
-
constructor() {
|
|
1956
|
-
super({
|
|
1957
|
-
id: GoToNextMessageAction.ID,
|
|
1958
|
-
f1: true,
|
|
1959
|
-
title: ( localize2WithPath(
|
|
1960
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1961
|
-
'testing.goToNextMessage',
|
|
1962
|
-
'Go to Next Test Failure'
|
|
1963
|
-
)),
|
|
1964
|
-
icon: Codicon.arrowDown,
|
|
1965
|
-
category: Categories.Test,
|
|
1966
|
-
keybinding: {
|
|
1967
|
-
primary: 512 | 66 ,
|
|
1968
|
-
weight: 100 + 1,
|
|
1969
|
-
when: navWhen,
|
|
1970
|
-
},
|
|
1971
|
-
menu: [{
|
|
1972
|
-
id: MenuId.TestPeekTitle,
|
|
1973
|
-
group: 'navigation',
|
|
1974
|
-
order: 2,
|
|
1975
|
-
}, {
|
|
1976
|
-
id: MenuId.CommandPalette,
|
|
1977
|
-
when: navWhen
|
|
1978
|
-
}],
|
|
1979
|
-
});
|
|
1980
|
-
}
|
|
1981
|
-
run(accessor) {
|
|
1982
|
-
const editor = getPeekedEditorFromFocus(accessor.get(ICodeEditorService));
|
|
1983
|
-
if (editor) {
|
|
1984
|
-
TestingOutputPeekController.get(editor)?.next();
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
}
|
|
1988
|
-
class GoToPreviousMessageAction extends Action2 {
|
|
1989
|
-
static { this.ID = 'testing.goToPreviousMessage'; }
|
|
1990
|
-
constructor() {
|
|
1991
|
-
super({
|
|
1992
|
-
id: GoToPreviousMessageAction.ID,
|
|
1993
|
-
f1: true,
|
|
1994
|
-
title: ( localize2WithPath(
|
|
1995
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
1996
|
-
'testing.goToPreviousMessage',
|
|
1997
|
-
'Go to Previous Test Failure'
|
|
1998
|
-
)),
|
|
1999
|
-
icon: Codicon.arrowUp,
|
|
2000
|
-
category: Categories.Test,
|
|
2001
|
-
keybinding: {
|
|
2002
|
-
primary: 1024 | 512 | 66 ,
|
|
2003
|
-
weight: 100 + 1,
|
|
2004
|
-
when: navWhen
|
|
2005
|
-
},
|
|
2006
|
-
menu: [{
|
|
2007
|
-
id: MenuId.TestPeekTitle,
|
|
2008
|
-
group: 'navigation',
|
|
2009
|
-
order: 1,
|
|
2010
|
-
}, {
|
|
2011
|
-
id: MenuId.CommandPalette,
|
|
2012
|
-
when: navWhen
|
|
2013
|
-
}],
|
|
2014
|
-
});
|
|
2015
|
-
}
|
|
2016
|
-
run(accessor) {
|
|
2017
|
-
const editor = getPeekedEditorFromFocus(accessor.get(ICodeEditorService));
|
|
2018
|
-
if (editor) {
|
|
2019
|
-
TestingOutputPeekController.get(editor)?.previous();
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
class OpenMessageInEditorAction extends Action2 {
|
|
2024
|
-
static { this.ID = 'testing.openMessageInEditor'; }
|
|
2025
|
-
constructor() {
|
|
2026
|
-
super({
|
|
2027
|
-
id: OpenMessageInEditorAction.ID,
|
|
2028
|
-
f1: false,
|
|
2029
|
-
title: ( localize2WithPath(
|
|
2030
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
2031
|
-
'testing.openMessageInEditor',
|
|
2032
|
-
'Open in Editor'
|
|
2033
|
-
)),
|
|
2034
|
-
icon: Codicon.goToFile,
|
|
2035
|
-
category: Categories.Test,
|
|
2036
|
-
menu: [{ id: MenuId.TestPeekTitle }],
|
|
2037
|
-
});
|
|
2038
|
-
}
|
|
2039
|
-
run(accessor) {
|
|
2040
|
-
accessor.get(ITestingPeekOpener).openCurrentInEditor();
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
class ToggleTestingPeekHistory extends Action2 {
|
|
2044
|
-
static { this.ID = 'testing.toggleTestingPeekHistory'; }
|
|
2045
|
-
constructor() {
|
|
2046
|
-
super({
|
|
2047
|
-
id: ToggleTestingPeekHistory.ID,
|
|
2048
|
-
f1: true,
|
|
2049
|
-
title: ( localize2WithPath(
|
|
2050
|
-
'vs/workbench/contrib/testing/browser/testingOutputPeek',
|
|
2051
|
-
'testing.toggleTestingPeekHistory',
|
|
2052
|
-
'Toggle Test History in Peek'
|
|
2053
|
-
)),
|
|
2054
|
-
icon: Codicon.history,
|
|
2055
|
-
category: Categories.Test,
|
|
2056
|
-
menu: [{
|
|
2057
|
-
id: MenuId.TestPeekTitle,
|
|
2058
|
-
group: 'navigation',
|
|
2059
|
-
order: 3,
|
|
2060
|
-
}],
|
|
2061
|
-
keybinding: {
|
|
2062
|
-
weight: 200 ,
|
|
2063
|
-
primary: 512 | 38 ,
|
|
2064
|
-
when: ( TestingContextKeys.isPeekVisible.isEqualTo(true)),
|
|
2065
|
-
},
|
|
2066
|
-
});
|
|
2067
|
-
}
|
|
2068
|
-
run(accessor) {
|
|
2069
|
-
const opener = accessor.get(ITestingPeekOpener);
|
|
2070
|
-
opener.historyVisible.value = !opener.historyVisible.value;
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
|
-
class CreationCache {
|
|
2074
|
-
constructor() {
|
|
2075
|
-
this.v = ( new WeakMap());
|
|
2076
|
-
}
|
|
2077
|
-
get(key) {
|
|
2078
|
-
return this.v.get(key);
|
|
2079
|
-
}
|
|
2080
|
-
getOrCreate(ref, factory) {
|
|
2081
|
-
const existing = this.v.get(ref);
|
|
2082
|
-
if (existing) {
|
|
2083
|
-
return existing;
|
|
2084
|
-
}
|
|
2085
|
-
const fresh = factory();
|
|
2086
|
-
this.v.set(ref, fresh);
|
|
2087
|
-
return fresh;
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2090
|
-
|
|
2091
|
-
export { CloseTestPeek, GoToNextMessageAction, GoToPreviousMessageAction, OpenMessageInEditorAction, TestResultsView, TestingOutputPeekController, TestingPeekOpener, ToggleTestingPeekHistory };
|