Rayrun
← Back to Discord Forum

Removed

zarrensaerden
zarrensaerden

When you say "value" do you mean the text property of the label elements or the value property? They are different and require different methods to assert on.

This thread is trying to answer question "How to distinguish between different values in label elements and assert on them using Playwright in TypeScript and C#?"

16 replies
vertigo448
vertigo448

Hi @jamesm3088 Could You paste the HTML structure of that section with elements ?

vertigo448
vertigo448

Something like this will work, not sure if You wanna rely on that <p> tho

// Get the text content of the element with the selector "label:has-text("Result:") + p" const result = await page.textContent('label:has-text("Result:") + p');

const dimension = await page.textContent('label:has-text("tmm:") + p');

// other way to get the text content of the element with the selector "label:has-text("Result:") + p" const result2 = await page.$eval('label:has-text("Result:") + p', (el) => el.textContent);

// other way to get the text content of the element with the selector "label:has-text("tmm:") + p"

const result3 = await page.locator('label:has-text("tmm:") + p').textContent();

// Assert the values for "Fail" and "tmm: 7.62mm" expect(result).toBe('FAIL'); expect(dimension).toBe('7.62mm');

expect(result2).toBe('FAIL'); expect(result3).toBe('7.62mm');

example_test.JPG
vertigo448
vertigo448

Sorry just noticed it is .net

using Microsoft.Playwright; using Xunit;

public class ExampleTest { [Fact] public async Task SomeTest() { using var playwright = await Playwright.CreateAsync(); await using var browser = await playwright.Chromium.LaunchAsync(); var page = await browser.NewPageAsync(); await page.GoToAsync("http://127.0.0.1:3000/"); await page.WaitForSelectorAsync("label:has-text("Result:")");

// Get the text content of the element with the selector "label:has-text(\"Result:\") + p"
    var result = await page.TextContentAsync("label:has-text(\"Result:\") + p");
    var dimension = await page.TextContentAsync("label:has-text(\"tmm:\") + p");

    // other way to get the text content of the element with the selector "label:has-text(\"Result:\") + p"
    var result2 = await page.EvalOnSelectorAsync<string>("label:has-text(\"Result:\") + p", "el => el.textContent");

    // other way to get the text content of the element with the selector "label:has-text(\"tmm:\") + p"
    var result3 = await page.Locator("label:has-text(\"tmm:\") + p").TextContentAsync();

    // Assert the values for "Fail" and "tmm: 7.62mm"
     this below will fail:
    Assert.Equal("FAILkjsahgfsadf", result);

    Assert.Equal("7.62mm", dimension);
    Assert.Equal("FAIL", result2);
    Assert.Equal("7.62mm", result3);
}

}

vertigo448
vertigo448

Och yeah it does not ..... will need to filter the selectors based on heading so it will always traverse below certain heading, I will check solution in the evening and let You know

vertigo448
vertigo448

Ok so I had a closer look and based on HTML You provided:

