Skip to content

Commit

Permalink
#63 - extending check step for auto test assertions
Browse files Browse the repository at this point in the history
WIP - more details at #63

- add visible() function to check whether element is visible
- this is a similar to present() but something that exists in the HTML
DOM may not be visible (for example if the display property is none or
visibility property is hidden)
- the visible() function addresses the use case for explicitly checking
that an element exists on the webpage and is visibly rendered to user

- update the count() function’s supporting function for casperjs to use
casperjs in-built function to maximize compatibility, the supporting
function for chrome mode is unchanged and uses the definition by
Puppeteer’s Dev Lead Andrey Lushnikov -
puppeteer/puppeteer#545
  • Loading branch information
kensoh committed Oct 28, 2017
1 parent 0591449 commit ea8da9c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 10 deletions.
26 changes: 21 additions & 5 deletions src/tagui_header.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ return false;}
// friendlier name to use check_tx() in if condition in flow
function present(element_locator) {if (!element_locator) return false; else return check_tx(element_locator);}

// friendlier name to check element visibility using elementVisible()
function visible(element_locator) {if (!element_locator) return false;
var element_located = tx(element_locator); var element_visible = casper.elementVisible(element_located);
// if tx() returns x('/html') means that the element is not found, so set element_visible to false
if (element_located.toString() == x('/html').toString()) element_visible = false; return element_visible;}

