Search code examples
playwrightstenciljs

How to test Stencil web component input tag 'readonly' attribute with Playwright?


I have a Stencil custom input component with several props and I'm having major problems testing the readonly attribute.

The Stencil class looks like this:

@Component({
  tag: 'my-input',
  shadow: true,
})
export class Input {
  @Prop() readonly: boolean = false;
  .
  .
   render() {
    return (
        .
        .
        .
        <input readonly={this.readonly}
        .
        .

What the actual rendered HTML looks like: [![enter image description here][1]][1]
The interesting part is if I edit the HTML it looks as if the readonly attribute is empty:

<input maxlength="524288" type="text" id="input" placeholder="Enter text" readonly="">

The Playwright test:

test('input is readonly', async ({ page }) => {
    const myinput = await page.locator('my-input');
    await myinput.evaluate((el) => {
        el.setAttribute('readonly', 'true');
    });

    const input = await page.locator('my-input >> input');
    const attrs = await input.evaluate(async (el) => el.getAttributeNames()); // doesnt work
    await expect(attrs.includes('readonly')).toBeTruthy(); // doesnt work
    await expect(input).toHaveAttribute('readonly', 'true'); // doesnt work
});

If I test the available attributes on the elements sometimes the readonly is not present. WHY is it so inconsistent? ☹️ [1]: https://i.sstatic.net/H5WD0.png


Solution

  • Your example contains a few problems:

    test('input is readonly', async ({ page }) => {
      // Dont't forget to open the page with the input
      // await page.goto('http://localhost:52330/index.html');
    
      // 1. remove await ↓           ↓ 2. provide valid selector            
      const myinput = page.locator('#input');
    
      await myinput.evaluate((el) => {
        el.setAttribute('readonly', 'true');
      });
    
      // 3. remove await ↓           ↓ 4. provide valid selector  
      const input = page.locator('#input');
      const attrs = await input.evaluate(async (el) => el.getAttributeNames());
      // 5. remove await ↓ 
      expect(attrs.includes('readonly')).toBeTruthy();
      await expect(input).toHaveAttribute('readonly', 'true');
    });
    

    Tested it with your HTML code:

    <input maxlength="524288" type="text" id="input" placeholder="Enter text" readonly="">
    

    and it works

    enter image description here