How to remove whitespace from a string in Cypress

Viewed 11795

I'm trying to remove a whitespace from a numerical value representing money.

For example, I want 1 000 kr to be 1000. This is the same case for when the currency is 10 000

I'm using this function to remove the kr but when I try to add another .replace it does not work:

Cypress.Commands.add('currency', (selector) => {
      cy.get(selector)
        .children()
        .eq(1)
        .invoke('text') // get text
        .then((text) => +text.replace('kr', '').trim());
    });

How would I add another .replace to remove the extra spacing from the numerical value? enter image description here

4 Answers

This should work:

function formatString(text) {
    return text.replace('kr', '').replace('\u00A0','').trim();
}

Cypress.Commands.add('currency', (selector) => {
      cy.get(selector)
        .children()
        .eq(1)
        .invoke('text') // get text
        .then(formatString)
    });

But you can also use Cypress to achieve this using a regex string (the first example in this Cypress FAQ is like yours):

Cypress.Commands.add('currency', (selector) => {
      cy.get(selector)
        .should('have.text', '\d+[\u00A0]*')
    });

You can test out the regex here: https://regex101.com/r/YC4szy/1. It will match strings with a number, followed by a blank space, and any subsequent characters. You can get fancy with the regex to test what you want.

My last suggestion, if matching regex patterns doesn't help, is that you can wrap your cypress command in a function that takes text content as an argument, which you pass into the should('have.text', ...) line.

  is a non breaking space which isn't the same as a "regular" breaking space:

const read = sel => document.querySelector(sel).textContent;

console.log(read('div') === '1 000 kr'); // false!
<div>1&nbsp;000 kr</div>

These two whitespace characters actually have different ascii code:

const read = sel => document.querySelector(sel).textContent;
const strencode = str => [...str].map(c => c.charCodeAt(0)).join('\t');

console.log(strencode('1 000 kr'));
console.log(strencode(read('div')));
<div>1&nbsp;000 kr</div>

See how the second characters differ?

You can normalise the strings with String#normalize:

const read = sel => document.querySelector(sel).textContent;

console.log(read('div').normalize('NFKC') === '1 000 kr')
<div>1&nbsp;000 kr</div>

So here's one possible answer to your question:

  1. Normalize your string
  2. Remove all spaces (ascii 32) characters with / /g
  3. Remove 'kr' at the end

const read = sel => document.querySelector(sel).textContent;
const clean = str => str.normalize('NFKC').replace(/ /g, '').replace(/kr$/, '');

console.log(clean(read('#div1')));
console.log(clean(read('#div2')));
<div id="div1">1&nbsp;000 kr</div>
<div id="div2">10&nbsp;000</div>

Please see How is a non-breaking space represented in a JavaScript string?

When doing .text(), all HTML entities are decoded to their character values.

Instead of comparing using the entity, compare using the actual raw character

if (x == '\xa0') { // Non-breakable space is char 0xa0 (160 dec)

This would be the expression you are looking for

+text.replace('kr', '')  
  .replace('\xa0', '')
  .trim()

Tested with

<div>1&nbsp;100 kr</div>

To illustrate the idea from @evolutionxbox, you can use a regex on element.innerText to replace non-breaking spaces.

Cypress.Commands.add('currency', (selector) => {
  cy.get(selector)   
    .children()
    .eq(1) 
    .then($el => +$el[0].innerText.replace(/\s/g, '').replace('kr', '') )
})
Related