Skip to content

Commit 962ccb7

Browse files
Add CalendarMonth widget
1 parent 13917b8 commit 962ccb7

4 files changed

Lines changed: 176 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Button - <https://www.patternfly.org/v4/components/button>
1717

1818
Bullet Chart - <https://www.patternfly.org/v4/charts/bullet-chart>
1919

20+
Calendar month - <https://www.patternfly.org/v4/components/calendar-month>
21+
2022
Card - <https://www.patternfly.org/v4/components/card>
2123

2224
Chip Group - <https://www.patternfly.org/v4/components/chip-group>

src/widgetastic_patternfly4/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from .breadcrumb import BreadCrumb
33
from .bulletchart import BulletChart
44
from .button import Button
5+
from .calendarmonth import CalendarMonth
56
from .card import Card
67
from .card import CardCheckBox
78
from .card import CardForCardGroup
@@ -64,6 +65,7 @@
6465
"BreadCrumb",
6566
"Button",
6667
"BulletChart",
68+
"CalendarMonth",
6769
"CheckboxMenu",
6870
"CheckboxSelect",
6971
"Chip",
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from selenium.common.exceptions import NoSuchElementException
2+
from widgetastic.utils import ParametrizedLocator
3+
from widgetastic.widget import Table
4+
from widgetastic.widget import TextInput
5+
from widgetastic.widget import Widget
6+
7+
from .select import Select
8+
9+
10+
class BaseCalendarMonth:
11+
"""Represents calendar month component.
12+
13+
https://www.patternfly.org/v4/components/calendar-month
14+
"""
15+
16+
CALENDAR_HEADER = ".//div[@class='pf-c-calendar-month__header']"
17+
MONTH_SELECT_LOCATOR = (
18+
f"{CALENDAR_HEADER}//div[contains(@class, 'header-month')]"
19+
f"//div[@data-ouia-component-type='PF4/Select']"
20+
)
21+
YEAR_INPUT_LOCATOR = f"{CALENDAR_HEADER}//div[contains(@class, 'header-year')]/input"
22+
23+
PREV_BUTTON_LOCATOR = f"{CALENDAR_HEADER}//div[contains(@class, 'prev-month')]"
24+
NEXT_BUTTON_LOCATOR = f"{CALENDAR_HEADER}//div[contains(@class, 'next-month')]"
25+
26+
TABLE = ".//table"
27+
SELECTED_DATE_LOCATOR = f"{TABLE}/tbody//td[contains(@class, 'pf-m-selected')]"
28+
29+
def prev(self):
30+
return self.browser.click(self.PREV_BUTTON_LOCATOR)
31+
32+
def next(self):
33+
return self.browser.click(self.NEXT_BUTTON_LOCATOR)
34+
35+
@property
36+
def year(self):
37+
el = self.browser.element(self.YEAR_INPUT_LOCATOR)
38+
return el.get_attribute("value")
39+
40+
@year.setter
41+
def year(self, value):
42+
year_input_widget = TextInput(self, locator=self.YEAR_INPUT_LOCATOR)
43+
year_input_widget.fill(value)
44+
45+
@property
46+
def month(self):
47+
el = self.browser.element(self.MONTH_SELECT_LOCATOR)
48+
return self.browser.text(el)
49+
50+
@month.setter
51+
def month(self, value):
52+
month_select_widget = Select(self, locator=self.MONTH_SELECT_LOCATOR)
53+
month_select_widget.item_select(value)
54+
55+
@property
56+
def day(self):
57+
try:
58+
el = self.browser.element(self.SELECTED_DATE_LOCATOR)
59+
except NoSuchElementException:
60+
return ""
61+
return self.browser.text(el)
62+
63+
@day.setter
64+
def day(self, value):
65+
table_widget = Table(self, locator=self.TABLE)
66+
for row in table_widget:
67+
for _, col in row:
68+
if col.text == value:
69+
col.click()
70+
return
71+
72+
def read(self):
73+
"""Returns the currently selected date in format DD MONTH YYYY."""
74+
return f"{self.day} {self.month} {self.year}"
75+
76+
def fill(self, items):
77+
"""Fills a Calendar with all items.
78+
Example dictionary: {'day': '22', 'month': 'November', 'year': '2023'}"
79+
80+
Args:
81+
items: A dictionary containing what items to select (True) or deselect (False)
82+
"""
83+
if type(items) is not dict:
84+
raise TypeError("Fill value has to be dictionary type. ")
85+
if "day" in items:
86+
self.day = items["day"]
87+
if "month" in items:
88+
self.month = items["month"]
89+
if "year" in items:
90+
self.year = items["year"]
91+
92+
93+
class CalendarMonth(BaseCalendarMonth, Widget):
94+
ROOT = ParametrizedLocator("{@locator}")
95+
96+
def __init__(self, parent, locator, logger=None):
97+
super().__init__(parent, logger=logger)
98+
self.locator = locator

