2023-10-05

Playwright page.locator selectOption does not work inside imported function

I have been having trouble with the elements with Playwright. I must click the div below the select before I can use the selectOption method from Playwright. However I created a function and imported it into the test to accomplish the two steps together but only the click step works. The select option step fails to work inside the function but it will work outside the function in the test itself.

The select element has a style of display:none. The result is that playwright refuses to select an option because it says the element is not visible. In fact the element is visible and the workaround seems to be to click on the div element below the select to get the options to be visible.

so I made a function that uses the select element's locator to find the div below it using .eval(el=>{ //click the div below the select}). This seems to work as the options then show up on the screen as a drop down.

This then allowed me to use myLocator.selectOption('thevalue') BUT this only works if the selectOption step occurs inside the test and not inside the imported function. I have no idea why. The page context is preserved because page is passed to the function and successfully used inside the function for clicking on the div. But Playwright refuses to select the option if the selectOption step occurs inside the function.

import { customSelectOption } from '../../../utils/DataEntry/customSelectOption.ts'
// other standard imports for playwright test

test('attempt to use select', async ({ page }) => {

    //......navigate to website.. etc...

    // create page object and set up locator
    const selectLocators = new SelectLocators(page);
    const selectLocatorObj = selectLocators.firstSelectElement;


    // clicks the div that occurs after the select 
    await customSelectOption(page, selectLocatorObj, 'desired Value To Select');

    // the step to use selectOption will work here but not inside the customSelectOption function
    await page.locator(selectLocatorString).selectOption(value);
});


export async function customSelectOption(page: Page, select: Locator, value: string | {}) {

    // convert locator back to simple string css locator - which looks like this 'Locator@#theID'
    // removing the first 8 characters results in the css locator as a string: #theID
    let selectLocatorString = select.toString();
    selectLocatorString = selectLocatorString.slice(8);

    // create a new string that uses the css locator to find the next sibling div
    let selectOptionsDiv = selectLocatorString + '+ div';

    // click on that div (This step always works)
    await page.locator(selectOptionsDiv).click();

    // the result is the the dropdown options on the select are now visible on the screen

    //HOWEVER: this next step does not work when it occurs in this function. 
    // If this next occurs after the function but inside the test then it will work, but why?
    await page.locator(selectLocatorString).selectOption(value);

}


No comments:

Post a Comment