API testing using Selenium - json

I'm new to API testing. I need to integrate only one flow of API through Selenium as rest of GUI is already present.
I use API url on client browser, I get the result[json format]
I tried on SoapUI [REST] with the url, it gave the result[json format]
But when I try it on Selenium, I'm getting internal server error 500.
Please let me know the config changes that I need to take care.
string apiurl = "https://example.org/alfresco/s/org/alfresco/faceted/search?"
Here is the snippet of code i tried
URL url = new URL(apiurl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
String authString = "user:Password";
byte[] bytesEncoded = Base64.encodeBase64(authString.getBytes());
String authEncoded = new String("Basic "+bytesEncoded);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Authorization", authEncoded);
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent", "Apache-HttpClient/4.1.1 (java 1.5)");
conn.connect();
System.out.println(conn.getResponseCode());
I split the URL as
URL url = new URL(url);
conn.setRequestProperty("resource", "/alfresco/s/org/alfresco/faceted/search?");
conn.setRequestProperty("query", "%28Keywords%3A%27test%27%29");
conn.setRequestProperty("format", "json");
conn.setRequestProperty("resource", url+ "alfresco/s/org/alfresco/faceted/search?query=%28Keywords%3A%27test%27%29&count=10&format=json");
conn.setRequestProperty("Accept", "application/json");
Here I get 200 as response, but the response is on the example.org and not on the query appended.
Kindly let me know what is wrong that have done or need to add any information.

Maybe it is a little rude and not regarding current topic but I want to prevent you from doing a wrong job in future.
Using Selenium Webdriver for API testing you'll suffer a lot of pain.
Selenium Webdriver is not used for this porpuse.
Instead it there are a lot of good automation tools to test API.
One of them is Postman (chrome extension https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en)
Using this tool you'll get much more features and will be able to test any API with any requirenments.
I doubt you'll be able to do it with selenium Webdriver.

Related

How to authenticate with Blockfrost.io API?

So I'm trying to import Cardano Blockchain data like address balance, amount staked, rewards etc into a Google Sheet. I found this project named Blockfrost.io which is an API for accessing Cardano blockchain info and import it into apps etc.
I think I can use this with Google Sheets. Problem is I don't know how to authenticate. I've searched all around on the documentation and it's not clear to me. It seems it's possible if your're building an app or using the terminal.
But I just want to authenticate in the easiest way possible like in the browser address bar that way it would be simple to get the JSON with the info I need and import the info to Google Sheets.
This is where it mentions the Authentication:
https://docs.blockfrost.io/#section/Authentication
I already have an API key to access. But how do I authenticate?
So if I want to check the blockchain metrics (mainnet1234567890 is a dummy key, I won't use mine here):
https://cardano-mainnet.blockfrost.io/api/v0/metrics/project_id:mainnet1234567890
The JSON will still output this:
status_code 403
error "Forbidden"
message "Missing project token. Please include project_id in your request."
Is there a correct way to authenticate on the browser address bar?
It's not clear which BlockFrost API you are using Go JavaScript etc...
the API key goes in as a header on the request object. I was manually trying to connect to the service and found for a request is what I had to do in C#...
var aWR = System.Net.WebRequest.Create(url);
aWR.Method = "GET";
aWR.Headers.Add("project_id", "mainnetTheRestOfMyKeyIsHidden");
var webResponse = aWR.GetResponse();
var webStream = webResponse.GetResponseStream();
var reader = new StreamReader(webStream);
var data = reader.ReadToEnd();
Later I realized I wanted to use their API cause they implement the rate limiter, something I would rather use than build... I use the following with the BlockFrost API in c#
const string apiKey = "mainnetPutYourKeyHere";
const string network = "mainnet";
// your key is set during the construction of the provider.
ServiceProvider provider = new ServiceCollection().AddBlockfrost(network, apiKey).BuildServiceProvider();
// from there individual services are created
var AddressService = provider.GetRequiredService<IAddressesService>();
// The call to get the data looked like
AddressTransactionsContentResponseCollection TXR = await AddressService.GetTransactionsAsync(sAddress, sHeightFrom, sHeightTo, 100, iAddressPage, ESortOrder.Desc, new System.Threading.CancellationToken());
// etc. your gonna need to set the bounds above in terms of block height
Try using postman and include the "project_id" header with api key as the value like this - it will clear up the concept for you I think:enter image description here

Apache HttpClient 4.5: Why does the second package wait for the ack of the first package?

I am using apache http client in version 4.5.13 within my java application to send a post request. I used following line of code to set up the http client.
SocketConfig socketConfig = SocketConfig.custom()
.setSoKeepAlive(true)
.setTcpNoDelay(true)
.build();
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE)
.setCharset(Consts.UTF_8)
.setMessageConstraints(messageConstraints)
.build();
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.setExpectContinueEnabled(true)
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
.setContentCompressionEnabled(true)
.build();
BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
connectionManager.setSocketConfig(socketConfig);
connectionManager.setConnectionConfig(connectionConfig);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(defaultRequestConfig)
.build();
And I am sending the data via
CloseableHttpResponse response = httpClient.execute(postRequest);
The issue I am experiencing is that when I look how the messages are send (using tshark) I can see that the application data is split in two messages. The first one leaves my system around 0.5ms after the httpClient.execute(postRequest), but the second part is send around 10ms-20ms after the first one. It looks like the second part is waiting to receive the ack for the first part of the message. I tried to change a a lot of configurations (buffer sizes, TcpNoDelay, different TLS ...) but cannot figure out what is causing this behavior.
I also tried http.net client to send post requests. With this client the message was also split in two messages but they where both send right after each other (with around 0.3ms delay).
I am pretty new to network so I would appreciate a helpful answer and apologize upfront if I did not explain it very well (I do not know all the specific wordings).
Thanks
Try disabling expect-continue handshake.

GameMaker runner crashes when making HTTP requests

I recently got back into using GameMaker:Studio, and hoo boy have there been some massive updates since I last used it! In fact the last time I used it they only had Windows and HTML5 as export options...
Anyway, eager to try out some of the new stuff, I decided to take a shot at the native HTTP functions, since they looked very promising.
I did a test using http_post_string() to great effect, sending a JSON string to my server and getting a JSON string back. The returned string actually represented an object with a single property, "echo", which contained the HTTP request that had been made, just to see what GM:S was sending.
I didn't like that it sent Content-Type: application/x-www-form-urlencoded when it was quite clearly JSON, and I wanted the ability to set my own User Agent string so that the server could know which game was talking to it without having to pass an extra parameter.
So I re-created the same request using the lower-level http_request() function. Everything looked fine, so I tested it.
It crashed. Like, no error messages or anything, just a total crash and Windows had to force-close it.
So here I am with code that by all rights should work fine, but crashes when run...
///send_request(file,ds_map_data,callback_event_id)
var request = ds_map_create();
request[? "instance"] = id;
request[? "event"] = argument2;
if( !instance_exists(obj_ajax_callback)) {
instance_create(0,0,obj_ajax_callback);
}
var payload = json_encode(argument1);
var headers = ds_map_create();
headers[? "Content-Length"] = string_length(payload);
headers[? "Content-Type"] = "application/json";
headers[? "User-Agent"] = obj_ajax_callback.uastring;
var xhr = http_request("https://example.com/"+argument0,"POST",headers,payload);
with(obj_ajax_callback) {
active_callbacks[? xhr] = request;
}
ds_map_destroy(headers);
obj_ajax_callback is an object that maintains a ds_map of active requests, and in its HTTP event it listens for those requests' callbacks and reacts along the lines of with(request[? "instance"]) event_user(request[? "event"]) so that the calling object can handle the response. This hasn't changed from the fully working http_post_string() attempt.
Any idea what could be causing this crash?
The reason why this crashes is because you are sending the Content-Length header as a real instead of a string. If you change your line to
headers[? "Content-Length"] = string(string_length(payload));
It should work.

How to check NON-html responses with Geb?

Some of requests to my Web Application return data not in HTML format (JSON).
How to handle this correctly?
I wrote the following page definition:
import com.fasterxml.jackson.databind.ObjectMapper
import geb.Page
class JsonResponse extends Page {
static url = null;
static at = {
true;
}
static ObjectMapper mapper = new ObjectMapper();
static content = {
readTree {
def jsonString = $("pre").text();
mapper.readTree(jsonString)
}
}
}
and it apparently works. But the question is, how correct it is?
It takes data from inside pre tag. This is because I saw this content inside driver.pageSource. Is this correct? May be it is driver-dependent?
I put null into url, since the page has different url depending on query. Is this correct?
Geb is not intended to be used to interact with HTTP API endpoints because it is built on top of WebDriver and hence expects to be used via a browser and on HTML pages.
If you want to test HTTP API endpoints then I would suggest using an http client to back your tests. There are many of them out in the wild, just to name a few in no particular order:
Apache HttpClient
RestAssured - this one is specifically for testing
Ratpack's TestHttpClient - again intended to be used for testing
OkHttp
Unirest
I was able to download the content of a PDF in a geb unit test using the Direct Download API. It is handy because it takes all the cookies from the session but does the download separately from the browser.
Example from that documentation:
Browser.drive {
    go "http://myapp.com/login"
 
    // login
    username = "me"
    password = "secret"
    login().click()
 
    // now find the pdf download link
    def downloadLink = $("a.pdf-download-link")
 
    // now get the pdf bytes
    def bytes = downloadBytes(downloadLink.#href)
}
There are different methods for downloading different kinds of data. See the DownloadSupport API docs.
Because geb uses HttpsURLConnection to connect to an https endpoint instead of using the browser you can have problems with self-signed certificates. I solved that using this Stack Overflow answer.
I agree that Geb is not intended to be used to interact with HTTP API endpoints, but there are some contexts where this can be helpful, so add this snippet here for posterity:
when: 'I retrieve the JSON transaction list'
go '/transaction/transactionList'
then: 'Valid data is retrieved'
JsonSlurper jsonSlurper = new JsonSlurper()
Map<String, List> transactionList = jsonSlurper.parseText(driver.pageSource)
assert transactionList.categories.class == ArrayList

HttpClient Portable returns 404 notfound on WP8

I'm porting a W8 application that uses httpclient library to connect to our server.
The main purpose of the application is to send images, but when I try to send pictures on my WP8 I got a 404 not found error (seems that Microsoft remapped to 404 a lot of errors), if i check the server logs, I can see that the server recevied about 1/4 of the image before failling. The same function seems to works fine in my W8 application (didn't tested on 3G), and works on WP8 if I use Wifi connection. I think that the problem could be the waiting time, so I tried to add Keep-Alive headers without success.
The current code I have is:
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMinutes(10);
Stream streamW = new MemoryStream();
this.bSyncOK = await Send(streamW);
streamW.Seek(0, SeekOrigin.Begin);
HttpResponseMessage response = await httpClient.PostAsync(sUri, new StreamContent(streamW));
if (response.IsSuccessStatusCode)
{
Stream streamR = await response.Content.ReadAsStreamAsync();
this.bSyncOK = await Recv(streamR);
streamR.Dispose();
}
else
throw new HostNotFoundException();
}
The same server is used to upload pictures on other platforms like IOS and Android without problems.
I reproduced the problem using fiddler to simulate modem speeds. The problem is happening because Phone's HTTPWebRequest implementation will timeout the request whenever it exceeds around 60s. In the debugger I see them getting back ERROR_INTERNET_TIMEOUT from their native layer. The only workaround I can think of at the moment would be to send the file in smaller POSTs, assuming the server supports that.