diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index ecc532d5c0..834b64bc1c 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -721,99 +721,6 @@ await Expect(locator).ToBeVisibleAsync(); ### option: LocatorAssertions.toBeVisible.timeout = %%-csharp-java-python-assertions-timeout-%% * since: v1.18 -## async method: LocatorAssertions.toContainClass -* since: v1.24 -* langs: - - alias-java: containsClass - -Ensures the [Locator] points to an element that contains the given CSS class (or multiple). -In contrast to [`method: LocatorAssertions.toHaveClass`] which requires that the [Locator] has exactly the provided classes, `toContainClass` verifies that the [Locator] has a subset (or all) of the given CSS classes. - -```html -
-``` - -```js -const locator = page.locator('#component'); -await expect(locator).toContainClass('bar baz'); // pass, both classes are on element -await expect(locator).toContainClass('ba'); // fail, element has no 'ba' class - -const itemLocator = page.locator('#component .item'); -await expect(itemLocator).toContainClass(['alice', 'bob']); // pass, first element has alice, second bob -await expect(itemLocator).toContainClass(['alice', 'bob carl']); // no carl class found on second item element -await expect(itemLocator).toContainClass(['alice', 'bob', 'foobar']); // we expect 3 elements with the item class, but there are only 2 -``` - -```java -Locator locator = page.locator("#component"); -assertThat(locator).containsClass("bar baz"); // pass, both classes are on element -assertThat(locator).containsClass("ba"); // fail, element has no 'ba' class - -Locator itemLocator = page.locator("#component .item"); -assertThat(itemLocator).toContainClass(new String[] {"alice", "bob"}); // pass, first element has alice, second bob -assertThat(itemLocator).toContainClass(new String[] {"alice", "bob carl"}); // no carl class found on second item element -assertThat(itemLocator).toContainClass(new String[] {"alice", "bob", "foobar"}); // we expect 3 elements with the item class, but there are only 2 -``` - -```python async -from playwright.async_api import expect - -locator = page.locator('#component') -expect(locator).to_contain_class('bar baz') # pass, both classes are on element -expect(locator).to_contain_class('ba') # fail, element has no 'ba' class - -item_locator = page.locator('#component .item') -expect(item_locator).to_contain_class(['alice', 'bob']) # pass, first element has alice, second bob -expect(item_locator).to_contain_class(['alice', 'bob carl']) # no carl class found on second item element -expect(item_locator).to_contain_class(['alice', 'bob', 'foobar']) # we expect 3 elements with the item class, but there are only 2 -``` - -```python sync -from playwright.sync_api import expect - -locator = page.locator('#component') -await expect(locator).to_contain_class('bar baz') # pass, both classes are on element -await expect(locator).to_contain_class('ba') # fail, element has no 'ba' class - -item_locator = page.locator('#component .item') -await expect(item_locator).to_contain_class(['alice', 'bob']) # pass, first element has alice, second bob -await expect(item_locator).to_contain_class(['alice', 'bob carl']) # no carl class found on second item element -await expect(item_locator).to_contain_class(['alice', 'bob', 'foobar']) # we expect 3 elements with the item class, but there are only 2 -``` - -```csharp -var locator = Page.Locator("#component"); -await Expect(locator).ToContainClassAsync("bar baz"); // pass, both classes are on element -await Expect(locator).ToContainClassAsync("ba"); // fail, element has no "ba" class - -var itemLocator = page.locator("#component .item"); -await Expect(itemLocator).ToContainClassAsync(new string[]{"alice", "bob"}); // pass, first element has alice, second bob -await Expect(itemLocator).ToContainClassAsync(new string[]{"alice", "bob carl"}); // no carl class found on second item element -await Expect(itemLocator).ToContainClassAsync(new string[]{"alice", "bob", "foobar"}); // we expect 3 elements with the item class, but there are only 2 -``` - -Note that locator must point to a single element when passing a string or to multiple elements when passing an array. - -### param: LocatorAssertions.toContainClass.expected -* since: v1.24 -- `expected` <[string]|[Array]<[string]>> - -Expected classnames, whitespace separated. When passing an array, the given classes must be present on the locator elements. - -### option: LocatorAssertions.toContainClass.ignoreCase -* since: v1.24 -- `ignoreCase` <[boolean]> - -Whether to perform case-insensitive match. - -### option: LocatorAssertions.toContainClass.timeout = %%-js-assertions-timeout-%% -* since: v1.24 -### option: LocatorAssertions.toContainClass.timeout = %%-csharp-java-python-assertions-timeout-%% -* since: v1.24 - ## async method: LocatorAssertions.toContainText * since: v1.20 * langs: @@ -977,7 +884,7 @@ Expected attribute value. - alias-java: hasClass Ensures the [Locator] points to an element with given CSS classes. This needs to be a full match -or using a relaxed regular expression. For matching partial class names, use [`method: LocatorAssertions.toContainClass`]. +or using a relaxed regular expression. ```html diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 030098fae0..d1e6538458 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -1071,7 +1071,7 @@ export class InjectedScript { let received: string | undefined; if (expression === 'to.have.attribute') { received = element.getAttribute(options.expressionArg) || ''; - } else if (expression === 'to.have.class' || expression === 'to.contain.class') { + } else if (expression === 'to.have.class') { received = element.classList.toString(); } else if (expression === 'to.have.css') { received = window.getComputedStyle(element).getPropertyValue(options.expressionArg); @@ -1092,9 +1092,7 @@ export class InjectedScript { if (received !== undefined && options.expectedText) { const matcher = new ExpectedTextMatcher(options.expectedText[0]); - return { received, matches: matcher.matches(received, { - toContainClass: expression === 'to.contain.class', - }) }; + return { received, matches: matcher.matches(received) }; } } @@ -1114,7 +1112,7 @@ export class InjectedScript { let received: string[] | undefined; if (expression === 'to.have.text.array' || expression === 'to.contain.text.array') received = elements.map(e => options.useInnerText ? (e as HTMLElement).innerText : e.textContent || ''); - else if (expression === 'to.have.class.array' || expression === 'to.contain.class.array') + else if (expression === 'to.have.class.array') received = elements.map(e => e.classList.toString()); if (received && options.expectedText) { @@ -1128,9 +1126,7 @@ export class InjectedScript { const matchers = options.expectedText.map(e => new ExpectedTextMatcher(e)); let mIndex = 0, rIndex = 0; while (mIndex < matchers.length && rIndex < received.length) { - if (matchers[mIndex].matches(received[rIndex], { - toContainClass: expression === 'to.contain.class.array', - })) + if (matchers[mIndex].matches(received[rIndex])) ++mIndex; ++rIndex; } @@ -1265,9 +1261,7 @@ class ExpectedTextMatcher { } } - matches(text: string, { toContainClass }: { toContainClass?: boolean } = {}): boolean { - if (toContainClass) - return this.matchesClassList(text); + matches(text: string): boolean { if (!this._regex) text = this.normalize(text)!; if (this._string !== undefined) @@ -1279,18 +1273,6 @@ class ExpectedTextMatcher { return false; } - private matchesClassList(received: string): boolean { - const expected = this.normalizeClassList(this._string || ''); - if (expected.length === 0) - return false; - const normalizedReceived = this.normalizeClassList(received); - return expected.every(classListEntry => normalizedReceived.includes(classListEntry)); - } - - private normalizeClassList(classList: string): string[] { - return classList.trim().split(/\s+/g).map(c => this.normalize(c)).filter(c => c) as string[]; - } - private normalize(s: string | undefined): string | undefined { if (!s) return s; diff --git a/packages/playwright-test/src/expect.ts b/packages/playwright-test/src/expect.ts index d96af9f6a3..eb17f3b7d5 100644 --- a/packages/playwright-test/src/expect.ts +++ b/packages/playwright-test/src/expect.ts @@ -29,7 +29,6 @@ import { toContainText, toHaveAttribute, toHaveClass, - toContainClass, toHaveCount, toHaveCSS, toHaveId, @@ -135,7 +134,6 @@ const customMatchers = { toContainText, toHaveAttribute, toHaveClass, - toContainClass, toHaveCount, toHaveCSS, toHaveId, diff --git a/packages/playwright-test/src/matchers/matchers.ts b/packages/playwright-test/src/matchers/matchers.ts index 01c8b9111b..c45f4b4ad8 100644 --- a/packages/playwright-test/src/matchers/matchers.ts +++ b/packages/playwright-test/src/matchers/matchers.ts @@ -164,25 +164,6 @@ export function toHaveClass( } } -export function toContainClass( - this: ReturnType