Jasmine - Testing Links Through Webdriver I / O

I am working on an end-to-end test using Jasmine's Webdriver I / O. One specific scenario gave me serious problems.

I have a page with 5 links to it. In fact, the number of links is related to the dynamics of the page. I want to check the links to see if each link corresponds to the title title page to which it refers. Due to the fact that links are dynamically generated, I can’t just hard-code the code for each link. So, I am trying to do the following:

 it('should match link titles to page titles', function(done) { client = webdriverio.remote(settings.capabilities).init() .url('http://www.example.com') .elements('a').then(function(links) { var mappings = []; // For every link store the link title and corresponding page title var results = []; for (var i=0; i<links.value.length; i++) { mappings.push({ linkTitle: links.value[0].title, pageTitle: '' }); results.push(client.click(links.value[i]) .getTitle().then(function(title, i) { mappings[i].pageTitle = title; }); ); } // Once all promises have resolved, compared each link title to each corresponding page title Promise.all(results).then(function() { for (var i=0; i<mappings.length; i++) { var mapping = mappings[i]; expect(mapping.linkTitle).toBe(mapping.pageTitle); } done(); }); }); ; }); 

I can’t even confirm if I got the link name correctly. I believe that I completely do not understand. I don't even get every title property of the links. I definitely do not get the corresponding page title. I think I am lost in the closing world here. However, I am not sure.

UPDATE - NOV 24 I still do not understand this. However, I believe this is due to the fact that Webdriver I / O uses the Q promise library. I came to this conclusion because the following test works:

 it('should match link titles to page titles', function(done) { var promise = new Promise(function(resolve, reject) { setTimeout(function() { resolve(); }, 1000); }); promise.then(function() { var promises = []; for (var i=0; i<3; i++) { promises.push( new Promise(function(resolve, reject) { setTimeout(function() { resolve(); }, 500); }) ); } Promise.all(promises).then(function() { expect(true).toBe(true) done(); }); }); 

However, it does NOT :

 it('should match link titles to page titles', function(done) { client = webdriverio.remote(settings.capabilities).init() .url('http://www.example.com') .elements('a').then(function(links) { var mappings = []; // For every link store the link title and corresponding page title var results = []; for (var i=0; i<links.value.length; i++) { mappings.push({ linkTitle: links.value[0].title, pageTitle: '' }); results.push(client.click(links.value[i]) .getTitle().then(function(title, i) { mappings[i].pageTitle = title; }); ); } // Once all promises have resolved, compared each link title to each corresponding page title Q.all(results).then(function() { for (var i=0; i<mappings.length; i++) { var mapping = mappings[i]; expect(mapping.linkTitle).toBe(mapping.pageTitle); } done(); }); }) ; }); 

I have no exceptions. However, the code inside Q.all does not seem to be executing. I'm not sure what to do here.

+5
source share
1 answer

Reading the WebdriverIO manual, I feel that there are several things in your approach:

  • elements('a') returns WebElement JSON objects ( https://code.google.com/p/selenium/wiki/JsonWireProtocol#WebElement_JSON_Object ) NOT WebElements, so there is no title property, so linkTitle will always be undefined - http: // webdriver.io/api/protocol/elements.html
  • Also, since this is a WebElement JSON object, you cannot use it as input client.click(..) , which expects the selector string to be not an object - http://webdriver.io/api/action/click.html . To click the WebElement JSON object client.elementIdClick client.elementIdClick(ID) instead, which takes the value of the ELEMENT property of the WebElement JSON object.
  • When client.elementIdClick is client.elementIdClick , the client will move around the page trying to call client.elementIdClick in the next loop of the cycle when the next identifier will not be executed, because there is no such element that you removed from the page. It will sound something like invalid element cache....

So, I propose another solution for your task:

  • Find all elements like you using elements('a')
  • Read href and title with client.elementIdAttribute(ID) for each of the elements and store in the object
  • Go through all the objects, go to each of the href -s using client.url('href') , get the page title with .getTitle and compare it with object.title .

The source I experimented with, not triggered by Jasmine, but should give an idea:

  var client = webdriverio .remote(options) .init(); client .url('https://www.google.com') .elements('a') .then(function (elements) { var promises = []; for (var i = 0; i < elements.value.length; i++) { var elementId = elements.value[i].ELEMENT; promises.push( client .elementIdAttribute(elementId, 'href') .then(function (attributeRes) { return client .elementIdAttribute(elementId, 'title') .then(function (titleRes) { return {href: attributeRes.value, title: titleRes.value}; }); }) ); } return Q .all(promises) .then(function (results) { console.log(arguments); var promises = []; results.forEach(function (result) { promises.push( client .url(result.href) .getTitle() .then(function (title) { console.log('Title of ', result.href, 'is', title, 'but expected', result.title); }) ); }); return Q.all(promises); }); }) .then(function () { client.end(); }); 

NOTE:

  • This does not solve your problem when links start navigation with JavaScript event handlers, rather than href attributes.
+4
source

Source: https://habr.com/ru/post/1236327/


All Articles