jobProgressToken: Jira (Zephyr) Rest API - rest

I am using Jira (Zephyr) rest calls to create Test Cycle and add Tests cases into it. According to information mentioned here1 if I use this rest call to add tests to Cycle then as a response I will get JobProgressToken. JobProgressToken is nothing but will tell the progress of Test Case addition in Test Cycle.
Now the problem which I am facing is I am not getting any output from this JobProgressToken. I tried firing the GET rest call using the format mentioned but I am getting empty response.
Can somebody please explain how to use this JobProgressToken to get the Progress of my task?
I want to verify that the tests which I added to Cycle are added susccessfully or not?

Just ysterday I had the same issue. ZAPI documentation is really confusing. I found the following solution:
GET request for retrieving a job progress has the following form: http://jira/rest/zapi/latest/execution/jobProgress/0001498157843923-5056b64fdb-0001
where 0001498157843923-5056b64fdb-0001 is a value of the particular jobProgressToken
Right after getting a jobProgressToken as a result of some async operation, my code is waiting for the progress to became 1 (it is groing up from zero to 1)
//get the job progress token as a result of some async operation invocation
String jobProgressToken = new JSONObject(zapiResponse).getString("jobProgressToken");
waitAsyncJobToBeCompleted(jobProgressToken);
void waitAsyncJobToBeCompleted(String jobProgressToken) {
double jobProgress;
do {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
LOG.error("Error while try to make the thread sleeping 500ms. " + e.getLocalizedMessage());
e.printStackTrace();
}
jobProgress = getJobProgress(jobProgressToken);
} while (Double.compare(jobProgress, 1) <0);
private double getJobProgress(String jobProgressToken) {
URI uri = makeUriFromString(String.format(
GET_GetJobProgress, //Get request pattern
connectionParameters.getJiraUrl(),//host
jobProgressToken)); //parameters
HttpResponse response = executeHttpRequestWithResponse(new HttpGet(uri));
String zapiResponse = null;
try {
zapiResponse = EntityUtils.toString(response.getEntity());
LOG.trace("ZAPI RESPONSE: " + zapiResponse);
EntityUtils.consumeQuietly(response.getEntity()); //cleanup the HTTP response
double progress = new JSONObject(zapiResponse).getDouble("progress");
LOG.debug("Job progress: " + progress);
return progress;
} catch (IOException e) {
String err = String.format("Error while getting Zephyr API response: %s",
e.getLocalizedMessage());
LOG.fatal(err);
throw new RestApiException(err, e);
} catch (JSONException e) {
String err = String.format("Error while retrieving the job progress from JSON: %s\n%s",
zapiResponse, e.getLocalizedMessage());
LOG.fatal(err);
throw new RestApiException(err, e);
}
}
This is all magic :)
Following two logs: 1st for cloning test cycle, 2nd for deleting
ZephyrClient.invokeHttpPost - URI=http://jira/rest/zapi/latest/cycle JSON payload={"projectId": "13795","clonedCycleId": 2643,"name": "ZAPI client test","description": "Created With ZAPI client unit test","versionId": "-1"}
ZephyrClient.cloneTestCycle - RESPONSE JSON: {"jobProgressToken":"0001498218783350-5056b64fdb-0001"}
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/execution/jobProgress/0001498218783350-5056b64fdb-0001 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.getJobProgress - ZAPI RESPONSE: {"timeTaken":"0 min, 1 sec","stepMessage":"","summaryMessage":"","errorMessage":"","progress":0.56,"message":"","stepLabel":"","stepMessages":[]}
ZephyrClient.getJobProgress - Job progress: 0.56
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/execution/jobProgress/0001498218783350-5056b64fdb-0001 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.getJobProgress - ZAPI RESPONSE: {"timeTaken":"0 min, 1 sec","stepMessage":"","summaryMessage":"","errorMessage":"","progress":0.98,"message":"","stepLabel":"","stepMessages":[]}
ZephyrClient.getJobProgress - Job progress: 0.98
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/execution/jobProgress/0001498218783350-5056b64fdb-0001 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.getJobProgress - ZAPI RESPONSE: {"timeTaken":"0 min, 2 sec","stepMessage":"","summaryMessage":"","errorMessage":"","progress":0.98,"message":"","stepLabel":"","stepMessages":[]}
ZephyrClient.getJobProgress - Job progress: 0.98
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/execution/jobProgress/0001498218783350-5056b64fdb-0001 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.getJobProgress - ZAPI RESPONSE: {"timeTaken":"0 min, 3 sec","stepMessage":"","summaryMessage":"","errorMessage":"","progress":1.0,"message":"Cycle ZAPI client test created successfully.","stepLabel":"","stepMessages":[]}
ZephyrClient.getJobProgress - Job progress: 1.0
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/cycle?projectId=13795&versionId=-1 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.invokeHttpDelete - URI=http://jira/rest/zapi/latest/cycle/2727
ZephyrClient.deleteTestCycle - RESPONSE JSON: {"jobProgressToken":"0001498218815183-5056b64fdb-0001"}
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/execution/jobProgress/0001498218815183-5056b64fdb-0001 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
ZephyrClient.getJobProgress - ZAPI RESPONSE: {"timeTaken":"0 min, 0 sec","stepMessage":"","summaryMessage":"","errorMessage":"","progress":1.0,"message":"{\"success\":\"Cycle ZAPI client test успешно удален\"}","stepLabel":"","stepMessages":[]}
ZephyrClient.getJobProgress - Job progress: 1.0
ZephyrClient.executeHttpRequestWithResponse - HTTP REQUEST: GET http://jira/rest/zapi/latest/cycle?projectId=13795&versionId=-1 HTTP/1.1
ZephyrClient.executeHttpRequestWithResponse - HTTP RESPONSE: HTTP/1.1 200 OK
P.S. This is not about how it should be done.
This is about how does it work for me ;)

