From 03478bee8719f2ddb16a326c6b122ceff1ed1423 Mon Sep 17 00:00:00 2001 From: Amy Skerry Date: Thu, 25 Oct 2018 21:05:52 -0700 Subject: [PATCH 1/2] Migrate image display test to selenium Migrates a single js test (testing image display functionality) to selenium as per issue #3335. Test Plan: py.test -v notebook/tests/selenium/test_display_image.py --- notebook/tests/notebook/display_image.js | 63 ---------------- notebook/tests/selenium/test_display_image.py | 71 +++++++++++++++++++ notebook/tests/selenium/utils.py | 12 +++- 3 files changed, 80 insertions(+), 66 deletions(-) delete mode 100644 notebook/tests/notebook/display_image.js create mode 100644 notebook/tests/selenium/test_display_image.py diff --git a/notebook/tests/notebook/display_image.js b/notebook/tests/notebook/display_image.js deleted file mode 100644 index 1e980e683..000000000 --- a/notebook/tests/notebook/display_image.js +++ /dev/null @@ -1,63 +0,0 @@ -// -// Test display of images -// -// The effect of shape metadata is validated, -// using Image(retina=True) -// - - -// 2x2 black square in b64 jpeg and png -b64_image_data = { - "image/png" : "b'iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAC0lEQVR4nGNgQAYAAA4AAamRc7EA\\nAAAASUVORK5CYII='", - "image/jpeg" : "b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAACAAIDASIA\\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5/ooo\\noA//2Q=='" -} - - -casper.notebook_test(function () { - this.test_img_shape = function(fmt, retina) { - this.thenEvaluate(function (b64data, retina) { - IPython.notebook.insert_cell_at_index("code", 0); - var cell = IPython.notebook.get_cell(0); - cell.set_text([ - "import base64", - "from IPython.display import display, Image", - "data = base64.decodestring(" + b64data + ")", - "retina = bool(" + retina + ")", - "display(Image(data, retina=retina))" - ].join("\n")); - cell.execute(); - }, {b64data : b64_image_data[fmt], retina : retina ? 1:0 }); - - this.wait_for_output(0); - - this.then(function() { - var img = this.evaluate(function() { - // get a summary of the image that was just displayed - var cell = IPython.notebook.get_cell(0); - var img = $(cell.output_area.element.find("img")[0]); - return { - src : img.attr("src"), - width : img.width(), - height : img.height(), - width_attr : img.attr("width"), - height_attr : img.attr("height") - }; - }); - var prefix = "Image('" + fmt + "', retina=" + retina + ") "; - this.test.assertType(img, "object", prefix + "img was displayed"); - this.test.assertEquals(img.src.split(',')[0], "data:" + fmt + ";base64", - prefix + "data-uri prefix" - ); - var sz = retina ? 1 : 2; - var sz_attr = retina ? "1" : undefined; - this.test.assertEquals(img.height, sz, prefix + "measured height"); - this.test.assertEquals(img.width, sz, prefix + "measured width"); - this.test.assertEquals(img.height_attr, sz_attr, prefix + "height attr"); - this.test.assertEquals(img.width_attr, sz_attr, prefix + "width attr"); - }); - }; - this.test_img_shape("image/png", false); - this.test_img_shape("image/png", true); - this.test_img_shape("image/jpeg", false); - this.test_img_shape("image/jpeg", true); -}); diff --git a/notebook/tests/selenium/test_display_image.py b/notebook/tests/selenium/test_display_image.py new file mode 100644 index 000000000..d6b3d28e8 --- /dev/null +++ b/notebook/tests/selenium/test_display_image.py @@ -0,0 +1,71 @@ +"""Test display of images + +The effect of shape metadata is validated, using Image(retina=True) +""" + +from .utils import wait_for_tag + + +# 2x2 black square in b64 jpeg and png +b64_image_data = { + "image/png" : b'iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAC0lEQVR4nGNgQAYAAA4AAamRc7EA\\nAAAASUVORK5CYII', + "image/jpeg" : b'/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAACAAIDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5/ooo\noAoo2Qoo' +} + + +def imports(notebook): + commands = [ + 'import base64', + 'from IPython.display import display, Image', + ] + notebook.edit_cell(index=0, content="\n".join(commands)) + notebook.execute_cell(0) + + +def validate_img(notebook, cell_index, image_fmt, retina): + """Validate that image renders as expected.""" + + b64data = b64_image_data[image_fmt] + commands = [ + 'b64data = %s' % b64data, + 'data = base64.decodebytes(b64data)', + 'display(Image(data, retina=%s))' % retina + ] + notebook.append("\n".join(commands)) + notebook.execute_cell(cell_index) + + # Find the image element that was just displayed + import time + time.sleep(1) + wait_for_tag(notebook.cells[cell_index], "img", single=True) + img_element = notebook.cells[cell_index].find_element_by_tag_name("img") + + src = img_element.get_attribute("src") + prefix = src.split(',')[0] + expected_prefix = "data:%s;base64" % image_fmt + assert prefix == expected_prefix + + width = img_element.size["width"] + height = img_element.size["height"] + width_attr = img_element.get_attribute("width") + height_attr = img_element.get_attribute("height") + expected_size = 1 if retina else 2 + assert width == expected_size + assert height == expected_size + assert width_attr == str(expected_size) + assert height_attr == str(expected_size) + + +def test_display_image(notebook): + imports(notebook) + # PNG, non-retina + validate_img(notebook, 1, "image/png", False) + + # PNG, retina display + validate_img(notebook, 2, "image/png", True) + + # JPEG, non-retina + validate_img(notebook, 3, "image/jpeg", False) + + # JPEG, retina display + validate_img(notebook, 4, "image/jpeg", True) diff --git a/notebook/tests/selenium/utils.py b/notebook/tests/selenium/utils.py index c93200dc6..9c03b0128 100644 --- a/notebook/tests/selenium/utils.py +++ b/notebook/tests/selenium/utils.py @@ -12,8 +12,14 @@ from contextlib import contextmanager pjoin = os.path.join -def wait_for_selector(browser, selector, timeout=10, visible=False, single=False): - wait = WebDriverWait(browser, timeout) +def wait_for_selector(driver, selector, timeout=10, visible=False, single=False): + return _wait_for(driver, By.CSS_SELECTOR, selector, timeout, visible, single) + +def wait_for_tag(driver, tag, timeout=10, visible=False, single=False): + return _wait_for(driver, By.TAG_NAME, tag, timeout, visible, single) + +def _wait_for(driver, locator_type, locator, timeout=10, visible=False, single=False): + wait = WebDriverWait(driver, timeout) if single: if visible: conditional = EC.visibility_of_element_located @@ -24,7 +30,7 @@ def wait_for_selector(browser, selector, timeout=10, visible=False, single=False conditional = EC.visibility_of_all_elements_located else: conditional = EC.presence_of_all_elements_located - return wait.until(conditional((By.CSS_SELECTOR, selector))) + return wait.until(conditional((locator_type, locator))) class CellTypeError(ValueError): From a5a6e4ad089b5fdc479e377e268972cba8e658b1 Mon Sep 17 00:00:00 2001 From: Amy Skerry Date: Wed, 7 Nov 2018 20:35:26 -0800 Subject: [PATCH 2/2] Address review feedback - remove sleep hack cruft - consolidate/remove unncessary intermediate variables --- notebook/tests/selenium/test_display_image.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/notebook/tests/selenium/test_display_image.py b/notebook/tests/selenium/test_display_image.py index d6b3d28e8..0ee9f0c80 100644 --- a/notebook/tests/selenium/test_display_image.py +++ b/notebook/tests/selenium/test_display_image.py @@ -35,8 +35,6 @@ def validate_img(notebook, cell_index, image_fmt, retina): notebook.execute_cell(cell_index) # Find the image element that was just displayed - import time - time.sleep(1) wait_for_tag(notebook.cells[cell_index], "img", single=True) img_element = notebook.cells[cell_index].find_element_by_tag_name("img") @@ -45,15 +43,11 @@ def validate_img(notebook, cell_index, image_fmt, retina): expected_prefix = "data:%s;base64" % image_fmt assert prefix == expected_prefix - width = img_element.size["width"] - height = img_element.size["height"] - width_attr = img_element.get_attribute("width") - height_attr = img_element.get_attribute("height") expected_size = 1 if retina else 2 - assert width == expected_size - assert height == expected_size - assert width_attr == str(expected_size) - assert height_attr == str(expected_size) + assert img_element.size["width"] == expected_size + assert img_element.size["height"] == expected_size + assert img_element.get_attribute("width") == str(expected_size) + assert img_element.get_attribute("height") == str(expected_size) def test_display_image(notebook):