I achieved the best results for a similar use case with the following:
await page.waitForSelector("button[type=submit]");
await page.click("button[type=submit]", {
      waitUntil: "networkidle2",
});
await page.screenshot({path: 'example.png'});
Basically, the use case differs for every website configuration. I highly recommend to create a command based function like i did for my project:
const puppeteer = require('puppeteer');
// Sample command set
const commands = [
{ id: 1, type: 'goto', target: '/dummy-product/' },
{ id: 2, type: 'goto', target: '/about-page' },
{ id: 4, type: 'goto', target: '/test-page' }, //size text label
];
const bot = async (url, commands) => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
const statuses = [];
for (let command of commands) {
    let status = { id: command.id, status: 'failed' };
    try {
        switch (command.type) {
            case 'click':
                await page.waitForSelector(command.target);
                await page.click(command.target, {
                    waitUntil: "networkidle2",
                  });
                if(command.form){
                    await page.waitForNavigation({ waitUntil: 'networkidle0' })
                }
                status.status = 'success';
                status.message = `${command.type}: ${command.target}`;
                break;
            case 'goto':
                await page.goto(url + command.target, {
                    waitUntil: "networkidle2",
                  });
                await page.screenshot({path: 'example.png'});
                status.status = 'success';
                status.message = `${command.type}: ${command.target}`;
                break;
            case 'select':
                await page.waitForSelector(command.target);
                await page.focus(command.target, {delay: 1000});
                await page.select(command.target, command.value);
                status.status = 'success';
                status.message = `${command.type}: ${command.target}`;
                break;
            case 'input':
                await page.waitForSelector(command.target);
                await page.focus(command.target);
                await page.keyboard.type(command.value);
                status.status = 'success';
                status.message = `${command.type}: ${command.target}`;
                break;
            // You can add more command types here.
            default:
                console.log(`Unknown command type: ${command.type}`);
                status.status = 'failed';
                status.message = 'Unknown command type';
                break;
        }
    } catch (error) {
        status.status = `failed`;
        status.message = error.message;
    }
    statuses.push(status);
}
await browser.close();
return statuses;
}
bot('https://example.com/', commands)
.then(statuses => console.log(statuses))
.catch(err => console.error(err));