Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] add option to normalize whitespace to expect().toHaveValue() #23037

Open
kLjubomir opened this issue May 16, 2023 · 5 comments · May be fixed by #33909
Open

[Feature] add option to normalize whitespace to expect().toHaveValue() #23037

kLjubomir opened this issue May 16, 2023 · 5 comments · May be fixed by #33909

Comments

@kLjubomir
Copy link

System info

  • Playwright Version: [v1.30]
  • Operating System: [Windows 10]
  • Browser: [Chromium]
  • Other info:

Source code

    
    const unformattedPrice = "11250";
    await purchaseVehiclePage.enterAskingPrice(unformattedPrice);
    await purchaseVehiclePage.enterTradeInPrice(unformattedPrice);
    await purchaseVehiclePage.enterResalePrice(unformattedPrice);
    await purchaseVehiclePage.removeFieldFocus();

    const priceFields = [
        purchaseVehiclePage.askingPriceField,
        purchaseVehiclePage.tradeInPriceField,
        purchaseVehiclePage.resalePriceField
    ];
    let expectedFormattedPrice = Utils.removeCurrency(Utils.convertToCurrencyFormat(parseInt(unformattedPrice),
        workerInfo.project.name));

    for (const priceField of priceFields) {
         if(workerInfo.project.name==='at') {
            await expect(await priceField.inputValue()).toContain("11 250,00");
        } else {
            await purchaseVehicleAssertion.assertPriceFormat(priceField, expectedFormattedPrice);
    }
  }
    

Steps:

Hello, the code itself will probably not have explained much, so here's how to reproduce:
Have a value > 1000.
Have an input field that instead of a "." or a "," puts a whitespace to separate "numeric" values (which are actually string), so for example "11250" would become "11 250,00" or 1000235 would become 1 000 235,00
Grab the .inputValue() of the field after typing or filling an unformatted raw numeric value into the field.

Assert the field with expect(await element.inputValue()).toBe("11 250,00")

Expected

Since "11 250,00" which was fetched from inputValue() is the same as "11 250,00" which was set there as a string in assertions, using any of the matching assertions should correctly deduce the two fields as equal.

Actual
If the inptValue() contains a whitespace, using assertions like .toBe() or .toContain(), comparing string with identical string causes an assertion error. This issue is not reproduced if the inputValue() of the string does not contain a whitespace, so if the number is parsed to "11.250,00" any assertion asserting this inputValue() to be or contain "11.250,00" will pass.

Error: expect(received).toBe(expected) // Object.is equality

Expected: "11 250,00"
Received: "11 250,00"

