0
votes

Helo, Whenever I input to the google location dropdown, I cannot validate it, I have to click on an option which is not present for me.

this is what I'm referring to: https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/places-autocomplete

let modal1 = element(by.className('classname'));

await modal1.element(by.css('[role = "combobox"]')).sendKeys("location");

I have tried sending a down arrow and an enter, but unfortunately it did not work, please ignore the sleep, only there so i can test it:


   await modal1.element(by.css('[role = "combobox"]')).sendKeys(protractor.Key.DOWN_ARROW);
   browser.sleep(2000);
   await modal1.element(by.css('[role = "combobox"]')).sendKeys(protractor.Key.ENTER);
   browser.sleep(2000);

I don't want to move my mouse to a certain pos. and click as I see that as a rather bad solution, if anyone knows something elegant please post it

1

1 Answers

0
votes

Man, I know the struggle. Here is how I solved this:

  1. First problem was to locate the elements. Locators always change. Each dropdown is attached separately to the HTML and not removed after you close it. This is why you can't just say 'use first occurrence that matches the locator'
  2. Second problem was actual logic. Sometimes you type, and the location dropdown is not prepopulated. So you have to retry. To be completely honest, this is the ugliest solution in my frameworks, but it does what it supposed to do
class Common {

    constructor() {

        /**
         * Elements
         */
        this.$locationDropdownContainer = element.all(by.xpath('//div[contains(@class,"pac-container") and not(contains(@style,"width: 0px")) and not(contains(@style,"display: none"))]')).last();
        this.$locationInput = $("#location");
        this.$$locationOptions = $$(".pac-container .pac-item .pac-item-query");
    }

    /**
     * Types provided location and selects the first option
     * @param criteria
     * @param [retry=true] retry on failure
     * @returns
     */
    async enterLocation(criteria, retry = true) {

        log(`enterLocation(${criteria},${retry})`);
        await browser.sleep(350);
        await sendKeys(this.$locationInput, criteria);
        await browser.sleep(400);
        try {
            await browser.wait(ExpectedConditions.visibilityOf(this.$locationDropdownContainer));
        } catch (e) {
            await this.$locationInput.click();
            try {
                await browser.wait(ExpectedConditions.visibilityOf(this.$locationDropdownContainer));
            } catch (e) {
                if (retry) {
                    this.enterLocation(criteria, false);
                }
            }
        }
        await this.$$locationOptions.get(0).click();
        await browser.sleep(350);
    }
}

Where sendKeys is just a custom method for typing, you can use input.sendKeys()

And waitUntilElementHasAttribute is a method to wait until an element has certain substring in an attribute. In this case, location Dropdown Container (wrapper element) should not have "style" attribute containing "display: none"

As can be seen from JSDoc description I select first option, but it's possible to figure out a way for selecting particular one