DOM Events
DOM Events: Event Bubbling — Event propagates up the DOM tree DOM events are messages triggered when the user does something — clicking a button, typing, or moving the mouse.
Event Bubbling — Event propagates up the DOM tree
DOM events are messages triggered when the user does something — clicking a button, typing, or moving the mouse. Think of it like a doorbell ringing (event), the doorman arriving (listener), and opening the door (handler). In Java we'd use ActionListener; in JavaScript addEventListener is far simpler and more powerful. But why should a QA engineer care about this chain — don't we just write `click()` and move on? This is exactly where one of automation's most maddening bugs is born: Selenium's or Playwright's `click()` fires a real browser event, but frameworks like React attach their listeners AFTER the page has loaded. If the element is visible while its listener is not yet bound, the click physically happens and NOTHING occurs — no error, no warning. Java's ActionListener never has this problem, because the component and its listener are constructed together; in a browser the DOM and the JavaScript become ready at different moments. The result is the classic flaky-test picture: passes locally, fails at random in CI — and the fix is not adding a `sleep`, it is waiting for the element to be genuinely interactive rather than merely visible.
Most Common Event Types
addEventListener — Basic Usage
// ─── addEventListener syntax ───────────────────────────────── // element.addEventListener(eventType, handler, useCapture=false) // 1. Button click — most common usage const btn = document.querySelector('#submit-btn'); btn.addEventListener('click', function(event) { console.log('Clicked! Target element:', event.target.id); event.preventDefault(); // prevent form auto-submit }); // 2. Arrow function (shorter — standard in Playwright tests) btn.addEventListener('click', (e) => { console.log('Event type:', e.type, '| X,Y:', e.clientX, e.clientY); }); // 3. Input event tracking (live form validation) const emailInput = document.querySelector('#email'); emailInput.addEventListener('input', (e) => { const val = e.target.value; const isValid = val.includes('@'); console.log('Email valid?', isValid ? '✅' : '❌'); }); // 4. Removing a listener (prevents memory leaks) function handleClick(e) { console.log('Clicked'); } btn.addEventListener('click', handleClick); btn.removeEventListener('click', handleClick); // clean up
Micro Lab: JavaScript QA coding practice
Replace the TODO line with the critical line from the expected solution. This is not a real runtime; the goal is to reinforce writing the correct structure in a controlled way.
Step by Step: JavaScript QA coding practice
Read the goal and async dependencies
Place await / Promise chain in the right spot
Complete the assertion or expectation line
Run and read console or test output
If flaky, add a wait strategy or retry
What is the safe order for writing and testing JavaScript QA code?