Skip to content

Commit 6c6ffa3

Browse files
authored
Merge pull request microsoft#184675 from microsoft/aamunger/streamingOutput
select previous output to be replaced correctly
2 parents f4e50f2 + 3767249 commit 6c6ffa3

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

extensions/notebook-renderers/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,10 @@ function renderStream(outputInfo: OutputItem, outputElement: HTMLElement, error:
285285

286286
const scrollTop = outputScrolling ? findScrolledHeight(outputElement) : undefined;
287287

288-
const existingContent = outputElement.querySelector(`[output-item-id="${outputInfo.id}"]`) as HTMLElement | null;
289288
const previousOutputParent = getPreviousMatchingContentGroup(outputElement);
290-
291289
// If the previous output item for the same cell was also a stream, append this output to the previous
292290
if (previousOutputParent) {
291+
const existingContent = previousOutputParent.querySelector(`[output-item-id="${outputInfo.id}"]`) as HTMLElement | null;
293292
if (existingContent) {
294293
existingContent.replaceWith(newContent);
295294

@@ -299,6 +298,7 @@ function renderStream(outputInfo: OutputItem, outputElement: HTMLElement, error:
299298
previousOutputParent.classList.toggle('scrollbar-visible', previousOutputParent.scrollHeight > previousOutputParent.clientHeight);
300299
previousOutputParent.scrollTop = scrollTop !== undefined ? scrollTop : previousOutputParent.scrollHeight;
301300
} else {
301+
const existingContent = outputElement.querySelector(`[output-item-id="${outputInfo.id}"]`) as HTMLElement | null;
302302
let contentParent = existingContent?.parentElement;
303303
if (existingContent && contentParent) {
304304
existingContent.replaceWith(newContent);

extensions/notebook-renderers/src/test/notebookRenderer.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ suite('Notebook builtin output renderer', () => {
9898
this.firstOutput = outputElement;
9999
}
100100

101+
public get cellElement() {
102+
return this.cell;
103+
}
104+
101105
public getFirstOuputElement() {
102106
return this.firstOutput;
103107
}
@@ -241,6 +245,50 @@ suite('Notebook builtin output renderer', () => {
241245
assert.ok(inserted.innerHTML.indexOf('>third stream content</') > -1, `Content was not added to output element: ${outputElement.innerHTML}`);
242246
});
243247

248+
test(`Consolidated streaming outputs should replace matching outputs correctly`, async () => {
249+
const context = createContext({ outputScrolling: false });
250+
const renderer = await activate(context);
251+
assert.ok(renderer, 'Renderer not created');
252+
253+
const outputHtml = new OutputHtml();
254+
const outputElement = outputHtml.getFirstOuputElement();
255+
const outputItem1 = createOutputItem('first stream content', stdoutMimeType, '1');
256+
const outputItem2 = createOutputItem('second stream content', stdoutMimeType, '2');
257+
await renderer!.renderOutputItem(outputItem1, outputElement);
258+
const secondOutput = outputHtml.appendOutputElement();
259+
await renderer!.renderOutputItem(outputItem2, secondOutput);
260+
const newOutputItem1 = createOutputItem('replaced content', stdoutMimeType, '2');
261+
await renderer!.renderOutputItem(newOutputItem1, secondOutput);
262+
263+
264+
const inserted = outputElement.firstChild as HTMLElement;
265+
assert.ok(inserted, `nothing appended to output element: ${outputElement.innerHTML}`);
266+
assert.ok(inserted.innerHTML.indexOf('>first stream content</') > -1, `Content was not added to output element: ${outputHtml.cellElement.innerHTML}`);
267+
assert.ok(inserted.innerHTML.indexOf('>replaced content</') > -1, `Content was not added to output element: ${outputHtml.cellElement.innerHTML}`);
268+
assert.ok(inserted.innerHTML.indexOf('>second stream content</') === -1, `Content was not replaced in output element: ${outputHtml.cellElement.innerHTML}`);
269+
});
270+
271+
test(`Streaming outputs interleaved with other mime types will produce separate outputs`, async () => {
272+
const context = createContext({ outputScrolling: false });
273+
const renderer = await activate(context);
274+
assert.ok(renderer, 'Renderer not created');
275+
276+
const outputHtml = new OutputHtml();
277+
const firstOutputElement = outputHtml.getFirstOuputElement();
278+
const outputItem1 = createOutputItem('first stream content', stdoutMimeType, '1');
279+
const outputItem2 = createOutputItem(JSON.stringify(error), errorMimeType, '2');
280+
const outputItem3 = createOutputItem('second stream content', stdoutMimeType, '3');
281+
await renderer!.renderOutputItem(outputItem1, firstOutputElement);
282+
const secondOutputElement = outputHtml.appendOutputElement();
283+
await renderer!.renderOutputItem(outputItem2, secondOutputElement);
284+
const thirdOutputElement = outputHtml.appendOutputElement();
285+
await renderer!.renderOutputItem(outputItem3, thirdOutputElement);
286+
287+
assert.ok(firstOutputElement.innerHTML.indexOf('>first stream content</') > -1, `Content was not added to output element: ${outputHtml.cellElement.innerHTML}`);
288+
assert.ok(secondOutputElement.innerHTML.indexOf('>NameError</') > -1, `Content was not added to output element: ${outputHtml.cellElement.innerHTML}`);
289+
assert.ok(thirdOutputElement.innerHTML.indexOf('>second stream content</') > -1, `Content was not added to output element: ${outputHtml.cellElement.innerHTML}`);
290+
});
291+
244292
test(`Multiple adjacent streaming outputs, rerendering the first should erase the rest`, async () => {
245293
const context = createContext();
246294
const renderer = await activate(context);

0 commit comments

Comments
 (0)