UNPKG

funcunit

Version:
574 lines (562 loc) 25.3 kB
var $ = require("funcunit/browser/jquery"); var FuncUnit = require("funcunit/browser/core"); /** * @add FuncUnit */ //list of jQuery functions we want, number is argument index //for wait instead of getting value FuncUnit.funcs = { // methods /** * @function FuncUnit.prototype.size .size() * @parent dimensions * @signature `size([size] [,timeout] [,success] [,message])` * Gets the number of elements matched by the selector or * waits until the the selector is size. You can also * provide a function that continues to the next action when * it returns true. * * @codestart *F(".recipe").size() //gets the number of recipes * *F(".recipe").size(2) //waits until there are 2 recipes * * //waits until size is count *F(".recipe").size(function(size){ * return size == count; * }) * @codeend * @param {Number|Function} [size] number or a checking function. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {Number} if the size parameter is not provided, size returns the number * of elements matched. */ 'size' : 0, /** * @function FuncUnit.prototype.attr .attr() * @parent manipulation * @signature `attr(data, value [,timeout] [,success] [,message])` * Gets the value of an attribute from an element or waits until the attribute * equals the attr param. * * @codestart * //waits until the abc attribute == some *F("#something").attr("abc","some") * @codeend * @param {String} data The attribute to get, or wait for. * @param {String|Function} value If provided uses this as a check before continuing to the next action * * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {Object} if the attr parameter is not provided, returns * the attribute. */ 'attr' : 1, /** * @function FuncUnit.prototype.hasClass .hasClass() * @parent css * @signature `hasClass(className [,value] [,timeout] [,success] [,message])` * * @codestart * //returns if the element has the class in its className *F("#something").hasClass("selected"); * * //waits until #something has selected in its className *F("#something").hasClass("selected",true); * * //waits until #something does not have selected in its className *F("#something").hasClass("selected",false); * @codeend * @param {String} className The part of the className to search for. * @param {Boolean|Function} [value] If provided uses this as a check before continuing to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {Boolean|funcUnit} if the value parameter is not provided, returns * if the className is found in the element's className. If a value paramters is provided, returns funcUnit for chaining. */ 'hasClass' : 1, //makes wait /** * @function FuncUnit.prototype.html .html() * @parent manipulation * @signature `html([html] [,timeout] [,success] [,message])` * Gets the [http://api.jquery.com/html/ html] from an element or waits until the html is a certain value. * * @codestart * //checks foo's html has "JupiterJS" * ok( /JupiterJS/.test(F('#foo').html() ) ) * * //waits until foo's html has JupiterJS *F('#foo').html(/JupiterJS/) * * //waits until foo's html is JupiterJS *F('#foo').html("JupiterJS") * @codeend * * @param {String|Function} [html] If provided uses this as a check before continuing to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the html parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the html of the selector. */ 'html' : 0, /** * @function FuncUnit.prototype.text .text() * @parent manipulation * @signature `text([text] [,timeout] [,success] [,message])` * Gets the [http://api.jquery.com/text/ text] from an element or waits until the text is a certain value. * * @codestart * //checks foo's text has "JupiterJS" * ok( /JupiterJS/.test(F('#foo').text() ) ) * * //waits until bar's text has JupiterJS *F('#foo').text(/JupiterJS/) * * //waits until bar's text is JupiterJS *F('#foo').text("JupiterJS") * @codeend * * @param {String|Function} [text] If provided uses this as a check before continuing to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the text parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the html of the selector. */ 'text' : 0, /** * @function FuncUnit.prototype.val .val() * @parent manipulation * @signature `val([val] [,timeout] [,success] [,message])` * Gets the [http://api.jquery.com/val/ val] from an element or waits until the val is a certain value. * * @codestart * //checks foo's val has "JupiterJS" * ok( /JupiterJS/.test(F('input#foo').val() ) ) * * //waits until bar's val has JupiterJS *F('input#foo').val(/JupiterJS/) * * //waits until bar's val is JupiterJS *F('input#foo').val("JupiterJS") * @codeend * * @param {String|Function} [val] If provided uses this as a check before continuing to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the val parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the html of the selector. */ 'val' : 0, /** * @function FuncUnit.prototype.css .css() * @parent css * @signature `css(prop [,val] [,timeout] [,success] [,message])` * Gets a [http://api.jquery.com/css/ css] property from an element or waits until the property is * a specified value. * * @codestart * // gets the color *F("#foo").css("color") * * // waits until the color is red *F("#foo").css("color","red") * @codeend * * @param {String} prop A css property to get or wait until it is a specified value. * @param {String|Function} [val] If provided uses this as a check before continuing to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the val parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the css of the selector. */ 'css': 1, 'prop': 1, /** * @function FuncUnit.prototype.offset .offset() * @parent dimensions * @signature `offset([offset] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/offset/ offset] or waits until * the offset is a specified value. * * @codestart * // gets the offset *F("#foo").offset(); * * // waits until the offset is 100, 200 *F("#foo").offset({top: 100, left: 200}) * @codeend * * @param {Object|Function} [offset] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the offset parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the css of the selector. */ 'offset' : 0, /** * @function FuncUnit.prototype.position .position() * @parent dimensions * @signature `position([position] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/position/ position] or waits until * the position is a specified value. * * @codestart * // gets the position *F("#foo").position(); * * // waits until the position is 100, 200 *F("#foo").position({top: 100, left: 200}) * @codeend * * @param {Object|Function} [position] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if the position parameter is provided, * returns the funcUnit selector for chaining, otherwise returns the offset of the selector. */ 'position' : 0, /** * @function FuncUnit.prototype.scrollTop .scrollTop() * @parent dimensions * @signature `scrollTop([scrollTop] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/scrollTop/ scrollTop] or waits until * it equals a specified value. * * @codestart * // gets the scrollTop *F("#foo").scrollTop(); * * // waits until the scrollTop is 100 *F("#foo").scrollTop(100) * @codeend * * @param {Number|Function} [scrollTop] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if scrollTop is provided, * returns the funcUnit selector for chaining, otherwise returns the scrollTop of the selector. */ 'scrollTop' : 0, /** * @function FuncUnit.prototype.scrollLeft .scrollLeft() * @parent dimensions * @signature `scrollLeft([scrollLeft] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/scrollLeft/ scrollLeft] or waits until * it equals a specified value. * * @codestart * // gets the scrollLeft *F("#foo").scrollLeft(); * * // waits until the scrollLeft is 100 *F("#foo").scrollLeft(100) * @codeend * * @param {Number|Function} [scrollLeft] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if scrollLeft is provided, * returns the funcUnit selector for chaining, otherwise returns the scrollLeft of the selector. */ 'scrollLeft' : 0, /** * @function FuncUnit.prototype.height .height() * @parent dimensions * @signature `height([height] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/height/ height] or waits until * it equals a specified value. * * @codestart * // gets the height *F("#foo").height(); * * // waits until the height is 100 *F("#foo").height(100) * @codeend * * @param {Number|Function} [height] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if height is provided, * returns the funcUnit selector for chaining, otherwise returns the height of the selector. */ 'height' : 0, /** * @function FuncUnit.prototype.width .width() * @parent dimensions * @signature `width([width] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/width/ width] or waits until * it equals a specified value. * * @codestart * // gets the width *F("#foo").width(); * * // waits until the width is 100 *F("#foo").width(100) * @codeend * * @param {Number|Function} [width] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if width is provided, * returns the funcUnit selector for chaining, otherwise returns the width of the selector. */ 'width' : 0, /** * @function FuncUnit.prototype.innerHeight .innerHeight() * @parent dimensions * @signature `innerHeight([innerHeight] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/innerHeight/ innerHeight] or waits until * it equals a specified value. * * @codestart * // gets the innerHeight *F("#foo").innerHeight(); * * // waits until the innerHeight is 100 *F("#foo").innerHeight(100) * @codeend * * @param {Number|Function} [innerHeight] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if innerHeight is provided, * returns the funcUnit selector for chaining, otherwise returns the innerHeight of the selector. */ 'innerHeight' : 0, /** * @function FuncUnit.prototype.innerWidth .innerWidth() * @parent dimensions * @signature `innerWidth([innerWidth] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/innerWidth/ innerWidth] or waits until * it equals a specified value. * * @codestart * // gets the innerWidth *F("#foo").innerWidth(); * * // waits until the innerWidth is 100 *F("#foo").innerWidth(100) * @codeend * * @param {Number|Function} [innerWidth] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if innerWidth is provided, * returns the funcUnit selector for chaining, otherwise returns the innerWidth of the selector. */ 'innerWidth' : 0, /** * @function FuncUnit.prototype.outerHeight .outerHeight() * @parent dimensions * @signature `outerHeight([outerHeight] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/outerHeight/ outerHeight] or waits until * it equals a specified value. * * @codestart * // gets the outerHeight *F("#foo").outerHeight(); * * // waits until the outerHeight is 100 *F("#foo").outerHeight(100) * @codeend * * @param {Number|Function} [outerHeight] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if outerHeight is provided, * returns the funcUnit selector for chaining, otherwise returns the outerHeight of the selector. */ 'outerHeight' : 0, /** * @function FuncUnit.prototype.outerWidth .outerWidth() * @parent dimensions * @signature `outerWidth([outerWidth] [,timeout] [,success] [,message])` * Gets an element's [http://api.jquery.com/outerWidth/ outerWidth] or waits until * it equals a specified value. * * @codestart * // gets the outerWidth *F("#foo").outerWidth(); * * // waits until the outerWidth is 100 *F("#foo").outerWidth(100) * @codeend * * @param {Number|Function} [outerWidth] If provided uses this as a check before continuing to the next action. Or you can * provide a function that returns true to continue to the next action. * @param {Number} [timeout] overrides FuncUnit.timeout. If provided, the wait will fail if not completed before this timeout. * @param {Function} [success] a callback that will run after this action completes. * @param {String} [message] if provided, an assertion will be passed when this wait condition completes successfully * @return {String|funcUnit} if outerWidth is provided, * returns the funcUnit selector for chaining, otherwise returns the outerWidth of the selector. */ 'outerWidth' : 0 }; //makes a jQuery like command. FuncUnit.makeFunc = function(fname, argIndex){ var orig = FuncUnit.fn[fname]; //makes a read / wait function FuncUnit.prototype[fname] = function(){ //assume last arg is success var args = FuncUnit.makeArray(arguments), isWait = args.length > argIndex, success, self = this; args.unshift(this.selector,this.frame,fname) if(isWait){ //get the args greater and equal to argIndex var tester = args[argIndex+3], timeout = args[argIndex+4], success = args[argIndex+5], message = args[argIndex+6], testVal = tester, errorMessage = "waiting for "+fname +" on " + this.selector, frame = this.frame, logMessage = "Checking "+fname+" on '"+this.selector+"'", ret; // can pass in an object or list of arguments if(typeof tester == 'object' && !(tester instanceof RegExp)){ timeout = tester.timeout; success = tester.success; message = tester.message; if(tester.errorMessage){ errorMessage = tester.errorMessage } if(typeof tester.logMessage !== "undefined"){ logMessage = tester.logMessage } tester = tester.condition; } if(typeof timeout == 'function'){ message = success; success = timeout; timeout = undefined; } if(typeof timeout == 'string'){ message = timeout; timeout = undefined; success = undefined; } if(typeof message !== 'string'){ message = undefined; } args.splice(argIndex+3, args.length- argIndex - 3); if(typeof tester != 'function'){ errorMessage += " !== "+testVal tester = function(val){ return FuncUnit.unit.equiv(val, testVal) || (testVal instanceof RegExp && testVal.test(val) ); } } if(message){ errorMessage = message; } FuncUnit.repeat({ method : function(print){ // keep getting new collection because the page might be updating, we need to keep re-checking if(this.bind.prevObject && this.bind.prevTraverser){ var prev = this.bind; this.bind = this.bind.prevObject[this.bind.prevTraverser](this.bind.prevTraverserSelector) this.bind.prevTraverser = prev.prevTraverser; this.bind.prevTraverserSelector = prev.prevTraverserSelector; } else { // pass false so it will only do one synchronous request this.bind =F(this.selector, { frame: frame, forceSync: true }) } if(logMessage){ print(logMessage) } var methodArgs = []; // might need an argument if(argIndex > 0){ methodArgs.push(args[3]); } // lazy flag to ignore the getter error below FuncUnit._ignoreGetterError = true; ret = this.bind[fname].apply(this.bind, methodArgs) FuncUnit._ignoreGetterError = false; var passed = tester.call(this.bind, ret); // unless this is a "size" command, require size to be non-zero (don't pass through if there's no elements) if(this.bind.length === 0 && fname !== "size"){ passed = false; } if(passed){ // if document is still loading if(!FuncUnit.documentLoaded()){ passed = false; } else { // after every successful wait, check for a new document (if someone clicked a link), // and overwrite alert/confirm/prompt // TODO this creates a potential race if a new document is loaded but its steal isn't ready...should poll FuncUnit.checkForNewDocument(); } } return passed; }, success : function(){ if(message){ FuncUnit.unit.assertOK(true, message) } success && success.apply(this, arguments); }, error : function(){ var msg = errorMessage; if(ret){ msg += ", actual value: "+ret; } FuncUnit.unit.assertOK(false, msg); }, timeout : timeout, bind: this, type: "wait" }) return this; }else{ // throw a warning if user tries to use a getter after the start of the test (if there are other async methods) if(!FuncUnit._ignoreGetterError && !FuncUnit._incallback && FuncUnit._haveAsyncQueries()){ console && console.error("You can't run getters after actions and waits. Please put your getters in a callback or at the beginning of the test.") } // just call the original jQ method var methodArgs = []; if(argIndex > 0){ methodArgs.push(args[3]); } return orig.apply(this, methodArgs); } } } for (var prop in FuncUnit.funcs) { FuncUnit.makeFunc(prop, FuncUnit.funcs[prop]); } module.exports = FuncUnit;