<html lang="en">
   <head>
      <div class="row pb-3">
      <!--!-->
      <div class="col-lg-4 mb-4">
      <div class="card wg-card h-100">
      <div class=" h4 card-header text-center">Wall Thickness Applicability Check</div>
      <!--!-->
      <div class="card-body wg-result-border_fail ">
      <!--!-->
      <div class="wg-cardinfoRow mb-3">
         <label class="mr-3">Criterion:</label><!--!-->
         <p>tmm - FCA &gt; max [0.5tmin,tlim] (Where: tlim = max[0.2tnom,2.5 mm]</p>
      </div>
      <!--!-->
      <!--!-->
      <div class="wg-cardinfoRow mb-3">
         <label class="mr-3">Result:</label><!--!-->
         <!--!-->
         <p class="wg-result_fail text-danger font-weight-bold p-1">FAIL</p>
      </div>
      <!--!-->
      <!--!-->
      <div class="wg-card__infoRow mb-3">
         <label class="mr-3">tmm:</label><!--!-->
         <p>7.62mm</p>
      </div>
      <!--!-->
   </head>
</html>```


It will be hard to have a nice way to distinguish particular set based on `<div class=" h4 card-header text-center">` 
Since it is a sibling to rest
vertigo448
vertigo448

This will work:

test('Some test', async ({ page }) => {
  // starting example html page on localhost
  await page.goto('http://127.0.0.1:3000/');
  expect(await page.waitForSelector('label:has-text("Result:")')).toBeTruthy();

  async function assertLabels(headingText: string,expectedValues: { label: string; siblingValue: string }[]): Promise<void> {
    const locators =  await page.$$(`//*[text()='${headingText}']/parent::*//label`);

    for await (const element of locators) {
      const labelText = await element.innerText();
      const expectedValue = expectedValues.find((expected) => expected.label === labelText);
  
      if (expectedValue) {
        const siblingElement = await element.$('xpath=following-sibling::p');
        if (!siblingElement) {
          throw new Error('Sibling element not found');
        }
        const siblingText = await siblingElement.innerText();
  
        expect(siblingText).toBe(expectedValue.siblingValue);
      }
    }
  }

  /* this will fail will error:
  Error: expect(received).toBe(expected) // Object.is equality

Expected: "PASS"
Received: "FAIL"

  31 |         const siblingText = await siblingElement.innerText();
  32 |   
> 33 |         expect(siblingText).toBe(expectedValue.siblingValue);
     |                             ^
  34 |       }
  35 |     }
  36 |   }
  */
  const expectedValues = [ { label: 'Result:', siblingValue: 'PASS' } ]

  await assertLabels('Wall Thickness Applicability Check', expectedValues);

  // this will pass
  const expectedValues2 = [ { label: 'Result:', siblingValue: 'FAIL' } ]

  await assertLabels('Wall Thickness Applicability Check', expectedValues2);

});```
vertigo448
vertigo448

Side note I would rather add some data test ids to elements so it would be easier not to look by layout

vertigo448
vertigo448

np just noticed I did it in TS instead of C# 😄 😄

vertigo448
vertigo448

here is C# version:

vertigo448
vertigo448
using Xunit;

public class ExampleTest
{
    [Fact]
    public async Task SomeTest()
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync();
        var page = await browser.NewPageAsync();
        await page.GoToAsync("http://127.0.0.1:3000/");
        await page.WaitForSelectorAsync("label:has-text(\"Result:\")");

        async Task AssertLabels(string headingText, List<(string label, string siblingValue)> expectedValues)
        {
            var locators = await page.QuerySelectorAllAsync($"//*[text()='{headingText}']/parent::*//label");

            foreach (var element in locators)
            {
                var labelText = await element.InnerTextAsync();
                var expectedValue = expectedValues.Find(expected => expected.label == labelText);

                if (expectedValue != null)
                {
                    var siblingElement = await element.QuerySelectorAsync("xpath=following-sibling::p");
                    if (siblingElement == null)
                    {
                        throw new Exception("Sibling element not found");
                    }
                    var siblingText = await siblingElement.InnerTextAsync();

                    Assert.Equal(expectedValue.siblingValue, siblingText);
                }
            }
        }

        // this will fail with error:
        // Error: Assert.Equal() Failure
        // Expected: "PASS"
        // Actual: "FAIL"
        var expectedValues = new List<(string label, string siblingValue)> { ("Result:", "PASS") };
        await AssertLabels("Wall Thickness Applicability Check", expectedValues);

        // this will pass
        var expectedValues2 = new List<(string label, string siblingValue)> { ("Result:", "FAIL") };
        await AssertLabels("Wall Thickness Applicability Check", expectedValues2);
    }
}```
vertigo448
vertigo448

Think overall for better maintenance You could do or ask for like heading data test id so HTML would look like: <header datatest-id="Somemeaing full stuff for certain section" everything else is child of it </header>

vertigo448
vertigo448

so You could easy filter etc without that traversing

jamesm3088

Removed

TwitterGitHubLinkedIn
AboutQuestionsDiscord ForumBrowser ExtensionTagsQA Jobs

Rayrun is a community for QA engineers. I am constantly looking for new ways to add value to people learning Playwright and other browser automation frameworks. If you have feedback, email [email protected].