1

I was trying to write a test case to verify context on the page.

There are several iterating, the content for a single page could be merged by the solution from: How to use scriptAll to find all the <div> with id or style attributes in Karate

There is one more issue with this scenario - the content has been cut off into multiple pages. There is no button available to go to next page unless pressing Enter key.

Also the only way to identify if it has come to the end of the context is from following section:

<div id="msgList" class="test">
   <table>
      <tbody>
         <tr class="infoText">
            <td class="Type">reminder</td>
            <td class="Text">99  more data to view</td>
            <td class="messageNumber">#12345</td>
         </tr>
      </tbody>
   </table>
   <div id="message" style="display:none;">reminder  more data to view</div>
</div>

It will change as below until coming to the last page:

<div id="msgList" class="test">
   <table>
      <tbody>
         <tr>
            <td class="Type">23456</td>
            <td class="Text">enter your input</td>
         </tr>
      </tbody>
   </table>
   <div id="message" style="display:none;">23456 enter your input</div>
</div>

EDITED: or ('.messageNumber' still displaying - but with different value)

<div id="msgList" class="test">
   <table>
      <tbody>
         <tr>
            <td class="Type">reminder</td>
            <td class="Text">66  no more data to view</td>
            <td class="messageNumber">#98765</td>
         </tr>
      </tbody>
   </table>
   <div id="message" style="display:none;">random text</div>
</div>

Just wondering is there a way to use conditional logic to loop through all pages and merge the content(with solution extracting context from each single page) together for assertion?

The format for each page is exactly the same.

EDITED: Eventually made it work with a js function

    * def allData = []
    * def loopContent =
    """
    function() {
    while (allData) {
        let list = locateAll('form div', x => { let id = x.attribute('id'); return id ? id.startsWith('line1_R') : false });
        let data = list.map(x => x.text.trim());
        let msgText = script('.Text','_.textContent').trim();

    if (msgText != "reminder  more data to view"){
        allData.push(data);
        return allData;
        }

        else if(msgText == "reminder  more data to view){
        allData.push(data);
        input('body', Key.ENTER);
        }

        else{
        karate.fail("Content not being looped properly");
        }
    }
    }

    """

    * def letterContent = loopContent()
    * print letterContent

Many thanks

Jackson
  • 91
  • 1
  • 6

1 Answers1

1

Yes, it may need some experimenting, but please read the description of waitUntil() with function.

Maybe this other answer will give you some hints: https://stackoverflow.com/a/76268570/143475

EDIT: based on the updated question, here is how you could "collect" all the data from the loops:

* def allData = []
* def loopContent =
"""
function() {
    if (!exists('.messageNumber')) {
        let list = locateAll('form div', x => { let id = x.attribute('id'); return id ? id.startsWith('line1_R') : false });
        let data = list.map(x => x.text.trim());
        allData.push(data);
        return true;
    }
    input('body', Key.ENTER);
}
"""
* waitUntil(loopContent)
* print allData

This is possibly going to duplicate all the first few pages, but I think you can improve the routine to only push() the newly loaded rows. That may be tricky.

Do note that there is a helper function to de-duplicate an array:

* def cleaned = karate.distinct(allData)
Peter Thomas
  • 54,465
  • 21
  • 84
  • 248
  • 1
    Hi Peter, much appreciated for the hints. I have tried the waitUntil function and it did loop through all the pages. The only problem now is that it could only print out the content on last page. Could you please suggest how to push the context from each page into the map? I have updated my current code on the original question. Thanks – Jackson May 28 '23 at 11:07
  • @Jackson that looks great. please see my edit and it should get you there, let me know if it works ! – Peter Thomas May 28 '23 at 11:50
  • Hi Peter, thanks for the suggestions. I made a few twists in the logic due to the change in UI behavior (Please see updates in original question). It would loop the function for few times and did push the content into 'allData' array (checked by adding breakpoint). However after 3 times of retry it would always break the loop and error out. Could you please advise what could be the reason and solution for that? Many thanks – Jackson Jun 01 '23 at 10:20
  • @Jackson only suggestion is note that `locate()` always expects a target to exist if it doesn't find it - it will throw a fatal error (and trigger a retry). so maybe you need to think hard about where you use `exists()` instead. your logic to `if (messageNumber != "#12345" || !exists('.messageNumber')) {` is most likely the problem, or the `locate()` just before it – Peter Thomas Jun 01 '23 at 10:37
  • 1
    Hi Peter, unfortunately I couldn't find a distinct element on last page. So instead i used a js function to verify the (.'Text') field since it was always being displayed - and it did work (please see the update). The suggestion of locateAll() and map function really helped a lot. Thanks so much for pointing out the direction. – Jackson Jun 06 '23 at 10:48