141 | for (const priceField of priceFields) {
142 | if(workerInfo.project.name==='at') {

143 | await expect(await priceField.inputValue()).toBe("11 250,00");
| ^
144 | } else {
145 | await purchaseVehicleAssertion.assertPriceFormat(priceField, expectedFormattedPrice);
146 | }

@kLjubomir
Copy link
Author

kLjubomir commented May 17, 2023

After some debugging it looks like .inputValue() returns a different whitespace charCode.

If a whitespace is obtained using .inputValue() it's charCode will be 160 (or a Non-Breaking Space)
Unicode representation: U+00A0
HTML entity:  

while a charCode in a regular string within a program is usually charCode 32.
Unicode representation: U+0020
HTML entity:   or simply a regular space character

This causes inconsistencies if ever an input from the web is fetched with .inputValue() to be used in further comparison operations, be it JavaScripts default equal operators or any sort of assertions.

Proposed solution to the bug:
Make the whitespace that is returned from .inputValue() action be a regular space character or charCode 32 instead of a nbsp with charCode 160 so the value that is obtained in this way can be compared.

@dgozman
Copy link
Contributor

dgozman commented May 22, 2023

@kLjubomir I tried to reproduce this, but was not able to, unfortunately. Could you please share the repro that we can run locally, including the page you are testing?

I tried various <input> fields with emulating locale to "fr-Fr" and/or changing my computer's locale, but was not able to reproduce the issue. I suspect this may be specific to your particular web page.

@kLjubomir
Copy link
Author

So the locale on the page yields:
console.log(navigator.languages);
['en-US', 'en']

I don't think that the nested HTML will tell you much, but I can say that the page is coded in Angular, will still attach the element as an example below.

I have tried using .inputValue() on google's textarea element and confirmed that the whitespace returned is a regular whitespace, so I'm really not sure why on the page I'm working on it was returned as a nbsp, maybe it really could be due to the way that the page is coded, so I am not sure what to do with this information, I used normalization in these cases where it was required, but is it possible for me to locally overwrite playwrights inputValue function, so I could code in my regex to regulate the whitespace charCode?

for keeping the business secret reasons I can not provide more information like page's domain and credentials etc.

<div _ngcontent-yex-c327="" ngclass.lt-mv="mobile" class="content-box"><vpfa-number-field _ngcontent-yex-c752="" fcname="askingPrice" fieldwidth="100%" _nghost-yex-c281=""><vpfa-field-container _ngcontent-yex-c281="" _nghost-yex-c274=""><vpfa-field-validation-container _ngcontent-yex-c274="" _nghost-yex-c273=""><div _ngcontent-yex-c273="" class="field-validation-container"><div _ngcontent-yex-c273="" vpfagetclientboundingrect="" class="currency"><nz-form-control _ngcontent-yex-c274="" class="ng-tns-c253-963 ant-form-item-control ant-col ng-star-inserted"><div class="ant-form-item-control-input ng-tns-c253-963"><div class="ant-form-item-control-input-content ng-tns-c253-963" style="flex-direction: row; box-sizing: border-box; display: flex;"><nz-input-group _ngcontent-yex-c281="" class="ng-tns-c253-963 ant-input-affix-wrapper ant-input-affix-wrapper-sm" style="flex: 1 1 100%; box-sizing: border-box; max-width: 100%;"><span nz-input-group-slot="" type="prefix" class="ant-input-prefix ng-star-inserted"><!----><vpfa-active-currency _ngcontent-yex-c281="" _nghost-yex-c280="" class="ng-star-inserted"><span _ngcontent-yex-c280="" class="input-hint-mode ng-star-inserted"> € <!----><!----><!----></span><!----></vpfa-active-currency><!----><!----><!----></span><!----><input _ngcontent-yex-c281="" nz-input="" type="text" vpfacharcountlimiter="" vpfanumberformatter="" class="ant-input ng-untouched ng-dirty ng-valid ant-input-sm ng-star-inserted currency-symbol" placeholder=""><!----><!----><!----><!----><!----><!----><!----><!----></nz-input-group></div><span class="ant-form-item-children-icon ng-tns-c253-963"><!----></span></div><!----><!----></nz-form-control></div><div _ngcontent-yex-c273="" nz-popover="" nzpopovertrigger="focus" class="error-sign" hidden="" style="top: 3px; right: -25px;"><!----></div><!----></div></vpfa-field-validation-container></vpfa-field-container><!----><!----></vpfa-number-field><!----></div>

@dgozman
Copy link
Contributor

dgozman commented May 24, 2023

@kLjubomir I agree this is most likely page-specific.

is it possible for me to locally overwrite playwrights inputValue function

That's not possible. I'd recommend creating a helper function that you call instead of inputValue():

export function getInputValue(locator) {
  const value = await locator.inputValue();
  return value.replace(...);
}

That said, we can probably add an option to expect(locator).toHaveValue(), something like normalizeWhiteSpace or similar. Let's use this issue to track this feature request.

@dgozman dgozman changed the title [BUG] inputValue asserted as not equal to identical text in the presence of a whitespace [Feature] add option to normalize whitespace to expect().toHaveValue() May 24, 2023
@farukyucel5
Copy link

farukyucel5 commented Jul 1, 2023

Playwright Version: [v1.35.1]
Operating System: [Windows 11]
Browser: [Chromium]

In case one of them has an extra whitespace, when two distinct texts are asserted by the method "toHaveText", it does not throw an error and the test passes.

The text of the web element ="Book Store Application"
await expect(page.getByText("Book Store Application")).toHaveText("Book Store Application"); //it is supported to pass and it passes
await expect(page.getByText("Book Store Application")).toHaveText(" Book Store Application"); //but it is not expexted to pass but it passes as well :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants