Skip to content

[BUG] toHaveAttribute always passes when given a blank value string #16517

@radium-v

Description

@radium-v

Context:

  • Playwright Version: 1.25
  • Operating System: Windows 11, Ubuntu 22.04 via WSL2
  • Node.js version: 16.16.0
  • Browser: All

Code Snippet

import { expect, test } from "@playwright/test";

test("should return false for nonexistent attributes", async ({ page }) => {
    await page.setContent(`<div></div>`);

    const element = page.locator("div");

    // always passes
    await expect(element).toHaveAttribute("", "");

    // always passes
    await expect(element).toHaveAttribute("any-arbitrary-attribute", "");

    // always fails, `value` must be a string
    await expect(element).not.toHaveAttribute("any-attribute", "");

    // always fails (Matcher error: expected value must be a string or regular expression)
    await expect(element).not.toHaveAttribute("attr");

    // workaround: passes when the attribute is not present
    expect(await element.getAttribute("attr")).toBeNull();

    await element.evaluate(node => node.toggleAttribute("attr"));

    // workaround: this solution checks for the existence of boolean attributes with no value, but doesn't cover every valid boolean attribute situation
    expect(await element.getAttribute("attr")).toBe("");
});

Describe the bug

The toHaveAttribute matcher doesn't work as expected with the checks above, since await expect(element).toHaveAttribute("anything", "") will always pass. Likewise, await expect(element).not.toHaveAttribute("anything", "") will always fail for any attribute when used as a check for the presence of attributes. In our case, this primarily affects the use of boolean attributes like checked, disabled, hidden, open, which are considered true when they're present, regardless of value.

I think the value parameter for toHaveAttribute could be made optional, which would allow checking for the existence of attributes. The always-failing not.toHaveAttribute matcher would then be able to pass. This may also help to address #16270, though boolean attributes likely would need their own logic to match the allowed validity rules described in this MDN article.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions