DEV Community

Harshil Patel
Harshil Patel

Posted on • Edited on

Contributing to Node.js: Implementing Dynamic Colors for Test Runner Diagnostics (2/3)

Introduction

This is the second blog in a series of three, where I am sharing my experience contributing to the Node.js core repository. You can read the previous blog here: Contributing to Node.js: Improving Test Runner Coverage Reporting. In the previous blog, I discussed how I discovered the issue and confirmed that it exists in Node.js.

After that, I forked and cloned the Node.js repository and opened it in VS Code. One thing I’ve learned from working on many open-source repositories is that finding where to add or modify code is just as important as knowing what code to add. Fortunately, there was another pull request linked to the issue I was working on, which gave me some useful context.

That pull request also addressed the issue I was working on, but it hardcoded the value for the color. My task, on the other hand, was to implement a level parameter and update the event reader to handle the logic for adding colors dynamically. For example, my issue was to ensure that error messages for coverage would appear in red, but instead of hardcoding the color, the level parameter would allow developers to set it appropriately based on the severity.

Tracing the Code

From the linked pull request, I knew where I could start. The first file to investigate was test.js, which prints the error message when the test coverage threshold isn't met.

Code Snippet

Here, I noticed a call to reporter.diagnostic(). To better understand what was happening, I backtracked to locate the definition of this function. After spending a good amount of time, I found the definition of diagnostic() in tests_stream.js.

diagnostic(nesting, loc, message, level = 'info') {
  this[kEmitMessage]('test:diagnostic', {
    __proto__: null,
    nesting,
    message,
    level,
    ...loc,
  });
}
Enter fullscreen mode Exit fullscreen mode

I added a level parameter here, defaulting it to 'info'. This was the first step to make the error color configurable.

Adding Logic for Severity-Based Colors

Next, I located the handler for test:diagnostic in spec.js. Here, I added logic to dynamically retrieve the color using reporterColorMap, which maps severity levels (e.g., info, warn, error) to specific colors.

#handleEvent({ type, data }) {
  switch (type) {
    // ...
    case 'test:diagnostic': {
      const diagnosticColor = reporterColorMap[data.level] || reporterColorMap['test:diagnostic'];
      return `${diagnosticColor}${indent(data.nesting)}${reporterUnicodeSymbolMap[type]}${data.message}${colors.white}\n`;
    }
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

I then traced the reporterColorMap definition in utils.js and updated it to map severity levels to appropriate colors. Here’s the updated code:

const reporterColorMap = {
  '__proto__': null,
  get 'test:fail'() {
    return colors.red;
  },
  get 'test:pass'() {
    return colors.green;
  },
  get 'test:diagnostic'() {
    return colors.blue;
  },
  get 'info'() {
    return colors.blue;
  },
  get 'warn'() {
    return colors.yellow;
  },
  get 'error'() {
    return colors.red;
  },
};
Enter fullscreen mode Exit fullscreen mode

With these changes, the level parameter now dynamically controls the color of the diagnostic message, making it easier for developers to identify severity levels at a glance.

Building Node.js Locally

Now that the changes were made, it was time to test my work. To do this, I needed to build Node.js locally. I referred to the Building.md file for instructions. Before building, I had to install the prerequisites for my environment. The document mentioned three options for installing these prerequisites.

Initially, I tried the second option, which involved using WinGet. However, during installation, it prompted me to grant several permissions, one of which required uninstalling Visual Studio Code. Since I didn’t want to reinstall Visual Studio Code, I canceled the installation. I then reached out to the maintainer for advice, and they recommended the third option: building with Boxstarter.

Maintainer's Recommendation

Testing the Build

After preparing the prerequisites using Boxstarter, I started building Node.js locally. However, the build process ran for over 1 hour and 30 minutes without completing. This seemed unusual, so I asked the maintainer about it in the issue thread. They mentioned that the build process typically takes about 25 minutes.

Maintainer's Response

After reading that, I canceled the build and decided to try again the next day. On the next attempt, the build completed in just 10 minutes. With the locally built version of Node.js ready, I went back to the sample repository I had created earlier to test the issue of error printing in blue (as described in my first blog). This time, I ran the same test cases but used the locally built Node.js. And guess what? It worked! The error was successfully printed in red.

Test Result

Opening a Pull Request

After confirming that my changes worked, I committed them and opened a pull request. In the pull request, I described the changes I made and asked the maintainer for a review. Shortly after, I received a response from the maintainer, who mentioned that I needed to update the documentation and write test cases for the changes I had made.

Maintainer's Feedback

Conclusion

That’s it for this blog. In the next blog, I will share how I updated the documentation and added test cases to complete the pull request.
Next Blog: My Journey Contributing to Node.js Core: The Final Chapter (3/3)

Top comments (0)