Camunda: Test whether JSON array contains an element - bpmn

I would like a conditional flow to depend on whether a JSON attribute (containing a JSON array of strings) contains a specific element.
The following expression works if the element is present, but throws an exception if it is not:
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">
${ json_array.indexOf("foo")!=-1 }
</bpmn:conditionExpression>
The equivalent expression with lastIndexOf() also fails despite the documentation claiming that should not happen (issue 134).
Is there another way to do this?

This works, but seems rather clunky:
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">
${ json_array.toString().contains("\"foo\"") }
</bpmn:conditionExpression>
I hope there is a better way.

Related

For the W3C WebDriver "Find Element From Element" command, how does one format the element ID in request URL?

I'm learning how a WebDriver works, and I don't understand how to format the request URL for Find Element From Element.
The element ID of Find Element will return something like this:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
As I understand it, the above {key: value} format IS the element ID. If that is the case, how does one user that as the {element id} in "POST /session/{session id}/element/{element id}/element"? If {key: value} IS NOT the element ID, what is? And what would a properly formatted request URL look like?
Thanks!
In the above example, the element ID is "e72b0320-5d61-4886-b903-5b2e4bb43d88". It's a bit confusing because rather than creating an object that looks like this:
{"ELEMENT": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
We have the very odd:
{"element-6066-11e4-a52e-4f735466cecf": "e72b0320-5d61-4886-b903-5b2e4bb43d88"}
What's going on here? It has been deemed from on high that the key which in a JSON object indicates that we are dealing with an element ID is the arbitrary and constant string "element-6066-11e4-a52e-4f735466cecf". The reason is that any non-arbitrary key might end up being a return value of some unrelated JavaScript code. Consider this JavaScript code:
return document.getElementById('foo');
This could be used in ExecuteScript as follows (for example in Python):
driver.execute_script("return document.getElementById('foo');");
What should be returned here? Well we are dealing with an actual HTML element, which can't be converted into JSON and sent back over the wire to the Python client. So instead, WebDriver stores a reference to that element as an ID, and sends that back. But it can't just send back the ID as a string, because there's no way for driver.execute_script to know in advance what sort of thing might be returned. Maybe it's not an element ID--maybe it's some other string related to your application. In the past, the standard format for a JSON WebElement was as I noted above (with the ELEMENT key).
At some point, however, someone must have written some JavaScript code which resulted in a JS object which contained the word ELEMENT as key somewhere inside. This object had nothing to do with WebElements, but when it was returned via a call to driver.execute_script, the client converted it into a WebElement object!
Whether or not this scenario ever actually happened is beside the point; the point is that a simple short word like ELEMENT is ripe for name clashes. The spec authors wanted a way to unambiguously denote that we are dealing with a WebElement even if we encounter it in a serialized JSON format, and in a way that is not likely to clash with other things web developers or testers are doing.
So the most direct answer to your question is, your POST request should look like:
POST /session/{session id}/element/e72b0320-5d61-4886-b903-5b2e4bb43d88/element

hapijs - route config 'id' attribute - won't accept string value

I'm not sure if this is a bug or not, so I'm asking here, rather than submitting a bug report.
In the documentation for the latest version of hapijs (16.1.1)
https://hapijs.com/api#serverlookupid
For server.lookup, it clearly indicates that an 'id' property can be a string.
const route = server.lookup('root');
However strings are expressively forbidden by the actual implementation code.
https://github.com/hapijs/hapi/blob/master/lib/connection.js#L340
Hoek.assert(id && typeof id === 'string', 'Invalid route id:', id);
Am I missing something here? Is this a bug, or an error in the documentation, or am I simply misunderstanding something?
It seems an strange limitation to impose. Strings are a lot more logical for a route id.
The other issue, is that in the index.d.ts, it specifically forces the use of a string parameter.
This functionality just seems completely broken. How am I supposed to use it, if when creating a route I need to use a numeric id, and then when trying to retrieve it I'm forced to use a string?
You are reading the assert backwards. The error message only displays if the assertion fails. If an id is provided it can only be of type string.

When i use Assert.assertFalse(), to check the absence of an element, my scripts are getting failed

Assert.assertFalse(driver.findElement(By.xpath("element's xpath")).isDisplayed(),
"Bug!! The element is appeared");
When i run my code with the above script, my scripts are failing with the statement like "can't find the element, (Which is mentioned int he element's xpath)"
Now what i have to do? My notion is to verify the element is not present in the screen
findElement throws an exception if no matching element is found, so you tests will fail with the selenium exception, not JUnit.
you can use findElements (which doesn't throws exceptions) and check that the returned list length is equals to 0
See details in the Selenium documentation
I see that this has been asked a long while ago, but perhaps someone who is looking for a solution to the similar problem will find it useful now.
I have a certain way to deal with such problems, not sure if it's a good way to do this, but at least it makes sense and does the job.
Firstly, I usually define a separate method for finding such elements:
private static WebElement element = null;
public static WebElement findYourElement(WebDriver driver) {
try {
element = driver.findElement(By.xpath("your_xpath_here"));
}
catch(NoSuchElementException e) {
System.out.println(e.getMessage());
element = null;
return element;
}
return element;
}
You can see here that the possible NoSuchElementException is being caught should it be thrown. In case of exception, the value for "element" is also set to null, since in my program there might be values from previous elements stored here and we don't to have any other non-relevant elements here.
Next comes the assertion:
Assert.assertFalse(findYourElement != null, "Bug!! The element is there!"
Here the assertFalse method fails if the element returned by the findYourElement is not empty, yielding a True result from element != null comparison and making assertFalse fail, as it is expecting to have a false value in order to continue.
You could just as well go:
Assert.assertTrue(findYourElement = null, "Bug!! The element is there!"
I think that such solution helps to keep things well organized, but on the other hand it may be larger in terms of code volume and more complicated too. It also depends how good are you with Java and if you are willing to mess with the exceptions.
I am no Java guru myself, so any contribution towards improving my current solution will be much appreciated!
Do this small change, it definitely works
Assert.assertTrue(driver.findElements(By.xpath("element's xpath")).size()<1;,
"Bug!! The element is appeared");

Why does Javassist insist on looking for a default annotation value when one is explicitly specified?

I am using Javassist to add and modify annotations on a package-info "class".
In some cases, I need to deal with the following edge case. Someone has (incorrectly) specified an #XmlJavaTypeAdapters annotation on the package-info package, but has not supplied a value attribute (which is defined as being required). So it looks like this:
#XmlJavaTypeAdapters // XXX incorrect; value() is required, but javac has no problem
package com.foobar;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
In Javassist, this comes through slightly oddly.
The javassist.bytecode.annotation.Annotation representing the #XmlJavaTypeAdapters annotation does not have a member value (getMemberValue("value") returns null), as expected.
It is of course possible to add a value() member value, and that is what I've done:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(new AnnotationMemberValue(constantPool), constantPool);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
In the code snippet above, I've created a new member value to hold an array of annotations, because the value() attribute of #XmlJavaTypeAdapters is an array of #XmlJavaTypeAdapter. I've specified its array type by trying to divine the Zen-like documentation's intent—it seems that if you supply another MemberValue that this MemberValue will somehow serve as the array's type. In my case I want the type of the array to be #XmlJavaTypeAdapter, which is an annotation, so the only kind of MemberValue that seemed appropriate was AnnotationMemberValue. So I've created an empty one of those and set it as the array type.
This works fine as far as it goes, as long as you stay "within" Javassist.
However, something seems to have gone wrong. If I ask Javassist to convert all of its proprietary annotations into genuine Java java.lang.annotation.Annotations, then when I try to access the value() attribute of this #XmlJavaTypeAdapters annotation, Javassist tells me that there is no default value. Huh?
In other words, that's fine—indeed there is not—but I have specified what I had hoped was a zero-length array (that is, the default value shouldn't be used; my explicitly specified zero-length array should be used instead):
final List<Object> annotations = java.util.Arrays.asList(packageInfoClass.getAnnotations());
for (final Object a : annotations) {
System.out.println("*** class annotation: " + a); // OK; one of these is #XmlJavaTypeAdapters
System.out.println(" ...of type: " + a.getClass()); // OK; resolves to XmlJavaTypeAdapters
System.out.println(" ...assignable to java.lang.annotation.Annotation? " + java.lang.annotation.Annotation.class.isInstance(a)); // OK; returns true
if (a instanceof XmlJavaTypeAdapters) {
final XmlJavaTypeAdapters x = (XmlJavaTypeAdapters)a;
System.out.println(" ...value: " + java.util.Arrays.asList(x.value())); // XXX x.value() throws an exception
}
}
So why is Javassist looking for a default value in this case?
My larger issue is of course to handle this (unfortunately somewhat common) case where #XmlJavaTypeAdapters is specified with no further information on it. I need to add a value member value that can hold an array of #XmlJavaTypeAdapter annotations. I can't seem to figure out how to accomplish this with Javassist. As always, all help appreciated.
For posterity, it appears that in this particular case (to avoid a NullPointerException and/or a RuntimeException), you need to do this:
if (adaptersAnnotation.getMemberValue("value") == null) {
final ArrayMemberValue amv = new ArrayMemberValue(constantPool);
amv.setValue(new AnnotationMemberValue[0]);
adaptersAnnotation.addMemberValue("value", amv);
annotationsAttribute.addAnnotation(adaptersAnnotation);
}
Note in particular that I deliberately omit the array type when building the ArrayMemberValue (including one of any kind will result in an exception). Then I explicitly set its value to an empty array of type AnnotationMemberValue. Any other combination here will result in an exception.
Additionally, and very oddly, the last line in that if block is critical. Even though in this particular case the annotation itself was found, and so hence was already present in the AnnotationsAttribute, you must re-add it. If you do not, you will get a RuntimeException complaining about the lack of a default value.
I hope this helps other Javassist hackers.

Is it meaningful to verifyText() on an element that has just had type() executed on it?

I'm curious about whether the following functional test is possible. I'm working with PHPUnit_Extensions_SeleniumTestCase with Selenium-RC here, but the principle (I think) should apply everywhere.
Suppose I execute the following command on a particular div:
function testInput() {
$locator = $this->get_magic_locator(); // for the sake of abstraction
$this->type( $locator, "Beatles" ); // Selenium API call
$this->verifyText( $locator, "Beatles" ); // Selenium API call
}
Conceptually, I feel that this test should work. I'm entering data into a particular field, and I simply want to verify that the text now exists as entered.
However, the results of my test (the verifyText assertion fails) suggest that the content of the $locator element are empty, even after input.
There was 1 failure:
1) test::testInput
Failed asserting that <string:> matches PCRE pattern "/Beatles/".`
Has anyone else tried anything like this? Should it work? Am I making a simple mistake?
You should use verifyValue(locator,texttoverify) rather than verifyText(locator,value) for validating the textbox values
To answer your initial question ("Is it meaningful ..."), well, maybe. What you're testing at that point is the browser's ability to respond to keystrokes, which would be sort of lame. Unless you've got some JavaScript code wired to some of the field's properties, in which case it might be sort of important.
Standard programmer's answer - "It depends".