@@ -12,7 +12,7 @@ test("test", async ({ page }) => {
1212 const nextButton = calendar . locator ( ".calendar-nav-next" ) ;
1313
1414 // Assert the calendar is displayed
15- await expect ( calendar ) . toBeVisible ( ) ;
15+ await expect ( calendar ) . toBeVisible ( { timeout : 30000 } ) ;
1616 // Assert the current month is displayed
1717 const currentMonth = calendar . locator ( ".calendar-month-select" ) ;
1818 let currentMonthText = await currentMonth . inputValue ( ) ;
@@ -31,7 +31,7 @@ test("test", async ({ page }) => {
3131 // Move focus to the calendar with tab
3232 await page . keyboard . press ( "Tab" ) ;
3333 const focusedDay = calendar . locator (
34- '.calendar-grid-cell[data-month="current"]:focus' ,
34+ '.calendar-grid-cell[data-month="current"]:focus'
3535 ) ;
3636 // Assert a day is focused
3737 const firstDay = focusedDay . first ( ) ;
@@ -53,13 +53,13 @@ test("test", async ({ page }) => {
5353 // Assert the next week day is focused
5454 const nextWeekDayNumber = parseInt (
5555 ( await nextWeekDay . textContent ( ) ) || "" ,
56- 10 ,
56+ 10
5757 ) ;
5858 let current_date = new Date ( ) ;
5959 let daysInMonth = new Date (
6060 current_date . getFullYear ( ) ,
6161 current_date . getMonth ( ) + 1 ,
62- 0 ,
62+ 0
6363 ) . getDate ( ) ;
6464 if ( dayNumber + 7 > daysInMonth ) {
6565 // If the next week day is in the next month, it should wrap around
@@ -71,3 +71,206 @@ test("test", async ({ page }) => {
7171 await page . keyboard . press ( "ArrowUp" ) ;
7272 await expect ( firstDay ) . toContainText ( day || "failure" ) ;
7373} ) ;
74+
75+ test ( "year navigation by moving 52 weeks with arrow keys" , async ( { page } ) => {
76+ await page . goto ( "http://127.0.0.1:8080/component/?name=calendar&" , {
77+ timeout : 20 * 60 * 1000 ,
78+ } ) ;
79+
80+ // Find the calendar element
81+ const calendar = page . locator ( ".calendar" ) . nth ( 0 ) ;
82+ const monthSelect = calendar . locator ( ".calendar-month-select" ) ;
83+ const yearSelect = calendar . locator ( ".calendar-year-select" ) ;
84+
85+ // Assert the calendar is displayed
86+ await expect ( calendar ) . toBeVisible ( { timeout : 30000 } ) ;
87+
88+ // Get the initial month and year
89+ const initialMonth = await monthSelect . inputValue ( ) ;
90+ const initialYear = await yearSelect . inputValue ( ) ;
91+ const initialYearNumber = parseInt ( initialYear , 10 ) ;
92+ const initialMonthNumber = parseInt ( initialMonth , 10 ) ;
93+
94+ // Calculate the exact number of weeks needed to move to the next year
95+ // Start from the first day of the current month
96+ const startDate = new Date ( initialYearNumber , initialMonthNumber - 1 , 1 ) ;
97+ // Calculate the same date next year
98+ const targetDate = new Date ( initialYearNumber + 1 , initialMonthNumber - 1 , 1 ) ;
99+ // Calculate the difference in days
100+ const daysDifference = Math . floor (
101+ ( targetDate . getTime ( ) - startDate . getTime ( ) ) / ( 1000 * 60 * 60 * 24 )
102+ ) ;
103+ // Calculate the number of weeks (round to nearest week)
104+ const weeksToMove = Math . ceil ( daysDifference / 7 ) ;
105+
106+ // Move focus to the calendar manually
107+ const firstDay = calendar
108+ . locator ( '.calendar-grid-cell[data-month="current"]' )
109+ . first ( ) ;
110+ await firstDay . focus ( ) ;
111+
112+ // Press ArrowDown the calculated number of times to move forward by one year
113+ for ( let i = 0 ; i < weeksToMove ; i ++ ) {
114+ await page . keyboard . press ( "ArrowDown" ) ;
115+ }
116+
117+ // Assert the year has changed to the next year
118+ const nextYear = await yearSelect . inputValue ( ) ;
119+ const nextYearNumber = parseInt ( nextYear , 10 ) ;
120+ expect ( nextYearNumber ) . toBe ( initialYearNumber + 1 ) ;
121+
122+ // The month should be exactly the same
123+ const nextMonth = await monthSelect . inputValue ( ) ;
124+ expect ( nextMonth ) . toBe ( initialMonth ) ;
125+
126+ // Press ArrowUp the same number of times to move back by one year
127+ for ( let i = 0 ; i < weeksToMove ; i ++ ) {
128+ await page . keyboard . press ( "ArrowUp" ) ;
129+ }
130+
131+ // Assert the year has changed back to the original year
132+ const currentYear = await yearSelect . inputValue ( ) ;
133+ expect ( currentYear ) . toBe ( initialYear ) ;
134+
135+ // The month should be exactly the same
136+ const currentMonth = await monthSelect . inputValue ( ) ;
137+ expect ( currentMonth ) . toBe ( initialMonth ) ;
138+ } ) ;
139+
140+ test ( "shift + arrow keys navigation" , async ( { page } ) => {
141+ await page . goto ( "http://127.0.0.1:8080/component/?name=calendar&" , {
142+ timeout : 20 * 60 * 1000 ,
143+ } ) ;
144+
145+ // Find the calendar element
146+ const calendar = page . locator ( ".calendar" ) . nth ( 0 ) ;
147+ const monthSelect = calendar . locator ( ".calendar-month-select" ) ;
148+ const yearSelect = calendar . locator ( ".calendar-year-select" ) ;
149+
150+ // Assert the calendar is displayed
151+ await expect ( calendar ) . toBeVisible ( { timeout : 30000 } ) ;
152+
153+ // Get the initial month and year
154+ const initialMonth = await monthSelect . inputValue ( ) ;
155+ const initialYear = await yearSelect . inputValue ( ) ;
156+ const initialYearNumber = parseInt ( initialYear , 10 ) ;
157+ const initialMonthNumber = parseInt ( initialMonth , 10 ) ;
158+
159+ // Move focus to the calendar
160+ const firstDay = calendar
161+ . locator ( '.calendar-grid-cell[data-month="current"]' )
162+ . first ( ) ;
163+ await firstDay . focus ( ) ;
164+
165+ // Test Shift + ArrowDown - should move forward by one month
166+ await page . keyboard . press ( "Shift+ArrowDown" ) ;
167+
168+ let currentMonth = await monthSelect . inputValue ( ) ;
169+ let currentYear = await yearSelect . inputValue ( ) ;
170+ let expectedMonth = initialMonthNumber === 12 ? 1 : initialMonthNumber + 1 ;
171+ let expectedYear =
172+ initialMonthNumber === 12 ? initialYearNumber + 1 : initialYearNumber ;
173+
174+ expect ( parseInt ( currentMonth , 10 ) ) . toBe ( expectedMonth ) ;
175+ expect ( parseInt ( currentYear , 10 ) ) . toBe ( expectedYear ) ;
176+
177+ // Test Shift + ArrowUp - should move back to the initial month
178+ await page . keyboard . press ( "Shift+ArrowUp" ) ;
179+
180+ currentMonth = await monthSelect . inputValue ( ) ;
181+ currentYear = await yearSelect . inputValue ( ) ;
182+ expect ( currentMonth ) . toBe ( initialMonth ) ;
183+ expect ( currentYear ) . toBe ( initialYear ) ;
184+ } ) ;
185+
186+ async function testArrowKeyNavigation (
187+ page : any ,
188+ arrowKey : "ArrowRight" | "ArrowLeft" ,
189+ startPosition : "first" | "last" ,
190+ expectedOrder : "ascending" | "descending"
191+ ) {
192+ await page . goto ( "http://127.0.0.1:8080/component/?name=calendar&" , {
193+ timeout : 20 * 60 * 1000 ,
194+ } ) ;
195+
196+ // Find the calendar element
197+ const calendar = page . locator ( ".calendar" ) . nth ( 0 ) ;
198+ const monthSelect = calendar . locator ( ".calendar-month-select" ) ;
199+ const yearSelect = calendar . locator ( ".calendar-year-select" ) ;
200+
201+ // Assert the calendar is displayed
202+ await expect ( calendar ) . toBeVisible ( { timeout : 30000 } ) ;
203+
204+ // Get the current month and year to calculate days in month
205+ const currentMonthValue = await monthSelect . inputValue ( ) ;
206+ const currentYearValue = await yearSelect . inputValue ( ) ;
207+ const monthNumber = parseInt ( currentMonthValue , 10 ) ;
208+ const yearNumber = parseInt ( currentYearValue , 10 ) ;
209+
210+ // Calculate the number of days in the current month
211+ const daysInMonth = new Date ( yearNumber , monthNumber , 0 ) . getDate ( ) ;
212+
213+ // Move focus to the starting day of the current month
214+ const startDay = calendar
215+ . locator ( '.calendar-grid-cell[data-month="current"]' )
216+ [ startPosition ] ( ) ;
217+ await startDay . focus ( ) ;
218+
219+ // Get the focused day selector
220+ const focusedDay = calendar . locator (
221+ '.calendar-grid-cell[data-month="current"]:focus'
222+ ) ;
223+
224+ // Array to track all days visited
225+ const daysVisited = [ ] ;
226+
227+ // Get the starting day number
228+ let dayText = await focusedDay . first ( ) . textContent ( ) ;
229+ let dayNumber = parseInt ( dayText || "" , 10 ) ;
230+ daysVisited . push ( dayNumber ) ;
231+
232+ // Press arrow key to navigate through all remaining days of the month
233+ for ( let i = 1 ; i < daysInMonth ; i ++ ) {
234+ await page . keyboard . press ( arrowKey ) ;
235+
236+ // Get the new focused day
237+ dayText = await focusedDay . first ( ) . textContent ( ) ;
238+ dayNumber = parseInt ( dayText || "" , 10 ) ;
239+ daysVisited . push ( dayNumber ) ;
240+ }
241+
242+ // Assert that we visited the correct number of days
243+ expect ( daysVisited . length ) . toBe ( daysInMonth ) ;
244+
245+ // Sort the days visited to check we got all days from 1 to daysInMonth
246+ const sortedDays = [ ...daysVisited ] . sort ( ( a , b ) => a - b ) ;
247+
248+ // Create the expected array [1, 2, 3, ..., daysInMonth]
249+ const expectedDays = Array . from ( { length : daysInMonth } , ( _ , i ) => i + 1 ) ;
250+
251+ // Assert that we visited every day exactly once
252+ expect ( sortedDays ) . toEqual ( expectedDays ) ;
253+
254+ // Verify we traversed in the expected order
255+ if ( expectedOrder === "ascending" ) {
256+ expect ( daysVisited ) . toEqual ( expectedDays ) ;
257+ } else {
258+ const expectedReverseDays = Array . from (
259+ { length : daysInMonth } ,
260+ ( _ , i ) => daysInMonth - i
261+ ) ;
262+ expect ( daysVisited ) . toEqual ( expectedReverseDays ) ;
263+ }
264+ }
265+
266+ test ( "right arrow key navigates through all days of the month" , async ( {
267+ page,
268+ } ) => {
269+ await testArrowKeyNavigation ( page , "ArrowRight" , "first" , "ascending" ) ;
270+ } ) ;
271+
272+ test ( "left arrow key navigates through all days of the month in reverse" , async ( {
273+ page,
274+ } ) => {
275+ await testArrowKeyNavigation ( page , "ArrowLeft" , "last" , "descending" ) ;
276+ } ) ;
0 commit comments