Capture REST calls with Selenium

3.1k views Asked by At

I run integration test with Selenium as a test runner and webdriver.io javascript library for Selenium API. My test goes as follows: I load an html page and click on a button. I want to check if a Get REST call was invoked.

I found a plugin for webdriver.io called webdriverajax that intend to fit to my requirements but it just doesn't work.

Any ideas how do capture rest calls?

2

There are 2 answers

0
gihan-maduranga On

You can achieve this by using custom HttpClient class that is out side from selenium code.As far as i know selenium doesn't support this feature.

Assume when you clicked the button it will called a REST service , the URL can be grab from the HTML DOM element.Then you can use your custom code to verify if URL is accessible or not.Then you can decide if your test is pass or failed based on the status code or some other your mechanism.

FileDownloader.java(Sample code snippet)

private String downloader(WebElement element, String attribute) throws IOException, NullPointerException, URISyntaxException {
        String fileToDownloadLocation = element.getAttribute(attribute);
        if (fileToDownloadLocation.trim().equals("")) throw new NullPointerException("The element you have specified does not link to anything!");

        URL fileToDownload = new URL(fileToDownloadLocation);
        File downloadedFile = new File(this.localDownloadPath + fileToDownload.getFile().replaceFirst("/|\\\\", ""));
        if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);

        HttpClient client = new DefaultHttpClient();
        BasicHttpContext localContext = new BasicHttpContext();

        LOG.info("Mimic WebDriver cookie state: " + this.mimicWebDriverCookieState);
        if (this.mimicWebDriverCookieState) {
            localContext.setAttribute(ClientContext.COOKIE_STORE, mimicCookieState(this.driver.manage().getCookies()));
        }

        HttpGet httpget = new HttpGet(fileToDownload.toURI());
        HttpParams httpRequestParameters = httpget.getParams();
        httpRequestParameters.setParameter(ClientPNames.HANDLE_REDIRECTS, this.followRedirects);
        httpget.setParams(httpRequestParameters);

        LOG.info("Sending GET request for: " + httpget.getURI());
        HttpResponse response = client.execute(httpget, localContext);
        this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
        LOG.info("HTTP GET request status: " + this.httpStatusOfLastDownloadAttempt);
        LOG.info("Downloading file: " + downloadedFile.getName());
        FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
        response.getEntity().getContent().close();

        String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
        LOG.info("File downloaded to '" + downloadedFileAbsolutePath + "'");

        return downloadedFileAbsolutePath;
    }

TestClass.java

@Test
public void downloadAFile() throws Exception {


       FileDownloader downloadTestFile = new FileDownloader(driver);
        driver.get("http://www.localhost.com/downloadTest.html");
        WebElement downloadLink = driver.findElement(By.id("fileToDownload"));
        String downloadedFileAbsoluteLocation = downloadTestFile.downloadFile(downloadLink);

        assertThat(new File(downloadedFileAbsoluteLocation).exists(), is(equalTo(true)));
        assertThat(downloadTestFile.getHTTPStatusOfLastDownloadAttempt(), is(equalTo(200)));
 // you can use status code to valid  the REST URL
    }

Here is the reference.

Note: This may not exactly fit into your requirement but you can get some idea and modify it accordingly to fit into your requirement.

Also refer the BrowserMob Proxy using this you can also achieve what you want.

0
orenMos On

The problem was the webdriver.io version. Apparently, webdriverajax works fine just with webdriver.io v3.x but not with v4.x. I use v4.5.2.

I decide not using a plugin and implement a mock for window.XMLHttpRequest open and send methods, as follows:

proxyXHR() {
  this.browser.execute(() => {
    const namespace = '__scriptTests';
    window[namespace] = { open: [], send: [] };
    const originalOpen = window.XMLHttpRequest.prototype.open;
    window.XMLHttpRequest.prototype.open = function (...args) {
      window[namespace].open.push({
        method: args[0],
        url: args[1],
        async: args[2],
        user: args[3],
        password: args[4]
      });
      originalOpen.apply(this, [].slice.call(args));
    };
    window.XMLHttpRequest.prototype.send = function (...args) {
      window[namespace].send.push(JSON.parse(args[0]));
    };
  });
}

getXHRsInfo() {
  const result = this.browser.execute(() => {
    const namespace = '__scriptTests';
    return window[namespace];
  });
  return result.value;
}