Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit 9f1a439

Browse files
authored
Fix clearable (#599)
* 🐛 fix #594 * 🐛 this fixes #593 * 💄 fix lint * ⚗️ add wait for clickable * :add percy reset * 🔧 add percy reset * rename job * 🔧 try on_fail step * 👌 add more check so less superfluous * 🔍
1 parent 9794c5a commit 9f1a439

File tree

4 files changed

+128
-56
lines changed

4 files changed

+128
-56
lines changed

.circleci/config.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobs:
1212
environment:
1313
PYTHON_VERSION: py27
1414
PERCY_PARALLEL_TOTAL: '-1'
15+
- image: percyio/agent
1516

1617
steps:
1718
- checkout
@@ -53,6 +54,11 @@ jobs:
5354
python --version
5455
npm run test
5556
57+
- run:
58+
name: Percy TearDown
59+
command: percy --finalize -all
60+
when: on_fail
61+
5662
'python-3.6':
5763
<<: *test-template
5864
docker:
@@ -73,7 +79,7 @@ workflows:
7379
version: 2
7480
build:
7581
jobs:
76-
- 'python-2.7'
82+
- python-2.7
7783
- "percy-finalize":
7884
requires:
7985
- 'python-2.7'

src/components/DatePickerRange.react.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default class DatePickerRange extends Component {
4646
}
4747

4848
onDatesChange({startDate: start_date, endDate: end_date}) {
49-
const {setProps, updatemode} = this.props;
49+
const {setProps, updatemode, clearable} = this.props;
5050

5151
const oldMomentDates = convertToMoment(this.state, [
5252
'start_date',
@@ -71,6 +71,16 @@ export default class DatePickerRange extends Component {
7171
});
7272
}
7373
}
74+
75+
if (
76+
clearable &&
77+
!start_date &&
78+
!end_date &&
79+
(oldMomentDates.start_date !== start_date ||
80+
oldMomentDates.end_date !== end_date)
81+
) {
82+
setProps({start_date: null, end_date: null});
83+
}
7484
}
7585

