Example #1
0
    def test_click_sortable(self, bokeh_model_page):
        data = {
            'x': [1, 2, 3, 4],
            'y': [4, 3, 2, 1],
            'd': ['foo', 'bar', 'baz', 'quux']
        }
        source = ColumnDataSource(data)
        table = DataTable(columns=[
            TableColumn(field="x", title="x"),
            TableColumn(field="y", title="y", sortable=False),
            TableColumn(field="d", title="d", sortable=True),
        ],
                          source=source)

        page = bokeh_model_page(table)

        for i, x in enumerate(['foo', 'bar', 'baz', 'quux'], 1):
            elt = get_table_cell(page.driver, i, 3)
            assert elt.text == x

        h4 = get_table_header(page.driver, 4)
        h4.click()

        for i, x in enumerate(['bar', 'baz', 'foo', 'quux'], 1):
            elt = get_table_cell(page.driver, i, 3)
            assert elt.text == x

        h4 = get_table_header(page.driver, 4)
        h4.click()

        for i, x in enumerate(['quux', 'foo', 'baz', 'bar'], 1):
            elt = get_table_cell(page.driver, i, 3)
            assert elt.text == x

        assert page.has_no_console_errors()
Example #2
0
    def test_row_highlights_reflect_js_selection(self, bokeh_model_page):

        source = ColumnDataSource({'values': [1, 2]})
        col = TableColumn(field='values', title='values')
        table = DataTable(source=source, columns=[col], editable=False, width=600)

        button = ButtonWrapper("Click", callback=CustomJS(args=dict(s=source), code="""
            s.selected.indices = [1]
        """))

        page = bokeh_model_page(column(button.obj, table))

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' not in row1.get_attribute('class')

        button.click(page.driver)

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' in row1.get_attribute('class')

        assert page.has_no_console_errors()
Example #3
0
    def test_row_highlights_reflect_ui_selection(self,
                                                 bokeh_model_page) -> None:

        source = ColumnDataSource({'values': [1, 2]})
        column = TableColumn(field='values', title='values')
        table = DataTable(source=source,
                          columns=[column],
                          editable=False,
                          width=600)

        page = bokeh_model_page(table)

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' not in row1.get_attribute('class')

        cell = get_table_cell(page.driver, 2, 1)
        cell.click()

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' in row1.get_attribute('class')

        assert page.has_no_console_errors()
Example #4
0
    def test_row_highlights_reflect_js_selection(self,
                                                 bokeh_model_page) -> None:

        source = ColumnDataSource({'values': [1, 2]})
        col = TableColumn(field='values', title='values')
        table = DataTable(source=source,
                          columns=[col],
                          editable=False,
                          width=600)

        button = ButtonWrapper("Click",
                               callback=CustomJS(args=dict(s=source),
                                                 code="""
            s.selected.indices = [1]
        """))

        page = bokeh_model_page(column(button.obj, table))

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' not in row1.get_attribute('class')

        button.click(page.driver)

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' in row1.get_attribute('class')

        assert page.has_no_console_errors()
Example #5
0
    def test_row_highlights_reflect_no_initial_selection(self, bokeh_model_page):

        source = ColumnDataSource({'values': [1, 2]})
        column = TableColumn(field='values', title='values')
        table = DataTable(source=source, columns=[column], editable=False, width=600)

        page = bokeh_model_page(table)

        row0 = get_table_cell(page.driver, 1, 1)
        assert 'selected' not in row0.get_attribute('class')

        row1 = get_table_cell(page.driver, 2, 1)
        assert 'selected' not in row1.get_attribute('class')

        assert page.has_no_console_errors()
    def test_server_source_callback_triggered_after_edit(self, bokeh_server_page) -> None:
        data = {'x': [1,2,5,6], 'y': [60,50,20,10]}
        source = ColumnDataSource(data)

        result = []

        def modify_doc(doc):
            plot = Plot(height=400, width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y", title="y", sortable=True, editor=NumberEditor())
            ], source=source, editable=True)

            def cb(attr, old, new):
                result.append("CALLED")

            source.on_change('data', cb)
            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        assert result == []

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '20'
        enter_text_in_cell(page.driver, cell, '100')

        assert result == ["CALLED"]
    def test_server_source_callback_triggered_after_edit(self, bokeh_server_page):
        data = {'x': [1,2,5,6], 'y': [60,50,20,10]}
        source = ColumnDataSource(data)

        result = []

        def modify_doc(doc):
            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y", title="y", sortable=True, editor=NumberEditor())
            ], source=source, editable=True)

            def cb(attr, old, new):
                result.append("CALLED")

            source.on_change('data', cb)
            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        assert result == []

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '20'
        enter_text_in_cell(page.driver, cell, '100')

        assert result == ["CALLED"]
