Skip to content

Commit 47fda28

Browse files
renemadsenclaude
andcommitted
fix: use evaluate(el.click()) for mat-checkbox MDC compatibility
Angular Material MDC checkboxes have invisible labels that can't be clicked via Playwright's normal click. Use JS evaluate to click the input element directly. Also wait for delete button to be enabled before clicking, and dispatch input event for tag creation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9975c3a commit 47fda28

3 files changed

Lines changed: 25 additions & 17 deletions

File tree

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,17 @@ export class PairingRowObject {
142142
clickCancel = false
143143
) {
144144
if (clickOnPairRow) {
145-
await this.pairRowForClick.click({ force: true });
145+
await this.pairRowForClick.locator('input').evaluate((el: HTMLInputElement) => el.click());
146+
await this.page.waitForTimeout(500);
146147
if ((await this.pairRow.locator('input').isChecked()) !== pair) {
147-
await this.pairRowForClick.click({ force: true });
148+
await this.pairRowForClick.locator('input').evaluate((el: HTMLInputElement) => el.click());
149+
await this.page.waitForTimeout(500);
148150
}
149151
} else {
150152
for (let i = 0; i < this.pairCheckboxesForClick.length; i++) {
151153
if ((await this.pairCheckboxes[i].locator('input').isChecked()) !== pair) {
152-
await this.pairCheckboxesForClick[i].click({ force: true });
154+
await this.pairCheckboxesForClick[i].locator('input').evaluate((el: HTMLInputElement) => el.click());
155+
await this.page.waitForTimeout(500);
153156
}
154157
}
155158
}
@@ -161,7 +164,7 @@ export class PairingRowObject {
161164
indexDeviceForPair: number,
162165
clickCancel = false
163166
) {
164-
await this.pairCheckboxesForClick[indexDeviceForPair].click({ force: true });
167+
await this.pairCheckboxesForClick[indexDeviceForPair].locator('input').evaluate((el: HTMLInputElement) => el.click());
165168
await this.page.waitForTimeout(1000);
166169
await this.pairingPage.savePairing(clickCancel);
167170
}
@@ -213,14 +216,17 @@ export class PairingColObject {
213216
clickCancel = false
214217
) {
215218
if (clickOnPairRow) {
216-
await this.pairColForClick.click({ force: true });
219+
await this.pairColForClick.locator('input').evaluate((el: HTMLInputElement) => el.click());
220+
await this.page.waitForTimeout(500);
217221
if ((await this.pairCol.locator('input').isChecked()) !== pair) {
218-
await this.pairColForClick.click({ force: true });
222+
await this.pairColForClick.locator('input').evaluate((el: HTMLInputElement) => el.click());
223+
await this.page.waitForTimeout(500);
219224
}
220225
} else {
221226
for (let i = 0; i < this.pairCheckboxesForClick.length; i++) {
222227
if ((await this.pairCheckboxes[i].locator('input').isChecked()) !== pair) {
223-
await this.pairCheckboxesForClick[i].click({ force: true });
228+
await this.pairCheckboxesForClick[i].locator('input').evaluate((el: HTMLInputElement) => el.click());
229+
await this.page.waitForTimeout(500);
224230
}
225231
}
226232
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export class ItemsPlanningPlanningPage extends PageWithNavbarPage {
170170
}
171171

172172
async openMultipleDelete() {
173-
await this.deleteMultiplePluginsBtn.waitFor({ state: 'visible', timeout: 40000 });
173+
await this.page.locator('#deleteMultiplePluginsBtn:not([disabled])').waitFor({ state: 'visible', timeout: 40000 });
174174
await this.page.waitForTimeout(500);
175175
await this.deleteMultiplePluginsBtn.click();
176176
}
@@ -195,9 +195,9 @@ export class ItemsPlanningPlanningPage extends PageWithNavbarPage {
195195
if (!pickOne) {
196196
const isChecked = await this.selectAllPlanningsCheckbox.locator('input').isChecked().catch(() => false);
197197
if (isChecked !== valueCheckbox) {
198-
// Click on the mat-checkbox element itself to toggle
199-
await this.selectAllPlanningsCheckbox.click({ force: true, position: { x: 10, y: 10 } });
200-
await this.page.waitForTimeout(500);
198+
// Use JavaScript click on the internal checkbox input to ensure Angular detects the change
199+
await this.selectAllPlanningsCheckbox.locator('input').evaluate((el: HTMLInputElement) => el.click());
200+
await this.page.waitForTimeout(1000);
201201
}
202202
} else {
203203
const plannings = await this.getAllPlannings(0, false);
@@ -437,7 +437,8 @@ export class PlanningRowObject {
437437
async clickOnCheckboxForMultipleDelete(valueCheckbox = true) {
438438
const isChecked = await this.checkboxDelete.locator('input').isChecked().catch(() => false);
439439
if (isChecked !== valueCheckbox) {
440-
await this.checkboxDelete.click({ force: true, position: { x: 10, y: 10 } });
440+
await this.checkboxDelete.locator('input').evaluate((el: HTMLInputElement) => el.click());
441+
await this.page.waitForTimeout(500);
441442
}
442443
}
443444

eform-client/playwright/e2e/plugins/items-planning-pn/c/items-planning.tags.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ test.describe.serial('Items planning - Tags', () => {
2828
test('should create tag', async () => {
2929
const tagsModalPage = new TagsModalPage(page);
3030
const tagsRowsBeforeCreate = await tagsModalPage.rowNum();
31-
// Manually create tag — click new tag button, type name, click save
3231
await tagsModalPage.newTagBtn().click();
3332
await page.waitForTimeout(500);
3433
await page.locator('#newTagName').waitFor({ state: 'visible', timeout: 90000 });
35-
// Use click + type instead of fill to ensure Angular ngModel picks up the value
36-
await tagsModalPage.newTagNameInput().click();
37-
await tagsModalPage.newTagNameInput().pressSequentially(tagName, { delay: 50 });
34+
await tagsModalPage.newTagNameInput().fill(tagName);
35+
await page.waitForTimeout(500);
36+
// Dispatch input event to ensure Angular ngModel picks up the value
37+
await tagsModalPage.newTagNameInput().evaluate((el: HTMLInputElement) => {
38+
el.dispatchEvent(new Event('input', { bubbles: true }));
39+
});
3840
await page.waitForTimeout(500);
39-
// Verify button is enabled before clicking
4041
await page.locator('#newTagSaveBtn:not([disabled])').waitFor({ state: 'visible', timeout: 10000 });
4142
await tagsModalPage.newTagSaveBtn().click();
4243
await page.waitForTimeout(500);

0 commit comments

Comments
 (0)