Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/test/browser/cellOutput.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import { VSBuffer } from '../../../../../base/common/buffer.js';
8
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
9
import { CellOutputContainer } from '../../browser/view/cellParts/cellOutput.js';
10
import { CodeCellRenderTemplate } from '../../browser/view/notebookRenderingCommon.js';
11
import { CodeCellViewModel } from '../../browser/viewModel/codeCellViewModel.js';
12
import { CellKind, INotebookRendererInfo, IOutputDto } from '../../common/notebookCommon.js';
13
import { setupInstantiationService, withTestNotebook } from './testNotebookEditor.js';
14
import { FastDomNode } from '../../../../../base/browser/fastDomNode.js';
15
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
16
import { INotebookService } from '../../common/notebookService.js';
17
import { mock } from '../../../../../base/test/common/mock.js';
18
import { IMenu, IMenuService } from '../../../../../platform/actions/common/actions.js';
19
import { Event } from '../../../../../base/common/event.js';
20
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
21
import { getAllOutputsText } from '../../browser/viewModel/cellOutputTextHelper.js';
22
23
suite('CellOutput', () => {
24
const store = ensureNoDisposablesAreLeakedInTestSuite();
25
let instantiationService: TestInstantiationService;
26
let outputMenus: IMenu[] = [];
27
28
setup(() => {
29
outputMenus = [];
30
instantiationService = setupInstantiationService(store);
31
instantiationService.stub(INotebookService, new class extends mock<INotebookService>() {
32
override getOutputMimeTypeInfo(_textModel: any, _kernelProvides: readonly string[] | undefined, output: IOutputDto) {
33
return [{
34
rendererId: 'plainTextRendererId',
35
mimeType: 'text/plain',
36
isTrusted: true
37
}, {
38
rendererId: 'htmlRendererId',
39
mimeType: 'text/html',
40
isTrusted: true
41
}, {
42
rendererId: 'errorRendererId',
43
mimeType: 'application/vnd.code.notebook.error',
44
isTrusted: true
45
}, {
46
rendererId: 'stderrRendererId',
47
mimeType: 'application/vnd.code.notebook.stderr',
48
isTrusted: true
49
}, {
50
rendererId: 'stdoutRendererId',
51
mimeType: 'application/vnd.code.notebook.stdout',
52
isTrusted: true
53
}]
54
.filter(info => output.outputs.some(output => output.mime === info.mimeType));
55
}
56
override getRendererInfo(): INotebookRendererInfo {
57
return {
58
id: 'rendererId',
59
displayName: 'Stubbed Renderer',
60
extensionId: { _lower: 'id', value: 'id' },
61
} as INotebookRendererInfo;
62
}
63
});
64
instantiationService.stub(IMenuService, new class extends mock<IMenuService>() {
65
override createMenu() {
66
const menu = new class extends mock<IMenu>() {
67
override onDidChange = Event.None;
68
override getActions() { return []; }
69
override dispose() { outputMenus = outputMenus.filter(item => item !== menu); }
70
};
71
outputMenus.push(menu);
72
return menu;
73
}
74
});
75
});
76
77
test('Render cell output items with multiple mime types', async function () {
78
const outputItem = { data: VSBuffer.fromString('output content'), mime: 'text/plain' };
79
const htmlOutputItem = { data: VSBuffer.fromString('output content'), mime: 'text/html' };
80
const output1: IOutputDto = { outputId: 'abc', outputs: [outputItem, htmlOutputItem] };
81
const output2: IOutputDto = { outputId: 'def', outputs: [outputItem, htmlOutputItem] };
82
83
await withTestNotebook(
84
[
85
['print(output content)', 'python', CellKind.Code, [output1, output2], {}],
86
],
87
(editor, viewModel, disposables, accessor) => {
88
89
const cell = viewModel.viewCells[0] as CodeCellViewModel;
90
const cellTemplate = createCellTemplate(disposables);
91
const output = disposables.add(accessor.createInstance(CellOutputContainer, editor, cell, cellTemplate, { limit: 100 }));
92
output.render();
93
cell.outputsViewModels[0].setVisible(true);
94
assert.strictEqual(outputMenus.length, 1, 'should have 1 output menus');
95
assert(cellTemplate.outputContainer.domNode.style.display !== 'none', 'output container should be visible');
96
cell.outputsViewModels[1].setVisible(true);
97
assert.strictEqual(outputMenus.length, 2, 'should have 2 output menus');
98
cell.outputsViewModels[1].setVisible(true);
99
assert.strictEqual(outputMenus.length, 2, 'should still have 2 output menus');
100
},
101
instantiationService
102
);
103
});
104
105
test('One of many cell outputs becomes hidden', async function () {
106
const outputItem = { data: VSBuffer.fromString('output content'), mime: 'text/plain' };
107
const htmlOutputItem = { data: VSBuffer.fromString('output content'), mime: 'text/html' };
108
const output1: IOutputDto = { outputId: 'abc', outputs: [outputItem, htmlOutputItem] };
109
const output2: IOutputDto = { outputId: 'def', outputs: [outputItem, htmlOutputItem] };
110
const output3: IOutputDto = { outputId: 'ghi', outputs: [outputItem, htmlOutputItem] };
111
112
await withTestNotebook(
113
[
114
['print(output content)', 'python', CellKind.Code, [output1, output2, output3], {}],
115
],
116
(editor, viewModel, disposables, accessor) => {
117
118
const cell = viewModel.viewCells[0] as CodeCellViewModel;
119
const cellTemplate = createCellTemplate(disposables);
120
const output = disposables.add(accessor.createInstance(CellOutputContainer, editor, cell, cellTemplate, { limit: 100 }));
121
output.render();
122
cell.outputsViewModels[0].setVisible(true);
123
cell.outputsViewModels[1].setVisible(true);
124
cell.outputsViewModels[2].setVisible(true);
125
cell.outputsViewModels[1].setVisible(false);
126
assert(cellTemplate.outputContainer.domNode.style.display !== 'none', 'output container should be visible');
127
assert.strictEqual(outputMenus.length, 2, 'should have 2 output menus');
128
},
129
instantiationService
130
);
131
});
132
133
test('get all adjacent stream outputs', async () => {
134
const stdout = { data: VSBuffer.fromString('stdout'), mime: 'application/vnd.code.notebook.stdout' };
135
const stderr = { data: VSBuffer.fromString('stderr'), mime: 'application/vnd.code.notebook.stderr' };
136
const output1: IOutputDto = { outputId: 'abc', outputs: [stdout] };
137
const output2: IOutputDto = { outputId: 'abc', outputs: [stderr] };
138
139
await withTestNotebook(
140
[
141
['print(output content)', 'python', CellKind.Code, [output1, output2], {}],
142
],
143
(_editor, viewModel) => {
144
const cell = viewModel.viewCells[0];
145
const notebook = viewModel.notebookDocument;
146
const result = getAllOutputsText(notebook, cell);
147
148
assert.strictEqual(result, 'stdoutstderr');
149
},
150
instantiationService
151
);
152
});
153
154
test('get all mixed outputs of cell', async () => {
155
const stdout = { data: VSBuffer.fromString('stdout'), mime: 'application/vnd.code.notebook.stdout' };
156
const stderr = { data: VSBuffer.fromString('stderr'), mime: 'application/vnd.code.notebook.stderr' };
157
const plainText = { data: VSBuffer.fromString('output content'), mime: 'text/plain' };
158
const error = { data: VSBuffer.fromString(`{"name":"Error Name","message":"error message","stack":"error stack"}`), mime: 'application/vnd.code.notebook.error' };
159
const output1: IOutputDto = { outputId: 'abc', outputs: [stdout] };
160
const output2: IOutputDto = { outputId: 'abc', outputs: [stderr] };
161
const output3: IOutputDto = { outputId: 'abc', outputs: [plainText] };
162
const output4: IOutputDto = { outputId: 'abc', outputs: [error] };
163
164
await withTestNotebook(
165
[
166
['print(output content)', 'python', CellKind.Code, [output1, output2, output3, output4], {}],
167
],
168
(_editor, viewModel) => {
169
const cell = viewModel.viewCells[0];
170
const notebook = viewModel.notebookDocument;
171
const result = getAllOutputsText(notebook, cell);
172
173
assert.strictEqual(result,
174
'Cell output 1 of 3\n' +
175
'stdoutstderr\n' +
176
'Cell output 2 of 3\n' +
177
'output content\n' +
178
'Cell output 3 of 3\n' +
179
'error stack'
180
);
181
},
182
instantiationService
183
);
184
185
});
186
187
188
});
189
190
function createCellTemplate(disposables: DisposableStore) {
191
return {
192
outputContainer: new FastDomNode(document.createElement('div')),
193
outputShowMoreContainer: new FastDomNode(document.createElement('div')),
194
focusSinkElement: document.createElement('div'),
195
templateDisposables: disposables,
196
elementDisposables: disposables,
197
} as unknown as CodeCellRenderTemplate;
198
}
199
200