question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Event listeners not working in custom elements

See original GitHub issue

Current behavior

An event emitted from an element inside of the shadow DOM does not trigger an event listener in a parent custom element. The DOM in my example is as follows:

  • page-element (a custom element)
    • text-input (another custom element)
      • input
    • input

The page-element has an event listener on the text-input for an input event which removes the disabled attribute from the input element in the shadow DOM of the page-element. When tested in Cypress, the disabled attribute is never removed, however strangely if I run the test with cypress open and type in the input field myself after the test completes, the disabled attribute is removed instantly. I put in a 10 second wait after visit to make sure all the components are loaded and connected. Result in my example below is as follows:

  Test event listeners
    1) makes sure event listener works


  0 passing (15s)
  1 failing

  1) Test event listeners
       makes sure event listener works:
     AssertionError: Timed out retrying after 4000ms: expected '[ <input>, 1 more... ]' not to have attribute 'disabled'
      at Context.eval (http://localhost:63324/__cypress/tests?p=cypress\integration\spec.js:103:25)

Desired behavior

The test should cause the disabled attribute in the input element with type=submit to be removed.

Test code to reproduce

Clone this fork:

https://github.com/jrtcppv/cypress-test-tiny

Run the following:

npm install cypress
./node_modules/bin/cypress run

Cypress Version

7.7.0, 8.0.0, 8.1.0

Other

Really want Cypress to work for us, but our application has a ton of nested custom elements like this… hopefully this example will give us some insight into what the problem is. I’m also a Cypress noob so possible I am just doing something wrong.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:7

github_iconTop GitHub Comments

1reaction
sainthkhcommented, Aug 16, 2021

Sorry for another misunderstanding.

Cypress emulates the type events by sending them programatically. And I learned that the input message isn’t sent to the elements under shadow root.

Confirmed that the bug happens.

it('shadow DOM', () => {
  cy.visit('fixtures/a.html')

  cy
  .get('page-element').shadow()
  .find('text-input').shadow()
  .find('input').type('asdf')

  cy
  .get('page-element').shadow()
  .find('input[type=submit]')
  .should('not.have.attr', 'disabled')
})

it('non-shadow DOM', () => {
  cy.visit('fixtures/aa.html')

  cy.get('#s').should('have.attr', 'disabled')
  cy.get('#a').type('asdf')
  cy.get('#s').should('not.have.attr', 'disabled')
})
<!-- a.html -->
<html>
  <head>
    <script>
      class TextInput extends HTMLElement {
        constructor() {
          super();
          this._shadow = this.attachShadow({mode: "open"});

          this.label = document.createElement("label");
          this.label.setAttribute("class", "d-flex flex-justify-between flex-items-center py-1");
          this._shadow.appendChild(this.label);

          this._name = document.createTextNode("");
          this.label.appendChild(this._name);

          this._input = document.createElement("input");
          this._input.setAttribute("type", "text");
          this.label.appendChild(this._input);
        }

        static get observedAttributes() {
          return ["name"];
        }

        attributeChangedCallback(name, oldValue, newValue) {
          switch (name) {
            case "name":
              this._name.nodeValue = newValue;
              break;
          }
        }
      }

      customElements.define("text-input", TextInput);

      class PageElement extends HTMLElement {
        constructor() {
          super();
          this._shadow = this.attachShadow({mode: "open"});

          const input = document.createElement("text-input");
          input.setAttribute("name", "Label");
          this._shadow.appendChild(input);

          const button = document.createElement("input");
          button.setAttribute("type", "submit");
          button.setAttribute("disabled", "");
          this._shadow.appendChild(button);

          input.addEventListener("input", () => {
            console.log('hi?')
            button.removeAttribute("disabled");
          });
        }
      }

      customElements.define("page-element", PageElement);
    </script>
  </head>
  <body>
    <page-element></page-element>
  </body>
</html>
<!-- aa.html -->
<html>
<head>
</head>
<body>
  <input type="text" id="a">
  <input type="submit" id="s" disabled="disabled">
  <script>
    document.getElementById("a").addEventListener("input", function(e) {
      document.getElementById("s").disabled = ""
    })
  </script>
</body> 
</html>
0reactions
cypress-bot[bot]commented, Dec 4, 2021

Released in 9.1.1.

This comment thread has been locked. If you are still experiencing this issue after upgrading to Cypress v9.1.1, please open a new issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Event listeners not working? 3 key areas to troubleshoot
Events are dispatched by specific elements (their target ). Code can then add listeners to run custom logic in response. But it's not...
Read more >
addEventListener not working in custom element
I'm making a monopoly game for my website, and I have a problem that I can't add event listeners for "i" element in...
Read more >
Custom Elements, event listener and this - Jonas Fährmann
I use Custom Elements a lot. I also like to use .bind(this) in Custom Element event listeners for several reasons. Why this can...
Read more >
Events - Lit.dev
If you're not using decorators, you can customize event listener options by passing an object to the event listener expression. The object must...
Read more >
Custom Element event listener not triggered | Velo by Wix
Hi, I've got a super basic example of a Custom Element firing a Custom Event, but the listener is never triggered.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found