// friendlier name to count elements using countElements()
function count(element_locator) {if (!element_locator) return 0;
var element_located = tx(element_locator); var element_count = casper.countElements(element_located);
Expand Down Expand Up @@ -186,6 +192,15 @@ else var ws_message = chrome_step('Runtime.evaluate',{expression: chrome_context
try {var ws_json = JSON.parse(ws_message); if (ws_json.result.result.value > 0) return true; else return false;}
catch(e) {return false;}};

chrome.elementVisible = function(selector) { // same as chrome.exists, except for checking visibility
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
var ws_message = chrome_step('Runtime.evaluate',{expression: 'var e = document.evaluate(\''+selector+'\','+chrome_context+',null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0); var visible = false; if (!e) visible = false; else {var style = window.getComputedStyle(e); visible = style && style.display !== \'none\' && style.visibility !== \'hidden\' && style.opacity !== \'0\';}; visible'});}
else var ws_message = chrome_step('Runtime.evaluate',{expression: 'var e = '+chrome_context+'.querySelector(\''+selector+'\'); var visible = false; if (!e) visible = false; else {var style = window.getComputedStyle(e); visible = style && style.display !== \'none\' && style.visibility !== \'hidden\' && style.opacity !== \'0\';}; visible'});
try {var ws_json = JSON.parse(ws_message); if (ws_json.result.result.value == true)
return ws_json.result.result.value; else return false;}
catch(e) {return false;}};

chrome.countElements = function(selector) { // same as chrome.exists, except element count is returned
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
Expand Down Expand Up @@ -753,6 +768,7 @@ source_code = source_code.replace(/casper\.mouse/g,'chrome.mouse').replace(/this
source_code = source_code.replace(/casper\.sendKeys/g,'chrome.sendKeys').replace(/this\.sendKeys/g,'chrome.sendKeys');
source_code = source_code.replace(/casper\.selectOptionByValue/g,'chrome.selectOptionByValue').replace(/this\.selectOptionByValue/g,'chrome.selectOptionByValue');
source_code = source_code.replace(/casper\.countElements/g,'chrome.countElements').replace(/this\.countElements/g,'chrome.countElements');
source_code = source_code.replace(/casper\.elementVisible/g,'chrome.elementVisible').replace(/this\.elementVisible/g,'chrome.elementVisible');
source_code = source_code.replace(/casper\.fetchText/g,'chrome.fetchText').replace(/this\.fetchText/g,'chrome.fetchText');
source_code = source_code.replace(/casper\.capture/g,'chrome.capture').replace(/this\.capture/g,'chrome.capture');
source_code = source_code.replace(/casper\.captureSelector/g,'chrome.captureSelector').replace(/this\.captureSelector/g,'chrome.captureSelector');
Expand Down Expand Up @@ -789,12 +805,12 @@ if (!found && opt.value.indexOf(valueToMatch) !== -1) {select.selectedIndex = i;
var evt = document.createEvent("UIEvents"); // dispatch change event in case there is validation
evt.initUIEvent("change", true, true); select.dispatchEvent(evt);}, selector, valueToMatch);};

// custom function to return element visibility
casper.elementVisible = function(selector) {return casper.visible(selector);} // use casperjs to maximize compatibility

// custom function to return element count
casper.countElements = function(selector) { // different handling for xpath and css to support both
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
var count_result = casper.evaluate(function(selector) {return document.evaluate(selector,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotLength;},selector);}
else var count_result = casper.evaluate(function(selector) {return document.querySelectorAll(selector).length;},selector);
casper.countElements = function(selector) { // use casperjs in-built function to maximize compatibility
var count_result = casper.evaluate(function(selector) {return __utils__.findAll(selector).length;},selector);
try {if (count_result > 0) return count_result; else return 0;} catch(e) {return 0;}};

// flow path for save_text and snap_image
3 changes: 3 additions & 0 deletions src/tagui_parse.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
// for countElements check for '(' in order to only overwrite calls and not the custom function casper.countElements()
$script_content = str_replace("casper.countElements(","chrome.countElements(",$script_content); // count elements
$script_content = str_replace("this.countElements(","chrome.countElements(",$script_content); // count elements
// for elementVisible check for '(' in order to only overwrite calls and not the custom function casper.elementVisible()
$script_content = str_replace("casper.elementVisible(","chrome.elementVisible(",$script_content); // check element visible
$script_content = str_replace("this.elementVisible(","chrome.elementVisible(",$script_content); // check element visible
$script_content = str_replace("casper.fetchText","chrome.fetchText",$script_content); // change fetchText method to chrome
$script_content = str_replace("this.fetchText","chrome.fetchText",$script_content); // change this.fetchText call as well
$script_content = str_replace("casper.capture","chrome.capture",$script_content); // change capture method to chrome
Expand Down
10 changes: 10 additions & 0 deletions src/test/positive_test
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,16 @@ else
echo 'footer not found'
}

// test visible function
if visible('footer')
{
echo 'footer is visible'
}
else
{
echo 'footer not visible'
}

// test title function
echo title()
if title() contains 'About'
Expand Down
43 changes: 38 additions & 5 deletions src/test/positive_test.signature
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ return false;}
// friendlier name to use check_tx() in if condition in flow
function present(element_locator) {if (!element_locator) return false; else return check_tx(element_locator);}

// friendlier name to check element visibility using elementVisible()
function visible(element_locator) {if (!element_locator) return false;
var element_located = tx(element_locator); var element_visible = casper.elementVisible(element_located);
// if tx() returns x('/html') means that the element is not found, so set element_visible to false
if (element_located.toString() == x('/html').toString()) element_visible = false; return element_visible;}

