fix: event-delegatie naar init() verplaatst (1x registreren, niet per render) — move/delete werken nu
Root cause: listEl.addEventListener werd elke renderDagboek call opnieuw toegevoegd → 4+ handlers per klik. Fix: delegatie in init() met _delegationSetup flag, slechts 1 registratie.
This commit is contained in:
parent
4925169ac9
commit
a08baabe7c
3 changed files with 182 additions and 179 deletions
|
|
@ -2913,85 +2913,6 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// === Unified meal-group action delegation ===
|
|
||||||
listEl.addEventListener('click', (e) => {
|
|
||||||
const btn = e.target.closest('[data-action]');
|
|
||||||
if (!btn) return;
|
|
||||||
const action = btn.dataset.action;
|
|
||||||
const momentId = btn.dataset.moment;
|
|
||||||
const entryIdx = btn.dataset.entry != null ? parseInt(btn.dataset.entry) : null;
|
|
||||||
|
|
||||||
if (action === 'toggle-meal') {
|
|
||||||
const group = btn.closest('.eetmoment-meal-group');
|
|
||||||
if (!group) return;
|
|
||||||
const wrap = group.querySelector('.eetmoment-meal-items-wrap');
|
|
||||||
const actions = group.querySelector('.eetmoment-meal-actions');
|
|
||||||
if (wrap) {
|
|
||||||
wrap.classList.toggle('hidden');
|
|
||||||
if (actions) actions.classList.toggle('hidden');
|
|
||||||
const arrow = btn.querySelector('span:last-child i');
|
|
||||||
if (arrow) {
|
|
||||||
arrow.className = wrap.classList.contains('hidden') ? 'fas fa-chevron-down' : 'fas fa-chevron-up';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (action === 'edit-porties') {
|
|
||||||
showBulkPortieEdit(activeDate, momentId, entryIdx);
|
|
||||||
}
|
|
||||||
else if (action === 'delete-meal') {
|
|
||||||
const dayData = getOrCreateDay(activeDate);
|
|
||||||
const entry = (dayData[momentId] || [])[entryIdx];
|
|
||||||
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
|
||||||
showConfirmModal('Maaltijd verwijderen',
|
|
||||||
'Deze hele maaltijd verwijderen uit je dagboek?',
|
|
||||||
() => {
|
|
||||||
dayData[momentId].splice(entryIdx, 1);
|
|
||||||
saveDagboek();
|
|
||||||
renderDagboek();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (action === 'move-meal') {
|
|
||||||
const overlay = document.createElement('div');
|
|
||||||
overlay.className = 'modal-overlay';
|
|
||||||
overlay.style.zIndex = '500';
|
|
||||||
const options = EETMOMENTEN.map(m =>
|
|
||||||
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
|
||||||
).join('');
|
|
||||||
overlay.innerHTML = `
|
|
||||||
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
|
||||||
<div class="modal-handle"></div>
|
|
||||||
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
|
||||||
<div class="modal-body" style="padding:0 20px 20px;">
|
|
||||||
<select class="add-meal-select" id="moveTarget">${options}</select>
|
|
||||||
<div style="display:flex;gap:10px;margin-top:16px;">
|
|
||||||
<button class="btn-cancel" id="moveCancel">Annuleren</button>
|
|
||||||
<button class="btn-save" id="moveOk" style="flex:1;">Verplaatsen</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
const close = () => {
|
|
||||||
overlay.classList.add('closing');
|
|
||||||
setTimeout(() => overlay.remove(), 250);
|
|
||||||
};
|
|
||||||
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
|
||||||
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
|
||||||
const target = overlay.querySelector('#moveTarget').value;
|
|
||||||
const dayData = getOrCreateDay(activeDate);
|
|
||||||
const entry = (dayData[momentId] || [])[entryIdx];
|
|
||||||
if (!entry) return close();
|
|
||||||
dayData[momentId].splice(entryIdx, 1);
|
|
||||||
if (!dayData[target]) dayData[target] = [];
|
|
||||||
dayData[target].push(entry);
|
|
||||||
saveDagboek();
|
|
||||||
close();
|
|
||||||
renderDagboek();
|
|
||||||
});
|
|
||||||
overlay.addEventListener('click', (ev) => { if (ev.target === overlay) close(); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -4783,6 +4704,89 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
loadVoedingsData();
|
loadVoedingsData();
|
||||||
registerServiceWorker();
|
registerServiceWorker();
|
||||||
|
|
||||||
|
// === Global meal-group action delegation (setup once, not per render) ===
|
||||||
|
const listEl = document.getElementById('eetmomentList');
|
||||||
|
if (listEl && !listEl._delegationSetup) {
|
||||||
|
listEl._delegationSetup = true;
|
||||||
|
listEl.addEventListener('click', (e) => {
|
||||||
|
const btn = e.target.closest('[data-action]');
|
||||||
|
if (!btn) return;
|
||||||
|
const action = btn.dataset.action;
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = btn.dataset.entry != null ? parseInt(btn.dataset.entry) : null;
|
||||||
|
|
||||||
|
if (action === 'toggle-meal') {
|
||||||
|
const group = btn.closest('.eetmoment-meal-group');
|
||||||
|
if (!group) return;
|
||||||
|
const wrap = group.querySelector('.eetmoment-meal-items-wrap');
|
||||||
|
const actions = group.querySelector('.eetmoment-meal-actions');
|
||||||
|
if (wrap) {
|
||||||
|
wrap.classList.toggle('hidden');
|
||||||
|
if (actions) actions.classList.toggle('hidden');
|
||||||
|
const arrow = btn.querySelector('span:last-child i');
|
||||||
|
if (arrow) {
|
||||||
|
arrow.className = wrap.classList.contains('hidden') ? 'fas fa-chevron-down' : 'fas fa-chevron-up';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action === 'edit-porties') {
|
||||||
|
showBulkPortieEdit(activeDate, momentId, entryIdx);
|
||||||
|
}
|
||||||
|
else if (action === 'delete-meal') {
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
||||||
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
|
'Deze hele maaltijd verwijderen uit je dagboek?',
|
||||||
|
() => {
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
saveDagboek();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (action === 'move-meal') {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
const options = EETMOMENTEN.map(m =>
|
||||||
|
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
||||||
|
).join('');
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
||||||
|
<div class="modal-body" style="padding:0 20px 20px;">
|
||||||
|
<select class="add-meal-select" id="moveTarget">${options}</select>
|
||||||
|
<div style="display:flex;gap:10px;margin-top:16px;">
|
||||||
|
<button class="btn-cancel" id="moveCancel">Annuleren</button>
|
||||||
|
<button class="btn-save" id="moveOk" style="flex:1;">Verplaatsen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
||||||
|
const target = overlay.querySelector('#moveTarget').value;
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
if (!entry) return close();
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
if (!dayData[target]) dayData[target] = [];
|
||||||
|
dayData[target].push(entry);
|
||||||
|
saveDagboek();
|
||||||
|
close();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (ev) => { if (ev.target === overlay) close(); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the app
|
// Start the app
|
||||||
|
|
|
||||||
162
index.html
162
index.html
|
|
@ -2913,85 +2913,6 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// === Unified meal-group action delegation ===
|
|
||||||
listEl.addEventListener('click', (e) => {
|
|
||||||
const btn = e.target.closest('[data-action]');
|
|
||||||
if (!btn) return;
|
|
||||||
const action = btn.dataset.action;
|
|
||||||
const momentId = btn.dataset.moment;
|
|
||||||
const entryIdx = btn.dataset.entry != null ? parseInt(btn.dataset.entry) : null;
|
|
||||||
|
|
||||||
if (action === 'toggle-meal') {
|
|
||||||
const group = btn.closest('.eetmoment-meal-group');
|
|
||||||
if (!group) return;
|
|
||||||
const wrap = group.querySelector('.eetmoment-meal-items-wrap');
|
|
||||||
const actions = group.querySelector('.eetmoment-meal-actions');
|
|
||||||
if (wrap) {
|
|
||||||
wrap.classList.toggle('hidden');
|
|
||||||
if (actions) actions.classList.toggle('hidden');
|
|
||||||
const arrow = btn.querySelector('span:last-child i');
|
|
||||||
if (arrow) {
|
|
||||||
arrow.className = wrap.classList.contains('hidden') ? 'fas fa-chevron-down' : 'fas fa-chevron-up';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (action === 'edit-porties') {
|
|
||||||
showBulkPortieEdit(activeDate, momentId, entryIdx);
|
|
||||||
}
|
|
||||||
else if (action === 'delete-meal') {
|
|
||||||
const dayData = getOrCreateDay(activeDate);
|
|
||||||
const entry = (dayData[momentId] || [])[entryIdx];
|
|
||||||
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
|
||||||
showConfirmModal('Maaltijd verwijderen',
|
|
||||||
'Deze hele maaltijd verwijderen uit je dagboek?',
|
|
||||||
() => {
|
|
||||||
dayData[momentId].splice(entryIdx, 1);
|
|
||||||
saveDagboek();
|
|
||||||
renderDagboek();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (action === 'move-meal') {
|
|
||||||
const overlay = document.createElement('div');
|
|
||||||
overlay.className = 'modal-overlay';
|
|
||||||
overlay.style.zIndex = '500';
|
|
||||||
const options = EETMOMENTEN.map(m =>
|
|
||||||
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
|
||||||
).join('');
|
|
||||||
overlay.innerHTML = `
|
|
||||||
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
|
||||||
<div class="modal-handle"></div>
|
|
||||||
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
|
||||||
<div class="modal-body" style="padding:0 20px 20px;">
|
|
||||||
<select class="add-meal-select" id="moveTarget">${options}</select>
|
|
||||||
<div style="display:flex;gap:10px;margin-top:16px;">
|
|
||||||
<button class="btn-cancel" id="moveCancel">Annuleren</button>
|
|
||||||
<button class="btn-save" id="moveOk" style="flex:1;">Verplaatsen</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
const close = () => {
|
|
||||||
overlay.classList.add('closing');
|
|
||||||
setTimeout(() => overlay.remove(), 250);
|
|
||||||
};
|
|
||||||
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
|
||||||
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
|
||||||
const target = overlay.querySelector('#moveTarget').value;
|
|
||||||
const dayData = getOrCreateDay(activeDate);
|
|
||||||
const entry = (dayData[momentId] || [])[entryIdx];
|
|
||||||
if (!entry) return close();
|
|
||||||
dayData[momentId].splice(entryIdx, 1);
|
|
||||||
if (!dayData[target]) dayData[target] = [];
|
|
||||||
dayData[target].push(entry);
|
|
||||||
saveDagboek();
|
|
||||||
close();
|
|
||||||
renderDagboek();
|
|
||||||
});
|
|
||||||
overlay.addEventListener('click', (ev) => { if (ev.target === overlay) close(); });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
listEl.querySelectorAll('.eetmoment-add-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', (e) => {
|
btn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -4783,6 +4704,89 @@ button:active, .btn:active, .meal-card-main:active, .dagboek-item:active, .food-
|
||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
loadVoedingsData();
|
loadVoedingsData();
|
||||||
registerServiceWorker();
|
registerServiceWorker();
|
||||||
|
|
||||||
|
// === Global meal-group action delegation (setup once, not per render) ===
|
||||||
|
const listEl = document.getElementById('eetmomentList');
|
||||||
|
if (listEl && !listEl._delegationSetup) {
|
||||||
|
listEl._delegationSetup = true;
|
||||||
|
listEl.addEventListener('click', (e) => {
|
||||||
|
const btn = e.target.closest('[data-action]');
|
||||||
|
if (!btn) return;
|
||||||
|
const action = btn.dataset.action;
|
||||||
|
const momentId = btn.dataset.moment;
|
||||||
|
const entryIdx = btn.dataset.entry != null ? parseInt(btn.dataset.entry) : null;
|
||||||
|
|
||||||
|
if (action === 'toggle-meal') {
|
||||||
|
const group = btn.closest('.eetmoment-meal-group');
|
||||||
|
if (!group) return;
|
||||||
|
const wrap = group.querySelector('.eetmoment-meal-items-wrap');
|
||||||
|
const actions = group.querySelector('.eetmoment-meal-actions');
|
||||||
|
if (wrap) {
|
||||||
|
wrap.classList.toggle('hidden');
|
||||||
|
if (actions) actions.classList.toggle('hidden');
|
||||||
|
const arrow = btn.querySelector('span:last-child i');
|
||||||
|
if (arrow) {
|
||||||
|
arrow.className = wrap.classList.contains('hidden') ? 'fas fa-chevron-down' : 'fas fa-chevron-up';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (action === 'edit-porties') {
|
||||||
|
showBulkPortieEdit(activeDate, momentId, entryIdx);
|
||||||
|
}
|
||||||
|
else if (action === 'delete-meal') {
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
const mealName = (entry && entry.mealNaam) || 'maaltijd';
|
||||||
|
showConfirmModal('Maaltijd verwijderen',
|
||||||
|
'Deze hele maaltijd verwijderen uit je dagboek?',
|
||||||
|
() => {
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
saveDagboek();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (action === 'move-meal') {
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.className = 'modal-overlay';
|
||||||
|
overlay.style.zIndex = '500';
|
||||||
|
const options = EETMOMENTEN.map(m =>
|
||||||
|
`<option value="${m.id}" ${m.id === momentId ? 'selected' : ''}>${m.icon} ${m.name}</option>`
|
||||||
|
).join('');
|
||||||
|
overlay.innerHTML = `
|
||||||
|
<div class="modal-sheet" style="max-width:360px;border-radius:var(--radius);margin:auto;max-height:none;padding:0;">
|
||||||
|
<div class="modal-handle"></div>
|
||||||
|
<div class="modal-header"><h2 class="modal-title">Verplaatsen naar</h2></div>
|
||||||
|
<div class="modal-body" style="padding:0 20px 20px;">
|
||||||
|
<select class="add-meal-select" id="moveTarget">${options}</select>
|
||||||
|
<div style="display:flex;gap:10px;margin-top:16px;">
|
||||||
|
<button class="btn-cancel" id="moveCancel">Annuleren</button>
|
||||||
|
<button class="btn-save" id="moveOk" style="flex:1;">Verplaatsen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
const close = () => {
|
||||||
|
overlay.classList.add('closing');
|
||||||
|
setTimeout(() => overlay.remove(), 250);
|
||||||
|
};
|
||||||
|
overlay.querySelector('#moveCancel').addEventListener('click', close);
|
||||||
|
overlay.querySelector('#moveOk').addEventListener('click', () => {
|
||||||
|
const target = overlay.querySelector('#moveTarget').value;
|
||||||
|
const dayData = getOrCreateDay(activeDate);
|
||||||
|
const entry = (dayData[momentId] || [])[entryIdx];
|
||||||
|
if (!entry) return close();
|
||||||
|
dayData[momentId].splice(entryIdx, 1);
|
||||||
|
if (!dayData[target]) dayData[target] = [];
|
||||||
|
dayData[target].push(entry);
|
||||||
|
saveDagboek();
|
||||||
|
close();
|
||||||
|
renderDagboek();
|
||||||
|
});
|
||||||
|
overlay.addEventListener('click', (ev) => { if (ev.target === overlay) close(); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the app
|
// Start the app
|
||||||
|
|
|
||||||
|
|
@ -358,18 +358,15 @@ test.describe('Karby Eetdagboek', () => {
|
||||||
|
|
||||||
test('confirm modal: deletion dialog shows design-conforme buttons', async ({ page }) => {
|
test('confirm modal: deletion dialog shows design-conforme buttons', async ({ page }) => {
|
||||||
await page.goto(BASE);
|
await page.goto(BASE);
|
||||||
// Go to maaltijden tab
|
// Add item + save as meal from search tab
|
||||||
await page.locator('#navMaaltijden').click();
|
|
||||||
await page.waitForTimeout(600);
|
|
||||||
// Quick-save a meal first if none exist (via search)
|
|
||||||
await page.locator('.search-input').fill('brood');
|
await page.locator('.search-input').fill('brood');
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(800);
|
||||||
await page.locator('.food-item').first().click();
|
await page.locator('.food-item').first().click();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
await page.locator('#detailAddBtn').click();
|
await page.locator('#detailAddBtn').click();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
await page.locator('#addMealSubmit').click();
|
await page.locator('#addMealSubmit').click();
|
||||||
await page.waitForTimeout(600);
|
await page.waitForTimeout(800);
|
||||||
// Navigate to diary, save as meal
|
// Navigate to diary, save as meal
|
||||||
await page.locator('#navDagboek').click();
|
await page.locator('#navDagboek').click();
|
||||||
await page.waitForTimeout(600);
|
await page.waitForTimeout(600);
|
||||||
|
|
@ -380,18 +377,16 @@ test.describe('Karby Eetdagboek', () => {
|
||||||
await page.locator('#mealNameInput').fill('Test');
|
await page.locator('#mealNameInput').fill('Test');
|
||||||
await page.locator('#mealNameSave').click();
|
await page.locator('#mealNameSave').click();
|
||||||
await page.waitForTimeout(600);
|
await page.waitForTimeout(600);
|
||||||
// Now go to maaltijden and delete
|
// Go to maaltijden and delete
|
||||||
await page.locator('#navMaaltijden').click();
|
await page.locator('#navMaaltijden').click();
|
||||||
await page.waitForTimeout(600);
|
await page.waitForTimeout(600);
|
||||||
// Open first meal edit
|
// Open first meal edit
|
||||||
await page.locator('.meal-card-main').first().click();
|
await page.locator('.meal-card-main').first().click();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
// Click delete
|
|
||||||
const deleteBtn = page.locator('#mealEditDelete');
|
const deleteBtn = page.locator('#mealEditDelete');
|
||||||
if (await deleteBtn.isVisible().catch(() => false)) {
|
if (await deleteBtn.isVisible().catch(() => false)) {
|
||||||
await deleteBtn.click();
|
await deleteBtn.click();
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
// Confirm modal should show
|
|
||||||
await expect(page.locator('#confirmOk')).toBeVisible({ timeout: 3000 });
|
await expect(page.locator('#confirmOk')).toBeVisible({ timeout: 3000 });
|
||||||
await expect(page.locator('#confirmCancel')).toBeVisible();
|
await expect(page.locator('#confirmCancel')).toBeVisible();
|
||||||
await page.locator('#confirmCancel').click();
|
await page.locator('#confirmCancel').click();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue