@@ -71,3 +71,198 @@ 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 . locator (
108+ '.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 . locator (
161+ '.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 = initialMonthNumber === 12 ? initialYearNumber + 1 : initialYearNumber ;
172+
173+ expect ( parseInt ( currentMonth , 10 ) ) . toBe ( expectedMonth ) ;
174+ expect ( parseInt ( currentYear , 10 ) ) . toBe ( expectedYear ) ;
175+
176+ // Test Shift + ArrowUp - should move back to the initial month
177+ await page . keyboard . press ( "Shift+ArrowUp" ) ;
178+
179+ currentMonth = await monthSelect . inputValue ( ) ;
180+ currentYear = await yearSelect . inputValue ( ) ;
181+ expect ( currentMonth ) . toBe ( initialMonth ) ;
182+ expect ( currentYear ) . toBe ( initialYear ) ;
183+ } ) ;
184+
185+ async function testArrowKeyNavigation (
186+ page : any ,
187+ arrowKey : "ArrowRight" | "ArrowLeft" ,
188+ startPosition : "first" | "last" ,
189+ expectedOrder : "ascending" | "descending"
190+ ) {
191+ await page . goto ( "http://127.0.0.1:8080/component/?name=calendar&" , {
192+ timeout : 20 * 60 * 1000 ,
193+ } ) ;
194+
195+ // Find the calendar element
196+ const calendar = page . locator ( ".calendar" ) . nth ( 0 ) ;
197+ const monthSelect = calendar . locator ( ".calendar-month-select" ) ;
198+ const yearSelect = calendar . locator ( ".calendar-year-select" ) ;
199+
200+ // Assert the calendar is displayed
201+ await expect ( calendar ) . toBeVisible ( { timeout : 30000 } ) ;
202+
203+ // Get the current month and year to calculate days in month
204+ const currentMonthValue = await monthSelect . inputValue ( ) ;
205+ const currentYearValue = await yearSelect . inputValue ( ) ;
206+ const monthNumber = parseInt ( currentMonthValue , 10 ) ;
207+ const yearNumber = parseInt ( currentYearValue , 10 ) ;
208+
209+ // Calculate the number of days in the current month
210+ const daysInMonth = new Date ( yearNumber , monthNumber , 0 ) . getDate ( ) ;
211+
212+ // Move focus to the starting day of the current month
213+ const startDay = calendar . locator (
214+ '.calendar-grid-cell[data-month="current"]' ,
215+ ) [ startPosition ] ( ) ;
216+ await startDay . focus ( ) ;
217+
218+ // Get the focused day selector
219+ const focusedDay = calendar . locator (
220+ '.calendar-grid-cell[data-month="current"]:focus' ,
221+ ) ;
222+
223+ // Array to track all days visited
224+ const daysVisited = [ ] ;
225+
226+ // Get the starting day number
227+ let dayText = await focusedDay . first ( ) . textContent ( ) ;
228+ let dayNumber = parseInt ( dayText || "" , 10 ) ;
229+ daysVisited . push ( dayNumber ) ;
230+
231+ // Press arrow key to navigate through all remaining days of the month
232+ for ( let i = 1 ; i < daysInMonth ; i ++ ) {
233+ await page . keyboard . press ( arrowKey ) ;
234+
235+ // Get the new focused day
236+ dayText = await focusedDay . first ( ) . textContent ( ) ;
237+ dayNumber = parseInt ( dayText || "" , 10 ) ;
238+ daysVisited . push ( dayNumber ) ;
239+ }
240+
241+ // Assert that we visited the correct number of days
242+ expect ( daysVisited . length ) . toBe ( daysInMonth ) ;
243+
244+ // Sort the days visited to check we got all days from 1 to daysInMonth
245+ const sortedDays = [ ...daysVisited ] . sort ( ( a , b ) => a - b ) ;
246+
247+ // Create the expected array [1, 2, 3, ..., daysInMonth]
248+ const expectedDays = Array . from ( { length : daysInMonth } , ( _ , i ) => i + 1 ) ;
249+
250+ // Assert that we visited every day exactly once
251+ expect ( sortedDays ) . toEqual ( expectedDays ) ;
252+
253+ // Verify we traversed in the expected order
254+ if ( expectedOrder === "ascending" ) {
255+ expect ( daysVisited ) . toEqual ( expectedDays ) ;
256+ } else {
257+ const expectedReverseDays = Array . from ( { length : daysInMonth } , ( _ , i ) => daysInMonth - i ) ;
258+ expect ( daysVisited ) . toEqual ( expectedReverseDays ) ;
259+ }
260+ }
261+
262+ test ( "right arrow key navigates through all days of the month" , async ( { page } ) => {
263+ await testArrowKeyNavigation ( page , "ArrowRight" , "first" , "ascending" ) ;
264+ } ) ;
265+
266+ test ( "left arrow key navigates through all days of the month in reverse" , async ( { page } ) => {
267+ await testArrowKeyNavigation ( page , "ArrowLeft" , "last" , "descending" ) ;
268+ } ) ;
0 commit comments