How to construct the By.xpath method for customized locators? - selenium

I'm trying to use the By method for the setting of variables in my page object class. One of my scenario requires the table to loop with customized value based on user input.
So I had to write customized xpath. But when trying to write to fit into the By method i'm stuck on how to handle the iteration number. For example the below shows my locator:
By test = By.xpath("//thead/tr[1]/th[" + i + "]"));
It shows error for the "i" value in the declaration, even if int i ; is declared.
Please let me know how to handle this.

As the variable i is of type integer, you have to convert it into a string before constructing the effective locator strategy as follows:
By test = By.xpath("//thead/tr[1]/th[" + toString(i) + "]"));

Related

intercept field access to log with bytebuddy

I am trying to log field writes with bytebuddy. After reading some earlier posts, I started using MemberSubstitution and got something going using the following code:
private static Method FIELD_INTERCEPTOR = // reflective reference to interceptFieldWrite
AsmVisitorWrapper VISITOR = MemberSubstitution.relaxed()
.field(ElementMatchers.any())
.onWrite()
.replaceWith(FIELD_INTERCEPTOR)
.on(ElementMatchers.isMethod());
..
public static void interceptFieldWrite(Object object,Object value) {
System.out.println("intercepted field write in object " + object + " , attempt to set value to " + value);
}
..
The part I am struggling with is how to pass a reference to the field for which the access is intercepted to interceptFieldWrite (as string or instance of Field). If possible I would of course like to avoid reflection completely. I don't actually want to completely substitute field access, but just want to add a method with some checks just before it takes place. Is there a feature in bytebuddy to do this, or do I have to use something more low-level than ASM to achieve this ?
Byte Buddy offers this but you will have to compose your own StackManipulations to do so. The mechanism in MemberSubstitution is called replaceWithChain. Here you specify Steps where each step can do what you intend:
invoke a method via MethodInvocation.
write a field via FieldAccessor.
You will have to load the arguments to the method call and the field access prior to using the above stack manipulations via the MethodVariableAccess where the targeted element's offsets are represented by offsets.
In your case, this would require to read the target instance via
MethodVaribaleAccess.of(parameters.get(0)).loadFrom(offsets.get(0));
MethodVaribaleAccess.of(parameters.get(1)).loadFrom(offsets.get(1));
and the to execute the method or field write in question. The targeted field will be passed as target, you can cast it to FieldDescription if you only ever intercept fields.
Make sure you only intercept non-static fields where the this instance will not be passed.

Can you build an expression inside of a custom code function in Report Builder?

