Reputation: 637
Scenario: I have a table where I am trying to iteratively go through each row that matches my expected text and grab a particular column value for that row.
The html looks something like this:
<table class="table">
<tbody>
<tr xpath="1">
<td>
<a href="link">Write</a>
</td>
<td>
123
</td>
<td>
1.0.1.8
</td>
<td>
TargetProduct1
</td>
<td>
</td>
<td>
P1
</td>
<td>
10.0
</td>
<td>
en-US
</td>
<td>
</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>
On that table, my goal is to go through each row and pick any row that has the value of "TargetProduct" and get the fifth column value of that row.
I am using the following Karate command:
* def getProduct = scriptAll('//table//tbody//tr', '_.innerText', function(x){ return x.contains('TargetProduct') })
However, when I do a karate.log on getProduct, I get something like the following:
Write 123 1.0.1.8 TargetProduct1 P1 10.0 en-US
Write 4586 1.0.1.3 TargetProduct5 Test2 10.1 en-US
Write 134 1.0.1.1 TargetProduct0 Four2 10.3 en-US
Write 3 1.0.1.2 TargetProduct2 Boo3 10.1 en-US
Along with many more like it under it (due to each row that matches the criteria).
It looks like primitive data structure, but I am not well versed in JS to know that. However, my goal is to grab the 5th index of each sets of results like above (basically generate a list with just these values: (P1, Test2, Four2, Boo3). What is one way to do that? Historically I have been able to get values using keys (i.e targetJson.result). However, there are no keys in this case to call to.
I have looked over JSON Transforms section of the documentation and I have tried some potential solutions like mapWithKey, however, they have not worked due to the strange data structure.
Please advise.
Upvotes: 1
Views: 165
Reputation: 327
You could return an array from the JavaScript expression, containing a first value for filtering and a second string containing the text from your fifth column.
* def filter = function(x){ return x[0].contains('TargetProduct') }
* def rows = scriptAll('//table//tbody//tr', 'function(e){ return [e.innerText, e.cells[4].innerText] }', filter)
* def fifthCols = map(rows, function(x){ return x[1] })
Upvotes: 1
Reputation: 58088
First, read up on innerText
to see what it does: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText - it just returns a single string, concatenating all child elements.
Suggestion: try to do this in multiple steps:
* def rows = locateAll('//table//tbody//tr')
* def filtered = rows.filter(x => x.text.includes('TargetProduct'))
* def temp = filtered.map(x => x.locateAll('td'))
What I have above is a guess, sorry I don't have time to dig into the details.
Upvotes: 1