Example #8
0
    def test_server_edit_does_not_duplicate_data_update_event(
            self, bokeh_server_page):
        def modify_doc(doc):
            data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}
            source = ColumnDataSource(data)

            plot = Plot(plot_height=400,
                        plot_width=400,
                        x_range=Range1d(0, 1),
                        y_range=Range1d(0, 1),
                        min_border=0)
            plot.add_tools(
                CustomAction(callback=CustomJS(args=dict(s=source),
                                               code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x"),
                TableColumn(field="y", editor=NumberEditor())
            ],
                              source=source,
                              editable=True)

            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        page.click_custom_action()

        results = page.results
        assert results == {'data': {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}}

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '30'
        enter_text_in_cell(page.driver, cell, '100')

        page.click_custom_action()

        results = page.results
        assert results == {'data': {'x': [1, 2, 3, 4], 'y': [10, 20, 100, 40]}}

        # if the server receives something back like:
        #
        # Message 'PATCH-DOC' (revision 1) content: {
        #     'events': [{
        #         'kind': 'ModelChanged',
        #         'model': {'type': 'ColumnDataSource', 'id': '1001'},
        #         'attr': 'data', 'new': {'x': [1,2,3,4], 'y': [10, 20, 100, 40]}
        #     }],
        #     'references': []
        # }
        #
        # Then that means the client got our stream message and erroneously ping
        # ponged a full data update back to us
        for msg in page.message_test_port.received:
            assert not any(
                is_cds_data_patch(evt)
                for evt in msg.content.get('events', []))
Example #9
0
    def test_server_edit_does_not_duplicate_data_update_event(
            self, bokeh_server_page: BokehServerPage) -> None:
        data = {'x': [1, 2, 3, 4], 'y': [10, 20, 30, 40]}
        source = ColumnDataSource(data)

        table = DataTable(columns=[
            TableColumn(field="x"),
            TableColumn(field="y", editor=NumberEditor())
        ],
                          source=source,
                          editable=True)

        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")))

            doc.add_root(column(plot, table))

        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]}}

        cell = get_table_cell(page.driver, table, 3, 2)
        assert cell.text == '30'
        enter_text_in_cell(page.driver, table, 3, 2, '100')

        page.eval_custom_action()

        results = page.results
        assert results == {'data': {'x': [1, 2, 3, 4], 'y': [10, 20, 100, 40]}}

        # 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], 'y': [10, 20, 100, 40]}
        #     }],
        #     '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)
