user11090827
user11090827

Reputation:

How to Select an opion from a Google Forms popup dropdown Puppeteer NodeJS

everybody, I have recently been trying to implement automation for a google form and I'm stumped with this dropdown.

I simply have been unable to select the value I want from the popup dropdown. As the dropdown autocompletes if I use puppeteer to write in the field ie. United space Kingdom it autocompletes the form to United Arab Emeries (the first value after United) as when the space character is used, it enters on the form and selects the first value.

I have made a dummy google form to simulate my scenario: https://docs.google.com/forms/d/e/1FAIpQLSeY-5GpBQ7ww3qm-EUn5ENTl-KOVD02PIwlyblw8ItjfOfhtQ/viewform?usp=sf_link

Thank you all in advance!

Upvotes: 1

Views: 1076

Answers (1)

Edi Imanto
Edi Imanto

Reputation: 2509

I try and this is what i code.

NOTES:

I'm not code this by clicking and selecting element by normally mouse method, because it's really hard to debug when it's gone error.

You have to declare the root selector of the dropdown, and if there are multiple dropdown, you have to find the right selector by yourself.

And don't forget to select the desiredOption in this code.

const puppeteer = require ('puppeteer')

const formURL = 'https://docs.google.com/forms/d/e/1FAIpQLSeY-5GpBQ7ww3qm-EUn5ENTl-KOVD02PIwlyblw8ItjfOfhtQ/viewform'

const dropDownRootElemSelector = 'div.quantumWizMenuPaperselectEl'

const desiredOption = 'United Kingdom' // Write down your desired option here