I need to provide my RDL files to teammates so that they can make minor customizations for each client. One of the ways I thought I might improve the efficiency is if I could build more complex expressions inside of custom code functions so that they can input some simple arguments and have the function handle the "heavy lifting" of adjusting the expression accordingly.
This is a very simple example, and not one I would take this step for, but I thought it the easiest place to start figuring out if I can make this work. For instance, in a tablix we want a count returned based on a value where the value is customized per client (and isn't a parameter).
=Count(iif(trim(Fields!Category.Value)="OPTIONA",1,nothing))
Is there a way I could build a function so that my teammates would just need to enter the following?
=Code.CustomFunction("OPTIONA")
My understanding is that the custom code in Report Builder can't query datasets, or at least not in the way that an expression within a tablix would be able to. I've built custom functions that work with the results of an expression added as the argument, but I can't seem to wrap my head around if there's a way to construct an expression within a custom function and pass it back to the expression.
For instance:
Public Function CustomFunction(field As String) As String
Dim customExpression As String = "Count(iif(trim(Fields!Category.Value)=" & field & ",1,nothing))"
Return customExpression
End Function
As expected, this just returns a string with the text of the expression, but not an executed expression. Is what I'm trying to achieve possible with Report Builder?
Or, as an alternative approach, can I somehow place variables at the beginning of an expression that are used later so that anyone else working on the expression just needs to worry about the beginning? Essentially create multiple custom functions and call them later on?
=Code.CustomFunction("OPTIONA",Count(iif(trim(Fields!Category.Value)=Code.CustFunc01(),1,nothing)))
Honestly not sure how I would go about building the functions themselves from here.
You can use a function instead of the related field. The function takes the field string as an argument and the filter string for which will increase the counter. Finally it returns the original field value
Private Dim Counter As Integer
Public Function SetCounter( Expr As String, Filter As String) As String
If Expr = Filter Then Counter = Counter + 1
Return Expr
End Function
Public Function GetCounter( ) As Integer
Return Counter
End Function
For the field value you can use the following expression (yellow color)
=Code.SetCounter( Fields!MyString.Value,"OPTION A")
To get the counter value you can either use the following expression calling a function (orange color)
= Code.GetCounter()
Or make the variable public and use Code.Counter as the expression

Error 500 while trying to set a variable in Jmeter

I tried to create a variable in groovy and Jmeter.
I want it to be the counter of a while loop that I am planning to run.
I want in each iteration to add 1 to this counter.
the problem is that I can not set it to be variable, that I could use later in the program in another sampler.
int while_counter = 0;
vars.put("while_counter",0);
System.out.println("Loop Counter");
I just want to create an integer that will be a counter and all the sampler will know, and can address him ${while_counter}.
and to perform while_counter = while_counter++
what I am missing
Response code: 500
Response message: javax.script.ScriptException: javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: org.apache.jmeter.threads.JMeterVariables.put() is applicable for argument types: (java.lang.String, java.lang.Integer) values: [while_counter, 0]
Possible solutions: put(java.lang.String, java.lang.String), get(java.lang.String), putAt(java.lang.String, java.lang.Object), wait(), any(), dump()
Can someone please advise how to create a simple while loop in Jmeter
and to add 1 to counter
Define variable "i" as 0/1 at start of Test Plan in User Defined Variable/User Parameters
While loop condition:
${__groovy(vars["i"].toInteger() < 5)}
Inside loop add your JSR223 Sampler/Preprocessor with increment it:
String i = vars.get("i");
int counter = Integer.parseInt(i);
counter++;
vars.put("i", "" + counter);
Don't use Javascript function as it doesn't scale as well as Groovy
It is recommended to avoid scripting where possible so:
If you are running an "internal" loop driven by Loop Controller or While Controller it makes sense to add a Counter test element which will generate an incrementing number each time it will be called. You will be able to refer counter's current value using "normal" JMeter variable defined in the counter's "Reference Name" section
For Thread Group level iterations you can use __iterationNum() function
With regards to your question itself, you cannot pass an integer to vars.put() method if you need to store an integer in JMeter Variables you should go for vars.putObject() method instead.

Passing parameters in #FindBy Page factory

Is there any way so that we can parameterize the string which we pass to create a page object using a page factory?
ex:
String v = "password";
#FindBy(name=v)
private WebElementFacade password_Field;
I am trying to push the string v into the #FindBy but I am getting an error.
I am getting
The value for annotation attribute FindBy.name must be a constant expression.
Yes. It is possible. Please find the solution below:
In your Page, instead of using #FindBy, get the WebElementFacade using find method of the Page and then use it for operations.
For example: If you need to click on an element, please see the code below:
public void click(String elementId) {
WebElementFacade element = find(ById.id(elementId));
element.click();
}
This works perfectly for me. And the element id is coming all the way from .story examples.
No, Unfortunately, it's not possible to send arguments to annotation (reference). Since Java annotations does not allow dynamic parameterization. The compiler evaluates annotation metadata at compile time. So, it must be present. Though there are work around for this.
Check this- Java Annotations values provided in dynamic manner

Can I use e.parameter in conjunction with a global variable to retrieve an external variable in Google Apps Scripts?

I realize the question is confusing. I'm trying to reference many widgets that were created in the main loop of my script from a secondary function using e.parameter.
Instead of referencing each e.parameter separately, by its name, I'd like to be able to make one reference to e.parameter and have the parameter name portion be a globally defined variable.
As in:
e.parameter.some_id
Would be the same as:
var test=[]
test[0]='some_id'
e.parameter.(test[0])
Or some other syntax. I'm trying to reference the parameters in a loop, and using the array means I can increment a for loop counter instead doing if tests for each parameter individually.
I'm certain there's an easier way to do this, but I'm still new to java.
Use e.parameter[test[0]] . It is not java but JavaScript