diff --git a/.circleci/config.yml b/.circleci/config.yml index 803e5ea88..75ed4940b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,13 +1,20 @@ -version: 2 +version: 2.1 jobs: "server-test": docker: - image: circleci/python:3.7.6-node-browsers + environment: + PERCY_PARALLEL_TOTAL: -1 - image: cypress/base:10 steps: - checkout + - run: + name: Inject Percy Environment variables + command: | + echo 'export PERCY_TOKEN="$PERCY_TOKEN_E2E"' >> $BASH_ENV + - restore_cache: key: dep-{{ .Branch }}-{{ checksum "package-lock.json" }}-{{ checksum "package.json" }}-{{ checksum ".circleci/config.yml" }} - run: @@ -44,6 +51,10 @@ jobs: command: | . venv/bin/activate npm run test.server + - run: + name: 🦔 percy finalize + command: npx percy finalize --all + when: always "standalone-test": diff --git a/CHANGELOG.md b/CHANGELOG.md index 98da0dddf..37f9decc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [#841](https://github.com/plotly/dash-table/pull/841) - Fix prop-types regression causing console errors in browser devtools - Fix syntax highlighting regression for Markdown cells +- [#844](https://github.com/plotly/dash-table/pull/844) Fix a bug where the table is using classes that are styled by Bootstrap - [#842](https://github.com/plotly/dash-table/pull/842) Fix a regression introduced with [#722](https://github.com/plotly/dash-table/pull/722) causing the tooltips to be misaligned with respect to their parent cell and incompletely addressed in [#817](https://github.com/plotly/dash-table/pull/817) ### Added diff --git a/dev-requirements.txt b/dev-requirements.txt index ff7e6f601..54c6d04fc 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,3 +1,4 @@ +dash-bootstrap-components==0.10.7 pandas preconditions xlrd \ No newline at end of file diff --git a/package.json b/package.json index 0999bc6ea..23deb5851 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "postbuild": "es-check es5 dash_table/*.js", "format": "run-s private::format.*", "lint": "run-s private::lint.*", - "test.server": "pytest tests/selenium", + "test.server": "pytest --nopercyfinalize tests/selenium", "test.standalone": "run-p --race private::host_js private::test.standalone", "test.unit": "run-s private::test.python private::test.unit", "test.visual": "build-storybook && percy-storybook", diff --git a/src/dash-table/components/ControlledTable/index.tsx b/src/dash-table/components/ControlledTable/index.tsx index 0e0c87124..b205cdd34 100644 --- a/src/dash-table/components/ControlledTable/index.tsx +++ b/src/dash-table/components/ControlledTable/index.tsx @@ -1010,7 +1010,7 @@ export default class ControlledTable extends PureComponent<
{arrayMap3( diff --git a/src/dash-table/components/Table/Table.less b/src/dash-table/components/Table/Table.less index def317038..a303dbb0c 100644 --- a/src/dash-table/components/Table/Table.less +++ b/src/dash-table/components/Table/Table.less @@ -222,6 +222,11 @@ flex-direction: row; position: relative; + // This overrides Bootstrap 3.4.1 body styling + // https://github.com/twbs/bootstrap/blob/v3-dev/dist/css/bootstrap.css#L1087 + // Also unapplies with the latest `in development` 5.0.0-alpha2 (https://github.com/twbs/bootstrap/blob/main/dist/css/bootstrap.css#L51) + line-height: initial; + // This overrides Chrome's default `font-size: medium;` which is causing performance issues // with AutoInputResize sub-component in react-select // https://github.com/JedWatson/react-input-autosize/blob/05b0f86a7f8b16de99c2b31296ff0d3307f15957/src/AutosizeInput.js#L58 @@ -234,6 +239,19 @@ } } + input[type="radio"] { + // These override Bootstrap 3.4.1 type="radio" styling + // https://github.com/twbs/bootstrap/blob/v3-dev/dist/css/bootstrap.css#L2621 + // This is not a problem with the latest `in development` 5.0.0-alpha2 + margin: initial; + line-height: initial; + // These override Bootstrap 4.5.0 type="radio" styling + // https://github.com/twbs/bootstrap/blob/v4-dev/dist/css/bootstrap.css#L287 + // This is not a problem with the latest `in development` 5.0.0-alpha2 + box-sizing: initial; + padding: initial; + } + .dash-spreadsheet-inner { box-sizing: border-box; display: flex; @@ -295,7 +313,7 @@ } &:not(.dash-empty-11) { - .row-0 { + .dt-table-container__row-0 { tr:last-of-type { td, th { border-bottom: none !important; @@ -344,13 +362,13 @@ &.dash-virtualized { overflow: hidden !important; - .row-0 { + .dt-table-container__row-0 { display: flex; flex: 0 0 auto; flex-direction: row; } - .row-1 { + .dt-table-container__row-1 { display: flex; flex-direction: row; overflow: auto; diff --git a/tests/cypress/src/DashTable.ts b/tests/cypress/src/DashTable.ts index e27b2105e..ad07e4809 100644 --- a/tests/cypress/src/DashTable.ts +++ b/tests/cypress/src/DashTable.ts @@ -149,7 +149,7 @@ export class DashTableHelper { } public toggleScroll(toggled: boolean) { - cy.get('.row-1').then($el => { + cy.get('.dt-table-container__row-1').then($el => { $el[0].style.overflow = toggled ? '' : 'unset'; }); } diff --git a/tests/cypress/tests/standalone/scrolling_test.ts b/tests/cypress/tests/standalone/scrolling_test.ts index fb583f945..9d129d990 100644 --- a/tests/cypress/tests/standalone/scrolling_test.ts +++ b/tests/cypress/tests/standalone/scrolling_test.ts @@ -21,7 +21,7 @@ variants.forEach(([mode, flavors]) => { DashTable.clickCellById(0, 'rows'); DashTable.getSelectedCells().should('have.length', 1); - cy.get('.row-1').scrollTo(0, 1000); + cy.get('.dt-table-container__row-1').scrollTo(0, 1000); DashTable.getSelectedCells().should('have.length', 0); }); @@ -29,10 +29,10 @@ variants.forEach(([mode, flavors]) => { DashTable.clickCellById(0, 'rows'); DashTable.getActiveCell().should('have.length', 1); - cy.get('.row-1').scrollTo(0, 1000); + cy.get('.dt-table-container__row-1').scrollTo(0, 1000); DashTable.getActiveCell().should('have.length', 0); - cy.get('.row-1').scrollTo(0, 0); + cy.get('.dt-table-container__row-1').scrollTo(0, 0); DashTable.getActiveCell().should('have.length', 1); }); @@ -45,10 +45,10 @@ variants.forEach(([mode, flavors]) => { DashTable.getSelectedCells().should('have.length', 6); - cy.get('.row-1').scrollTo(0, 1000); + cy.get('.dt-table-container__row-1').scrollTo(0, 1000); DashTable.getSelectedCells().should('have.length', 0); - cy.get('.row-1').scrollTo(0, 0); + cy.get('.dt-table-container__row-1').scrollTo(0, 0); DashTable.getSelectedCells().should('have.length', 6); }); @@ -57,7 +57,7 @@ variants.forEach(([mode, flavors]) => { DashTable.clickCell(0, 0); DashTable.toggleScroll(true); - cy.get('.row-1').scrollTo(0, 1000); + cy.get('.dt-table-container__row-1').scrollTo(0, 1000); cy.wait(1000); DashTable.clickCell(10, 1); diff --git a/tests/selenium/conftest.py b/tests/selenium/conftest.py index 176b45381..0530fa14b 100644 --- a/tests/selenium/conftest.py +++ b/tests/selenium/conftest.py @@ -376,9 +376,7 @@ def test(request, dash_thread_server, tmpdir): remote_url=request.config.getoption("remote_url"), headless=request.config.getoption("headless"), options=request.config.hook.pytest_setup_options(), - download_path=tmpdir.mkdir("download").strpath, - percy_assets_root=request.config.getoption("percy_assets"), + download_path=tmpdir.mkdir("dt-download").strpath, percy_finalize=request.config.getoption("nopercyfinalize"), - percy_run=False, ) as dc: yield dc diff --git a/tests/selenium/test_bootstrap.py b/tests/selenium/test_bootstrap.py new file mode 100644 index 000000000..c38f0bb9c --- /dev/null +++ b/tests/selenium/test_bootstrap.py @@ -0,0 +1,76 @@ +import dash +import pytest + +import dash_bootstrap_components as dbc +import dash_html_components as html +from dash_table import DataTable + +import pandas as pd + +url = "https://github.com/plotly/datasets/raw/master/" "26k-consumer-complaints.csv" +rawDf = pd.read_csv(url) +df = rawDf.to_dict("rows") + + +def get_app(fixed_rows, fixed_columns, ops): + app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) + + props = dict( + id="table", + data=df[0:250], + columns=[ + {"name": i, "id": i, "hideable": i == "Complaint ID"} for i in rawDf.columns + ], + style_table=dict(height="500px", maxHeight="500px", overflow="auto"), + editable=True, + sort_action="native", + include_headers_on_copy_paste=True, + **fixed_rows, + **fixed_columns, + **ops + ) + + app.layout = html.Div([DataTable(**props)]) + + return app + + +@pytest.mark.parametrize( + "fixed_rows,fixed_rows_description", + [(dict(), "unfixed_rows"), (dict(fixed_rows=dict(headers=True)), "fixed_rows")], +) +@pytest.mark.parametrize( + "fixed_columns,fixed_columns_description", + [ + (dict(), "unfixed_columns"), + (dict(fixed_columns=dict(headers=True)), "fixed_columns"), + ], +) +@pytest.mark.parametrize( + "ops,ops_description", + [ + (dict(), "ops: none"), + (dict(row_selectable="single", row_deletable=True), "ops: sinle+deletable"), + (dict(row_selectable="multi", row_deletable=True), "ops: multi+deletable"), + ], +) +def test_tbbs001_display( + dash_thread_server, + dash_duo, + test, + fixed_rows, + fixed_columns, + ops, + fixed_rows_description, + fixed_columns_description, + ops_description, +): + test.start_server(get_app(fixed_rows, fixed_columns, ops)) + + test.table("table").is_ready() + + test.percy_snapshot( + "DataTable Bootstrap side-effects with rows={} columns={} ops={}".format( + fixed_rows_description, fixed_columns_description, ops_description + ) + ) diff --git a/tests/selenium/test_scrolling.py b/tests/selenium/test_scrolling.py index bd7cea152..f70da7a4c 100644 --- a/tests/selenium/test_scrolling.py +++ b/tests/selenium/test_scrolling.py @@ -29,13 +29,15 @@ def get_margin(test): def get_scroll(test): return test.driver.execute_script( - "return document.querySelector('#table .row-1').scrollLeft;" + "return document.querySelector('#table .dt-table-container__row-1').scrollLeft;" ) def scroll_by(test, value): test.driver.execute_script( - "document.querySelector('#table .row-1').scrollBy({}, 0);".format(value) + "document.querySelector('#table .dt-table-container__row-1').scrollBy({}, 0);".format( + value + ) ) diff --git a/tests/visual/percy-storybook/Hideable.percy.tsx b/tests/visual/percy-storybook/Hideable.percy.tsx index e93fd417e..2b8b60e5d 100644 --- a/tests/visual/percy-storybook/Hideable.percy.tsx +++ b/tests/visual/percy-storybook/Hideable.percy.tsx @@ -6,6 +6,7 @@ import { storiesOf } from '@storybook/react'; import DataTable from 'dash-table/dash/DataTable'; import dataset from './../../assets/gapminder.csv'; + const result = parser.parse(dataset, { delimiter: ',', header: true }); const getColumns = () => R.addIndex(R.map)(