testing/test_calendarmonth.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import calendar
2+
3+
import pytest
4+
from widgetastic.widget import View
5+
6+
from widgetastic_patternfly4 import CalendarMonth
7+
8+
TESTING_PAGE_URL = "https://patternfly-react.surge.sh/components/calendar-month"
9+
10+
MONTHS_LIST = list(calendar.month_name[1:])
11+
12+
13+
@pytest.fixture
14+
def calendar_month_view(browser):
15+
class TestView(View):
16+
ROOT = ".//div[@id='ws-react-c-calendar-month-selectable-date']"
17+
calendar = CalendarMonth(locator=".//div[@class='pf-c-calendar-month']")
18+
19+
return TestView(browser)
20+
21+
22+
def test_year_selection(calendar_month_view):
23+
assert calendar_month_view.calendar.year
24+
calendar_month_view.calendar.year = "2023"
25+
assert calendar_month_view.calendar.year == "2023"
26+
27+
28+
def test_month_selection(calendar_month_view):
29+
assert calendar_month_view.calendar.month
30+
calendar_month_view.calendar.month = "December"
31+
assert calendar_month_view.calendar.month == "December"
32+
33+
34+
def test_day_selection(calendar_month_view):
35+
calendar_month_view.calendar.day = "20"
36+
assert calendar_month_view.calendar.day == "20"
37+
calendar_month_view.calendar.next()
38+
assert not calendar_month_view.calendar.day
39+
40+
41+
def _get_proper_month_index(index):
42+
max_index = len(MONTHS_LIST) - 1
43+
if index < 0:
44+
index = max_index
45+
elif index > max_index:
46+
index = 0
47+
48+
return index
49+
50+
51+
def test_month_navigation(calendar_month_view):
52+
current_month = calendar_month_view.calendar.month
53+
prev_month_index = _get_proper_month_index(MONTHS_LIST.index(current_month) - 1)
54+
next_month_index = _get_proper_month_index(MONTHS_LIST.index(current_month) + 1)
55+
56+
calendar_month_view.calendar.prev()
57+
prev_month = calendar_month_view.calendar.month
58+
assert prev_month == MONTHS_LIST[prev_month_index]
59+
60+
# reset to current default month
61+
calendar_month_view.calendar.month = current_month
62+
63+
calendar_month_view.calendar.next()
64+
next_month = calendar_month_view.calendar.month
65+
assert next_month == MONTHS_LIST[next_month_index]
66+
67+
68+
def test_fill_and_read(calendar_month_view):
69+
calendar_month_view.calendar.fill({"day": "10", "month": "February", "year": "2023"})
70+
result = calendar_month_view.calendar.read()
71+
assert result == "10 February 2023"
72+
73+
with pytest.raises(TypeError):
74+
calendar_month_view.calendar.fill("foo")

0 commit comments

Comments
 (0)