;(async () => {

    const browser = await puppeteer.launch ({
        headless: false,
        devtools: false
    })

    const [page] = await browser.pages ()

    const open = await page.goto ( formURL, { waitUntil: 'networkidle0', timeout: 0 } )

    while ( await page.evaluate ( dropDownRootElemSelector => !document.querySelector(dropDownRootElemSelector).classList.contains('isFocused'), dropDownRootElemSelector ) ) {
        await page.keyboard.press('Tab')
        await page.waitFor(250)
    }

    await page.keyboard.press('Space')

    while ( await page.evaluate ( dropDownRootElemSelector => document.querySelector(dropDownRootElemSelector).lastElementChild.childElementCount === 0, dropDownRootElemSelector ) ) {
        await page.waitFor(200)
    }

    const optionExist = async () => {
        await page.evaluate ( (dropDownRootElemSelector, desiredOption) => {

            var optionsDropDown = []

            document.querySelectorAll( dropDownRootElemSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"]').forEach(elem => optionsDropDown.push(elem.textContent) )

            return ( optionsDropDown.includes(desiredOption) )

        }, dropDownRootElemSelector, desiredOption)
    }

    if ( optionExist () ) {
        await page.keyboard.press('ArrowDown')
    }

    while ( await page.evaluate ( (dropDownRootElemSelector) => document.querySelector( dropDownRootElemSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected') === null, dropDownRootElemSelector ) ) {
        await page.waitFor(250)
    }

    while ( optionExist () && await page.evaluate ( (dropDownRootElemSelector, desiredOption) => document.querySelector( dropDownRootElemSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value !== desiredOption, dropDownRootElemSelector, desiredOption) ) {
        // console.log ( await page.evaluate ( (dropDownRootElemSelector) => document.querySelector( dropDownRootElemSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value, dropDownRootElemSelector ) )
        await page.keyboard.press('ArrowDown')
        await page.waitFor(250)
    }

    await page.keyboard.press('Enter')


})()

If you have multiple dropdowns, then it's simple.

You can add a unique identifier at the selector, for this example, you can add [data-item-id="ID_NUMBER"] for each dropdown.

Don't forget to add delay by placing await page.waitFor(1000) at the end of every dropdown code to avoid unselected dropdown caused by fast running script.

Added new answer for multiple dropdown:

const puppeteer = require ('puppeteer')

const formURL = 'https://docs.google.com/forms/d/e/1FAIpQLSeY-5GpBQ7ww3qm-EUn5ENTl-KOVD02PIwlyblw8ItjfOfhtQ/viewform'

const dropDownRootCountrySelector = '[data-item-id="1058991397"] > div.quantumWizMenuPaperselectEl'
const dropDownRootZoneSelector = '[data-item-id="50474009"] > div.quantumWizMenuPaperselectEl'

const desiredCountry = 'United Kingdom' // Write down your desired option here
const desiredZone = 'Europe' // Write down your desired option here

;(async () => {

    const browser = await puppeteer.launch ({
        headless: false,
        devtools: false
    })

    const [page] = await browser.pages ()

    const open = await page.goto ( formURL, { waitUntil: 'networkidle0', timeout: 0 } )

    // FIRST DROPDOWN => COUNTRY

    while ( await page.evaluate ( dropDownRootCountrySelector => !document.querySelector(dropDownRootCountrySelector).classList.contains('isFocused'), dropDownRootCountrySelector ) ) {
        await page.keyboard.press('Tab')
        await page.waitFor(250)
    }

    await page.keyboard.press('Space')

    while ( await page.evaluate ( dropDownRootCountrySelector => document.querySelector(dropDownRootCountrySelector).lastElementChild.childElementCount === 0, dropDownRootCountrySelector ) ) {
        await page.waitFor(200)
    }

    const optionExistCountry = async () => {
        await page.evaluate ( (dropDownRootCountrySelector, desiredCountry) => {

            var optionsDropDown = []

            document.querySelectorAll( dropDownRootCountrySelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"]').forEach(elem => optionsDropDown.push(elem.textContent) )

            return ( optionsDropDown.includes(desiredCountry) )

        }, dropDownRootCountrySelector, desiredCountry)
    }

    if ( optionExistCountry () ) {
        await page.keyboard.press('ArrowDown')
    }

    while ( await page.evaluate ( (dropDownRootCountrySelector) => document.querySelector( dropDownRootCountrySelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected') === null, dropDownRootCountrySelector ) ) {
        await page.waitFor(250)
    }

    while ( optionExistCountry () && await page.evaluate ( (dropDownRootCountrySelector, desiredCountry) => document.querySelector( dropDownRootCountrySelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value !== desiredCountry, dropDownRootCountrySelector, desiredCountry) ) {
        // console.log ( await page.evaluate ( (dropDownRootCountrySelector) => document.querySelector( dropDownRootCountrySelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value, dropDownRootCountrySelector ) )
        await page.keyboard.press('ArrowDown')
        await page.waitFor(250)
    }

    await page.keyboard.press('Enter')

    await page.waitFor(1000)
    // SECOND DROPDOWN => ZONE

    while ( await page.evaluate ( dropDownRootZoneSelector => !document.querySelector(dropDownRootZoneSelector).classList.contains('isFocused'), dropDownRootZoneSelector ) ) {
        await page.keyboard.press('Tab')
        await page.waitFor(250)
    }

    await page.keyboard.press('Space')

    while ( await page.evaluate ( dropDownRootZoneSelector => document.querySelector(dropDownRootZoneSelector).lastElementChild.childElementCount === 0, dropDownRootZoneSelector ) ) {
        await page.waitFor(200)
    }

    const optionExistZone = async () => {
        await page.evaluate ( (dropDownRootZoneSelector, desiredZone) => {

            var optionsDropDown = []

            document.querySelectorAll( dropDownRootZoneSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"]').forEach(elem => optionsDropDown.push(elem.textContent) )

            return ( optionsDropDown.includes(desiredZone) )

        }, dropDownRootZoneSelector, desiredZone)
    }

    if ( optionExistZone () ) {
        await page.keyboard.press('ArrowDown')
    }

    while ( await page.evaluate ( (dropDownRootZoneSelector) => document.querySelector( dropDownRootZoneSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected') === null, dropDownRootZoneSelector ) ) {
        await page.waitFor(250)
    }

    while ( optionExistZone () && await page.evaluate ( (dropDownRootZoneSelector, desiredZone) => document.querySelector( dropDownRootZoneSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value !== desiredZone, dropDownRootZoneSelector, desiredZone) ) {
        // console.log ( await page.evaluate ( (dropDownRootZoneSelector) => document.querySelector( dropDownRootZoneSelector + ' > div[role="presentation"] ~ div[role="presentation"] > div[role="option"] ~ div[role="presentation"] ~ div[role="option"].isSelected').dataset.value, dropDownRootZoneSelector ) )
        await page.keyboard.press('ArrowDown')
        await page.waitFor(250)
    }

    await page.keyboard.press('Enter')

})()

Upvotes: 2

Related Questions