const { spawn } = require('node:child_process');

const child = spawn('npm', ['run start']);

Will spawn a child process. Unlike exec, spawn returns data with the stream api like so

child.stdout.on('data', (data) => {
	console.log(`stdout:\n${data}`);
});

So I’m having the error Error: spawn npm ENOENT when I set {cwd: '/home/joseph/workspace/webui-workshop'} in the options to spawn, but when cwd: './', I get that Unknown command: "run start" from npm. also with cwd: ../

child = spawn('pwd', {cwd: './'}); gives /home/joetorsney/workspace/webui-workshop, which is correct! Despite the fact spawn is running from ./test.
**Spawn’s cwd is the root directory of the project

The solution uses node to launch the server instead of npm:

// solution
spawn('node', ['index.js'], {stdio: 'pipe'});

// me
spawn('npm', ['run start'], {cwd: './'});
  • Isn’t this bad? what if the command to run the server changes?work

In chrome developer options, we can copy the CSS selector by (right click) > copy > copy CSS path [(source)][https://stackoverflow.com/questions/4500572/how-can-i-get-the-css-selector-in-chrome]

In puppeteer, when we click and wait for navigation, we must use page.waitForNavigation for each click, or we will encounter race conditions. e.g. [(source)][https://pptr.dev/api/puppeteer.page.click]

const [response] = await Promise.all([
  page.waitForNavigation(waitOptions),
  page.click(selector, clickOptions),
]);

However in the solution for the workshop, we don’t use this pattern. We use page.evaluate instead:work

await page.evaluate(() => document.querySelector('body > div > div:nth-child(2) > div > button').click());

await page.waitFor(200);

And page.waitFor is not a function!!