TESTEROPS

A pragmatic approach to QA and OPS

Add and Remove an HTML Attribute using Playwright

FE testing is messy because FE is susceptible to various delays from API calls, and also since it is the front page to the audience, it is the most common way to attack a website – which may be attached to a business.

So that means you may want to include the tests in your test suite where you play with the HTML attributes on the page and then enter some values to modify the behavior.

One of such situations may be to enable or disable an input box or make an element hidden or visible. Let’s see how we can do that in Playwright. In Selenium, we can use js functions in the javascriptexecutor method to execute plain js to modify the HTML attributes. How can we do that in Playwright ?

Well, surprisingly, we have to do this the same way. Use the inbuilt js methods to achieve such functionality. There is no easy method in Playwright for this. Sad. I hope they really look into this and give us a method for that. Although I know it would be very difficult to do that.

Now let’s see how we can add or remove an HTML attribute on the page.

As usual we head over to our practice page, which is given by SelectorsHub.

There are many input fields on this page, so it is like a gold mine for this kind of test. Let’s pick the input element which has a placeholder text Enter your company

<input name="company" type="text" class="form-control" placeholder="Enter your company">

As you can see that this input element is perfectly fine , and interact-able by a normal user. Let’s try to disable this input field. How to do that.

We’ll use the page.evaluate() method to call a native js function setAttribute() on this element.

   await page.evaluate(()=>{
        const selector = document.querySelector("input[placeholder$='Enter your company']");
        selector.setAttribute('disabled','disabled');
    });

    await page.waitForTimeout(5000);

Let’s see the full code

import { chromium,test } from "@playwright/test";
test.use({ viewport: { width: 1400, height: 1000 } });
test('Launch the Selectors hub test page',async()=>{
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://selectorshub.com/xpath-practice-page/&quot;);
await page.waitForSelector('.dropbtn',{
state: "visible"
});
await page.waitForTimeout(5000);
// set disabled attribute
await page.evaluate(()=>{
const selector = document.querySelector("input[placeholder$='Enter your company']");
selector.setAttribute('disabled','disabled');
});
await page.waitForTimeout(5000);
});
view raw disabled.js hosted with ❤ by GitHub

Now we run the test and it passes successfully. But how to validate this worked?

So we will use the page.pause() method in the script. What it does is – it pauses the script execution until user input is given. Read about the page.pause() method here. Also we will use the --debug flag to open in debug mode – like this

npx playwright test add_remove_attr.spec.ts --debug

This will open the Playwright inspector and then we will start the execution by clicking the green arrow at the top.

Once the script execution pauses, open the element inspector and look at the element in the DOM – you’ll see a disabled attribute added with the value disabled

Now you see that the element becomes disabled and cannot be interacted with. Now we will remove the disabled attribute and make the input box interact-able again.

Now to the same element, we will use the removeAttribute() method to remove the disable attribute like this

await page.evaluate(()=>{
        const selector = document.querySelector("input[placeholder$='Enter your company']");
        selector.removeAttribute('disabled')
    });

Let’s see the whole code

import { chromium,test } from "@playwright/test";
test.use({ viewport: { width: 1400, height: 1000 } });
test('Launch the Selectors hub test page',async()=>{
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://selectorshub.com/xpath-practice-page/&quot;);
await page.waitForSelector('.dropbtn',{
state: "visible"
});
await page.waitForTimeout(5000);
// set disabled attribute
await page.evaluate(()=>{
const selector = document.querySelector("input[placeholder$='Enter your company']");
selector.setAttribute('disabled','disabled');
});
await page.waitForTimeout(5000);
// now remove the attribute and make the input enabled
await page.evaluate(()=>{
const selector = document.querySelector("input[placeholder$='Enter your company']");
selector.removeAttribute('disabled')
});
await page.waitForTimeout(5000);
});
view raw disabled2.js hosted with ❤ by GitHub

Run again with the --debug mode on. You can also ignore it since you can visually see the difference since there is a wait of 5seconds on the script. The page.waitForTimeout() has been added just for showcase purposes. Please avoid using this in real tests and rely on other assertions.

Now to test if the input is enabled and can be interacted with, we’ll just send a small text in the input box.

import { chromium,test } from "@playwright/test";
test.use({ viewport: { width: 1400, height: 1000 } });
test('Launch the Selectors hub test page',async()=>{
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("https://selectorshub.com/xpath-practice-page/&quot;);
await page.waitForSelector('.dropbtn',{
state: "visible"
});
await page.waitForTimeout(5000);
// set disabled attribute
await page.evaluate(()=>{
const selector = document.querySelector("input[placeholder$='Enter your company']");
selector.setAttribute('disabled','disabled');
});
await page.waitForTimeout(5000);
// now remove the attribute and make the input enabled
await page.evaluate(()=>{
const selector = document.querySelector("input[placeholder$='Enter your company']");
selector.removeAttribute('disabled')
});
await page.waitForTimeout(2000);
await page.locator("div[class='element-companyId'] input[placeholder='Enter your company']").fill('Google');
await page.screenshot({path: "attribute.png"});
});

I’ve added a page.screenshot() method to show that the input was actually made. When we run the script and check the screenshot we see the input word Google in the input box.

So now you can see that the element HTML attributes can be added or removed on the runtime in the test scripts using the page.evaluate() method and passing native js methods.

Honestly I thought it would be easier than this in js, but unfortunately, it isn’t. But that’s okay I think. Nothing can be perfect. Not even Playwright 😛

In next blog, I’ll try to fetch css values from elements and see how we can use web-first assertions for css already in place in Playwright. Upwards and onwards.

%d bloggers like this: