happy-dom: document.styleSheets is undefined

Is there a way to compute the document.styleSheets attribute once the window element is created and some HTML is added to it?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (10 by maintainers)

Commits related to this issue

Most upvoted comments

@Leprosy I managed to find what caused the problem now and I have fixed it in the latest release.

I recommend using a VM context to set Happy DOM as global if you will run scripts. You can also use @happy-dom/global-registrator in test environments. I do not recommend using @happy-dom/global-registrator in environments where you do not have control over the page HTML. If you plan to execute unknown code I recommend to use a VM context and disable script evaluation in the VM as it is always a risk that the script manages to jump out from the VM somehow.

I have also added support for the window “load” event and the document “readystatechange” event, but as your code seems to execute scripts I recommend using happyDOM.whenAsyncComplete() as it will also wait for the script to finish executing (timeouts, fetches etc.).

You can read more about the latest releases here: https://github.com/capricorn86/happy-dom/releases/tag/v2.17.1

I used this script for testing:

const { Window } = require('./packages/happy-dom');
const VM = require('vm');

async function getStyles() {
    const window = VM.createContext(new Window());
    const document = window.document;
    
    window.location.href = 'https://l3pro.netlify.app';
    
    document.write(`<!DOCTYPE html>
    <html>
      <head>
        <style>
          h1 { text-decoration: underline; }
        </style>
        <link rel="stylesheet" href="style.css">
      </head>
      <body>
        <h1> This is test </h1>
        <h2></h2>
    
        <p>This has some dynamic generated content</p>
        <p>This should be enought to test</p>
        <img src="celes.jpeg" width="50" height="100" />
        <img src="img/guitar.jpeg" width="50" height="100" />
    
        <script>
          const getQuote = async () => {
            let text = "";
            try {
              const res = await fetch("https://l3pro.netlify.app/.netlify/functions/test");
              text = await res.text();
            } catch(e) {
              text = \`Error fetching: \${e}\`;
            } finally {
              document.getElementsByTagName("h2")[0].innerHTML = text
            }
          }
    
          setTimeout(getQuote, 2000);
        </script>
      </body>
    </html>
    `);

    await window.happyDOM.whenAsyncComplete();

    return document.styleSheets;
}

getStyles().then(styleSheets => {
    let index = 0;
    
    for(const styleSheet of styleSheets) {
        console.log('Stylesheet #' + index + ':');
        for(const cssRule of styleSheet.cssRules) {
            console.log(cssRule.cssText);
        }
        index++;
    }
}).catch(error => {
    console.error(error);
    process.exit(1);
});

@Leprosy the code examples I sent is for server side. However, I am working on adding support for the “load” and “readystatechange” event that you will be able to use instead.

Thanks for reporting @Leprosy! 🙂

I will look into this as soon as possible.