javascriptnode.jsplaywrightreporters

Why doesn't Playwright reporter wait for async functions to complete?


I am using custom playwright reporter (but I think this issue is not only tied to reporter) and there in async OnTestEnd(test, result) I am trying to run exec command. With debugger turned on I see that as soon as program reaches this exec function it skips it and it ends.

const { exec } = require('child_process');

class CustomPDFReporter {
  onTestEnd(test, result) {
    const cmd = `C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe --quiet --print-media-type ...`;

    exec(cmd, (error, stdout, stderr) => {
      if (error) {
        console.error(`Error executing command: ${error.message}`);
        return;
      }

      if (stderr) {
        console.error(`Error output: ${stderr}`);
        return;
      }

      console.log("Generation successful!");
      console.log(`Command Output: ${stdout}`);
    });
  }
}

module.exports = CustomPDFReporter;

Above is one of many attempts to correctly run this function. But it skips all the time.


Solution

  • As mentioned in the comments, use execSync instead of the async callback version exec:

    const {execSync} = require("child_process");
    
    class CustomPDFReporter {
      onTestEnd(test, result) {
        const cmd = `C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe --quiet --print-media-type ...`;
        
        try {
          const {stdout, stderr} = execSync(cmd);
    
          if (stderr) {
            console.error(`Error output: ${stderr}`);
            return;
          }
    
          console.log("Generation successful!");
          console.log(`Command Output: ${stdout}`);
        }
        catch (error) {
          console.error(`Error executing command: ${error.message}`);
        }
      }
    }
    
    module.exports = CustomPDFReporter;
    

    If you happened to be in an async function, you can promisify exec to avoid its callback running in a separate promise chain (shown in vanilla Node):

    const {promisify} = require("util");
    const exec = promisify(require("child_process").exec);
    
    (async () => {
      try {
        const {stderr, stdout} = await exec("ls"); // or "dir" on windows
    
        if (stderr) {
          console.error(`Error output: ${stderr}`);
        }
        else {
          console.log("Generation successful!");
          console.log(`Command Output: ${stdout}`);
        }
      }
      catch (err) {
        console.error(`Error executing command: ${err.message}`);
      }
    })();