Using jQuery to trigger React state updates for controlled inputs in Puppeteer tests

I’m working with Puppeteer to test a React application and running into issues with controlled form elements. When I change input values directly through DOM manipulation, React doesn’t update its internal state or virtual DOM.

I found a workaround that manually dispatches events, but I want to simplify it using jQuery methods instead of custom event functions.

test('form interaction test', async () => {
  const browser = await puppeteer.launch({ headless: false });
  const webpage = await browser.newPage();
  await webpage.goto('http://localhost:3000/dashboard');
  await webpage.waitForSelector('.form-control', { visible: true });
  await webpage.addScriptTag({ url: 'https://code.jquery.com/jquery-3.2.1.min.js' });
  
  const elementVisible = await webpage.evaluate(() => {
    const $ = window.$;
    
    function triggerEvent(element, eventType) {
      const customEvent = new Event(eventType, { target: element, bubbles: true });
      return element ? element.dispatchEvent(customEvent) : false;
    }
    
    const dropdown = $('[data-testid="category-select"]')[0];
    dropdown.value = 'ShowHiddenContent';
    
    triggerEvent(dropdown, 'change');
    
    return $('.hidden-content-panel').length;
  });
  
  expect(elementVisible).toBe(1);
  await browser.close();
});

Is there a way to replace the triggerEvent function with native jQuery event methods?

yep! just use jQuery’s .trigger(‘change’) on that dropdown. you can skip the custom triggerEvent function - way simpler and works good with React’s controlled inputs in Puppeteer. good luck!

Yeah, you can totally ditch that custom function for jQuery’s built-in methods. Just use .val() to set the value and .trigger() to fire the event. Way cleaner:

const dropdown = $('[data-testid="category-select"]');
dropdown.val('ShowHiddenContent').trigger('change');

This chains everything together, which is how you’d normally write jQuery. .trigger() handles all the event stuff behind the scenes and plays nice with React’s synthetic events. I’ve done this tons of times in Puppeteer tests - always updates React state without problems.

The jQuery approach works great here. Skip the manual event dispatching and just do this:

const elementVisible = await webpage.evaluate(() => {
  const $ = window.$;
  
  $('[data-testid="category-select"]')
    .val('ShowHiddenContent')
    .trigger('change');
  
  return $('.hidden-content-panel').length;
});

I’ve used this exact setup in production Puppeteer tests with React apps. The .trigger() method creates proper synthetic events that React actually recognizes - way better than just changing DOM values directly. Just make sure jQuery’s loaded before you run the evaluate function or you’ll hit undefined errors. The chaining keeps everything clean and handles both setting the value and firing the event in one go.