7686
isOutsideRange(date) {
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import itertools
2+
import pytest
3+
4+
import dash_core_components as dcc
5+
import dash_html_components as html
6+
import dash
7+
from dash.dependencies import Input, Output
8+
import dash.testing.wait as wait
9+
10+
DAY_SELECTOR = 'div[data-visible="true"] td.CalendarDay'
11+
12+
13+
@pytest.mark.DCC594
14+
def test_cdpr001_date_clearable_true_works(dash_duo):
15+
16+
app = dash.Dash(__name__)
17+
app.layout = html.Div([dcc.DatePickerRange(id="dpr", clearable=True)])
18+
19+
dash_duo.start_server(app)
20+
21+
start_date = dash_duo.find_element('input[aria-label="Start Date"]')
22+
end_date = dash_duo.find_element('input[aria-label="End Date"]')
23+
24+
start_date.click()
25+
26+
dash_duo.find_elements(DAY_SELECTOR)[0].click()
27+
dash_duo.find_elements(DAY_SELECTOR)[-1].click()
28+
29+
close_btn = dash_duo.wait_for_element('button[aria-label="Clear Dates"]')
30+
31+
assert start_date.get_attribute("value") and end_date.get_attribute(
32+
"value"
33+
), "both start date and end date should get values"
34+
35+
close_btn.click()
36+
assert not start_date.get_attribute(
37+
"value"
38+
) and not end_date.get_attribute(
39+
"value"
40+
), "both start and end dates should be cleared"
41+
42+
43+
def test_cdpr002_updatemodes(dash_duo):
44+
app = dash.Dash(__name__)
45+
46+
app.layout = html.Div(
47+
[
48+
dcc.DatePickerRange(
49+
id="date-picker-range",
50+
start_date_id="startDate",
51+
end_date_id="endDate",
52+
start_date_placeholder_text="Select a start date!",
53+
end_date_placeholder_text="Select an end date!",
54+
updatemode="bothdates",
55+
),
56+
html.Div(id="date-picker-range-output"),
57+
]
58+
)
59+
60+
@app.callback(
61+
Output("date-picker-range-output", "children"),
62+
[
63+
Input("date-picker-range", "start_date"),
64+
Input("date-picker-range", "end_date"),
65+
],
66+
)
67+
def update_output(start_date, end_date):
68+
return "{} - {}".format(start_date, end_date)
69+
70+
dash_duo.start_server(app=app)
71+
72+
start_date = dash_duo.find_element("#startDate")
73+
start_date.click()
74+
75+
end_date = dash_duo.find_element("#endDate")
76+
end_date.click()
77+
78+
assert (
79+
dash_duo.find_element("#date-picker-range-output").text
80+
== "None - None"
81+
), "the output should not update when both clicked but no selection happen"
82+
83+
start_date.click()
84+
85+
dash_duo.find_elements(DAY_SELECTOR)[4].click()
86+
assert (
87+
dash_duo.find_element("#date-picker-range-output").text
88+
== "None - None"
89+
), "the output should not update when only one is selected"
90+
91+
eday = dash_duo.find_elements(DAY_SELECTOR)[-4]
92+
wait.until(lambda: eday.is_displayed() and eday.is_enabled(), timeout=2)
93+
eday.click()
94+
95+
date_tokens = set(start_date.get_attribute("value").split("/"))
96+
date_tokens.update(end_date.get_attribute("value").split("/"))
97+
98+
assert (
99+
set(
100+
itertools.chain(
101+
*[
102+
_.split("-")
103+
for _ in dash_duo.find_element(
104+
"#date-picker-range-output"
105+
).text.split(" - ")
106+
]
107+
)
108+
)
109+
== date_tokens
110+
), "date should match the callback output"

tests/test_integration.py

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,60 +1186,6 @@ def test_graphs_without_ids(self):
11861186

11871187
self.assertNotEqual(graph_1.get_attribute('id'), graph_2.get_attribute('id'))
11881188

1189-
def test_datepickerrange_updatemodes(self):
1190-
app = dash.Dash(__name__)
1191-
1192-
app.layout = html.Div([
1193-
dcc.DatePickerRange(
1194-
id='date-picker-range',
1195-
start_date_id='startDate',
1196-
end_date_id='endDate',
1197-
start_date_placeholder_text='Select a start date!',
1198-
end_date_placeholder_text='Select an end date!',
1199-
updatemode='bothdates'
1200-
),
1201-
html.Div(id='date-picker-range-output')
1202-
])
1203-
1204-
@app.callback(
1205-
dash.dependencies.Output('date-picker-range-output', 'children'),
1206-
[dash.dependencies.Input('date-picker-range', 'start_date'),
1207-
dash.dependencies.Input('date-picker-range', 'end_date')])
1208-
def update_output(start_date, end_date):
1209-
return '{} - {}'.format(start_date, end_date)
1210-
1211-
self.startServer(app=app)
1212-
1213-
start_date = self.wait_for_element_by_css_selector('#startDate')
1214-
start_date.click()
1215-
1216-
end_date = self.wait_for_element_by_css_selector('#endDate')
1217-
end_date.click()
1218-
1219-
self.wait_for_text_to_equal('#date-picker-range-output', 'None - None')
1220-
1221-
# using mouse click with fixed day range, this can be improved
1222-
# once we start refactoring the test structure
1223-
start_date.click()
1224-
1225-
sday = self.driver.find_element_by_xpath("//td[text()='1' and @tabindex='0']")
1226-
sday.click()
1227-
self.wait_for_text_to_equal('#date-picker-range-output', 'None - None')
1228-
1229-
eday = self.driver.find_elements_by_xpath("//td[text()='28']")[1]
1230-
eday.click()
1231-
1232-
date_tokens = set(start_date.get_attribute('value').split('/'))
1233-
date_tokens.update(end_date.get_attribute('value').split('/'))
1234-
1235-
self.assertEqual(
1236-
set(itertools.chain(*[
1237-
_.split('-')
1238-
for _ in self.driver.find_element_by_css_selector(
1239-
'#date-picker-range-output').text.split(' - ')])),
1240-
date_tokens,
1241-
"date should match the callback output")
1242-
12431189
def test_interval(self):
12441190
app = dash.Dash(__name__)
12451191
app.layout = html.Div([

0 commit comments

Comments
 (0)