Protractor: Is it possible to test that there are

2019-02-15 08:58发布

问题:

I'm new to protractor, I want to write a test to see that there are no anchors with urls giving 404 errors.

I've seen this How to test html links with protractor?, but is for one determined link only, I want to do it for all links in the page.

The test should pass for the http status 200, as stated here How to use protractor to get the response status code and response text?

I have two questions:

  • Does this test makes sense in protractor?
  • Is it possible to test this? If so, how?

回答1:

I think its definitely doable and would make sense to do it if the scope is limited since this is not a typical UI test that selenium-webdriver is used for. You could do something like, find all links, get underneath url and fire a GET request using a module like request. Here is a pseudo code.

var request = require('request');
var assert = require('assert');
element.all(by.tagName('a')).then(function(link) {
   var url = link.getAttribute('href');
   if(url) {
       request(url, function (error, response, body) {
           assert.equal(response.statusCode, 200, 'Status code is not OK');
       });
    }
});


回答2:

I wanted to implement this as a page object so I could use a simple one line expect statement for each pages spec file. In afterthought I think this could have been achieved in a much simpler manner using an API testing framework such as cheerio.js but here is how to implement it using protractor and jasmine (using ES2015 syntax so update node to the current version) ! Please remember to install the request, bluebird and request-promise npm packages.

PageObject.js

crawlLinks(){

    const request = require('request');
    const Promise = require('bluebird');
    const rp = require('request-promise');

    return $$('a').then(function(elems){
      return Promise.map(elems, elem => {
        return elem.getAttribute("href").then(function(url){
          if(url){
            var options = {
              method: 'GET',
              uri: url,
              resolveWithFullResponse: true
            };
            return rp(options).then(function(response){
              console.log('The response code for ' + url + ' is ' + response.statusCode);
              return response.statusCode === 200;
            });
          }
        });
      }).then((allCodes) => {
        console.log(allCodes);
        return Promise.resolve(allCodes);
      });
    });
  }

Test

it("should not have broken links", function(){
     expect(pageObject.crawlLinks()).not.toContain(false);
});


回答3:

404 errors appear in the browser console (at least in chrome they do) and you can access that from protractor

browser.manage().logs().get('browser').then(function(browserLogs) {
   browserLogs.forEach(function(log){
      expect(log).toBeFalsy();
   });
});

The code above will cause all console messages to be considered a test failure, you may adapt it to your needs. You can put similar code in afterAll on all your tests.



回答4:

Here I wrote a java demo which may meets your requirement. Also I am not familiar with protractor but hope this can help

package com.selenium.webdriver.test;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

public class Traverse {

   private WebDriver driver;
   private String baseUrl;
   private Map<String, String> tMap;

public Traverse(String url) {
    driver = new HtmlUnitDriver();
    baseUrl = url;
    tMap = new HashMap<String,String>();
}


//get status code.
public int getRespStatusCodeByGet(String url) throws HttpException, IOException {
    GetMethod method = new GetMethod(url);
    HttpClient client = new HttpClient();

    client.executeMethod(method);

    return method.getStatusCode();
}

//single page traversal
public boolean search(String url) throws HttpException, IOException {
    if(getRespStatusCodeByGet(url) != 200) {
        System.out.println("Bad page " + url);
        return false;
    }
    driver.get(url);

    List<WebElement> elements = driver.findElements(By.tagName("a"));

    for(int i=0;  i<elements.size(); i++) {
        String cUrl = elements.get(i).getAttribute("href");
        String cText = elements.get(i).getText();

        if(cUrl != null && cUrl.startsWith("http") && !tMap.containsKey(cText)) {

            tMap.put(cText, cUrl);

            System.out.println(cUrl);

            search(cUrl);


        }

    }
    return true;
}

//client
public static void main(String[] args) throws HttpException, IOException {
    Traverse t = new Traverse("http://www.oktest.me/");
    t.search(t.baseUrl);
}
}

Check the bad page you can get what you want.