from .support import PyScriptTest class TestPyRepl(PyScriptTest): def _replace(self, py_repl, newcode): """ Clear the editor and write new code in it. WARNING: this assumes that the textbox has already the focus """ # clear the editor, write new code self.page.keyboard.press("Control+A") self.page.keyboard.press("Backspace") self.page.keyboard.type(newcode) def test_repl_loads(self): self.pyscript_run( """ """ ) py_repl = self.page.query_selector("py-repl") assert py_repl assert "Python" in py_repl.inner_text() def test_execute_preloaded_source(self): """ Unfortunately it tests two things at once, but it's impossible to write a smaller test. I think this is the most basic test that we can write. We test that: 1. the source code that we put in the tag is loaded inside the editor 2. clicking the button executes it """ self.pyscript_run( """ print('hello from py-repl') """ ) py_repl = self.page.locator("py-repl") src = py_repl.inner_text() assert "print('hello from py-repl')" in src py_repl.locator("button").click() assert self.console.log.lines[-1] == "hello from py-repl" def test_execute_code_typed_by_the_user(self): self.pyscript_run( """ """ ) py_repl = self.page.locator("py-repl") py_repl.type('print("hello")') py_repl.locator("button").click() assert self.console.log.lines[-1] == "hello" def test_execute_on_shift_enter(self): self.pyscript_run( """ print("hello world") """ ) self.page.wait_for_selector("#runButton") self.page.keyboard.press("Shift+Enter") assert self.console.log.lines[0] == self.PY_COMPLETE assert self.console.log.lines[-1] == "hello world" def test_display(self): self.pyscript_run( """ display('hello world') """ ) py_repl = self.page.locator("py-repl") py_repl.locator("button").click() out_div = py_repl.locator("div.py-repl-output") assert out_div.all_inner_texts()[0] == "hello world" def test_show_last_expression(self): """ Test that we display() the value of the last expression, as you would expect by a REPL """ self.pyscript_run( """ 42 """ ) py_repl = self.page.locator("py-repl") py_repl.locator("button").click() out_div = py_repl.locator("div.py-repl-output") assert out_div.all_inner_texts()[0] == "42" def test_run_clears_previous_output(self): """ Check that we clear the previous output of the cell before executing it again """ self.pyscript_run( """ display('hello world') """ ) py_repl = self.page.locator("py-repl") out_div = py_repl.locator("div.py-repl-output") self.page.keyboard.press("Shift+Enter") assert out_div.all_inner_texts()[0] == "hello world" # # clear the editor, write new code, execute self._replace(py_repl, "display('another output')") self.page.keyboard.press("Shift+Enter") assert out_div.all_inner_texts()[1] == "another output" def test_python_exception(self): """ See also test01_basic::test_python_exception, since it's very similar """ self.pyscript_run( """ raise Exception('this is an error') """ ) py_repl = self.page.locator("py-repl") py_repl.locator("button").click() # # check that we sent the traceback to the console tb_lines = self.console.error.lines[-1].splitlines() assert tb_lines[0] == "[pyexec] Python exception:" assert tb_lines[1] == "Traceback (most recent call last):" assert tb_lines[-1] == "Exception: this is an error" # # check that we show the traceback in the page err_pre = py_repl.locator("div.py-repl-output > pre.py-error") tb_lines = err_pre.inner_text().splitlines() assert tb_lines[0] == "Traceback (most recent call last):" assert tb_lines[-1] == "Exception: this is an error" def test_python_exception_after_previous_output(self): self.pyscript_run( """ display('hello world') """ ) py_repl = self.page.locator("py-repl") out_div = py_repl.locator("div.py-repl-output") self.page.keyboard.press("Shift+Enter") assert out_div.all_inner_texts()[0] == "hello world" # # clear the editor, write new code, execute self._replace(py_repl, "0/0") self.page.keyboard.press("Shift+Enter") assert "hello world" not in out_div.all_inner_texts()[1] assert "ZeroDivisionError" in out_div.all_inner_texts()[1] def test_hide_previous_error_after_successful_run(self): """ this tests the fact that a new error div should be created once there's an error but also that it should disappear automatically once the error is fixed """ self.pyscript_run( """ raise Exception('this is an error') """ ) py_repl = self.page.locator("py-repl") out_div = py_repl.locator("div.py-repl-output") self.page.keyboard.press("Shift+Enter") assert "this is an error" in out_div.all_inner_texts()[0] # self._replace(py_repl, "display('hello')") self.page.keyboard.press("Shift+Enter") assert out_div.all_inner_texts()[1] == "hello" def test_output_attribute(self): self.pyscript_run( """ display('hello world')
""" ) py_repl = self.page.locator("py-repl") py_repl.locator("button").click() # # check that we did NOT write to py-repl-output out_div = py_repl.locator("div.py-repl-output") assert out_div.inner_text() == "" # check that we are using mydiv instead mydiv = self.page.locator("#mydiv") assert mydiv.all_inner_texts()[0] == "hello world" def test_output_attribute_does_not_exist(self): """ If we try to use an attribute which doesn't exist, we display an error instead """ self.pyscript_run( """ print('I will not be executed') """ ) py_repl = self.page.locator("py-repl") py_repl.locator("button").click() # out_div = py_repl.locator("div.py-repl-output") msg = "py-repl ERROR: cannot find the output element #I-dont-exist in the DOM" assert out_div.all_inner_texts()[0] == msg assert "I will not be executed" not in self.console.log.text def test_auto_generate(self): self.pyscript_run( """ """ ) py_repls = self.page.locator("py-repl") outputs = py_repls.locator("div.py-repl-output") assert py_repls.count() == 1 assert outputs.count() == 1 # # evaluate the py-repl, and wait for the newly generated one self.page.keyboard.type("'hello'") self.page.keyboard.press("Shift+Enter") self.page.locator('py-repl[exec-id="2"]').wait_for() assert py_repls.count() == 2 assert outputs.count() == 2 # # now we type something else: the new py-repl should have the focus self.page.keyboard.type("'world'") self.page.keyboard.press("Shift+Enter") self.page.locator('py-repl[exec-id="3"]').wait_for() assert py_repls.count() == 3 assert outputs.count() == 3 # # check that the code and the outputs are in order out_texts = [el.inner_text() for el in self.iter_locator(outputs)] assert out_texts == ["hello", "world", ""]