From 1864fe5adb541c3289dcd604dfef3152389e017a Mon Sep 17 00:00:00 2001 From: Jason Grout Date: Thu, 8 Dec 2016 19:18:42 -0800 Subject: [PATCH] Some tests for output callback overrides. --- notebook/tests/notebook/display_id.js | 85 ++++++++++++++ notebook/tests/notebook/output.js | 157 ++++++++++++++++++++++++-- 2 files changed, 230 insertions(+), 12 deletions(-) diff --git a/notebook/tests/notebook/display_id.js b/notebook/tests/notebook/display_id.js index 81f156dea..7c31063c9 100644 --- a/notebook/tests/notebook/display_id.js +++ b/notebook/tests/notebook/display_id.js @@ -79,4 +79,89 @@ casper.notebook_test(function () { this.test.assertEquals(outputs2[2].data['text/plain'], '4', 'output[2][2]'); }); + this.then(function () { + this.echo("Test output callback overrides work with display ids"); + }); + + this.thenEvaluate(function () { + Jupyter.notebook.insert_cell_at_index("code", 3); + var cell = Jupyter.notebook.get_cell(3); + cell.set_text([ + "display_with_id(5, 'here')", + "display_with_id(6, 'here', update=True)", + ].join('\n')); + cell.execute(); + var kernel = IPython.notebook.kernel; + var msg_id = cell.last_msg_id; + var callback_id = 'mycallbackid' + cell.iopub_messages = []; + var add_msg = function(msg) { + msg.content.output_type = msg.msg_type; + cell.iopub_messages.push(msg.content); + }; + kernel.set_callbacks_for_msg(callback_id, { + iopub: { + output: add_msg, + clear_output: add_msg, + } + }, false); + kernel.output_callback_overrides_push(msg_id, callback_id); + }); + + this.wait_for_idle(); + + this.then(function () { + var returned = this.evaluate(function () { + var cell = IPython.notebook.get_cell(3); + return [cell.output_area.outputs, cell.iopub_messages]; + }); + var cell_results = returned[0]; + var callback_results = returned[1]; + this.test.assertEquals(cell_results.length, 0, "correct number of cell outputs"); + this.test.assertEquals(callback_results.length, 2, "correct number of callback outputs"); + this.test.assertEquals(callback_results[0].output_type, 'display_data', 'check output_type 0'); + this.test.assertEquals(callback_results[0].transient.display_id, 'here', 'check display id 0'); + this.test.assertEquals(callback_results[0].data['text/plain'], '5', 'value'); + this.test.assertEquals(callback_results[1].output_type, 'update_display_data', 'check output_type 1'); + this.test.assertEquals(callback_results[1].transient.display_id, 'here', 'display id 1'); + this.test.assertEquals(callback_results[1].data['text/plain'], '6', 'value'); + }); + + this.thenEvaluate(function () { + Jupyter.notebook.insert_cell_at_index("code", 4); + var cell = Jupyter.notebook.get_cell(4); + cell.set_text([ + "display_with_id(7, 'here')", + "display_with_id(8, 'here', update=True)", + ].join('\n')); + cell.execute(); + }); + + this.wait_for_idle(); + + this.then(function () { + var returned = JSON.parse(this.evaluate(function () { + var cell3 = Jupyter.notebook.get_cell(3); + var cell4 = Jupyter.notebook.get_cell(4); + return JSON.stringify([cell4.output_area.outputs, cell3.iopub_messages]); + })); + var cell_results = returned[0]; + var callback_results = returned[1]; + this.test.assertEquals(cell_results.length, 1, "correct number of cell outputs"); + this.test.assertEquals(callback_results.length, 4, "correct number of callback outputs"); + this.test.assertEquals(callback_results[0].output_type, 'display_data', 'check output_type 0'); + this.test.assertEquals(callback_results[0].transient.display_id, 'here', 'check display id 0'); + this.test.assertEquals(callback_results[0].data['text/plain'], '5', 'value'); + this.test.assertEquals(callback_results[1].output_type, 'update_display_data', 'check output_type 1'); + this.test.assertEquals(callback_results[1].transient.display_id, 'here', 'display id 1'); + this.test.assertEquals(callback_results[1].data['text/plain'], '6', 'value'); + this.test.assertEquals(callback_results[2].output_type, 'display_data', 'check output_type 2'); + this.test.assertEquals(callback_results[2].transient.display_id, 'here', 'check display id 2'); + this.test.assertEquals(callback_results[2].data['text/plain'], '7', 'value'); + this.test.assertEquals(callback_results[3].output_type, 'update_display_data', 'check output_type 3'); + this.test.assertEquals(callback_results[3].transient.display_id, 'here', 'display id 3'); + this.test.assertEquals(callback_results[3].data['text/plain'], '8', 'value'); + }); + + }); diff --git a/notebook/tests/notebook/output.js b/notebook/tests/notebook/output.js index db6f276d7..cfc695838 100644 --- a/notebook/tests/notebook/output.js +++ b/notebook/tests/notebook/output.js @@ -4,6 +4,17 @@ casper.notebook_test(function () { + this.compare_outputs = function(results, expected) { + for (var i = 0; i < results.length; i++) { + var r = results[i]; + var ex = expected[i]; + this.test.assertEquals(r.output_type, ex.output_type, "output " + i + " = " + r.output_type); + if (r.output_type === 'stream') { + this.test.assertEquals(r.name, ex.name, "stream " + i + " = " + r.name); + this.test.assertEquals(r.text, ex.text, "content " + i); + } + } + } this.test_coalesced_output = function (msg, code, expected) { this.then(function () { this.echo("Test coalesced output: " + msg); @@ -24,31 +35,23 @@ casper.notebook_test(function () { return cell.output_area.outputs; }); this.test.assertEquals(results.length, expected.length, "correct number of outputs"); - for (var i = 0; i < results.length; i++) { - var r = results[i]; - var ex = expected[i]; - this.test.assertEquals(r.output_type, ex.output_type, "output " + i); - if (r.output_type === 'stream') { - this.test.assertEquals(r.name, ex.name, "stream " + i); - this.test.assertEquals(r.text, ex.text, "content " + i); - } - } + this.compare_outputs(results, expected); }); }; - + this.thenEvaluate(function () { IPython.notebook.insert_cell_at_index("code", 0); var cell = IPython.notebook.get_cell(0); cell.set_text([ "from __future__ import print_function", "import sys", - "from IPython.display import display" + "from IPython.display import display, clear_output" ].join("\n") ); cell.execute(); }); - + this.test_coalesced_output("stdout", [ "print(1)", "sys.stdout.flush()", @@ -123,4 +126,134 @@ casper.notebook_test(function () { }, }] ); + + this.then(function () { + this.echo("Test output callback overrides"); + }); + + this.thenEvaluate(function () { + IPython.notebook.insert_cell_at_index("code", 0); + var cell = IPython.notebook.get_cell(0); + cell.set_text(["print(1)", + "sys.stdout.flush()", + "print(2)", + "sys.stdout.flush()", + "print(3, file=sys.stderr)", + "sys.stdout.flush()", + "display(2)", + "clear_output()", + "sys.stdout.flush()", + "print('remove handler')", + "sys.stdout.flush()", + "print('back to cell')", + "sys.stdout.flush()", + ].join('\n')); + cell.execute(); + var kernel = IPython.notebook.kernel; + var msg_id = cell.last_msg_id; + var callback_id = 'mycallbackid' + cell.iopub_messages = []; + var add_msg = function(msg) { + if (msg.content.text==="remove handler\n") { + kernel.output_callback_overrides_pop(msg_id); + } + msg.content.output_type = msg.msg_type; + cell.iopub_messages.push(msg.content); + }; + kernel.set_callbacks_for_msg(callback_id, { + iopub: { + output: add_msg, + clear_output: add_msg, + } + }, false); + kernel.output_callback_overrides_push(msg_id, callback_id); + }); + + this.wait_for_idle(); + + this.then(function () { + var expected_callback = [{ + output_type: "stream", + name: "stdout", + text: "1\n" + }, { + output_type: "stream", + name: "stdout", + text: "2\n" + }, { + output_type: "stream", + name: "stderr", + text: "3\n" + },{ + output_type: "display_data", + },{ + output_type: "clear_output", + },{ + output_type: "stream", + name: "stdout", + text: "remove handler\n" + },] + var expected_cell = [{ + output_type: "stream", + name: "stdout", + text: "back to cell\n" + }] + var returned = this.evaluate(function () { + var cell = IPython.notebook.get_cell(0); + return [cell.output_area.outputs, cell.iopub_messages]; + }); + var cell_results = returned[0]; + var callback_results = returned[1]; + this.test.assertEquals(cell_results.length, expected_cell.length, "correct number of cell outputs"); + this.test.assertEquals(callback_results.length, expected_callback.length, "correct number of callback outputs"); + this.compare_outputs(cell_results, expected_cell); + this.compare_outputs(callback_results, expected_callback); + }); + + this.then(function () { + this.echo("Test output callback overrides get execute_results messages too"); + }); + + this.thenEvaluate(function () { + IPython.notebook.insert_cell_at_index("code", 0); + var cell = IPython.notebook.get_cell(0); + cell.set_text("'end'"); + cell.execute(); + var kernel = IPython.notebook.kernel; + var msg_id = cell.last_msg_id; + var callback_id = 'mycallbackid2' + cell.iopub_messages = []; + var add_msg = function(msg) { + msg.content.output_type = msg.msg_type; + cell.iopub_messages.push(msg.content); + }; + kernel.set_callbacks_for_msg(callback_id, { + iopub: { + output: add_msg, + clear_output: add_msg, + } + }, false); + kernel.output_callback_overrides_push(msg_id, callback_id); + }); + + this.wait_for_idle(); + + this.then(function () { + var expected_callback = [{ + output_type: "execute_result", + data: { + "text/plain" : "'end'" + } + }]; + var expected_cell = []; + var returned = this.evaluate(function () { + var cell = IPython.notebook.get_cell(0); + return [cell.output_area.outputs, cell.iopub_messages]; + }); + var cell_results = returned[0]; + var callback_results = returned[1]; + this.test.assertEquals(cell_results.length, expected_cell.length, "correct number of cell outputs"); + this.test.assertEquals(callback_results.length, expected_callback.length, "correct number of callback outputs"); + this.compare_outputs(callback_results, expected_callback); + }); });