Can anyone plz explain me how to verify the data in HTML table using WebDriver?
HTML is like below..I need to verify the values xyz, abcd, 1234, 5678 on the webpage
<table>
<tr>
<td>xyz</td>
<td>abcd</td>
</tr>
<tr>
<td>1234</td>
<td>5678</td>
</tr>
</table>
Thanks in Advance!!
mra.
Keeping in mind your excerpt from the question:
I need to verify the values xyz, abcd, 1234, 5678 on the webpage
I suggest you try to identify these values using locators and then asserting/verifying the same.
In this example I have used XPath ( a bit verbose for clarity)as the locating strategy.Hope this helps.
try {
assertEquals("xyz", driver.findElement(By.xpath("//table//tr[1]/td[1]")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
try {
assertEquals("abcd", driver.findElement(By.xpath("//table//tr[1]/td[2]")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
try {
assertEquals("1234", driver.findElement(By.xpath("//table//tr[2]/td[1]")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
try {
assertEquals("5678", driver.findElement(By.xpath("//table//tr[2]/td[2]")).getText());
} catch (Error e) {
verificationErrors.append(e.toString());
}
Your approach will depend on whether that table will only ever contain 2 rows and 2 columns. Will the rows and columns always exist in the same order? If not then the xcode example provider before will work, if not you might need to be a bit more creative.
One approach that I've used before to crawl through a table is similar to this.
Define a WebElement that represents your table.
WebElement yourTable = driver.findElement(By.tagname("table"));
Next create a List of WebElements that represent each row in the table.
List<WebElement> tableRows = yourTable.findElements(By.tagname("tr");
Finally, you can loop through the rows of the table until you find the data you are looking for.
for(int i=0; i<tableRows.size(); i++){
WebElement row = tableRows.get(i);
now do whatever you want with your WebElement that represents a single row of the table;
}
Hope this helps.
Related
I have some Couchbase data in the following format
{
"id": "12343",
"transaction": {
"2018-01-11": 10,
"2017-12-01" : 20
},
"_type": "TransactionData"
}
I would like to get the ids whose transaction list contains key older than a given date ( for example, this object would not be retrieved for a value of "2017-11-01", but it does for "2017-12-12".
I made a view, but I would like to parameterise the date String:
function (doc, meta) {
if (doc._type == 'TransactionData') {
for (var key in doc.transaction) {
//I want to send the String value from java
if (key < "2018-02-21") {
emit(doc.id, null);
break;
}
}
}
}
I tried writing some N1QL query, but my server doesn't allow that, I can't change this configuration.
I don't think I can use the startKey, because I return a map of (id, null) pairs.
How can I filter the ids that have transactions older than a configurable date?
Thanks.
You can do like this:
function (doc, meta) {
if (doc._type == 'TransactionData') {
for (var key in doc.transaction) {
emit(doc.id, null);
}
}
}
user _count for Reduce function, then you can query using
query.range("2018-02-21", {}).reduce(true)
then you can take the value to see how many rows there are
Views are static indexes. Documents are processed once after each change, and any emitted results put into the index. You can't parameterize your function because it isn't rerun for every query. So you can't solve the problem the way you're approaching it. (You can do that with N1QL.)
Typically you solve this by adding a key range filter to your query. Look at the documentation for querying views. There are examples on how to select by date. You'll have to decide how you want to structure the index (view) you create.
Say I have a nested object literal, and I want to display its contents in a table.
If the object is 2 levels deep, I can use:
<table>
<thead>
<tr>
<td>key</td>
<td>value</td>
</tr>
</thead>
<tbody ng-repeat="(key01, value01) in data">
<tr ng-repeat="(key02, value02) in value01">
<td>{{key02}}</td>
<td>{{value02}}</td>
</tr>
</tbody>
</table>
If I have a nested object that is 3 or 4 levels deep, using a similar method how would I display the data in a table? The best I have is from this previously answered question, however I do not want conduct this logic in a controller, as suggested here.
I need a way to nest more than 2 ng-Repeats as seen above since in my application, the key names are variable at data generation.
An example of a 3 level deep nest object:
$scope.someVar = { 'data': {
'A': {
'x':'someValue'
},
'B': {
'y':'anotherValue'
}
}
}
Unfortunately for your stated requirements it's not possible. The table element structure just doesn't have the kind of nesting you want. I know you said you don't want to do this in a controller but that's probably the best way of doing this as a table is a way of representing 2D information, not more.
Also it should be said that if you're putting a lot of data in these nested ngRepeats you're very likely to slow the browser down to an unusable state.
If you really can't do some kind of transformation in the controller (which is easier on the browser as it's done once, instead of every time something changes...) you would have to use div's with table like styling. Try here (link)
u should be doing something like this
$scope.someVar = { 'data': {
'A': {
'x':'someValue'
},
'B': {
'y':'anotherValue'
}
}
then you have to use ng-repeat like this,
<tbody ng-repeat="(key01, value01) in someVar.data">
<tr ng-repeat="(key02, value02) in value01">
At some stage in a concordion test I have, I set a value to some random number.
This value is passed along, and later on , I have some output. The output is "checked" using the concordion "table" setup, where i compare an output value to what I expect it to be.
The problem I have is that I would like to check against the random number mentioned above. When I get the random number, I can set it to something Concordion can store -
<span c:set="#prefixValue">Bob</span>
Well, you get the idea - I replace "Bob" with a getter for my value.
But when I try to use it:
<table c:execute="#actual = getValue(#report, #xpath)">
<tr>
<th>Field name</th>
<th c:assertEquals="#actual">Value</th>
<th c:set="#xpath">Xpath</th>
</tr>
<tr>
<td>UnrelatedValue</td>
<td>SomeDeterminateValue</td>
<td>theXpathForThisToCompareTo</td>
</tr>
<tr>
<td>prefix</td>
<td><span c:echo="#prefixValue" /></td>
<td>differentXpathForThisToCompareTo</td>
</tr>
The whole shebang grinds to a halt, complaining that
"
Commands must be placed on elements when using 'execute' or 'verifyRows' commands on a <table>.
"
How can I use a pre-determined value in a table in Concordion?
The specs aren't supposed to have random elements in them. They're supposed to contain a specific example or set of examples. Rather than using a random number, hardcode a particular value and then you can use it later on.
To tell the fixture about the hardcoded value you can do this:
<span c:execute="setPrefixValue(#TEXT)">Bob</span>
Then in the fixture:
public void setPrefixValue(String prefixValue) {
// TODO: Whatever system configuration you need to do
}
If it isn't actually possible to set the value in your system under test, then use your fixture code to map between the hardcoded value and the actual random value.
public String getValue(String report, String xpath) {
String value = report(report).get(xpath);
if (value.equals(knownRandomValue)) {
return hardcodedValue;
}
return value;
}
Oh Lord! I didn't realise Concordion was going to get all rigid on me.
To fix, I had to alter the Concordion method I was using to be less stupidly rigid.
Following the general ideas here:
http://automatingsoftwaretesting.wordpress.com/2011/05/27/write-your-own-concordion-command-an-example-for-asserting/
I wrote this:
#Override
public void verify(CommandCall commandCall, Evaluator evaluator, ResultRecorder resultRecorder) {
Object expected = evaluator.evaluate(commandCall.getChildren().get(0).getExpression());
Object actual = evaluator.evaluate(commandCall.getExpression());
Element element = setupTheGoshDarnElement(commandCall, expected);
if (actual.equals(expected)) {
resultRecorder.record(Result.SUCCESS);
announceSuccess(element);
} else {
resultRecorder.record(Result.FAILURE);
announceFailure(element, expected.toString(), actual);
}
}
private Element setupTheGoshDarnElement(CommandCall commandCall, Object expected) {
Element e = commandCall.getElement();
e.appendText(expected.toString());
return e;
}
private void announceFailure(Element element, String expected, Object actual) {
listeners.announce().failureReported(new AssertFailureEvent(element, expected, actual));
}
private void announceSuccess(Element element) {
listeners.announce().successReported(new AssertSuccessEvent(element));
}
And so made a new "evaluator" ~ the rest of the evaluator is identical to the AssertEqualsCommand, if you're wondering.
This neatly checks the element and evaluates. Why concordion didn't do this ~ it isn't rocket science at all ~ is beyond me!
NOTE that I still need to use the "expanded table" in my question to get this to work, the short-form table has it's own issues with evaluating inner expressions.
I have this code.I want to have some rows in JSON,to find it Im trying to use criteria. I want render each case as json.
Example: I want the row of my table that have Name:"pepito" .if I put params.nombre, but I want this only this row in JSON how can I do that?
Im trying to do that with findbyNombre(params.nombre) but if I put some if/else with his conditions it doesnt found.
Please,can somebody help me????I have to give my code for a job and Im lost!!!
THANKS!
case "GET":
def criterios=CatalogoJson.createCriteria().list() {
if (params.nombre) {
eq('nombre', params.nombre)
// render CatalogoJson.findByNombre(params.nombre)as JSON
}
if(params.id) {
eq('id', CatalogoJson.findById(params.id))
}
}
render criterios as JSON
break
I might not have got the question correctly as to what is expected. My assumption is that, you would have either of the params (either nombre or the Id or both) available in the request. Based on that assumption you can have the criteria implemented as below. Note:- I used toInteger() as you mentioned the datatype as int, generally ids are Long in conjunction with GORM and Hibernate persistence layer.
def criterios = CatalogoJson.createCriteria().listDistinct {
if(params.id) {
idEq(params.id.toInteger())
}
if (params.nombre) {
eq('nombre', params.nombre)
}
}
render criterios as JSON
UPDATE
Ok let me try this one more time. Again if I have followed you incorrectly, let me know.
The way you are expecting to map url is not RESTful. Instead, there is one best way to implement what you are expecting in the REST service:-
Pleasant way OR I-like-it-this-way
The url mapping should look like
"/catalog/$id?"(resource: 'catalog')
//Controller Action:-
def show(){
def criterios = CatalogoJson.createCriteria().list {
if(params.id) { //check 1
idEq(params.id.toInteger())
} else if(params.name) { //check 2
eq('name', params.name)
} else if(params.year){ //check 3
eq('year', params.year)
} else if(params.others){ //check 4
eq('others', params.others)
} //so on an so forth //Can also use Switch case if you want
}
render criterios as JSON
}
Use case:-
http://mydomain.com/catalog/134 --> should set the id to 134 and check 1 will be evaluated
http://mydomain.com/catalog?name=Pep --> should set the name to Pep and check 2 will be evaluated
http://mydomain.com/catalog?year=1987 --> should set the year to params as 1987 and check 3 will be evaluated
Inference-
Use of named query parameters to itemize your parameters with respect to your need in REST service and domain. If you want to use unnamed parameters then the url mapping would look like:
"/catalog/$id/$name?/$year?/$others?"(resource: 'catalog')
The problem in this approach is that your url should look like
http://mydomain.com/catalog/134
http://mydomain.com/catalog/134/Pep
http://mydomain.com/catalog/134/Pep/1987
Your optional parameters are no more optional. Have a look at Optional Variables in URL mapping
What would be the best way to filter records from a view based on tags in couchbase? I mean I understand that I can extract tags from the documents and use them as the keys using the map functionality in the view. But is there a way to select records from the view based on whether the record's key (which can be multiple values) contains a tag?
Example: I have a transaction that has the following tags (tag 1, tag2, tag3, tag4) and each view record (from the emit function) looks like this
emit ([tag1,tag2,tag3,tag4], null)
What I want to get is all the records that have tag2.
Thanks for any help.
Two suggestions... If the only purpose of the view is to find records with a particular tag, you could simply emit a view row for each tag.
function (doc) {
if (doc.tags) {
for(var idx in doc.tags) {
emit(doc.tags[idx], null);
}
}
}
This map function would give you rows as follows:
{"total_rows":13,"rows":[
{"id":"foo_doc_1","key":"a","value":null},
{"id":"foo_doc_3","key":"a","value":null},
{"id":"foo_doc_1","key":"b","value":null},
{"id":"foo_doc_2","key":"b","value":null},
{"id":"foo_doc_3","key":"b","value":null},
{"id":"foo_doc_1","key":"c","value":null},
{"id":"foo_doc_2","key":"c","value":null},
{"id":"foo_doc_1","key":"d","value":null},
{"id":"foo_doc_4","key":"d","value":null},
{"id":"foo_doc_4","key":"e","value":null}
]
}
When you query by key (e.g., key="a") you'll get the results for that key. If however, your concern is "give me all documents where the second tag is 'xyz'" then you could emit the index as well.
function (doc) {
if (doc.tags) {
for(var idx in doc.tags) {
emit([parseInt(idx), doc.tags[idx]], null);
}
}
}
In this example, the rows would like like:
{"total_rows":13,"rows":[
{"id":"foo_doc_1","key":[0,"a"],"value":null},
{"id":"foo_doc_3","key":[0,"a"],"value":null},
{"id":"foo_doc_2","key":[0,"b"],"value":null},
{"id":"foo_doc_4","key":[0,"d"],"value":null},
{"id":"foo_doc_1","key":[1,"b"],"value":null},
{"id":"foo_doc_3","key":[1,"b"],"value":null},
{"id":"foo_doc_2","key":[1,"c"],"value":null},
{"id":"foo_doc_4","key":[1,"e"],"value":null},
{"id":"foo_doc_1","key":[2,"c"],"value":null},
{"id":"foo_doc_4","key":[2,"f"],"value":null}
]
}
You would then query with an array key to get a key at a particular position (e.g., key=[1, "b"]).