diff --git a/src/client/datascience/jupyter/jupyterDebugger.ts b/src/client/datascience/jupyter/jupyterDebugger.ts index afa7df942137..796dd18ab771 100644 --- a/src/client/datascience/jupyter/jupyterDebugger.ts +++ b/src/client/datascience/jupyter/jupyterDebugger.ts @@ -3,6 +3,8 @@ 'use strict'; import type { nbformat } from '@jupyterlab/coreutils'; import { inject, injectable, named } from 'inversify'; +// tslint:disable-next-line: no-require-imports +import unescape = require('lodash/unescape'); import * as path from 'path'; import * as uuid from 'uuid/v4'; import { DebugConfiguration, Disposable } from 'vscode'; @@ -473,8 +475,10 @@ export class JupyterDebugger implements IJupyterDebugger, ICellHashListener { if (outputs.length > 0) { const data = outputs[0].data; if (data && data.hasOwnProperty('text/plain')) { + // Plain text should be escaped by our execution engine. Unescape it so + // we can parse it. // tslint:disable-next-line:no-any - return (data as any)['text/plain']; + return unescape((data as any)['text/plain']); } if (outputs[0].output_type === 'stream') { const stream = outputs[0] as nbformat.IStream; diff --git a/src/datascience-ui/interactive-common/cellOutput.tsx b/src/datascience-ui/interactive-common/cellOutput.tsx index b9a9d5bb2eee..8b545eac7086 100644 --- a/src/datascience-ui/interactive-common/cellOutput.tsx +++ b/src/datascience-ui/interactive-common/cellOutput.tsx @@ -314,7 +314,12 @@ export class CellOutput extends React.Component { input = JSON.stringify(output.data); renderWithScrollbars = true; isText = true; - } else if (output.output_type === 'execute_result' && input && input.hasOwnProperty('text/plain')) { + } else if ( + output.output_type === 'execute_result' && + input && + input.hasOwnProperty('text/plain') && + !input.hasOwnProperty('text/html') + ) { // Plain text should actually be shown as html so that escaped HTML shows up correctly mimeType = 'text/html'; isText = true; diff --git a/src/test/datascience/notebook.functional.test.ts b/src/test/datascience/notebook.functional.test.ts index aeec51594400..b8ff1d720cbd 100644 --- a/src/test/datascience/notebook.functional.test.ts +++ b/src/test/datascience/notebook.functional.test.ts @@ -182,7 +182,7 @@ suite('DataScience notebook tests', () => { const error = cell.outputs[0].evalue; if (error) { assert.ok(error, 'Error not found when expected'); - assert.equal(error, errorString, 'Unexpected error found'); + assert.ok(error.toString().includes(errorString), 'Unexpected error found'); } } @@ -757,7 +757,7 @@ suite('DataScience notebook tests', () => { await server!.waitForIdle(10000); console.log('Verifying restart'); - await verifyError(server, 'a', `name 'a' is not defined`); + await verifyError(server, 'a', `is not defined`); } catch (exc) { assert.ok( exc instanceof JupyterKernelPromiseFailedError, @@ -1031,7 +1031,7 @@ a`, mimeType: 'text/plain', cellType: 'code', result: ``, - verifyValue: (d) => assert.equal(d, escape(``), 'XML not escaped') + verifyValue: (d) => assert.ok(d.includes(escape(``)), 'XML not escaped') }, { markdownRegEx: undefined,