Search code examples
javascriptwebdriver-io

Create a Dictionary/Object from a JQuery Response


This JQuery $$('tbody[class="MuiTableBody-root"]')[5].innerText returns

"Subtotal   $0.00
Total   $0.00
Total Price/Unit    $0.00"

There is a new line character after the dollar amount, and there are additional spaces in the string.

How can I insert in/or create a dictionary to store the above response as shown below?

store = { 'Subtotal': $0.00, 'Total': $0.00, 'Total Price/Unit': $0.00" }

DOM:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>

<tbody class="MuiTableBody-root">
  <tr class="MuiTableRow-root">
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Subtotal</td>
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
  </tr>
  <tr class="MuiTableRow-root">
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Total</td>
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
  </tr>
  <tr class="MuiTableRow-root">
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Total Price/Unit</td>
    <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
  </tr>
</tbody>
</table>

I tried the regex on the response. Why is it only matching 2?enter image description here


Solution

  • You can use a regex applied with matchAll() to return an iterator of matches which you can map to an array of [key, value] pairs using Array.from() which can then be passed to Object.fromEntries to yield your final object.

    const response = `Subtotal   $0.00
    Total   $0.00
    Total Price/Unit    $0.00`
    
    const regex = /(.*?)(?=\$)(\$\d+.\d+)(?=[\r|\n]|$)/g;
    
    // return iterator from matchAll() 
    const matchIterator = response.matchAll(regex);
    
    // pass the iterator to Array.from() and use built in map() 
    // to return a [key, value] array with white space removed by trim()
    const keyValueArr = Array.from(matchIterator, ([_, key, value]) => ([key.trim(), value.trim()]));
    
    // pass the array to Object.fromEntries()
    const finalObject = Object.fromEntries(keyValueArr);
    
    // Or all in one call...
    const 
      reg = /(.*?)(?=\$)(\$\d+.\d+)(?=[\r|\n]|$)/g,
      object = Object.fromEntries(
        Array.from(response.matchAll(reg), ([_, key, value]) => ([key.trim(), value.trim()])));
    

    const response = `Subtotal   $0.00
    Total   $0.00
    Total Price/Unit    $0.00`
    
    const 
      reg = /(.*?)(?=\$)(\$\d+.\d+)(?=[\r|\n]|$)/g,
      object = Object.fromEntries(
        Array.from(response.matchAll(reg), ([_, key, value]) => ([key.trim(), value.trim()])));
    
    
    console.log(object);


    Or using DOM traversal

    const 
      rows = document.querySelectorAll('.MuiTableBody-root tr'),
      object = Object.fromEntries(
          [...rows].map(r => [...r.cells].map(c => c.innerText.trim()))
        );
    
    console.log(object);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <table>
    
    <tbody class="MuiTableBody-root">
      <tr class="MuiTableRow-root">
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Subtotal</td>
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
      </tr>
      <tr class="MuiTableRow-root">
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Total</td>
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
      </tr>
      <tr class="MuiTableRow-root">
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">Total Price/Unit</td>
        <td class="MuiTableCell-root jss93 MuiTableCell-body MuiTableCell-alignRight">$0.00</td>
      </tr>
    </tbody>
    </table>