def test_server_source_stream_does_not_duplicate_data_update_event( self, bokeh_server_page: BokehServerPage) -> None: btn = Button(label="Click Me!") data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]} source = ColumnDataSource(data) table = DataTable( columns=[TableColumn(field="x"), TableColumn(field="y")], source=source, editable=False) def modify_doc(doc): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.tags.append( CustomJS(name="custom-action", args=dict(s=source), code=RECORD("data", "s.data"))) @btn.on_click def btn_click(): source.stream({"x": [5], "y": [50]}) doc.add_root(column(plot, table, btn)) page = bokeh_server_page(modify_doc) page.eval_custom_action() results = page.results assert results == {'data': {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}} btn_el = find_element_for(page.driver, btn) btn_el.click() page.eval_custom_action() results = page.results assert results == { 'data': { 'x': [1, 2, 3, 4, 5], 'y': [10, 20, 30, 40, 50] } } # if the server receives something back like: # # Message 'PATCH-DOC' (revision 1) content: { # 'events': [{ # 'kind': 'ModelChanged', # 'model': {'id': '1001'}, # 'attr': 'data', 'new': {'x': [1, 2, 3, 4, 5], 'y': [10, 20, 30, 40, 50]} # }], # 'references': [] # } # # Then that means the client got our stream message and erroneously ping # ponged a full data update back to us assert not has_cds_data_patches(page.message_test_port.received)
def test_spinner_spinning_events(self, bokeh_model_page: BokehModelPage) -> None: spinner = Spinner(value=0, low=0, high=1, step=0.01) spinner.js_on_change('value', CustomJS(code=RECORD("value", "cb_obj.value"))) page = bokeh_model_page(spinner) input_el = find_element_for(page.driver, spinner, "input") btn_up_el = find_element_for(page.driver, spinner, ".bk-spin-btn-up") btn_down_el = find_element_for(page.driver, spinner, ".bk-spin-btn-down") enter_text_in_element(page.driver, input_el, "0.5") results = page.results assert results['value'] == 0.5 #click btn up actions = ActionChains(page.driver) actions.click(on_element=btn_up_el) actions.perform() results = page.results assert results['value'] == 0.51 #dbl click btn down actions = ActionChains(page.driver) actions.double_click(on_element=btn_down_el) actions.perform() results = page.results assert results['value'] == 0.49 #arrow up actions = ActionChains(page.driver) actions.click(on_element=input_el) actions.send_keys(Keys.ARROW_UP) actions.perform() results = page.results assert results['value'] == 0.50 #arrow down actions = ActionChains(page.driver) actions.click(on_element=input_el) actions.key_down(Keys.ARROW_DOWN) actions.perform() results = page.results assert results['value'] == 0.49 #page up actions = ActionChains(page.driver) actions.click(on_element=input_el) actions.key_down(Keys.PAGE_UP) actions.perform() results = page.results assert results['value'] == 0.59 #page down actions = ActionChains(page.driver) actions.click(on_element=input_el) actions.key_down(Keys.PAGE_DOWN) actions.perform() results = page.results assert results['value'] == 0.49 assert page.has_no_console_errors()
def test_server_on_change_round_trip( self, bokeh_server_page: BokehServerPage) -> None: button = Dropdown(label="Dropdown button", menu=items) def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1])) plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.add_glyph(source, Circle(x='x', y='y', size=20)) plot.tags.append( CustomJS(name="custom-action", args=dict(s=source), code=RECORD("data", "s.data"))) def cb(event): item = event.item if item == "item_1_value": source.data = dict(x=[10, 20], y=[10, 10]) elif item == "item_2_value": source.data = dict(x=[100, 200], y=[100, 100]) elif item == "item_3_value": source.data = dict(x=[1000, 2000], y=[1000, 1000]) button.on_event('menu_item_click', cb) doc.add_root(column(button, plot)) page = bokeh_server_page(modify_doc) button_el = find_element_for(page.driver, button, "button") button_el.click() item = find_element_for(page.driver, button, ".bk-menu > *:nth-child(1)") item.click() page.eval_custom_action() results = page.results assert results == {'data': {'x': [10, 20], 'y': [10, 10]}} button_el = find_element_for(page.driver, button, "button") button_el.click() item = find_element_for(page.driver, button, ".bk-menu > *:nth-child(3)") item.click() page.eval_custom_action() results = page.results assert results == {'data': {'x': [1000, 2000], 'y': [1000, 1000]}} button_el = find_element_for(page.driver, button, "button") button_el.click() item = find_element_for(page.driver, button, ".bk-menu > *:nth-child(2)") item.click() page.eval_custom_action() results = page.results assert results == {'data': {'x': [100, 200], 'y': [100, 100]}}
def test_arrow_cannot_escape_menu( self, bokeh_model_page: BokehModelPage) -> None: text_input = AutocompleteInput(title="title", completions=[ "100001", "12344556", "12344557", "3194567289", "209374209374" ]) page = bokeh_model_page(text_input) el = find_element_for(page.driver, text_input, ".bk-menu") assert 'display: none;' in el.get_attribute('style') el = find_element_for(page.driver, text_input, "input") enter_text_in_element(page.driver, el, "123", click=2, enter=False) el = find_element_for(page.driver, text_input, ".bk-menu") assert 'display: none;' not in el.get_attribute('style') items = el.find_elements_by_tag_name("div") assert len(items) == 2 assert items[0].text == "12344556" assert items[1].text == "12344557" assert "bk-active" in items[0].get_attribute('class') assert "bk-active" not in items[1].get_attribute('class') # arrow down moves to second item enter_text_in_element(page.driver, el, Keys.DOWN, click=0, enter=False) items = el.find_elements_by_tag_name("div") assert len(items) == 2 assert items[0].text == "12344556" assert items[1].text == "12344557" assert "bk-active" not in items[0].get_attribute('class') assert "bk-active" in items[1].get_attribute('class') # arrow down again has no effect enter_text_in_element(page.driver, el, Keys.DOWN, click=0, enter=False) items = el.find_elements_by_tag_name("div") assert len(items) == 2 assert items[0].text == "12344556" assert items[1].text == "12344557" assert "bk-active" not in items[0].get_attribute('class') assert "bk-active" in items[1].get_attribute('class') # arrow up moves to first item enter_text_in_element(page.driver, el, Keys.UP, click=0, enter=False) assert len(items) == 2 assert items[0].text == "12344556" assert items[1].text == "12344557" assert "bk-active" in items[0].get_attribute('class') assert "bk-active" not in items[1].get_attribute('class') # arrow up again has no effect enter_text_in_element(page.driver, el, Keys.UP, click=0, enter=False) assert len(items) == 2 assert items[0].text == "12344556" assert items[1].text == "12344557" assert "bk-active" in items[0].get_attribute('class') assert "bk-active" not in items[1].get_attribute('class') assert page.has_no_console_errors()
def test_server_sorted_after_stream( self, bokeh_server_page: BokehServerPage) -> None: button = Button() data = {'x': [1, 2, 5, 6], 'y': [60, 50, 20, 10]} source = ColumnDataSource(data) table = DataTable(columns=[ TableColumn(field="x", title="x", sortable=True), TableColumn(field="y", title="y", sortable=True) ], source=source, editable=False) def modify_doc(doc): plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.tags.append( CustomJS(name="custom-action", args=dict(s=source), code=RECORD("data", "s.data"))) def cb(): source.stream({'x': [100], 'y': [100]}) button.on_event('button_click', cb) doc.add_root(column(plot, table, button)) page = bokeh_server_page(modify_doc) page.eval_custom_action() results = page.results assert results == {'data': {'x': [1, 2, 5, 6], 'y': [60, 50, 20, 10]}} assert get_table_column_cells(page.driver, table, 1) == ['1', '2', '5', '6'] assert get_table_column_cells(page.driver, table, 2) == ['60', '50', '20', '10'] sort_table_column(page.driver, table, 1) assert get_table_column_cells(page.driver, table, 1) == ['1', '2', '5', '6'] assert get_table_column_cells(page.driver, table, 2) == ['60', '50', '20', '10'] sort_table_column(page.driver, table, 2, True) assert get_table_column_cells(page.driver, table, 1) == ['6', '5', '2', '1'] assert get_table_column_cells(page.driver, table, 2) == ['10', '20', '50', '60'] button_el = find_element_for(page.driver, button) button_el.click() page.eval_custom_action() results = page.results assert results == { 'data': { 'x': [1, 2, 5, 6, 100], 'y': [60, 50, 20, 10, 100] } } assert source.data == { 'x': [1, 2, 5, 6, 100], 'y': [60, 50, 20, 10, 100] } assert get_table_column_cells(page.driver, table, 1) == ['6', '5', '2', '1', '100'] assert get_table_column_cells(page.driver, table, 2) == ['10', '20', '50', '60', '100']