// friendlier name to count elements using countElements()
function count(element_locator) {if (!element_locator) return 0;
var element_located = tx(element_locator); var element_count = casper.countElements(element_located);
Expand Down Expand Up @@ -210,6 +216,15 @@ else var ws_message = chrome_step('Runtime.evaluate',{expression: chrome_context
try {var ws_json = JSON.parse(ws_message); if (ws_json.result.result.value > 0) return true; else return false;}
catch(e) {return false;}};

chrome.elementVisible = function(selector) { // same as chrome.exists, except for checking visibility
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
var ws_message = chrome_step('Runtime.evaluate',{expression: 'var e = document.evaluate(\''+selector+'\','+chrome_context+',null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0); var visible = false; if (!e) visible = false; else {var style = window.getComputedStyle(e); visible = style && style.display !== \'none\' && style.visibility !== \'hidden\' && style.opacity !== \'0\';}; visible'});}
else var ws_message = chrome_step('Runtime.evaluate',{expression: 'var e = '+chrome_context+'.querySelector(\''+selector+'\'); var visible = false; if (!e) visible = false; else {var style = window.getComputedStyle(e); visible = style && style.display !== \'none\' && style.visibility !== \'hidden\' && style.opacity !== \'0\';}; visible'});
try {var ws_json = JSON.parse(ws_message); if (ws_json.result.result.value == true)
return ws_json.result.result.value; else return false;}
catch(e) {return false;}};

chrome.countElements = function(selector) { // same as chrome.exists, except element count is returned
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
Expand Down Expand Up @@ -777,6 +792,7 @@ source_code = source_code.replace(/casper\.mouse/g,'chrome.mouse').replace(/this
source_code = source_code.replace(/casper\.sendKeys/g,'chrome.sendKeys').replace(/this\.sendKeys/g,'chrome.sendKeys');
source_code = source_code.replace(/casper\.selectOptionByValue/g,'chrome.selectOptionByValue').replace(/this\.selectOptionByValue/g,'chrome.selectOptionByValue');
source_code = source_code.replace(/casper\.countElements/g,'chrome.countElements').replace(/this\.countElements/g,'chrome.countElements');
source_code = source_code.replace(/casper\.elementVisible/g,'chrome.elementVisible').replace(/this\.elementVisible/g,'chrome.elementVisible');
source_code = source_code.replace(/casper\.fetchText/g,'chrome.fetchText').replace(/this\.fetchText/g,'chrome.fetchText');
source_code = source_code.replace(/casper\.capture/g,'chrome.capture').replace(/this\.capture/g,'chrome.capture');
source_code = source_code.replace(/casper\.captureSelector/g,'chrome.captureSelector').replace(/this\.captureSelector/g,'chrome.captureSelector');
Expand Down Expand Up @@ -813,12 +829,12 @@ if (!found && opt.value.indexOf(valueToMatch) !== -1) {select.selectedIndex = i;
var evt = document.createEvent("UIEvents"); // dispatch change event in case there is validation
evt.initUIEvent("change", true, true); select.dispatchEvent(evt);}, selector, valueToMatch);};

// custom function to return element visibility
casper.elementVisible = function(selector) {return casper.visible(selector);} // use casperjs to maximize compatibility

// custom function to return element count
casper.countElements = function(selector) { // different handling for xpath and css to support both
if ((selector.toString().length >= 16) && (selector.toString().substr(0,16) == 'xpath selector: '))
{if (selector.toString().length == 16) selector = ''; else selector = selector.toString().substring(16);
var count_result = casper.evaluate(function(selector) {return document.evaluate(selector,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotLength;},selector);}
else var count_result = casper.evaluate(function(selector) {return document.querySelectorAll(selector).length;},selector);
casper.countElements = function(selector) { // use casperjs in-built function to maximize compatibility
var count_result = casper.evaluate(function(selector) {return __utils__.findAll(selector).length;},selector);
try {if (count_result > 0) return count_result; else return 0;} catch(e) {return 0;}};

// flow path for save_text and snap_image
Expand Down Expand Up @@ -1729,6 +1745,23 @@ else
this.echo('footer not found');
})} // end of code block

// test visible function
if ((visible('footer')))

// start of code block
{casper.then(function() {

this.echo('footer is visible');
})} // end of code block

else

// start of code block
{casper.then(function() {

this.echo('footer not visible');
})} // end of code block

// test title function
this.echo(title());
if (((title().indexOf('About')>-1)))
Expand Down

1 comment on commit ea8da9c

@kensoh
Copy link
Member Author

@kensoh kensoh commented on ea8da9c Oct 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in commit comment, below is the intended meaning -

For count() function, the supporting function for chrome mode is unchanged, it basically queries using DevTools Protocol accordingly (whether XPath or CSS selector is provided), and returns the count.

For visible() function, the supporting function for chrome mode uses the definition by Puppeteer’s Dev Lead Andrey Lushnikov () checking opacity in addition to CasperJS's only checking visibility and display - puppeteer/puppeteer#545

Please sign in to comment.