Example #10
0
    def test_editing_updates_source_with_click_enter(self, bokeh_model_page):
        page = bokeh_model_page(self.table)

        # Click row 1 (which triggers the selection callback)
        cell = get_table_cell(page.driver, 1, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        # Now double click, enter the text new value and <enter>
        cell = get_table_cell(page.driver, 1, 1)
        enter_text_in_cell_with_click_enter(page.driver, cell, "baz")

        # Click row 2 (which triggers callback again so we can inspect the data)
        cell = get_table_cell(page.driver, 2, 1)
        cell.click()
        results = page.results
        assert results['values'] == ["baz", "bar"]

        assert page.has_no_console_errors()
Example #11
0
    def test_editing_updates_source_with_click_enter(self, bokeh_model_page):
        page = bokeh_model_page(self.table)

        # Click row 1 (which triggers the selection callback)
        cell = get_table_cell(page.driver, 1, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        # Now double click, enter the text new value and <enter>
        cell = get_table_cell(page.driver, 1, 1)
        enter_text_in_cell_with_click_enter(page.driver, cell, "baz")

        # Click row 2 (which triggers callback again so we can inspect the data)
        cell = get_table_cell(page.driver, 2, 1)
        cell.click()
        results = page.results
        assert results['values'] == ["baz", "bar"]

        assert page.has_no_console_errors()
Example #12
0
    def test_server_source_updated_after_edit(
            self, bokeh_server_page: BokehServerPage) -> None:
        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,
                        editor=NumberEditor())
        ],
                          source=source,
                          editable=True)

        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")))

            doc.add_root(column(plot, table))

        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']

        cell = get_table_cell(page.driver, table, 3, 2)
        assert cell.text == '20'
        enter_text_in_cell(page.driver, table, 3, 2, '100')

        page.eval_custom_action()

        results = page.results
        assert results == {'data': {'x': [1, 2, 5, 6], 'y': [60, 50, 100, 10]}}
        assert source.data == {'x': [1, 2, 5, 6], 'y': [60, 50, 100, 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', '100', '10']
Example #13
0
    def test_editing_updates_source(self,
                                    bokeh_model_page: BokehModelPage) -> None:
        table = make_table(self.editor, self.values)
        page = bokeh_model_page(table)

        # Click row 1 (which triggers the selection callback)
        cell = get_table_cell(page.driver, table, 1, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        # Now double click, enter the text new value and <enter>
        enter_text_in_cell(page.driver, table, 1, 1, "baz")

        # Click row 2 (which triggers callback again so we can inspect the data)
        cell = get_table_cell(page.driver, table, 2, 1)
        cell.click()
        results = page.results
        assert results['values'] == ["baz", "bar"]

        assert page.has_no_console_errors()
Example #14
0
    def test_editing_does_not_update_source_on_bad_values(self, bad, bokeh_model_page) -> None:
        self.table.editable = False
        page = bokeh_model_page(self.table)

        # Click row 1 (which triggers the selection callback)
        cell = get_table_cell(page.driver, 1, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        # Now double click, enter the text new value and <enter>
        cell = get_table_cell(page.driver, 1, 1)
        enter_text_in_cell(page.driver, cell, bad)

        # Click row 2 (which triggers callback again so we can inspect the data)
        cell = get_table_cell(page.driver, 2, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        assert page.has_no_console_errors()
Example #15
0
    def test_editing_does_not_update_source_on_bad_values(self, bad, bokeh_model_page):
        self.table.editable = False
        page = bokeh_model_page(self.table)

        # Click row 1 (which triggers the selection callback)
        cell = get_table_cell(page.driver, 1, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        # Now double click, enter the text new value and <enter>
        cell = get_table_cell(page.driver, 1, 1)
        enter_text_in_cell(page.driver, cell, bad)

        # Click row 2 (which triggers callback again so we can inspect the data)
        cell = get_table_cell(page.driver, 2, 1)
        cell.click()
        results = page.results
        assert results['values'] == self.values

        assert page.has_no_console_errors()
Example #16
0
    def test_server_sorted_after_edit(self, bokeh_server_page):
        data = {'x': [1,2,5,6], 'y': [60,50,20,10]}
        source = ColumnDataSource(data)

        def modify_doc(doc):

            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y", title="y", sortable=True, editor=NumberEditor())
            ], source=source, editable=True)

            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        page.click_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, 1) == ['1', '2', '5', '6']
        assert get_table_column_cells(page.driver, 2) == ['60', '50', '20', '10']

        sort_table_column(page.driver, 1)

        assert get_table_column_cells(page.driver, 1) == ['1', '2', '5', '6']
        assert get_table_column_cells(page.driver, 2) == ['60', '50', '20', '10']

        sort_table_column(page.driver, 2, True)

        assert get_table_column_cells(page.driver, 1) == ['6', '5', '2', '1']
        assert get_table_column_cells(page.driver, 2) == ['10', '20', '50', '60']

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '50'
        enter_text_in_cell(page.driver, cell, '100')

        page.click_custom_action()

        results = page.results
        assert results ==  {'data': {'x': [1,2,5,6], 'y': [60,100,20,10]}}
        assert source.data == {'x': [1,2,5,6], 'y': [60,100,20,10]}

        assert get_table_column_cells(page.driver, 1) == ['6', '5', '1', '2']
        assert get_table_column_cells(page.driver, 2) == ['10', '20', '60', '100']
    def test_server_sorted_after_edit(self, bokeh_server_page):
        data = {'x': [1,2,5,6], 'y': [60,50,20,10]}
        source = ColumnDataSource(data)

        def modify_doc(doc):

            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x", title="x", sortable=True),
                TableColumn(field="y", title="y", sortable=True, editor=NumberEditor())
            ], source=source, editable=True)

            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        page.click_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, 1) == ['1', '2', '5', '6']
        assert get_table_column_cells(page.driver, 2) == ['60', '50', '20', '10']

        sort_table_column(page.driver, 1)

        assert get_table_column_cells(page.driver, 1) == ['1', '2', '5', '6']
        assert get_table_column_cells(page.driver, 2) == ['60', '50', '20', '10']

        sort_table_column(page.driver, 2, True)

        assert get_table_column_cells(page.driver, 1) == ['6', '5', '2', '1']
        assert get_table_column_cells(page.driver, 2) == ['10', '20', '50', '60']

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '50'
        enter_text_in_cell(page.driver, cell, '100')

        page.click_custom_action()

        results = page.results
        assert results ==  {'data': {'x': [1,2,5,6], 'y': [60,100,20,10]}}
        assert source.data == {'x': [1,2,5,6], 'y': [60,100,20,10]}

        assert get_table_column_cells(page.driver, 1) == ['6', '5', '1', '2']
        assert get_table_column_cells(page.driver, 2) == ['10', '20', '60', '100']
    def test_server_edit_does_not_duplicate_data_update_event(self, bokeh_server_page):
        def modify_doc(doc):
            data = {'x': [1,2,3,4], 'y': [10,20,30,40]}
            source = ColumnDataSource(data)

            plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0)
            plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data"))))

            table = DataTable(columns=[
                TableColumn(field="x"),
                TableColumn(field="y", editor=NumberEditor())
            ], source=source, editable=True)

            doc.add_root(column(plot, table))

        page = bokeh_server_page(modify_doc)

        page.click_custom_action()

        results = page.results
        assert results ==  {'data': {'x': [1,2,3,4], 'y': [10,20,30,40]}}

        cell = get_table_cell(page.driver, 3, 2)
        assert cell.text == '30'
        enter_text_in_cell(page.driver, cell, '100')

        page.click_custom_action()

        results = page.results
        assert results ==  {'data': {'x': [1,2,3,4], 'y': [10, 20, 100, 40]}}

        # if the server receives something back like:
        #
        # Message 'PATCH-DOC' (revision 1) content: {
        #     'events': [{
        #         'kind': 'ModelChanged',
        #         'model': {'type': 'ColumnDataSource', 'id': '1001'},
        #         'attr': 'data', 'new': {'x': [1,2,3,4], 'y': [10, 20, 100, 40]}
        #     }],
        #     '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)