Related

How to check for proper format in my API response

Currently running tests for my REST API which:
takes an endpoint from the user
using that endpoint, grabs info from a server
sends it to another server to be translated
then proceeds to jsonify the data.
I've written a series of automated tests running and I cannot get one to pass - the test that actually identifies the content of the response. I've tried including several variations of what the test is expecting but I feel it's the actual implementation that's the issue. Here's the expected API response from the client request:
{ "name": "random_character", "description": "Translated description of requested character is output here" }
Here is the testing class inside my test_main.py:
class Test_functions(unittest.TestCase):
# checking if response of 200 is returned
def test_healthcheck_PokeAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/")
status_code = response.status_code
self.assertEqual(status_code, 200)
# the status code should be a redirect i.e. 308; so I made a separate test for this
def test_healthcheck_ShakesprAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.status_code, 308)
def test_response_content(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.content_type,
'application/json') <<<< this test is failing
def test_trans_shakespeare_response(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertFalse(b"doth" in response.data)
Traceback:
AssertionError: 'text/html; charset=utf-8' != 'application/json' - text/html; charset=utf-8 + application/json
Any help would be greatly appreciated

RESTful client in Unity - validation error

I have a RESTful server created with ASP.Net and am trying to connect to it with the use of a RESTful client from Unity. GET works perfectly, however I am getting a validation error when sending a POST request. At the same time both GET and POST work when sending requests from Postman.
My Server:
[HttpPost]
public IActionResult Create(User user){
Console.WriteLine("***POST***");
Console.WriteLine(user.Id+", "+user.sex+", "+user.age);
if(!ModelState.IsValid)
return BadRequest(ModelState);
_context.Users.Add(user);
_context.SaveChanges();
return CreatedAtRoute("GetUser", new { id = user.Id }, user);
}
My client:
IEnumerator PostRequest(string uri, User user){
string u = JsonUtility.ToJson(user);
Debug.Log(u);
using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, u)){
webRequest.SetRequestHeader("Content-Type","application/json");
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError || webRequest.isHttpError){
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
else{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
}
}
I was trying both with the Json conversion and writing the string on my own, also with the WWWForm, but the error stays.
The error says that it's an unknown HTTP error. When printing the returned text it says:
"One or more validation errors occurred.","status":400,"traceId":"|b95d39b7-4b773429a8f72b3c.","errors":{"$":["'%' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0."]}}
On the server side it recognizes the correct method and controller, however, it doesn't even get to the first line of the method (Console.WriteLine). Then it says: "Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'".
Here're all of the server side messages:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5001/user application/json 53
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Create", controller = "User"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Create(TheNewestDbConnect.Data.Entities.User) on controller TheNewestDbConnect.Controllers.UserController (TheNewestDbConnect).
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect) in 6.680400000000001ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 11.3971ms 400 application/problem+json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
I have no idea what is happening and how to solve it. Any help will be strongly appreciated!
Turned out I was just missing an upload handler. Adding this line solved it: webRequest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(JsonObject));

Groovy script for Jenkins: execute HTTP request without 3rd party libraries

I need to create a Groovy post build script in Jenkins and I need to make a request without using any 3rd party libraries as those can't be referenced from Jenkins.
I tried something like this:
def connection = new URL( "https://query.yahooapis.com/v1/public/yql?q=" +
URLEncoder.encode(
"select wind from weather.forecast where woeid in " + "(select woeid from geo.places(1) where text='chicago, il')",
'UTF-8' ) )
.openConnection() as HttpURLConnection
// set some headers
connection.setRequestProperty( 'User-Agent', 'groovy-2.4.4' )
connection.setRequestProperty( 'Accept', 'application/json' )
// get the response code - automatically sends the request
println connection.responseCode + ": " + connection.inputStream.text
but I also need to pass a JSON in the POST request and I'm not sure how I can do that. Any suggestion appreciated.
Executing POST request is pretty similar to a GET one, for example:
import groovy.json.JsonSlurper
// POST example
try {
def body = '{"id": 120}'
def http = new URL("http://localhost:8080/your/target/url").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Content-Type", 'application/json')
http.outputStream.write(body.getBytes("UTF-8"))
http.connect()
def response = [:]
if (http.responseCode == 200) {
response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))
} else {
response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))
}
println "response: ${response}"
} catch (Exception e) {
// handle exception, e.g. Host unreachable, timeout etc.
}
There are two main differences comparing to GET request example:
You have to set HTTP method to POST
http.setRequestMethod('POST')
You write your POST body to outputStream:
http.outputStream.write(body.getBytes("UTF-8"))
where body might be a JSON represented as string:
def body = '{"id": 120}'
Eventually it's good practice to check what HTTP status code returned: in case of e.g. HTTP 200 OK you will get your response from inputStream while in case of any error like 404, 500 etc. you will get your error response body from errorStream.

