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?