Skip to content

Commit cd63fc8

Browse files
renemadsenclaude
andcommitted
fix: use input.click() for mat-checkbox interaction in Playwright
Angular Material MDC checkboxes listen for click events on the native input element via _handleInputClick. Using evaluate to call input.click() bypasses visibility constraints while still triggering Angular's change detection properly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2c5321d commit cd63fc8

2 files changed

Lines changed: 37 additions & 26 deletions

File tree

eform-client/playwright/e2e/plugins/items-planning-pn/ItemsPlanningPairingPage.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,16 +142,25 @@ export class PairingRowObject {
142142
clickCancel = false
143143
) {
144144
if (clickOnPairRow) {
145-
await this.pairRowForClick.dispatchEvent('click');
145+
await this.pairRowForClick.evaluate((el: HTMLElement) => {
146+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
147+
if (input) input.click();
148+
});
146149
await this.page.waitForTimeout(500);
147150
if ((await this.pairRow.locator('input').isChecked()) !== pair) {
148-
await this.pairRowForClick.dispatchEvent('click');
151+
await this.pairRowForClick.evaluate((el: HTMLElement) => {
152+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
153+
if (input) input.click();
154+
});
149155
await this.page.waitForTimeout(500);
150156
}
151157
} else {
152158
for (let i = 0; i < this.pairCheckboxesForClick.length; i++) {
153159
if ((await this.pairCheckboxes[i].locator('input').isChecked()) !== pair) {
154-
await this.pairCheckboxesForClick[i].dispatchEvent('click');
160+
await this.pairCheckboxesForClick[i].evaluate((el: HTMLElement) => {
161+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
162+
if (input) input.click();
163+
});
155164
await this.page.waitForTimeout(500);
156165
}
157166
}
@@ -164,7 +173,10 @@ export class PairingRowObject {
164173
indexDeviceForPair: number,
165174
clickCancel = false
166175
) {
167-
await this.pairCheckboxesForClick[indexDeviceForPair].dispatchEvent('click');
176+
await this.pairCheckboxesForClick[indexDeviceForPair].evaluate((el: HTMLElement) => {
177+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
178+
if (input) input.click();
179+
});
168180
await this.page.waitForTimeout(1000);
169181
await this.pairingPage.savePairing(clickCancel);
170182
}
@@ -216,16 +228,25 @@ export class PairingColObject {
216228
clickCancel = false
217229
) {
218230
if (clickOnPairRow) {
219-
await this.pairColForClick.dispatchEvent('click');
231+
await this.pairColForClick.evaluate((el: HTMLElement) => {
232+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
233+
if (input) input.click();
234+
});
220235
await this.page.waitForTimeout(500);
221236
if ((await this.pairCol.locator('input').isChecked()) !== pair) {
222-
await this.pairColForClick.dispatchEvent('click');
237+
await this.pairColForClick.evaluate((el: HTMLElement) => {
238+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
239+
if (input) input.click();
240+
});
223241
await this.page.waitForTimeout(500);
224242
}
225243
} else {
226244
for (let i = 0; i < this.pairCheckboxesForClick.length; i++) {
227245
if ((await this.pairCheckboxes[i].locator('input').isChecked()) !== pair) {
228-
await this.pairCheckboxesForClick[i].dispatchEvent('click');
246+
await this.pairCheckboxesForClick[i].evaluate((el: HTMLElement) => {
247+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
248+
if (input) input.click();
249+
});
229250
await this.page.waitForTimeout(500);
230251
}
231252
}

eform-client/playwright/e2e/plugins/items-planning-pn/ItemsPlanningPlanningPage.ts

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -211,18 +211,11 @@ export class ItemsPlanningPlanningPage extends PageWithNavbarPage {
211211

212212
async selectAllPlanningsForDelete(valueCheckbox = true, pickOne = false) {
213213
if (!pickOne) {
214-
// Click the mdc-checkbox div which has visible dimensions
215-
const mdcCheckbox = this.selectAllPlanningsCheckbox.locator('.mdc-checkbox');
216-
await mdcCheckbox.waitFor({ state: 'attached', timeout: 10000 });
217-
const box = await mdcCheckbox.boundingBox();
218-
if (box && box.width > 0 && box.height > 0) {
219-
await this.page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
220-
} else {
221-
// Fallback: click the mat-checkbox via evaluate
222-
await this.selectAllPlanningsCheckbox.evaluate((el: HTMLElement) => {
223-
el.click();
224-
});
225-
}
214+
// Click the native input inside mat-checkbox — triggers Angular Material's _handleInputClick
215+
await this.selectAllPlanningsCheckbox.evaluate((el: HTMLElement) => {
216+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
217+
if (input) input.click();
218+
});
226219
await this.page.waitForTimeout(1000);
227220
} else {
228221
const plannings = await this.getAllPlannings(0, false);
@@ -462,13 +455,10 @@ export class PlanningRowObject {
462455
async clickOnCheckboxForMultipleDelete(valueCheckbox = true) {
463456
const isChecked = await this.checkboxDelete.locator('input').isChecked().catch(() => false);
464457
if (isChecked !== valueCheckbox) {
465-
const mdcCheckbox = this.checkboxDelete.locator('.mdc-checkbox');
466-
const box = await mdcCheckbox.boundingBox();
467-
if (box && box.width > 0 && box.height > 0) {
468-
await this.page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
469-
} else {
470-
await this.checkboxDelete.evaluate((el: HTMLElement) => { el.click(); });
471-
}
458+
await this.checkboxDelete.evaluate((el: HTMLElement) => {
459+
const input = el.querySelector('input[type="checkbox"]') as HTMLInputElement;
460+
if (input) input.click();
461+
});
472462
await this.page.waitForTimeout(500);
473463
}
474464
}

0 commit comments

Comments
 (0)