HTTP4S client. How to get the exact request and response body

I am writing a small http4s client
val client = SimpleHttp1Client()
val uri = Uri.fromString(requestUrl).valueOr(throw _)
val task = POST(uri, UrlForm("username" -> userName, "password" -> password)).map{request => println("request: " + request.body)}
try {
val response = client.expect[String](task).unsafePerformSync
println("token: " + response)
response
} catch {
case e: Exception => println(e.getMessage);"BadToken"
}
The output is like
[info] Running com.researchnow.nova.shield.NovaShieldSetup
[info] Emit(Vector(ByteVector(44 bytes, 0x757365726e616d653d616268737269766173746176612670617373776f72643d41726)))
[info] Failed: unexpected HTTP status: 400 Bad Request
[info] token: BadToken
How to convert the binary request body to String? I want to see the body and headers in clear text.
I had a conversation with the http4s team on gitter and found the response. since gitter talk is not returned by google I am putting the answer here
val loggedReq = req.copy(body = request.body.observe(scalaz.stream.io.stdOutBytes))
println(loggedReq)
this prints all the headers. If we do something with the loggedReq then we get the entire body which is posted
loggedReq.as[String].run

What can cause Rust's TcpSocket::write() to return "invalid input"?

For a little fun I wanted to make a simple HTTP request in Rust. I threw this together and it works great:
use std::io::TcpStream;
fn main() {
// This just does a "GET /" to www.stroustrup.com
println!("Establishing connection...");
let mut stream = TcpStream::connect("www.stroustrup.com:80").unwrap();
println!("Writing HTTP request...");
// unwrap() the result to make sure it succeeded, at least
let _ = stream.write(b"GET / HTTP/1.1\r\n\
Host: www.stroustrup.com\r\n\
Accept: */*\r\n\
Connection: close\r\n\r\n").unwrap();
println!("Reading response...");
let response = stream.read_to_string().unwrap();
println!("Printing response:");
println!("{}", response);
}
Response is:
Establishing connection...
Writing HTTP request...
Reading response...
Printing response:
HTTP/1.1 200 OK
...and the rest of the long HTTP response with all the HTML as I'd expect...
However, if I change the request to be /C++.html instead of /:
use std::io::TcpStream;
fn main() {
// The only change is to "GET /C++.html" instead of "GET /"
println!("Establishing connection...");
let mut stream = TcpStream::connect("www.stroustrup.com:80").unwrap();
println!("Writing HTTP request...");
// unwrap() the result to make sure it succeeded, at least
let _ = stream.write(b"GET /C++.html HTTP/1.1\r\n\
Host: www.stroustrup.com\r\n\
Accept: */*\r\n\
Connection: close\r\n\r\n").unwrap();
println!("Reading response...");
let response = stream.read_to_string().unwrap();
println!("Printing response:");
println!("{}", response);
}
The socket returns "invalid input":
Establishing connection...
Writing HTTP request...
Reading response...
thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: invalid input', /Users/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-mac/build/src/libcore/result.rs:746
Why does the socket return "invalid input"? The TCP socket isn't aware of the HTTP protocol (and I've tested my request with telnet and netcat: it's correct), so it can't be complaining about HTTP request/response.
What does "invalid input" even mean here? Why doesn't this work?
My rust version (I'm on OS X 10.10.1):
$ rustc --version
rustc 1.0.0-nightly (ea6f65c5f 2015-01-06 19:47:08 +0000)
The "invalid input" error isn't coming from the socket. It's coming from String. If the read_to_string() call is changed to read_to_end(), then the response is successful. Apparently the response isn't valid UTF-8.
More explicitly, the code:
println!("Reading response...");
let response = stream.read_to_end().unwrap();
println!("Printing response:");
println!("{}", String::from_utf8(response));
returns:
Err(invalid utf-8: invalid byte at index 14787)
So the HTTP response is bad. Looking at the web page, the error is here (the � characters are the problem):
Lang.Next'14 Keynote: What � if anything � have we learned from C++?
The offending characters are 0x96, indeed invalid utf-8. It should be U+2013 –
The document is either iso-8859-1 or windows 1252. There are a number of other problems with that HTML, such as unescaped &'s.