So I am using RestAssured to test some endpoints and pulling the test result into an Allure report.
I am currently trying to fill the report with useful information about each test case, like the endopoint pinged.
To extract the url I tried using the following:
RequestSpecification requestSpec = RestAssured.given().spec(Request.getRequestSpecification());
QueryableRequestSpecification queryRequest = SpecificationQuerier.query(requestSpec);
String retrieveURI = queryRequest.getBaseUri();
System.out.println("Base URI is : "+retrieveURI);
String retrievePath = queryRequest.getBasePath();
System.out.println("Base PATH is : "+retrievePath);
where the Request.getRequestSpecification() returns a RequestSpecification build with RequestSpecBuilder .
the thing is my basePath is something like /info/{unitId}/something the value here is filled with a pathParameter once built. but the block
String retrievePath = queryRequest.getBasePath();
System.out.println("Base PATH is : "+retrievePath);
returns my basepath with {unitId} in it instead of the actual path parameter passed.
Is there a way to extract the basePath of a RestAssured request with the pathParameter within it ?
note, I know there is .log().uri() but this outputs the info in the counsole and I need it in a variable to send it to the Allure report.
To anyone this might help, QueryableRequestSpecification actually has a .getURI() method that wil essentially return the full uri with the pathParameters in it :
RequestSpecification requestSpec = RestAssured.given().spec(Request.getRequestSpecification());
QueryableRequestSpecification queryRequest = SpecificationQuerier.query(requestSpec);
String retrieveURI = queryRequest.getURI()
System.out.println("Full URI is : "+retrieveURI);
I use intelliJ on windows and for some reason the method was showing up red in my IDE
point of reference https://javadoc.io/doc/io.rest-assured/rest-assured/3.1.1/io/restassured/specification/QueryableRequestSpecification.html#getURI--
Related
I want to store a randomized integer that has been called out in the request body and store it in test case Property so that it can be passed as a body parameter in the next request.
for example:
Request1:
id_num = randomNumeric(10)
Properties:
id_num = 1234567890
Request2:
trfered_IDNum = ${#TestCase#id_num}
The Structure looks like below,
Project
|---TestSuite
|-------TestCase
|------RestRequestTestStep1
|------RestRequestTestStep2
|------GroovyScript
Let's start with some assumptions.
RestRequestTestStep1 Response Body has below fields :
{"Resp1Field1Key":"Resp1Field1Value",
"Resp1Field2Key":"Resp1Field2Value"}
RestRequestTestStep2 Request Body has below fields :
{"Resp2Field1Key":"Resp2Field1Value",
"Resp2Field2Key":"Resp2Field2Value"}
Resp1Field1Value and Resp1Field2Value from first response will be substituted to Resp2Field1Value and Resp2Field2Value of second request.
RestRequestTestStep2 body should be as below as we will be substituting values from the testCase Property that will be set in the groovy script once first request is completed.
{
"Resp2Field1Key":"${#TestCase#Resp2Field1Value}",
"Resp2Field2Key":"${#TestCase#Resp2Field2Value}"
}
The Code..rather Script : The groovy script can be placed under the same Test Case and should do below,
import groovy.json.JsonSlurper
//Substitute with appropriate testSuiteName,testCaseName,testStepName1 and testStepName1 as per the Project Structure you have.
def testSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("testSuiteName")
def testCase = testSuite.getTestCaseByName("testCaseName")
def testStep1 = testCase.getTestStepByName("testStepName1")
def testStep2 = testCase.getTestStepByName("testStepName2")
// Call the first REST Request
testStep1.run(testRunner, context)
def response = testStep1.testRequest.response.responseContent
def jsonSlurper = new JsonSlurper().parseText(response)
//Assign it to a testCase Property to grab for second Rest Request
if (jsonSlurper.size() > 0) {
testCase.setPropertyValue("Resp1Field1Value",Resp1Field1Value)
testCase.setPropertyValue("Resp1Field2Value",Resp1Field2Value)
);
//Call the second Rest Request
testStep2.run(testRunner, context)
def response = testStep2.testRequest.response.responseContent
def jsonSlurper = new JsonSlurper().parseText(response)
// Perform Validation/assertion as desired
Use these 2 lines in your groovy script before second request in the same test case
def id_num = (new Random().nextInt(100000000)).toString()
testRunner.testCase.setPropertyValue( "id_num", id_num )
log.info id_num
Now since you have saved the value in a testcase properties in a soap step, you can use like below in the next request within same testcase
${#TestCase#id_num}
This way it will automatically replace the value once you run. To see the values replacement in soap UI , you can see the Raw Tab
check this out below.. the value got replaced
I have an url and would like to parse and extract params from it. My implementation is based on the following stackoverflow post
However my url is more complex than the one used in the post above. It looks like this:
https://example.com/cdscontent/login?initialURI=https%3A%2F%2Fexample.com%2Fdashboard%2F%3Fportal%3Dmyportal%26LO%3D4%26contentid%3D10007.786471%26viewmode%3Dcontent%26variant%3D%2Fmyportal%2F
As you can see it has the param initialURI which is (encoded) url itself and the order of the params in it cannot be changed.
When I run org.apache.http.client.utils.URLEncodedUtils#parse it returns
[initialURI=https://example.com/dashboard/?portal=myportal, LO=4, contentid=10007.786471, viewmode=content, variant=/myportal/]
as you can see it parses every param except portal. It is still bound to https://example.com/dashboard/ In other words I am expecting this:
[initialURI=https://example.com/dashboard/, portal=myportal, LO=4, contentid=10007.786471, viewmode=content, variant=/myportal/]
Am I doing here something wrong or do you think that URLEncodedUtils#parse cannot handle this case?
Do you have any alternative to suggest?
Thx a lot!
Unit test to try
public class UrlParserTest {
#Test
public void testParseUrl() throws UnsupportedEncodingException, URISyntaxException {
String url =
"https://www.example.com/cdscontent/login?initialURI=https%3A%2F%2Fwww.example.com%2Fdashboard%2F%3Fportal%3Dmyportal%26LO%3D4%26contentid%3D10007.786471%26viewmode%3Dcontent%26variant%3D%2Fmyportal%2F";
String decoded = URLDecoder.decode(url, "UTF-8");
List<NameValuePair> params = URLEncodedUtils.parse(new URI(decoded), "UTF-8");
System.out.println(params);
}
}
What are we working with
You have the following url (decoded):
https://www.example.com/cdscontent/login?initialURI=https://www.example.com/dashboard/?portal=myportal&LO=4&contentid=10007.786471&viewmode=content&variant=/myportal/
This url consists of the main url:
https://www.example.com/cdscontent/login
which has 1 query parameter initialURI:
https://www.example.com/dashboard/?portal=myportal&LO=4&contentid=10007.786471&viewmode=content&variant=/myportal/
This url has multiple query parameters (the ones you're looking for):
portal=myportal&LO=4&contentid=10007.786471&viewmode=content&variant=/myportal/
Solution
Step 1:
We first must get the url in the query parameter initialURI:
List<NameValuePair> params = URLEncodedUtils.parse(new URI(url), Charset.forName("UTF-8"));
// Find first NameValuePair where the name equals initialURI
Optional<NameValuePair> initialURI = params.stream()
.filter(e -> e.getName().equals("initialURI"))
.findFirst();
System.out.println(initialURI);
This prints:
Optional[initialURI=https://www.example.com/dashboard/?portal=myportal&LO=4&contentid=10007.786471&viewmode=content&variant=/myportal/]
Step 2:
Now we can get the query parameters of this url and print them:
List<NameValuePair> initialParams = URLEncodedUtils
.parse(new URI(initialURI.get().getValue()), Charset.forName("UTF-8"));
System.out.println(initialParams);
This results in:
[portal=myportal, LO=4, contentid=10007.786471, viewmode=content, variant=/myportal/]
Note
This is not entirely your expected behavior, you expected initialURI=https://example.com/dashboard/ to be in the list aswell. However you can see that this is not a query parameter, the entire url in initialURI (with it's query parameters) is the query parameter.
I have recently switched to Spring for consuming REST API calls hosted by ServiceNow.
I am building my URI as below:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUrl.toString());
logger.info("URI before Query Param: " + builder.build().encode().toUri());
builder.queryParam("sysparm_limit", "2000000");
builder.queryParam("sysparm_offset", "0");
builder.queryParam("sysparm_exclude_reference_link", "true");
//this line is the issue because there is a = sign here
builder.queryParam("sysparm_query=user_name", snUser.getUser_name());
logger.info("URI after Query Param: " + builder.build().encode().toUri());
The output of this code is:
INFO: URI before Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user
INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query%3Duser_name=AX0011
The problem is with the final builder.queryParam. I am getting output as this:
sysparm_query%3Duser_name=AX0011
but what I want is:
sysparm_query=user_name=AX0011
So that eventually the final URI looks like this:
INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query=user_name=Z001NR6
So I tried replacing,
builder.queryParam("sysparm_query=user_name", snUser.getUser_name());
by:
builder.query("sysparm_query=user_name=" + snUser.getUser_name());
which changed the original output from:
INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query%3Duser_name=Z001NR6
to:
INFO: URI after Query Param: https://sandbox.service-now.com/api/now/v1/table/sys_user?sysparm_limit=2000000&sysparm_offset=0&sysparm_exclude_reference_link=true&sysparm_query=user_name%3DZ001NR6
Notice how sysparm_query%3Duser_name=Z001NR6 changed to sysparm_query=user_name%3DZ001NR6
Is ther anyway to see a = instead of %3D in the output?
The param looks quite strange - however - you can add it manually using the UriComponentsBuilder#query method:
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl("https://example.com/api/")
.queryParam("param1", "12345")
.queryParam("param2", "abc")
.query("query=username=JOE");
System.out.println(builder.build().toString());
// produces https://example.com/api/?param1=12345¶m2=abc&query=username=JOE
System.out.println(builder.build().encode().toString());
// produces https://example.com/api/?param1=12345¶m2=abc&query=username%3DJOE
Manual concatenation:
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl("https://example.com/api/")
.queryParam("param1", "12345")
.queryParam("param2", "abc");
// the parameter has to be properly url-encoded manually (not shown here)
String uri = builder.build().encode().toString() + "&query=username=JOE";
System.out.println(uri);
// produces: https://example.com/api/?param1=12345¶m2=abc&query=username=JOE
The query component of a URL is frequently used to carry information in key=value pairs; you could think of this as a Map<String, String>. In this case, = and & are special characters that delimit these pairs, and they must be encoded when they form part of the key or the value to ensure that anything reading the query string this way is able to parse it properly.
In your case, how you use the builder depends on how you would want to retrieve your data later on. There are two options:
// Building the URL:
builder.queryParam("sysparm_query=user_name", snUser.getUser_name());
// URL contains ...&sysparm_query%3Duser_name=AX0011
// Reading the parsed query map:
Map<String, String> query = ...
String data = query.get("sysparm_query=user_name");
// value is AX0011
Or
// Building the URL:
builder.queryParam("sysparm_query", "user_name=" + snUser.getUser_name());
// URL contains ...&sysparm_query=user_name%3DAX0011
// Reading the parsed query map:
Map<String, String> query = ...
String value = query.get("sysparm_query");
// value is user_name=AX0011
In a correctly encoded URL, one of the = will always be encoded as %3D. Using a UriComponentsBuilder ensures that your URLs will be correctly encoded and that anything reading your URLs will be able to do so properly without data loss.
I tried using
String userAgent=req.getHeader("user-agent");
and also the following
#GET
#Path("/get")
public Response addUser(#HeaderParam("user-agent") String userAgent) {
return Response.status(200)
.entity("addUser is called, userAgent : " + userAgent)
.build();
}
But I need only, browser name as chrome,firefox,IE.Please help,if anyone know.
UPDATE : Got answer
public String browser(#HeaderParam("user-agent") String userAgent){
UserAgent browserName = UserAgent.parseUserAgentString(userAgent);
String browser=browserName.toString();
System.out.println(browser)
}
Getting information out of user agent strings is somewhat of a black art. Easiest is probably to use a library to parse the user agent string and extract the needed information.
I've used UADetector in the past with good results, but there are undoubtedly other libraries out there.
The following sample is from the UADetector documentation:
UserAgentStringParser parser = UADetectorServiceFactory.getResourceModuleParser();
ReadableUserAgent agent = parser.parse(request.getHeader("User-Agent"));
out.append("You're a <em>");
out.append(agent.getName());
out.append("</em> on <em>");
out.append(agent.getOperatingSystem().getName());
out.append("</em>!");
I'm trying to send a array / list of String to my REST server through Spring RestTemplate.
This is on my android side:
private List<String> articleids = new ArrayList<>();
articleids.add("563e5aeb0eab252dd4368ab7");
articleids.add("563f2dbd9bb0152bb0ea058e");
final String url = "https://10.0.3.2:5000/getsubscribedarticles";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("articleids", articleids);
java.net.URI builtUrl = builder.build().encode().toUri();
Log.e("builtUrl", builtUrl.toString());
The builtUrl is: https://10.0.3.2:5000/getsubscribedarticles?articleids=%5B563e5aeb0eab252dd4368ab7,%20563f2dbd9bb0152bb0ea058e%5D
On the server side:
#RequestMapping(value = "/getsubscribedarticles", method = RequestMethod.GET)
public List<Posts> getSubscribedPostFeed(#RequestParam("articleids") List<String> articleids){
for (String articleid : articleids {
logger.info(" articleid : " + articleid);
}
}
The server logs:
.13:11:35.370 [http-nio-8443-exec-5] INFO c.f.s.i.ServiceGatewayImpl
- articleid : [563e5aeb0eab252dd4368ab7
.13:11:35.370 [http-nio-8443-exec-5] INFO c.f.s.i.ServiceGatewayImpl
- articleid : 563f2dbd9bb0152bb0ea058e]
Which I can see is wrong as the list should not have a '[' on the first item and a ']' on the last item.
I have read this thread How to pass List or String array to getForObject with Spring RestTemplate but it does not actually answer the question.
The selected answer issues out a POST request, but I want to do a GET request , also it requires an additional object to work to hold the list and I would prefer to not create extra objects if I can do it with Spring RestTemplate natively.
Using Java 8, this worked for me :
UriComponentsBuilder builder = fromHttpUrl(url);
builder.queryParam("articleids", String.join(",", articleids));
URI uri = builder.build().encode().toUri();
It forms the URL like:
https://10.0.3.2:5000/getsubscribedarticles?articleids=123,456,789
I would expect that the correct working url is something like:
https://10.0.3.2:5000/getsubscribedarticles?articleids[]=123&articleids[]=456&articleids[]=789
After a quick look at the code of public UriComponentsBuilder queryParam(String name, Object... values), I would solve it by using UriComponentsBuilder this way:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("articleids[]", articleids.toArray(new String[0]));
It is important that, the second parameter is an array but not an Object/Collection!
You did everything correct. You just need to call it without the [].
Just invoke it with .../getsubscribedarticles/articleids=foo,bar,42
I tested this with Spring Boot 1.2.6 and it works like this.
Thanks to dOx for his suggestion - I managed to solve this with the PathVariable - i set the list in my url for android:
final String url = "https://10.0.3.2:5000/getsubscribedarticles/"+new ArrayList<>(articleids);
For my rest server:
#RequestMapping(value = "/getsubscribedarticles/[{articleids}]", method = RequestMethod.GET)
public List<Posts> getSubscribedPostFeed(#PathVariable String[] articleids){
}