View | Details | Raw Unified | Return to bug 39916
Collapse All | Expand All

(-)a/t/cypress/support/e2e.js (+1 lines)
Lines 26-31 Link Here
26
26
27
// Import Select2 helpers
27
// Import Select2 helpers
28
import "./select2";
28
import "./select2";
29
import "./flatpickr.js";
29
30
30
function get_fallback_login_value(param) {
31
function get_fallback_login_value(param) {
31
    var env_var = param == "username" ? "KOHA_USER" : "KOHA_PASS";
32
    var env_var = param == "username" ? "KOHA_USER" : "KOHA_PASS";
(-)a/t/cypress/support/flatpickr.js (-1 / +333 lines)
Line 0 Link Here
0
- 
1
// flatpickrHelpers.js - Cypress helper methods for interacting with flatpickr date pickers
2
3
/**
4
 * Gets the visible flatpickr input element using the ID of the original hidden input
5
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
6
 * @returns {Cypress.Chainable} - The visible flatpickr input element
7
 */
8
Cypress.Commands.add("getFlatpickr", originalInputSelector => {
9
    return cy
10
        .get(originalInputSelector)
11
        .parents()
12
        .find(".flatpickr_wrapper input.flatpickr-input");
13
});
14
15
/**
16
 * Opens a flatpickr calendar by clicking on its visible input element
17
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
18
 * @returns {Cypress.Chainable} - The Cypress chainable object for additional commands
19
 */
20
Cypress.Commands.add("openFlatpickr", originalInputSelector => {
21
    cy.getFlatpickr(originalInputSelector).click();
22
    // Ensure the calendar is open by checking for the flatpickr container
23
    cy.get(".flatpickr-calendar.open").should("be.visible");
24
    
25
    // Return the originalInputSelector to enable chaining
26
    return cy.wrap(originalInputSelector);
27
});
28
29
/**
30
 * Closes an open flatpickr calendar by clicking outside of it
31
 */
32
Cypress.Commands.add("closeFlatpickr", () => {
33
    // Click on the body element, but not on the calendar
34
    cy.get("body").click(0, 0);
35
    // Ensure the calendar is closed
36
    cy.get(".flatpickr-calendar.open").should("not.exist");
37
});
38
39
/**
40
 * Clears a flatpickr input by clicking the clear button
41
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
42
 */
43
Cypress.Commands.add("clearFlatpickr", originalInputSelector => {
44
    // Click the clear button (the .clear_date element)
45
    cy.get(originalInputSelector).parents().find(".clear_date").click();
46
47
    // Verify both the visible and hidden inputs are cleared
48
    cy.get(originalInputSelector).should("have.value", "");
49
    cy.getFlatpickr(originalInputSelector).should("have.value", "");
50
});
51
52
/**
53
 * Sets a date in a flatpickr by selecting it from the calendar
54
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
55
 * @param {Date|string} date - The date to select (Date object or YYYY-MM-DD string)
56
 */
57
Cypress.Commands.add("selectFlatpickrDate", (originalInputSelector, date) => {
58
    // Convert to Date object if string was provided
59
    const dateObj = typeof date === "string" ? new Date(date) : date;
60
    const year = dateObj.getFullYear();
61
    const month = dateObj.getMonth(); // 0-based index
62
    const day = dateObj.getDate();
63
64
    // Open the flatpickr calendar
65
    cy.openFlatpickr(originalInputSelector);
66
67
    // Navigate to the correct month and year
68
    cy.get(".flatpickr-current-month .cur-month").then($currentMonth => {
69
        cy.get(".flatpickr-current-month .numInput.cur-year").then(
70
            $currentYear => {
71
                const currentMonth = new Date(
72
                    $currentMonth.text() + " 1, " + $currentYear.val()
73
                ).getMonth();
74
                const currentYear = parseInt($currentYear.val());
75
76
                // Navigate to the correct year
77
                const yearDiff = year - currentYear;
78
                if (yearDiff !== 0) {
79
                    const arrowSelector =
80
                        yearDiff > 0
81
                            ? ".flatpickr-next-month"
82
                            : ".flatpickr-prev-month";
83
                    for (let i = 0; i < Math.abs(yearDiff) * 12; i++) {
84
                        cy.get(arrowSelector).click();
85
                        cy.wait(100); // Give time for the calendar to update
86
                    }
87
                }
88
89
                // Navigate to the correct month
90
                const monthDiff = month - currentMonth;
91
                if (monthDiff !== 0) {
92
                    const arrowSelector =
93
                        monthDiff > 0
94
                            ? ".flatpickr-next-month"
95
                            : ".flatpickr-prev-month";
96
                    for (let i = 0; i < Math.abs(monthDiff); i++) {
97
                        cy.get(arrowSelector).click();
98
                        cy.wait(100); // Give time for the calendar to update
99
                    }
100
                }
101
            }
102
        );
103
    });
104
105
    // Select the day
106
    cy.get(".flatpickr-day")
107
        .not(".prevMonthDay")
108
        .not(".nextMonthDay")
109
        .contains(day)
110
        .click();
111
112
    // Verify the hidden input has been updated
113
    const formattedDate = `${year}-${(month + 1).toString().padStart(2, "0")}-${day.toString().padStart(2, "0")}`;
114
    cy.get(originalInputSelector).should("have.value", formattedDate);
115
116
    // Return the originalInputSelector to enable chaining
117
    return cy.wrap(originalInputSelector);
118
});
119
120
/**
121
 * Sets a date in a flatpickr by typing directly into the visible input
122
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
123
 * @param {string} dateString - The date string to type in the format expected by flatpickr
124
 */
125
Cypress.Commands.add(
126
    "typeFlatpickrDate",
127
    (originalInputSelector, dateString) => {
128
        // Clear the input and type the new date
129
        cy.getFlatpickr(originalInputSelector).clear().type(dateString);
130
131
        // Click away to ensure the date is applied
132
        cy.get("body").click(0, 0);
133
134
        // Verify both inputs have been updated
135
        cy.get(originalInputSelector).should("have.value", dateString);
136
        
137
        // Return the originalInputSelector to enable chaining
138
        return cy.wrap(originalInputSelector);
139
    }
140
);
141
142
/**
143
 * Sets a date range in a flatpickr range picker
144
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
145
 * @param {string|Date} startDate - The start date to select
146
 * @param {string|Date} endDate - The end date to select
147
 */
148
Cypress.Commands.add(
149
    "selectFlatpickrDateRange",
150
    (originalInputSelector, startDate, endDate) => {
151
        // Open the flatpickr calendar
152
        cy.openFlatpickr(originalInputSelector);
153
154
        // Convert to Date objects if strings were provided
155
        const startDateObj =
156
            typeof startDate === "string" ? new Date(startDate) : startDate;
157
        const endDateObj =
158
            typeof endDate === "string" ? new Date(endDate) : endDate;
159
160
        // Select start date
161
        const startDay = startDateObj.getDate();
162
        cy.get(".flatpickr-day")
163
            .not(".prevMonthDay")
164
            .not(".nextMonthDay")
165
            .contains(startDay)
166
            .click();
167
168
        // Select end date
169
        const endDay = endDateObj.getDate();
170
        cy.get(".flatpickr-day")
171
            .not(".prevMonthDay")
172
            .not(".nextMonthDay")
173
            .contains(endDay)
174
            .click();
175
176
        // Verify the hidden input has been updated (format depends on your flatpickr configuration)
177
        cy.get(originalInputSelector).should("not.have.value", "");
178
        
179
        // Return the originalInputSelector to enable chaining
180
        return cy.wrap(originalInputSelector);
181
    }
182
);
183
184
/**
185
 * Gets the current date from a flatpickr input
186
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
187
 * @returns {string} The date value in the input
188
 */
189
Cypress.Commands.add("getFlatpickrValue", originalInputSelector => {
190
    return cy.get(originalInputSelector).invoke("val");
191
});
192
193
/**
194
 * Asserts that a flatpickr input has a specific date value
195
 * @param {string} originalInputSelector - The CSS selector for the original hidden input
196
 * @param {string} expectedDate - The expected date value in the input
197
 */
198
Cypress.Commands.add(
199
    "flatpickrShouldHaveValue",
200
    (originalInputSelector, expectedDate) => {
201
        cy.get(originalInputSelector).should("have.value", expectedDate);
202
    }
203
);
204
205
/**
206
 * Navigates to a specific month/year in an already open flatpickr calendar
207
 * @param {Date|string} date - The date to navigate to (only month/year are used)
208
 * @returns {Cypress.Chainable} - Chainable
209
 */
210
Cypress.Commands.add("navigateToMonth", date => {
211
    // Convert to Date object if string was provided
212
    const dateObj = typeof date === "string" ? new Date(date) : date;
213
    const year = dateObj.getFullYear();
214
    const month = dateObj.getMonth(); // 0-based index
215
216
    // Navigate to the correct month and year
217
    cy.get(".flatpickr-current-month .cur-month").then($currentMonth => {
218
        cy.get(".flatpickr-current-month .numInput.cur-year").then(
219
            $currentYear => {
220
                const currentMonth = new Date(
221
                    $currentMonth.text() + " 1, " + $currentYear.val()
222
                ).getMonth();
223
                const currentYear = parseInt($currentYear.val());
224
225
                // Navigate to the correct year
226
                const yearDiff = year - currentYear;
227
                if (yearDiff !== 0) {
228
                    const arrowSelector =
229
                        yearDiff > 0
230
                            ? ".flatpickr-next-month"
231
                            : ".flatpickr-prev-month";
232
                    for (let i = 0; i < Math.abs(yearDiff) * 12; i++) {
233
                        cy.get(arrowSelector).click();
234
                        cy.wait(100); // Give time for the calendar to update
235
                    }
236
                }
237
238
                // Navigate to the correct month
239
                const monthDiff = month - currentMonth;
240
                if (monthDiff !== 0) {
241
                    const arrowSelector =
242
                        monthDiff > 0
243
                            ? ".flatpickr-next-month"
244
                            : ".flatpickr-prev-month";
245
                    for (let i = 0; i < Math.abs(monthDiff); i++) {
246
                        cy.get(arrowSelector).click();
247
                        cy.wait(100); // Give time for the calendar to update
248
                    }
249
                }
250
            }
251
        );
252
    });
253
    
254
    return cy.wrap(date);
255
});
256
257
/**
258
 * Selects a day from the currently displayed month in an open flatpickr
259
 * @param {number|string} day - The day of the month to select
260
 * @param {string} [originalInputSelector] - Optional selector to verify the input value
261
 * @returns {Cypress.Chainable} - The originalInputSelector (if provided) for chaining
262
 */
263
Cypress.Commands.add("selectDay", (day, originalInputSelector = null) => {
264
    // Convert to number if string was provided
265
    const dayNum = parseInt(day, 10);
266
    
267
    // Select the day
268
    cy.get(".flatpickr-day")
269
        .not(".prevMonthDay")
270
        .not(".nextMonthDay")
271
        .contains(dayNum)
272
        .click();
273
    
274
    // If originalInputSelector is provided, verify it has a non-empty value
275
    if (originalInputSelector) {
276
        cy.get(originalInputSelector).should("not.have.value", "");
277
        return cy.wrap(originalInputSelector);
278
    }
279
    
280
    return cy.wrap(dayNum);
281
});
282
283
/**
284
 * Goes to the next month in an open flatpickr calendar
285
 * @returns {Cypress.Chainable} - Chainable
286
 */
287
Cypress.Commands.add("nextMonth", () => {
288
    cy.get(".flatpickr-next-month").click();
289
    cy.wait(100); // Give time for the calendar to update
290
    return cy.wrap("next");
291
});
292
293
/**
294
 * Goes to the previous month in an open flatpickr calendar
295
 * @returns {Cypress.Chainable} - Chainable
296
 */
297
Cypress.Commands.add("prevMonth", () => {
298
    cy.get(".flatpickr-prev-month").click();
299
    cy.wait(100); // Give time for the calendar to update
300
    return cy.wrap("prev");
301
});
302
303
/**
304
 * Sets the current year in an open flatpickr calendar
305
 * @param {number|string} year - The year to set
306
 * @returns {Cypress.Chainable} - Chainable
307
 */
308
Cypress.Commands.add("setYear", year => {
309
    const yearNum = parseInt(year, 10);
310
    cy.get(".flatpickr-current-month .numInput.cur-year")
311
        .clear()
312
        .type(yearNum.toString(), { force: true })
313
        .type("{enter}");
314
    cy.wait(100); // Give time for the calendar to update
315
    return cy.wrap(yearNum);
316
});
317
318
/**
319
 * Selects today's date in an open flatpickr calendar
320
 * @param {string} [originalInputSelector] - Optional selector to verify the input value
321
 * @returns {Cypress.Chainable} - The originalInputSelector (if provided) for chaining
322
 */
323
Cypress.Commands.add("selectToday", (originalInputSelector = null) => {
324
    cy.get(".flatpickr-day.today").click();
325
    
326
    // If originalInputSelector is provided, verify it has a non-empty value
327
    if (originalInputSelector) {
328
        cy.get(originalInputSelector).should("not.have.value", "");
329
        return cy.wrap(originalInputSelector);
330
    }
331
    
332
    return cy.wrap("today");
333
});

Return to bug 39916