1

I am trying to count the number of hyperlinks on a page and test them to see if they work. I have the ability to count all the links and display that count in JavaScript but I can't seem to return that value in protractor on Command Line.

Update Code based on Answers:

browser.waitForAngularEnabled(false);
describe('Clicks on the correct Drupal hyperlink', function() {

  it('should find all links', function () {
    browser.get('file:///C:/Users/Dasman/Documents/PROTRACTOR_E2E_TESTING/TestSite.html');
    let allLinks = element.all(by.tagName('a'));
    allLinks.count().then(function(link_tally){
      console.log('There are a total of ' + link_tally + " links on this page with proper tags.")
    })
  browser.sleep(2000);

  // A Protracterized httpGet() promise
function httpGet(siteUrl) {
  var http = require('http');
  var defer = protractor.promise.defer();

  http.get(siteUrl, function(response) {

      var bodyString = '';

      response.setEncoding('utf8');

      response.on("data", function(chunk) {
          bodyString += chunk;
      });

      response.on('end', function() {
          defer.fulfill({
              statusCode: response.statusCode,
              bodyString: bodyString
          });
      });

  }).on('error', function(e) {
      defer.reject("Got http.get error: " + e.message);
  });

  return defer.promise;
}

it('should return 200 and contain proper body', function() {
  httpGet(allLinks).then(function(result) {
    allLinks.count().then(function(statusCode){
      console.log('Status code is: ' + statusCode)
    })
      expect(result.statusCode).toBe(200);
      expect(result.bodyString).toContain('Apache');
  });
});
    });
});

In addition I want to "check" the links to see if they open. Is there a way to go to a URL and click all the links and have them open on separate windows? or get an attribute if the link works or has a valid URL?

I originally xpath the id and clicked the link and as the test ran - I visually verified. But with 15-20 links on a average page - I need a more automated way.

Ernst's answer pointed me to the solution, but it did need some code restructuring and encapsulation: https://github.com/SDasman/Angular_Protractor_End2End_Tests/tree/master/LinkCheck

Dasman
  • 317
  • 4
  • 19

2 Answers2

3

To report your count in the console you can do this:

//find all links
let linkCount = element.all(by.css('a'));

// count links, with then() resolve promise and log count result
linkCount.count().then(function(cnt){
    console.log('Total links = '+cnt);
});

//here you click each of the links:
linkCount.click()

You can find out more about count(), then() and element.all() here: http://protractortest.org/#/api

To check the response code of your links, it will be a bit tricky, because Protractor doesn't support such requests out of the box (see here).

However, there are two SO-Posts here and here, which provide a way to do it.

To get it tested one by one you should be able to use getAttribute('href'). It would be something like this (Note: not tested, but partly copied from above two mentioned SO-Answers)

linkCount.each(function(elem){
    elem.getAttribute('href').then(function(link){
        this.httpGet("http://localhost:80").then(function(result) {
            expect(result.statusCode).toBe(200);
        });
    });
});

// A Protracterized httpGet() promise
this.httpGet = function(siteUrl) {
    var http = require('http');
    var defer = protractor.promise.defer();

    http.get(siteUrl, function(response) {

        var bodyString = '';

        response.setEncoding('utf8');

        response.on("data", function(chunk) {
            bodyString += chunk;
        });

        response.on('end', function() {
            defer.fulfill({
                statusCode: response.statusCode,
                bodyString: bodyString
            });
        });

    }).on('error', function(e) {
        defer.reject("Got http.get error: " + e.message);
    });

    return defer.promise;
}
Ernst Zwingli
  • 1,402
  • 1
  • 8
  • 24
  • Hey Ernst this takes care of the console output part. – Dasman Dec 07 '17 at 15:38
  • any way to "test" the link other than verifying that it has a href tag. – Dasman Dec 07 '17 at 15:39
  • the `linkCount.click()` would basically click each link. However, I assumed that links will open in new Tab. If it opens in the same tab, it won't work that way (because after the first click you've left the page). What exactly do you want to "test" for the link? Function-wise you can check if each link has an href-attribute starting with "https://" by this line `expect($$('a[href^="https"]').count()).toEqual(cnt)`. But it really depends, what you'd like to "test". – Ernst Zwingli Dec 07 '17 at 15:47
  • clicking each link won't help I've realized since a 404 could happen and thats not helpful. Error or Response code is what really matters here - do the pages load. – Dasman Dec 07 '17 at 15:51
  • 1
    I updated my answer with what I found about how to check http-responses in protractor (it's not an out-of-the-box-thing). – Ernst Zwingli Dec 07 '17 at 16:33
  • I saw those two and have been trying to use the Get method. I just get this error: "httpGet is not defined." Should I be importing something? – Dasman Dec 07 '17 at 17:03
  • Sorry... I thought it's obvious, that you'd of course need to define the function. Extended my answer now to have the function included. Note, that it will be better to have the function in a separate helper/pageObject file and use `require / module.exports` to call it. – Ernst Zwingli Dec 08 '17 at 08:38
  • Hey Ernst! I have looked at it and used the define function. Didn't realize you had to manually define stuff in JS (new to JS). After using your code and defining it - I get the same error. Is there something I'm missing? I've updated my question with the spec.js. Is there some in conf.js I need to update? – Dasman Dec 08 '17 at 17:56
  • You missed to add `this.` in front of `httpGet`, where you call it. And probably you'll also need `var http = require('http');`. Cross-check with the linked SO-answer – Ernst Zwingli Dec 08 '17 at 18:07
  • Last follow up: I debugged and now the httpGet module works... but it doesnt print the status code or detect the a 404. I made a testsite.html with a broken link - no dice says all tests passed. – Dasman Dec 08 '17 at 20:43
0

You can also try to get Text from each link and count all array element like this:

var allLinks = element.all(By.tagName('a'));
allLinks.getText().then(function(findAllLink) {
var numberofLinks = findAllLink.length;
console.log(numberofLinks);
})