Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert display_id JS test to selenium (#3335) #5394

Closed
wants to merge 5 commits into from

Conversation

nfelger
Copy link
Contributor

@nfelger nfelger commented Apr 21, 2020

Hi @takluyver! This is my first time on this project, so please do let me know if anything about this PR isn't in line with how things are done here - and apologies in advance if so!

I was looking for a way to help out and found issue #3335, where I picked a test that seems not to have been converted yet.

The selenium test is passing and all assertions from the JS original are there, but I still have some questions, which I'll post as comments.

@@ -256,14 +260,15 @@ def edit_cell(self, cell=None, index=0, content="", render=False):
for line_no, line in enumerate(content.splitlines()):
if line_no != 0:
self.current_cell.send_keys(Keys.ENTER, "\n")
self.current_cell.send_keys(Keys.ENTER, Keys.HOME) # Avoid auto-indent.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I discovered the prefill_notebook fixture, I was having trouble with auto-indentation when setting cell content to a multiline string that ended in a colon. This resets the cursor to the start of the line before sending the line content.

It is now redundant because the display_id test uses prefill_notebook, which doesn't have that problem, but I figured it's a useful fix regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, looks like this doesn't quite work as I intended, so I'll remove it for now.

@nfelger
Copy link
Contributor Author

nfelger commented Apr 21, 2020

Ugh, apologies for the whitespace spam in the commits for utils.py - I've recently switched editors and wasn't aware that I had set it up to do this!

Comment on lines +83 to +108
notebook.browser.execute_script(textwrap.dedent("""\
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 cell = IPython.notebook.get_cell(3);
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);
"""))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up keeping most of this test in JavaScript. Why?

  • Starting with the second half (L. 92-108), seems to me like these callbacks have to be set from JS, but this is the first time I've come across iopub, so maybe I'm missing something?
  • As for the first bit (L. 84-90) - adding a cell and setting its contents - this could be done in selenium, via the UI. However, when I tried that, I started getting intermittent test failures. I played around with this in the browser and it turns out that adding just a slight delay (tens of milliseconds) on L. 91 causes the cell's iopub_messages array to remain empty.

It should be obvious from my comments that I don't know what I'm doing or what's going here! :)
If there's a better way to approach this or some documentation I could be reading to understand it better, I'd be all ears.

notebook = prefill_notebook(INITIAL_CELLS)
notebook.execute_cell(0)

#TODO describe test 1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is all one big, long test, it'd be nice to have a short description of what each part is testing. I'm not really sure what it is that is being tested here. Could someone who knows more maybe suggest a short summary?

assert cell1_outputs[1]['transient']['display_id'] == 'here', 'has transient display_id'
assert cell1_outputs[1]['data']['text/plain'] == '1', 'display_with_id produces output'

#TODO describe test 2
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

assert cell3_iopub_messages[1]['data']['text/plain'] == '6', 'value'
assert cell3_iopub_messages[1]['transient']['display_id'] == 'here', 'display id 1'

#TODO describe test 4
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

def _get_outputs(cell_idx):
return notebook.browser.execute_script(f"""\
var cell = Jupyter.notebook.get_cell({cell_idx});
return cell.output_area.outputs;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JS version converts the outputs first to JSON and then loads them back, I'm not sure why. I skipped this in the Python version (also because selenium probably does something similar anyway).

display('below')
"""))
notebook.wait_for_cell_output(1)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and at various other points in the test, the JS version calls wait_for_idle, which checks if IPython._status == "idle". I tried replicating this in the Python version, but it fails because there's no _status on the IPython object? I'm not sure what's going on here, but the tests don't seem affected by this.

from IPython.display import display
def display_with_id(obj, display_id, update=False, execute_result=False):
iopub = ip.kernel.iopub_socket
session = get_ipython().kernel.session
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing it's just an oversight by the original author that this line uses get_ipython() instead of the ip variable (like the other lines)?

Suggested change
session = get_ipython().kernel.session
session = ip.kernel.session

@Zsailer Zsailer changed the base branch from main to 6.4.x March 7, 2022 18:23
@nfelger nfelger closed this Oct 11, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant