From 6e3ba9aa1c9e63ae472c4a01104934b09f91c2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 11:32:39 -0500 Subject: [PATCH 01/13] add vertical slider test without fix --- CHANGELOG.md | 3 +++ test/test_integration.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e345c1b67..00672c08f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] +### Fixed +- Fix Vertical Slider regression [#479](https://github.com/plotly/dash/issues/479) ## [0.44.0] - 2019-03-04 ### Added diff --git a/test/test_integration.py b/test/test_integration.py index d73ce6c55..1ad043d29 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -328,12 +328,23 @@ def test_gallery(self): id='disabled-textinput', disabled=True), html.Label('Slider'), + html.Div(children=[dcc.Slider( + min=0, + max=9, + marks={i: 'Label {}'.format(i) if i == 1 else str(i) + for i in range(1, 6)}, + value=5, + )], style={'height': '500px'}), + + html.Label('Vertical Slider'), dcc.Slider( + id='vertical-slider' min=0, max=9, marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)}, value=5, + vertical=True, ), html.Label('Graph'), @@ -489,6 +500,12 @@ def test_gallery(self): 'but initial month is') dt_input_4.send_keys("1997-05-03") + v_slider = self.driver.find_element_by_css_selector( + '#vertical-slider' + ) + v_slider.click() + self.snapshot('gallery - Vertical Slider') + def test_tabs_in_vertical_mode(self): app = dash.Dash(__name__) From c8065a9864f59b779390bf6a81c1b1577651f00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 11:44:40 -0500 Subject: [PATCH 02/13] fix flake --- test/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_integration.py b/test/test_integration.py index 1ad043d29..10f08fc26 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -338,7 +338,7 @@ def test_gallery(self): html.Label('Vertical Slider'), dcc.Slider( - id='vertical-slider' + id='vertical-slider', min=0, max=9, marks={i: 'Label {}'.format(i) if i == 1 else str(i) From f261f573b08f74ae73db3699f91beb9dfdebb830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 11:57:45 -0500 Subject: [PATCH 03/13] more precise slider selector --- test/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_integration.py b/test/test_integration.py index 10f08fc26..da4b0348c 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -501,7 +501,7 @@ def test_gallery(self): dt_input_4.send_keys("1997-05-03") v_slider = self.driver.find_element_by_css_selector( - '#vertical-slider' + '#vertical-slider div[role="slider"]' ) v_slider.click() self.snapshot('gallery - Vertical Slider') From 1c9dc1bc4767858d0726319c5ce4e83204d472df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 15:05:31 -0500 Subject: [PATCH 04/13] update tests w/ console error watcher --- test/IntegrationTests.py | 64 ++++++++++++++++++++++------------------ test/test_integration.py | 46 ++++++++++++++++++----------- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/test/IntegrationTests.py b/test/IntegrationTests.py index 03dbac57f..08ddffefb 100644 --- a/test/IntegrationTests.py +++ b/test/IntegrationTests.py @@ -11,6 +11,36 @@ from selenium import webdriver from selenium.webdriver.chrome.options import Options +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + + +class WebdriverLogFacade(object): + + last_timestamp = 0 + + def __init__(self, webdriver): + self._webdriver = webdriver + + def get_log(self): + last_timestamp = self.last_timestamp + entries = self._webdriver.get_log("browser") + filtered = [] + + for entry in entries: + # check the logged timestamp against the + # stored timestamp + if entry["timestamp"] > self.last_timestamp: + filtered.append(entry) + + # save the last timestamp only if newer + # in this set of logs + if entry["timestamp"] > last_timestamp: + last_timestamp = entry["timestamp"] + + # store the very last timestamp + self.last_timestamp = last_timestamp + + return filtered class IntegrationTests(unittest.TestCase): @@ -20,11 +50,13 @@ def setUpClass(cls): super(IntegrationTests, cls).setUpClass() options = Options() + capabilities = DesiredCapabilities.CHROME + capabilities['loggingPrefs'] = { 'browser':'SEVERE' } if 'DASH_TEST_CHROMEPATH' in os.environ: options.binary_location = os.environ['DASH_TEST_CHROMEPATH'] - cls.driver = webdriver.Chrome(chrome_options=options) + cls.driver = webdriver.Chrome(options=options, desired_capabilities=capabilities) loader = percy.ResourceLoader( webdriver=cls.driver, base_url='/assets', @@ -32,6 +64,7 @@ def setUpClass(cls): ) cls.percy_runner = percy.Runner(loader=loader) cls.percy_runner.initialize_build() + cls.log_facade = WebdriverLogFacade(cls.driver) @classmethod def tearDownClass(cls): @@ -47,7 +80,8 @@ def tearDown(self): requests.get('http://localhost:8050/stop') else: self.server_process.terminate() - self.driver.back() + + self.log_facade.get_log() time.sleep(1) def startServer(self, app): @@ -102,29 +136,3 @@ def _stop_server_windows(): # Visit the dash page self.driver.get('http://localhost:8050') - - # Inject an error and warning logger - logger = ''' - window.tests = {}; - window.tests.console = {error: [], warn: [], log: []}; - - var _log = console.log; - var _warn = console.warn; - var _error = console.error; - - console.log = function() { - window.tests.console.log.push({method: 'log', arguments: arguments}); - return _log.apply(console, arguments); - }; - - console.warn = function() { - window.tests.console.warn.push({method: 'warn', arguments: arguments}); - return _warn.apply(console, arguments); - }; - - console.error = function() { - window.tests.console.error.push({method: 'error', arguments: arguments}); - return _error.apply(console, arguments); - }; - ''' - self.driver.execute_script(logger) diff --git a/test/test_integration.py b/test/test_integration.py index da4b0348c..b493b23f0 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -217,6 +217,34 @@ def test_upload_gallery(self): self.snapshot('test_upload_gallery') + def test_vertical_slider(self): + app = dash.Dash(__name__) + + app.layout = html.Div([ + html.Label('Vertical Slider'), + dcc.Slider( + id='vertical-slider', + min=0, + max=9, + marks={i: 'Label {}'.format(i) if i == 1 else str(i) + for i in range(1, 6)}, + value=5, + vertical=True, + ), + ], style={'height': '500px'}) + self.startServer(app) + + self.wait_for_element_by_css_selector('#vertical-slider') + self.snapshot('vertical slider') + + v_slider = self.driver.find_element_by_css_selector( + '#vertical-slider div[role="slider"]' + ) + v_slider.click() + + for entry in self.log_facade.get_log(): + raise Exception('browser error logged during test', entry) + def test_gallery(self): app = dash.Dash(__name__) @@ -336,17 +364,6 @@ def test_gallery(self): value=5, )], style={'height': '500px'}), - html.Label('Vertical Slider'), - dcc.Slider( - id='vertical-slider', - min=0, - max=9, - marks={i: 'Label {}'.format(i) if i == 1 else str(i) - for i in range(1, 6)}, - value=5, - vertical=True, - ), - html.Label('Graph'), dcc.Graph( id='graph', @@ -485,6 +502,7 @@ def test_gallery(self): dt_input_3 = self.driver.find_element_by_css_selector( '#dt-range-no-date-values #endDate' ) + dt_input_3.click() self.snapshot('gallery - DatePickerRange\'s datepicker ' 'when neither start date nor end date ' @@ -500,12 +518,6 @@ def test_gallery(self): 'but initial month is') dt_input_4.send_keys("1997-05-03") - v_slider = self.driver.find_element_by_css_selector( - '#vertical-slider div[role="slider"]' - ) - v_slider.click() - self.snapshot('gallery - Vertical Slider') - def test_tabs_in_vertical_mode(self): app = dash.Dash(__name__) From 1faedfc27523274a39ba040a7af43e110beb18f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 15:13:08 -0500 Subject: [PATCH 05/13] fix lint --- test/IntegrationTests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IntegrationTests.py b/test/IntegrationTests.py index 08ddffefb..70814a0e8 100644 --- a/test/IntegrationTests.py +++ b/test/IntegrationTests.py @@ -51,7 +51,7 @@ def setUpClass(cls): options = Options() capabilities = DesiredCapabilities.CHROME - capabilities['loggingPrefs'] = { 'browser':'SEVERE' } + capabilities['loggingPrefs'] = {'browser': 'SEVERE'} if 'DASH_TEST_CHROMEPATH' in os.environ: options.binary_location = os.environ['DASH_TEST_CHROMEPATH'] From 29abf7bab9b3747306f42731bf5e37235ed32455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 15:23:07 -0500 Subject: [PATCH 06/13] fix vertical slider --- src/components/Slider.react.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 9d415f355..5fe48e16a 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -26,6 +26,7 @@ export default class Slider extends Component { data-dash-is-loading={ (loading_state && loading_state.is_loading) || undefined } + style={{ display: 'initial' }} > { From a71633b149eb790a8f6aa6f66ffd599dfebeeee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 15:30:50 -0500 Subject: [PATCH 07/13] undo useless changes --- test/test_integration.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/test_integration.py b/test/test_integration.py index b493b23f0..976b86d64 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -356,13 +356,13 @@ def test_gallery(self): id='disabled-textinput', disabled=True), html.Label('Slider'), - html.Div(children=[dcc.Slider( + dcc.Slider( min=0, max=9, marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)}, value=5, - )], style={'height': '500px'}), + ), html.Label('Graph'), dcc.Graph( @@ -502,7 +502,6 @@ def test_gallery(self): dt_input_3 = self.driver.find_element_by_css_selector( '#dt-range-no-date-values #endDate' ) - dt_input_3.click() self.snapshot('gallery - DatePickerRange\'s datepicker ' 'when neither start date nor end date ' From fcc23ca665b9536ab0c337bca282828efe591596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Thu, 7 Mar 2019 15:31:26 -0500 Subject: [PATCH 08/13] prettier --- src/components/Slider.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 5fe48e16a..94e5512e7 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -26,7 +26,7 @@ export default class Slider extends Component { data-dash-is-loading={ (loading_state && loading_state.is_loading) || undefined } - style={{ display: 'initial' }} + style={{display: 'initial'}} > { From ae058b83decc0b80aeb4795904bd3526cc7f2804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 8 Mar 2019 09:56:31 -0500 Subject: [PATCH 09/13] change initial for inline --- src/components/Slider.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 94e5512e7..794b45553 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -26,7 +26,7 @@ export default class Slider extends Component { data-dash-is-loading={ (loading_state && loading_state.is_loading) || undefined } - style={{display: 'initial'}} + style={{display: 'inline'}} > { From 51ac3e67308dc12e6e1a4250308fad98a24eccca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Rivet?= Date: Fri, 8 Mar 2019 11:42:27 -0500 Subject: [PATCH 10/13] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00672c08f..76cc6214c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased] +## [unreleased] ### Fixed - Fix Vertical Slider regression [#479](https://github.com/plotly/dash/issues/479) From b79935b9f5aeb6ccd183daa1f88829d5e8ef18d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 8 Mar 2019 12:44:31 -0500 Subject: [PATCH 11/13] style vertical case with height --- src/components/Slider.react.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 794b45553..8bf41115a 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -18,7 +18,7 @@ export default class Slider extends Component { } render() { - const {id, setProps, updatemode, loading_state} = this.props; + const {id, loading_state, setProps, updatemode, vertical} = this.props; const {value} = this.state; return (
{ From ae84539de1ddf7386fbd5637fb02e93181ffc280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 8 Mar 2019 13:33:38 -0500 Subject: [PATCH 12/13] lint --- src/components/Slider.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Slider.react.js b/src/components/Slider.react.js index 8bf41115a..28378ecba 100644 --- a/src/components/Slider.react.js +++ b/src/components/Slider.react.js @@ -26,7 +26,7 @@ export default class Slider extends Component { data-dash-is-loading={ (loading_state && loading_state.is_loading) || undefined } - style={vertical ? { height: '100%' } : {}} + style={vertical ? {height: '100%'} : {}} > { From 8341d222e2fae3b10dc21e56f8f6cf9c13c149f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Rivet?= Date: Fri, 8 Mar 2019 14:01:14 -0500 Subject: [PATCH 13/13] refactor logs --- test/IntegrationTests.py | 45 +++++++++++++--------------------------- test/test_integration.py | 2 +- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/test/IntegrationTests.py b/test/IntegrationTests.py index 70814a0e8..55de61648 100644 --- a/test/IntegrationTests.py +++ b/test/IntegrationTests.py @@ -14,35 +14,6 @@ from selenium.webdriver.common.desired_capabilities import DesiredCapabilities -class WebdriverLogFacade(object): - - last_timestamp = 0 - - def __init__(self, webdriver): - self._webdriver = webdriver - - def get_log(self): - last_timestamp = self.last_timestamp - entries = self._webdriver.get_log("browser") - filtered = [] - - for entry in entries: - # check the logged timestamp against the - # stored timestamp - if entry["timestamp"] > self.last_timestamp: - filtered.append(entry) - - # save the last timestamp only if newer - # in this set of logs - if entry["timestamp"] > last_timestamp: - last_timestamp = entry["timestamp"] - - # store the very last timestamp - self.last_timestamp = last_timestamp - - return filtered - - class IntegrationTests(unittest.TestCase): @classmethod @@ -64,7 +35,6 @@ def setUpClass(cls): ) cls.percy_runner = percy.Runner(loader=loader) cls.percy_runner.initialize_build() - cls.log_facade = WebdriverLogFacade(cls.driver) @classmethod def tearDownClass(cls): @@ -81,7 +51,7 @@ def tearDown(self): else: self.server_process.terminate() - self.log_facade.get_log() + self.clear_log() time.sleep(1) def startServer(self, app): @@ -136,3 +106,16 @@ def _stop_server_windows(): # Visit the dash page self.driver.get('http://localhost:8050') + + def clear_log(self): + entries = self.driver.get_log("browser") + + if entries: + self.last_timestamp = entries[-1]["timestamp"] + + def get_log(self): + entries = self.driver.get_log("browser") + + return [entry for entry in entries if entry["timestamp"] > self.last_timestamp] + + last_timestamp = 0 diff --git a/test/test_integration.py b/test/test_integration.py index 976b86d64..3eca2dfc3 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -242,7 +242,7 @@ def test_vertical_slider(self): ) v_slider.click() - for entry in self.log_facade.get_log(): + for entry in self.get_log(): raise Exception('browser error logged during test', entry) def test_gallery(self):