how to find the dynamic xpath (changes every time when reload the page)

Viewed 289

Hello guys i need help to solve this, im trying to make a automation to login in Nike BR website (that is different from the others), but everytime that i reload the page the xpath keeps changing anyone could help me with this problem? appreciate you guys the website is https://www.nike.com.br/ you need to click in "Login / Inscreva-se" then the inputs will load

const puppeteer = require ('puppeteer');
const login = '//*[@id="anchor-acessar-unite-oauth2"]';
const emailinput = 'changing xpath'
const passwordinput = 'changing xpath'
(async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    
   
    await page.setViewport({ width: 1920, height: 1080});
    await page.goto ('https://www.nike.com.br');
    const login= await page.waitForXPath('//*[@id="anchor-acessar-unite-oauth2"]');
    await login.click();
    const emailinput = await page.type('changing xpath', 'myEmail@outlook.com', { delay: 110 });
    const passwordinput = await page.type('changing xpath', 'myEmail@outlook.com', { delay: 110 });

    

    

})();
1 Answers

Just don't use the dynamic parts and select the elements by something that's not changing between reloads. These should work as far as I can tell.

Selecting the e-mail address input box:

const emailinput = await page.type('//input[@name="emailAddress"]', 'myEmail@outlook.com', { delay: 110 });

Selecting the password input box:

const passwordinput = await page.type('//input[@name="password"]', 'password', { delay: 110 });

Update

Now I see why the above won't work straight away. The reason is that the content you're trying to select is not in the top frame, but in an iframe.

To make it work you'll need to modify your script to

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  await page.setViewport({ width: 1920, height: 1080 });
  await page.goto('https://www.nike.com.br');
  const login = await page.waitForXPath('//*[@id="anchor-acessar-unite-oauth2"]');
  await login.click();

  const frameElement = await page.waitForXPath('//iframe[@id="nike-unite-oauth2-iframe"]');
  const frame = await frameElement.contentFrame();

  const emailInput = await frame.waitForXPath('//input[@name="emailAddress"]');
  const passwordInput = await frame.waitForXPath('//input[@name="password"]');
  await emailInput.evaluate((elem) => elem.value = 'myEmail@outlook.com');
  await passwordInput.evaluate((elem) => elem.value = 'password');
})();

I changed type to evaluate to directly assign the value. I've found type to be unreliable and didn't have time to figure out why.

Update 2

To also click on the login button you can add this to the end:

const submitInput = await frame.waitForXPath('//div[contains(@class, "loginSubmit")]/input', { visible: true });
await submitInput.click();
Related