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.

Inconsistent results with takeCoverageDelta for dynamic CSS coverage

See original GitHub issue

I’m trying to see how dynamic code coverage for styles works using the devtools protocol. I’m manually evaluating a function which adds a class which was previously unused to the DOM which should ideally increase the coverage. But I keep getting inconsistent results in the coverage returned by takeCoverageDelta. Sometimes it logs [](wrong) and sometimes [{"styleSheetId":"35000.1","startOffset":0,"endOffset":31,"used":true}](correct)

I’m not sure if this is the right place to discuss this. Happy to move it to the Google groups if you can verify that my usage of CRI is not incorrect. Looks to me like some race condition that I’m unaware of or isnt documented in the chrome devtools docs.

Reproducible sample: I have a coverage.js which launches chrome, connects to remote debugging port, and opens index.html. This loads index.js and style.css.

// coverage.js
// Script to Launch and get CSS coverage
'use strict';

const CDP = require('chrome-remote-interface');
const ChromeLauncher = require('chrome-launcher');
const Path = require('path');

const styles = [];
const resources = [];

ChromeLauncher.launch({
  port: 9222,
  chromeFlags: ['--headless', '--disable-gpu'],
  chromePath:
    process.env.NODE_ENV === 'production' ? '/usr/bin/google-chrome' : undefined
})
  .then(() => {
    CDP().then(
      async client => {
        const { Page, Profiler, DOM, CSS, Runtime } = client;

        // Enables all necessary domains
        await Page.enable();
        await Runtime.enable();
        await DOM.enable();
        await CSS.enable();

        // Start capturing coverage data
        await CSS.startRuleUsageTracking();

        await Page.navigate({
          url: `file://${Path.resolve(__dirname, './')}/index.html`
        });

        // Save the data for each style added to the document.
        // This is because the rule usage data only includes styleSheetId.
        // This helps map it back to the file name to which it belongs.
        await CSS.styleSheetAdded(({ header }) => styles.push(header));

        // Fires when all assets have finished loading
        // This includes js, css, images, ads, etc.
        await Page.loadEventFired();

        const result = await Runtime.evaluate({
          awaitPromise: true,
          expression: 'coverMore()'
        });

        // Take a snapshot of all the coverage data ocne the load is complete
        let { coverage: styleSheetCoverages } = await CSS.takeCoverageDelta();

        // Sometimes logs []
        // Sometimes logs [{"styleSheetId":"35000.1","startOffset":0,"endOffset":31,"used":true}]
        console.log(JSON.stringify(styleSheetCoverages));

        // Stop capturing coverage data
        await CSS.stopRuleUsageTracking();
      },
      err => {
        console.log('Error with remote interface', err);
      }
    );
  })
  .catch(err => {
    console.log('Error with launcher', err);
  });
<!-- index.html -->
<head>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div class="app">
    <div class="app-body"></div>
  </div>
  <script src="index.js"></script>
</body>

</html>
// index.js

const coverMore = () => {
  const app = document.querySelector('.app');
  app.classList.add('app-test4');
};

/* style.css */

.app-test4 {
  display: flex;
}

Component Version
Operating system macOS Sierra 10.12.6
Node.js 8.6.0
Chrome/Chromium/… Chrome using Chrome Launcher 0.8.1
chrome-remote-interface 0.25.1

Is Chrome running in a container? NO

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
cyrus-andcommented, Oct 18, 2017

@karanjthakkar you’re welcome! The difference is explained here:

The only difference is that when callback is omitted the event is registered only once and a Promise object is returned.

Conversely if you add a callback the return value is unimportant and the callback is executed every time an event occurs; it’s just a plain Node.js event emitter.

0reactions
karanjthakkarcommented, Oct 18, 2017

@cyrus-and Understood. I missed out on that line when you linked it previously. Again, thanks for explaining! Closing the issue 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Coverage: Find unused JavaScript and CSS
How to find and analyze unused JavaScript and CSS code in Chrome DevTools. ... Click Stop Instrumenting Coverage And Show Results Stop ...
Read more >
Make Your CSS Dynamic with CSS Custom Properties - Toptal
Explore CSS custom properties and find out how they can be used to make better, more dynamic stylesheets.
Read more >
Chrome Devtools Coverage: how to save or capture code ...
I'm attempting to reduce the amount of Bootstrap CSS in my application; the file is more than 7000 lines. The only way to...
Read more >
Dynamic style - manipulating CSS with JavaScript - W3C Wiki
At this point in the JavaScript section of the Web Standards Curriculum, you've already covered the real basics of JavaScript usage, looked at...
Read more >
Making Custom Properties (CSS Variables) More Dynamic
People have been discussing these benefits from the cascade for a few ... trying to get a result from adding values with different...
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