How to use shorthand method in wpt

Best JavaScript code snippet using wpt

ui-element.js

Source:ui-element.js Github

copy

Full Screen

1//******************************************************************************2// Globals, including constants3var UI_GLOBAL = {4 UI_PREFIX: 'ui'5 , XHTML_DOCTYPE: '<!DOCTYPE html PUBLIC '6 + '"-//W3C//DTD XHTML 1.0 Strict//EN" '7 + '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'8 , XHTML_XMLNS: 'http://www.w3.org/1999/xhtml'9};10//*****************************************************************************11// Exceptions12function UIElementException(message)13{14 this.message = message;15 this.name = 'UIElementException';16}17function UIArgumentException(message)18{19 this.message = message;20 this.name = 'UIArgumentException';21}22function PagesetException(message)23{24 this.message = message;25 this.name = 'PagesetException';26}27function UISpecifierException(message)28{29 this.message = message;30 this.name = 'UISpecifierException';31}32function CommandMatcherException(message)33{34 this.message = message;35 this.name = 'CommandMatcherException';36}37//*****************************************************************************38// UI-Element core39/**40 * The UIElement object. This has been crafted along with UIMap to make41 * specifying UI elements using JSON as simple as possible. Object construction42 * will fail if 1) a proper name isn't provided, 2) a faulty args argument is43 * given, or 3) getLocator() returns undefined for a valid permutation of44 * default argument values. See ui-doc.html for the documentation on the45 * builder syntax.46 *47 * @param uiElementShorthand an object whose contents conform to the48 * UI-Element builder syntax.49 *50 * @return a new UIElement object51 * @throws UIElementException52 */53function UIElement(uiElementShorthand)54{55 // a shorthand object might look like:56 //57 // {58 // name: 'topic'59 // , description: 'sidebar links to topic categories'60 // , args: [61 // {62 // name: 'name'63 // , description: 'the name of the topic'64 // , defaultValues: topLevelTopics65 // }66 // ]67 // , getLocator: function(args) {68 // return this._listXPath +69 // "/a[text()=" + args.name.quoteForXPath() + "]";70 // }71 // , getGenericLocator: function() {72 // return this._listXPath + '/a';73 // }74 // // maintain testcases for getLocator()75 // , testcase1: {76 // // defaultValues used if args not specified77 // args: { name: 'foo' }78 // , xhtml: '<div id="topiclist">'79 // + '<ul><li><a expected-result="1">foo</a></li></ul>'80 // + '</div>'81 // }82 // // set a local element variable83 // , _listXPath: "//div[@id='topiclist']/ul/li"84 // }85 //86 // name cannot be null or an empty string. Enforce the same requirement for87 // the description.88 89 /**90 * Recursively returns all permutations of argument-value pairs, given91 * a list of argument definitions. Each argument definition will have92 * a set of default values to use in generating said pairs. If an argument93 * has no default values defined, it will not be included among the94 * permutations.95 *96 * @param args a list of UIArguments97 * @param inDocument the document object to pass to the getDefaultValues()98 * method of each argument.99 *100 * @return a list of associative arrays containing key value pairs101 */102 this.permuteArgs = function(args, inDocument) {103 if (args.length == 0) {104 return [];105 }106 107 var permutations = [];108 var arg = args[0];109 var remainingArgs = args.slice(1);110 var subsequentPermutations = this.permuteArgs(remainingArgs,111 inDocument);112 var defaultValues = arg.getDefaultValues(inDocument);113 114 // skip arguments for which no default values are defined. If the115 // argument is a required one, then no permutations are possible.116 if (defaultValues.length == 0) {117 if (arg.required) {118 return [];119 }120 else {121 return subsequentPermutations;122 }123 }124 125 for (var i = 0; i < defaultValues.length; ++i) {126 var value = defaultValues[i];127 var permutation;128 129 if (subsequentPermutations.length == 0) {130 permutation = {};131 permutation[arg.name] = value + "";132 permutations.push(permutation);133 }134 else {135 for (var j = 0; j < subsequentPermutations.length; ++j) {136 permutation = clone(subsequentPermutations[j]);137 permutation[arg.name] = value + "";138 permutations.push(permutation);139 }140 }141 }142 143 return permutations;144 }145 146 147 148 /**149 * Returns a list of all testcases for this UIElement.150 */151 this.getTestcases = function()152 {153 return this.testcases;154 }155 156 157 158 /**159 * Run all unit tests, stopping at the first failure, if any. Return true160 * if no failures encountered, false otherwise. See the following thread161 * regarding use of getElementById() on XML documents created by parsing162 * text via the DOMParser:163 *164 * http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/2b1b82b3c53a1282/165 */166 this.test = function()167 {168 var parser = new DOMParser();169 var testcases = this.getTestcases();170 testcaseLoop: for (var i = 0; i < testcases.length; ++i) {171 var testcase = testcases[i];172 var xhtml = UI_GLOBAL.XHTML_DOCTYPE + '<html xmlns="'173 + UI_GLOBAL.XHTML_XMLNS + '">' + testcase.xhtml + '</html>';174 var doc = parser.parseFromString(xhtml, "text/xml");175 if (doc.firstChild.nodeName == 'parsererror') {176 safe_alert('Error parsing XHTML in testcase "' + testcase.name177 + '" for UI element "' + this.name + '": ' + "\n"178 + doc.firstChild.firstChild.nodeValue);179 }180 181 // we're no longer using the default locators when testing, because182 // args is now required183 var locator = parse_locator(this.getLocator(testcase.args));184 var results;185 186 if (locator.type == 'xpath' || (locator.type == 'implicit' &&187 locator.string.substring(0, 2) == '//')) {188 // try using the javascript xpath engine to avoid namespace189 // issues. The xpath does have to be lowercase however, it190 // seems. 191 results = eval_xpath(locator.string, doc,192 { allowNativeXpath: false, returnOnFirstMatch: true });193 }194 else {195 // piece the locator back together196 locator = (locator.type == 'implicit')197 ? locator.string198 : locator.type + '=' + locator.string;199 results = eval_locator(locator, doc);200 }201 202 if (results.length && results[0].hasAttribute('expected-result')) {203 continue testcaseLoop;204 }205 206 // testcase failed207 if (is_IDE()) {208 var msg = 'Testcase "' + testcase.name209 + '" failed for UI element "' + this.name + '":';210 if (!results.length) {211 msg += '\n"' + (locator.string || locator) + '" did not match any elements!';212 }213 else {214 msg += '\n' + results[0] + ' was not the expected result!';215 }216 safe_alert(msg);217 }218 return false;219 }220 return true;221 };222 223 224 225 /**226 * Creates a set of locators using permutations of default values for227 * arguments used in the locator construction. The set is returned as an228 * object mapping locators to key-value arguments objects containing the229 * values passed to getLocator() to create the locator.230 *231 * @param opt_inDocument (optional) the document object of the "current"232 * page when this method is invoked. Some arguments233 * may have default value lists that are calculated234 * based on the contents of the page.235 *236 * @return a list of locator strings237 * @throws UIElementException238 */239 this.getDefaultLocators = function(opt_inDocument) {240 var defaultLocators = {};241 if (this.args.length == 0) {242 defaultLocators[this.getLocator({})] = {};243 }244 else {245 var permutations = this.permuteArgs(this.args, opt_inDocument);246 if (permutations.length != 0) {247 for (var i = 0; i < permutations.length; ++i) {248 var args = permutations[i];249 var locator = this.getLocator(args);250 if (!locator) {251 throw new UIElementException('Error in UIElement(): '252 + 'no getLocator return value for element "' + name253 + '"');254 }255 defaultLocators[locator] = args;256 }257 }258 else {259 // try using no arguments. Parse the locator to make sure it's260 // really good. If it doesn't work, fine.261 try {262 var locator = this.getLocator();263 parse_locator(locator);264 defaultLocators[locator] = {};265 }266 catch (e) {267 safe_log('debug', e.message);268 }269 }270 }271 return defaultLocators;272 };273 274 275 276 /**277 * Validate the structure of the shorthand notation this object is being278 * initialized with. Throws an exception if there's a validation error.279 *280 * @param uiElementShorthand281 *282 * @throws UIElementException283 */284 this.validate = function(uiElementShorthand)285 {286 var msg = "UIElement validation error:\n" + print_r(uiElementShorthand);287 if (!uiElementShorthand.name) {288 throw new UIElementException(msg + 'no name specified!');289 }290 if (!uiElementShorthand.description) {291 throw new UIElementException(msg + 'no description specified!');292 }293 if (!uiElementShorthand.locator294 && !uiElementShorthand.getLocator295 && !uiElementShorthand.xpath296 && !uiElementShorthand.getXPath) {297 throw new UIElementException(msg + 'no locator specified!');298 }299 };300 301 302 303 this.init = function(uiElementShorthand)304 {305 this.validate(uiElementShorthand);306 307 this.name = uiElementShorthand.name;308 this.description = uiElementShorthand.description;309 310 // construct a new getLocator() method based on the locator property,311 // or use the provided function. We're deprecating the xpath property312 // and getXPath() function, but still allow for them for backwards313 // compatability.314 if (uiElementShorthand.locator) {315 this.getLocator = function(args) {316 return uiElementShorthand.locator;317 };318 }319 else if (uiElementShorthand.getLocator) {320 this.getLocator = uiElementShorthand.getLocator;321 }322 else if (uiElementShorthand.xpath) {323 this.getLocator = function(args) {324 return uiElementShorthand.xpath;325 };326 }327 else {328 this.getLocator = uiElementShorthand.getXPath;329 }330 331 if (uiElementShorthand.genericLocator) {332 this.getGenericLocator = function() {333 return uiElementShorthand.genericLocator;334 };335 }336 else if (uiElementShorthand.getGenericLocator) {337 this.getGenericLocator = uiElementShorthand.getGenericLocator;338 }339 340 if (uiElementShorthand.getOffsetLocator) {341 this.getOffsetLocator = uiElementShorthand.getOffsetLocator;342 }343 344 // get the testcases and local variables345 this.testcases = [];346 var localVars = {};347 for (var attr in uiElementShorthand) {348 if (attr.match(/^testcase/)) {349 var testcase = uiElementShorthand[attr];350 if (uiElementShorthand.args &&351 uiElementShorthand.args.length && !testcase.args) {352 safe_alert('No args defined in ' + attr + ' for UI element '353 + this.name + '! Skipping testcase.');354 continue;355 } 356 testcase.name = attr;357 this.testcases.push(testcase);358 }359 else if (attr.match(/^_/)) {360 this[attr] = uiElementShorthand[attr];361 localVars[attr] = uiElementShorthand[attr];362 }363 }364 365 // create the arguments366 this.args = []367 this.argsOrder = [];368 if (uiElementShorthand.args) {369 for (var i = 0; i < uiElementShorthand.args.length; ++i) {370 var arg = new UIArgument(uiElementShorthand.args[i], localVars);371 this.args.push(arg);372 this.argsOrder.push(arg.name);373 // if an exception is thrown when invoking getDefaultValues()374 // with no parameters passed in, assume the method requires an375 // inDocument parameter, and thus may only be invoked at run376 // time. Mark the UI element object accordingly.377 try {378 arg.getDefaultValues();379 }380 catch (e) {381 this.isDefaultLocatorConstructionDeferred = true;382 }383 }384 385 }386 387 if (!this.isDefaultLocatorConstructionDeferred) {388 this.defaultLocators = this.getDefaultLocators();389 }390 };391 392 393 394 this.init(uiElementShorthand);395}396// hang this off the UIElement "namespace". This is a composite strategy.397UIElement.defaultOffsetLocatorStrategy = function(locatedElement, pageElement) {398 var strategies = [399 UIElement.linkXPathOffsetLocatorStrategy400 , UIElement.preferredAttributeXPathOffsetLocatorStrategy401 , UIElement.simpleXPathOffsetLocatorStrategy402 ];403 404 for (var i = 0; i < strategies.length; ++i) {405 var strategy = strategies[i];406 var offsetLocator = strategy(locatedElement, pageElement);407 408 if (offsetLocator) {409 return offsetLocator;410 }411 }412 413 return null;414};415UIElement.simpleXPathOffsetLocatorStrategy = function(locatedElement,416 pageElement)417{418 if (is_ancestor(locatedElement, pageElement)) {419 var xpath = "";420 var recorder = Recorder.get(locatedElement.ownerDocument.defaultView);421 var locatorBuilders = recorder.locatorBuilders;422 var currentNode = pageElement;423 424 while (currentNode != null && currentNode != locatedElement) {425 xpath = locatorBuilders.relativeXPathFromParent(currentNode)426 + xpath;427 currentNode = currentNode.parentNode;428 }429 430 var results = eval_xpath(xpath, locatedElement.ownerDocument,431 { contextNode: locatedElement });432 433 if (results.length > 0 && results[0] == pageElement) {434 return xpath;435 }436 }437 438 return null;439};440UIElement.linkXPathOffsetLocatorStrategy = function(locatedElement, pageElement)441{442 if (pageElement.nodeName == 'A' && is_ancestor(locatedElement, pageElement))443 {444 var text = pageElement.textContent445 .replace(/^\s+/, "")446 .replace(/\s+$/, "");447 448 if (text) {449 var xpath = '/descendant::a[normalize-space()='450 + text.quoteForXPath() + ']';451 452 var results = eval_xpath(xpath, locatedElement.ownerDocument,453 { contextNode: locatedElement });454 455 if (results.length > 0 && results[0] == pageElement) {456 return xpath;457 }458 }459 }460 461 return null;462};463// compare to the "xpath:attributes" locator strategy defined in the IDE source464UIElement.preferredAttributeXPathOffsetLocatorStrategy =465 function(locatedElement, pageElement)466{467 // this is an ordered listing of single attributes468 var preferredAttributes = [469 'name'470 , 'value'471 , 'type'472 , 'action'473 , 'alt'474 , 'title'475 , 'class'476 , 'src'477 , 'href'478 , 'onclick'479 ];480 481 if (is_ancestor(locatedElement, pageElement)) {482 var xpathBase = '/descendant::' + pageElement.nodeName.toLowerCase();483 484 for (var i = 0; i < preferredAttributes.length; ++i) {485 var name = preferredAttributes[i];486 var value = pageElement.getAttribute(name);487 488 if (value) {489 var xpath = xpathBase + '[@' + name + '='490 + value.quoteForXPath() + ']';491 492 var results = eval_xpath(xpath, locatedElement.ownerDocument,493 { contextNode: locatedElement });494 495 if (results.length > 0 && results[0] == pageElement) {496 return xpath;497 }498 }499 }500 }501 502 return null;503};504/**505 * Constructs a UIArgument. This is mostly for checking that the values are506 * valid.507 *508 * @param uiArgumentShorthand509 * @param localVars510 *511 * @throws UIArgumentException512 */513function UIArgument(uiArgumentShorthand, localVars)514{515 /**516 * @param uiArgumentShorthand517 *518 * @throws UIArgumentException519 */520 this.validate = function(uiArgumentShorthand)521 {522 var msg = "UIArgument validation error:\n"523 + print_r(uiArgumentShorthand);524 525 // try really hard to throw an exception!526 if (!uiArgumentShorthand.name) {527 throw new UIArgumentException(msg + 'no name specified!');528 }529 if (!uiArgumentShorthand.description) {530 throw new UIArgumentException(msg + 'no description specified!');531 }532 if (!uiArgumentShorthand.defaultValues &&533 !uiArgumentShorthand.getDefaultValues) {534 throw new UIArgumentException(msg + 'no default values specified!');535 }536 };537 538 539 540 /**541 * @param uiArgumentShorthand542 * @param localVars a list of local variables543 */544 this.init = function(uiArgumentShorthand, localVars)545 {546 this.validate(uiArgumentShorthand);547 548 this.name = uiArgumentShorthand.name;549 this.description = uiArgumentShorthand.description;550 this.required = uiArgumentShorthand.required || false;551 552 if (uiArgumentShorthand.defaultValues) {553 var defaultValues = uiArgumentShorthand.defaultValues;554 this.getDefaultValues =555 function() { return defaultValues; }556 }557 else {558 this.getDefaultValues = uiArgumentShorthand.getDefaultValues;559 }560 561 for (var name in localVars) {562 this[name] = localVars[name];563 }564 }565 566 567 568 this.init(uiArgumentShorthand, localVars);569}570/**571 * The UISpecifier constructor is overloaded. If less than three arguments are572 * provided, the first argument will be considered a UI specifier string, and573 * will be split out accordingly. Otherwise, the first argument will be574 * considered the path.575 *576 * @param uiSpecifierStringOrPagesetName a UI specifier string, or the pageset577 * name of the UI specifier578 * @param elementName the name of the element579 * @param args an object associating keys to values580 *581 * @return new UISpecifier object582 */583function UISpecifier(uiSpecifierStringOrPagesetName, elementName, args)584{585 /**586 * Initializes this object from a UI specifier string of the form:587 *588 * pagesetName::elementName(arg1=value1, arg2=value2, ...)589 *590 * into its component parts, and returns them as an object.591 *592 * @return an object containing the components of the UI specifier593 * @throws UISpecifierException594 */595 this._initFromUISpecifierString = function(uiSpecifierString) {596 var matches = /^(.*)::([^\(]+)\((.*)\)$/.exec(uiSpecifierString);597 if (matches == null) {598 throw new UISpecifierException('Error in '599 + 'UISpecifier._initFromUISpecifierString(): "'600 + this.string + '" is not a valid UI specifier string');601 }602 this.pagesetName = matches[1];603 this.elementName = matches[2];604 this.args = (matches[3]) ? parse_kwargs(matches[3]) : {};605 };606 607 608 609 /**610 * Override the toString() method to return the UI specifier string when611 * evaluated in a string context. Combines the UI specifier components into612 * a canonical UI specifier string and returns it.613 *614 * @return a UI specifier string615 */616 this.toString = function() {617 // empty string is acceptable for the path, but it must be defined618 if (this.pagesetName == undefined) {619 throw new UISpecifierException('Error in UISpecifier.toString(): "'620 + this.pagesetName + '" is not a valid UI specifier pageset '621 + 'name');622 }623 if (!this.elementName) {624 throw new UISpecifierException('Error in UISpecifier.unparse(): "'625 + this.elementName + '" is not a valid UI specifier element '626 + 'name');627 }628 if (!this.args) {629 throw new UISpecifierException('Error in UISpecifier.unparse(): "'630 + this.args + '" are not valid UI specifier args');631 }632 633 uiElement = UIMap.getInstance()634 .getUIElement(this.pagesetName, this.elementName);635 if (uiElement != null) {636 var kwargs = to_kwargs(this.args, uiElement.argsOrder);637 }638 else {639 // probably under unit test640 var kwargs = to_kwargs(this.args);641 }642 643 return this.pagesetName + '::' + this.elementName + '(' + kwargs + ')';644 };645 646 // construct the object647 if (arguments.length < 2) {648 this._initFromUISpecifierString(uiSpecifierStringOrPagesetName);649 }650 else {651 this.pagesetName = uiSpecifierStringOrPagesetName;652 this.elementName = elementName;653 this.args = (args) ? clone(args) : {};654 }655}656function Pageset(pagesetShorthand)657{658 /**659 * Returns true if the page is included in this pageset, false otherwise.660 * The page is specified by a document object.661 *662 * @param inDocument the document object representing the page663 */664 this.contains = function(inDocument)665 {666 var urlParts = parseUri(unescape(inDocument.location.href));667 var path = urlParts.path668 .replace(/^\//, "")669 .replace(/\/$/, "");670 if (!this.pathRegexp.test(path)) {671 return false;672 }673 for (var paramName in this.paramRegexps) {674 var paramRegexp = this.paramRegexps[paramName];675 if (!paramRegexp.test(urlParts.queryKey[paramName])) {676 return false;677 }678 }679 if (!this.pageContent(inDocument)) {680 return false;681 }682 683 return true;684 }685 686 687 688 this.getUIElements = function()689 {690 var uiElements = [];691 for (var uiElementName in this.uiElements) {692 uiElements.push(this.uiElements[uiElementName]);693 }694 return uiElements;695 };696 697 698 699 /**700 * Returns a list of UI specifier string stubs representing all UI elements701 * for this pageset. Stubs contain all required arguments, but leave702 * argument values blank. Each element stub is paired with the element's703 * description.704 *705 * @return a list of UI specifier string stubs706 */707 this.getUISpecifierStringStubs = function()708 {709 var stubs = [];710 for (var name in this.uiElements) {711 var uiElement = this.uiElements[name];712 var args = {};713 for (var i = 0; i < uiElement.args.length; ++i) {714 args[uiElement.args[i].name] = '';715 }716 var uiSpecifier = new UISpecifier(this.name, uiElement.name, args);717 stubs.push([718 UI_GLOBAL.UI_PREFIX + '=' + uiSpecifier.toString()719 , uiElement.description720 ]);721 }722 return stubs;723 }724 725 726 727 /**728 * Throws an exception on validation failure.729 */730 this._validate = function(pagesetShorthand)731 {732 var msg = "Pageset validation error:\n"733 + print_r(pagesetShorthand);734 if (!pagesetShorthand.name) {735 throw new PagesetException(msg + 'no name specified!');736 }737 if (!pagesetShorthand.description) {738 throw new PagesetException(msg + 'no description specified!');739 }740 if (!pagesetShorthand.paths &&741 !pagesetShorthand.pathRegexp &&742 !pagesetShorthand.pageContent) {743 throw new PagesetException(msg744 + 'no path, pathRegexp, or pageContent specified!');745 }746 };747 748 749 750 this.init = function(pagesetShorthand)751 {752 this._validate(pagesetShorthand);753 754 this.name = pagesetShorthand.name;755 this.description = pagesetShorthand.description;756 757 var pathPrefixRegexp = pagesetShorthand.pathPrefix758 ? RegExp.escape(pagesetShorthand.pathPrefix) : "";759 var pathRegexp = '^' + pathPrefixRegexp;760 761 if (pagesetShorthand.paths != undefined) {762 pathRegexp += '(?:';763 for (var i = 0; i < pagesetShorthand.paths.length; ++i) {764 if (i > 0) {765 pathRegexp += '|';766 }767 pathRegexp += RegExp.escape(pagesetShorthand.paths[i]);768 }769 pathRegexp += ')$';770 }771 else if (pagesetShorthand.pathRegexp) {772 pathRegexp += '(?:' + pagesetShorthand.pathRegexp + ')$';773 }774 this.pathRegexp = new RegExp(pathRegexp);775 this.paramRegexps = {};776 for (var paramName in pagesetShorthand.paramRegexps) {777 this.paramRegexps[paramName] =778 new RegExp(pagesetShorthand.paramRegexps[paramName]);779 }780 this.pageContent = pagesetShorthand.pageContent ||781 function() { return true; };782 this.uiElements = {};783 };784 785 786 787 this.init(pagesetShorthand);788}789/**790 * Construct the UI map object, and return it. Once the object is instantiated,791 * it binds to a global variable and will not leave scope.792 *793 * @return new UIMap object794 */795function UIMap()796{797 // the singleton pattern, split into two parts so that "new" can still798 // be used, in addition to "getInstance()"799 UIMap.self = this;800 801 // need to attach variables directly to the Editor object in order for them802 // to be in scope for Editor methods803 if (is_IDE()) {804 Editor.uiMap = this;805 Editor.UI_PREFIX = UI_GLOBAL.UI_PREFIX;806 }807 808 this.pagesets = new Object();809 810 811 812 /**813 * pageset[pagesetName]814 * regexp815 * elements[elementName]816 * UIElement817 */818 this.addPageset = function(pagesetShorthand)819 {820 try {821 var pageset = new Pageset(pagesetShorthand);822 }823 catch (e) {824 safe_alert("Could not create pageset from shorthand:\n"825 + print_r(pagesetShorthand) + "\n" + e.message);826 return false;827 }828 829 if (this.pagesets[pageset.name]) {830 safe_alert('Could not add pageset "' + pageset.name831 + '": a pageset with that name already exists!');832 return false;833 }834 835 this.pagesets[pageset.name] = pageset;836 return true;837 };838 839 840 841 /**842 * @param pagesetName843 * @param uiElementShorthand a representation of a UIElement object in844 * shorthand JSON.845 */846 this.addElement = function(pagesetName, uiElementShorthand)847 {848 try {849 var uiElement = new UIElement(uiElementShorthand);850 }851 catch (e) {852 safe_alert("Could not create UI element from shorthand:\n"853 + print_r(uiElementShorthand) + "\n" + e.message);854 return false;855 }856 857 // run the element's unit tests only for the IDE, and only when the858 // IDE is starting. Make a rough guess as to the latter condition.859 if (is_IDE() && !editor.selDebugger && !uiElement.test()) {860 safe_alert('Could not add UI element "' + uiElement.name861 + '": failed testcases!');862 return false;863 }864 865 try {866 this.pagesets[pagesetName].uiElements[uiElement.name] = uiElement;867 }868 catch (e) {869 safe_alert("Could not add UI element '" + uiElement.name870 + "' to pageset '" + pagesetName + "':\n" + e.message);871 return false;872 }873 874 return true;875 };876 877 878 879 /**880 * Returns the pageset for a given UI specifier string.881 *882 * @param uiSpecifierString883 * @return a pageset object884 */885 this.getPageset = function(uiSpecifierString)886 {887 try {888 var uiSpecifier = new UISpecifier(uiSpecifierString);889 return this.pagesets[uiSpecifier.pagesetName];890 }891 catch (e) {892 return null;893 }894 }895 896 897 898 /**899 * Returns the UIElement that a UISpecifierString or pageset and element900 * pair refer to.901 *902 * @param pagesetNameOrUISpecifierString903 * @return a UIElement, or null if none is found associated with904 * uiSpecifierString905 */906 this.getUIElement = function(pagesetNameOrUISpecifierString, uiElementName)907 {908 var pagesetName = pagesetNameOrUISpecifierString;909 if (arguments.length == 1) {910 var uiSpecifierString = pagesetNameOrUISpecifierString;911 try {912 var uiSpecifier = new UISpecifier(uiSpecifierString);913 pagesetName = uiSpecifier.pagesetName;914 var uiElementName = uiSpecifier.elementName;915 }916 catch (e) {917 return null;918 }919 }920 try {921 return this.pagesets[pagesetName].uiElements[uiElementName];922 }923 catch (e) {924 return null;925 }926 };927 928 929 930 /**931 * Returns a list of pagesets that "contains" the provided page,932 * represented as a document object. Containership is defined by the933 * Pageset object's contain() method.934 *935 * @param inDocument the page to get pagesets for936 * @return a list of pagesets937 */938 this.getPagesetsForPage = function(inDocument)939 {940 var pagesets = [];941 for (var pagesetName in this.pagesets) {942 var pageset = this.pagesets[pagesetName];943 if (pageset.contains(inDocument)) {944 pagesets.push(pageset);945 }946 }947 return pagesets;948 };949 950 951 952 /**953 * Returns a list of all pagesets.954 *955 * @return a list of pagesets956 */957 this.getPagesets = function()958 {959 var pagesets = [];960 for (var pagesetName in this.pagesets) {961 pagesets.push(this.pagesets[pagesetName]);962 }963 return pagesets;964 };965 966 967 968 /**969 * Returns a list of elements on a page that a given UI specifier string,970 * maps to. If no elements are mapped to, returns an empty list..971 *972 * @param uiSpecifierString a String that specifies a UI element with973 * attendant argument values974 * @param inDocument the document object the specified UI element975 * appears in976 * @return a potentially-empty list of elements977 * specified by uiSpecifierString978 */979 this.getPageElements = function(uiSpecifierString, inDocument)980 {981 var locator = this.getLocator(uiSpecifierString);982 var results = locator ? eval_locator(locator, inDocument) : [];983 return results;984 };985 986 987 988 /**989 * Returns the locator string that a given UI specifier string maps to, or990 * null if it cannot be mapped.991 *992 * @param uiSpecifierString993 */994 this.getLocator = function(uiSpecifierString)995 {996 try {997 var uiSpecifier = new UISpecifier(uiSpecifierString);998 }999 catch (e) {1000 safe_alert('Could not create UISpecifier for string "'1001 + uiSpecifierString + '": ' + e.message);1002 return null;1003 }1004 1005 var uiElement = this.getUIElement(uiSpecifier.pagesetName,1006 uiSpecifier.elementName);1007 try {1008 return uiElement.getLocator(uiSpecifier.args);1009 }1010 catch (e) {1011 return null;1012 }1013 }1014 1015 1016 1017 /**1018 * Finds and returns a UI specifier string given an element and the page1019 * that it appears on.1020 *1021 * @param pageElement the document element to map to a UI specifier1022 * @param inDocument the document the element appears in1023 * @return a UI specifier string, or false if one cannot be1024 * constructed1025 */1026 this.getUISpecifierString = function(pageElement, inDocument)1027 {1028 var is_fuzzy_match =1029 BrowserBot.prototype.locateElementByUIElement.is_fuzzy_match;1030 var pagesets = this.getPagesetsForPage(inDocument);1031 1032 for (var i = 0; i < pagesets.length; ++i) {1033 var pageset = pagesets[i];1034 var uiElements = pageset.getUIElements();1035 1036 for (var j = 0; j < uiElements.length; ++j) {1037 var uiElement = uiElements[j];1038 1039 // first test against the generic locator, if there is one.1040 // This should net some performance benefit when recording on1041 // more complicated pages.1042 if (uiElement.getGenericLocator) {1043 var passedTest = false;1044 var results =1045 eval_locator(uiElement.getGenericLocator(), inDocument);1046 for (var i = 0; i < results.length; ++i) {1047 if (results[i] == pageElement) {1048 passedTest = true;1049 break;1050 }1051 }1052 if (!passedTest) {1053 continue;1054 }1055 }1056 1057 var defaultLocators;1058 if (uiElement.isDefaultLocatorConstructionDeferred) {1059 defaultLocators = uiElement.getDefaultLocators(inDocument);1060 }1061 else {1062 defaultLocators = uiElement.defaultLocators;1063 }1064 1065 //safe_alert(print_r(uiElement.defaultLocators));1066 for (var locator in defaultLocators) {1067 var locatedElements = eval_locator(locator, inDocument);1068 if (locatedElements.length) {1069 var locatedElement = locatedElements[0];1070 }1071 else {1072 continue;1073 }1074 1075 // use a heuristic to determine whether the element1076 // specified is the "same" as the element we're matching1077 if (is_fuzzy_match) {1078 if (is_fuzzy_match(locatedElement, pageElement)) {1079 return UI_GLOBAL.UI_PREFIX + '=' +1080 new UISpecifier(pageset.name, uiElement.name,1081 defaultLocators[locator]);1082 }1083 }1084 else {1085 if (locatedElement == pageElement) {1086 return UI_GLOBAL.UI_PREFIX + '=' +1087 new UISpecifier(pageset.name, uiElement.name,1088 defaultLocators[locator]);1089 }1090 }1091 1092 // ok, matching the element failed. See if an offset1093 // locator can complete the match.1094 if (uiElement.getOffsetLocator) {1095 for (var k = 0; k < locatedElements.length; ++k) {1096 var offsetLocator = uiElement1097 .getOffsetLocator(locatedElements[k], pageElement);1098 if (offsetLocator) {1099 return UI_GLOBAL.UI_PREFIX + '=' +1100 new UISpecifier(pageset.name,1101 uiElement.name,1102 defaultLocators[locator])1103 + '->' + offsetLocator;1104 }1105 }1106 }1107 }1108 }1109 }1110 return false;1111 };1112 1113 1114 1115 /**1116 * Returns a sorted list of UI specifier string stubs representing possible1117 * UI elements for all pagesets, paired the their descriptions. Stubs1118 * contain all required arguments, but leave argument values blank.1119 *1120 * @return a list of UI specifier string stubs1121 */1122 this.getUISpecifierStringStubs = function() {1123 var stubs = [];1124 var pagesets = this.getPagesets();1125 for (var i = 0; i < pagesets.length; ++i) {1126 stubs = stubs.concat(pagesets[i].getUISpecifierStringStubs());1127 }1128 stubs.sort(function(a, b) {1129 if (a[0] < b[0]) {1130 return -1;1131 }1132 return a[0] == b[0] ? 0 : 1;1133 });1134 return stubs;1135 }1136}1137UIMap.getInstance = function() {1138 return (UIMap.self == null) ? new UIMap() : UIMap.self;1139}1140//******************************************************************************1141// Rollups1142/**1143 * The Command object isn't available in the Selenium RC. We introduce an1144 * object with the identical constructor. In the IDE, this will be redefined,1145 * which is just fine.1146 *1147 * @param command1148 * @param target1149 * @param value1150 */1151if (typeof(Command) == 'undefined') {1152 function Command(command, target, value) {1153 this.command = command != null ? command : '';1154 this.target = target != null ? target : '';1155 this.value = value != null ? value : '';1156 }1157}1158/**1159 * A CommandMatcher object matches commands during the application of a1160 * RollupRule. It's specified with a shorthand format, for example:1161 *1162 * new CommandMatcher({1163 * command: 'click'1164 * , target: 'ui=allPages::.+'1165 * })1166 *1167 * which is intended to match click commands whose target is an element in the1168 * allPages PageSet. The matching expressions are given as regular expressions;1169 * in the example above, the command must be "click"; "clickAndWait" would be1170 * acceptable if 'click.*' were used. Here's a more complete example:1171 *1172 * new CommandMatcher({1173 * command: 'type'1174 * , target: 'ui=loginPages::username()'1175 * , value: '.+_test'1176 * , updateArgs: function(command, args) {1177 * args.username = command.value;1178 * }1179 * })1180 *1181 * Here, the command and target are fixed, but there is variability in the 1182 * value of the command. When a command matches, the username is saved to the1183 * arguments object.1184 */1185function CommandMatcher(commandMatcherShorthand)1186{1187 /**1188 * Ensure the shorthand notation used to initialize the CommandMatcher has1189 * all required values.1190 *1191 * @param commandMatcherShorthand an object containing information about1192 * the CommandMatcher1193 */1194 this.validate = function(commandMatcherShorthand) {1195 var msg = "CommandMatcher validation error:\n"1196 + print_r(commandMatcherShorthand);1197 if (!commandMatcherShorthand.command) {1198 throw new CommandMatcherException(msg + 'no command specified!');1199 }1200 if (!commandMatcherShorthand.target) {1201 throw new CommandMatcherException(msg + 'no target specified!');1202 }1203 if (commandMatcherShorthand.minMatches &&1204 commandMatcherShorthand.maxMatches &&1205 commandMatcherShorthand.minMatches >1206 commandMatcherShorthand.maxMatches) {1207 throw new CommandMatcherException(msg + 'minMatches > maxMatches!');1208 }1209 };1210 /**1211 * Initialize this object.1212 *1213 * @param commandMatcherShorthand an object containing information used to1214 * initialize the CommandMatcher1215 */1216 this.init = function(commandMatcherShorthand) {1217 this.validate(commandMatcherShorthand);1218 1219 this.command = commandMatcherShorthand.command;1220 this.target = commandMatcherShorthand.target;1221 this.value = commandMatcherShorthand.value || null;1222 this.minMatches = commandMatcherShorthand.minMatches || 1;1223 this.maxMatches = commandMatcherShorthand.maxMatches || 1;1224 this.updateArgs = commandMatcherShorthand.updateArgs ||1225 function(command, args) { return args; };1226 };1227 1228 /**1229 * Determines whether a given command matches. Updates args by "reference"1230 * and returns true if it does; return false otherwise.1231 *1232 * @param command the command to attempt to match1233 */1234 this.isMatch = function(command) {1235 var re = new RegExp('^' + this.command + '$');1236 if (! re.test(command.command)) {1237 return false;1238 }1239 re = new RegExp('^' + this.target + '$');1240 if (! re.test(command.target)) {1241 return false;1242 }1243 if (this.value != null) {1244 re = new RegExp('^' + this.value + '$');1245 if (! re.test(command.value)) {1246 return false;1247 }1248 }1249 1250 // okay, the command matches1251 return true;1252 };1253 1254 // initialization1255 this.init(commandMatcherShorthand);1256}1257function RollupRuleException(message)1258{1259 this.message = message;1260 this.name = 'RollupRuleException';1261}1262function RollupRule(rollupRuleShorthand)1263{1264 /**1265 * Ensure the shorthand notation used to initialize the RollupRule has all1266 * required values.1267 *1268 * @param rollupRuleShorthand an object containing information about the1269 * RollupRule1270 */1271 this.validate = function(rollupRuleShorthand) {1272 var msg = "RollupRule validation error:\n"1273 + print_r(rollupRuleShorthand);1274 if (!rollupRuleShorthand.name) {1275 throw new RollupRuleException(msg + 'no name specified!');1276 }1277 if (!rollupRuleShorthand.description) {1278 throw new RollupRuleException(msg + 'no description specified!');1279 }1280 // rollupRuleShorthand.args is optional1281 if (!rollupRuleShorthand.commandMatchers &&1282 !rollupRuleShorthand.getRollup) {1283 throw new RollupRuleException(msg1284 + 'no command matchers specified!');1285 }1286 if (!rollupRuleShorthand.expandedCommands &&1287 !rollupRuleShorthand.getExpandedCommands) {1288 throw new RollupRuleException(msg1289 + 'no expanded commands specified!');1290 }1291 1292 return true;1293 };1294 /**1295 * Initialize this object.1296 *1297 * @param rollupRuleShorthand an object containing information used to1298 * initialize the RollupRule1299 */1300 this.init = function(rollupRuleShorthand) {1301 this.validate(rollupRuleShorthand);1302 1303 this.name = rollupRuleShorthand.name;1304 this.description = rollupRuleShorthand.description;1305 this.pre = rollupRuleShorthand.pre || '';1306 this.post = rollupRuleShorthand.post || '';1307 this.alternateCommand = rollupRuleShorthand.alternateCommand;1308 this.args = rollupRuleShorthand.args || [];1309 1310 if (rollupRuleShorthand.commandMatchers) {1311 // construct the rule from the list of CommandMatchers1312 this.commandMatchers = [];1313 var matchers = rollupRuleShorthand.commandMatchers;1314 for (var i = 0; i < matchers.length; ++i) {1315 if (matchers[i].updateArgs && this.args.length == 0) {1316 // enforce metadata for arguments1317 var msg = "RollupRule validation error:\n"1318 + print_r(rollupRuleShorthand)1319 + 'no argument metadata provided!';1320 throw new RollupRuleException(msg);1321 }1322 this.commandMatchers.push(new CommandMatcher(matchers[i]));1323 }1324 1325 // returns false if the rollup doesn't match, or a rollup command1326 // if it does. If returned, the command contains the1327 // replacementIndexes property, which indicates which commands it1328 // substitutes for.1329 this.getRollup = function(commands) {1330 // this is a greedy matching algorithm1331 var replacementIndexes = [];1332 var commandMatcherQueue = this.commandMatchers;1333 var matchCount = 0;1334 var args = {};1335 for (var i = 0, j = 0; i < commandMatcherQueue.length;) {1336 var matcher = commandMatcherQueue[i];1337 if (j >= commands.length) {1338 // we've run out of commands! If the remaining matchers1339 // do not have minMatches requirements, this is a1340 // match. Otherwise, it's not.1341 if (matcher.minMatches > 0) {1342 return false;1343 }1344 ++i;1345 matchCount = 0; // unnecessary, but let's be consistent1346 }1347 else {1348 if (matcher.isMatch(commands[j])) {1349 ++matchCount;1350 if (matchCount == matcher.maxMatches) {1351 // exhausted this matcher's matches ... move on1352 // to next matcher1353 ++i;1354 matchCount = 0;1355 }1356 args = matcher.updateArgs(commands[j], args);1357 replacementIndexes.push(j);1358 ++j; // move on to next command1359 }1360 else {1361 //alert(matchCount + ', ' + matcher.minMatches);1362 if (matchCount < matcher.minMatches) {1363 return false;1364 }1365 // didn't match this time, but we've satisfied the1366 // requirements already ... move on to next matcher1367 ++i;1368 matchCount = 0;1369 // still gonna look at same command1370 }1371 }1372 }1373 1374 var rollup;1375 if (this.alternateCommand) {1376 rollup = new Command(this.alternateCommand,1377 commands[0].target, commands[0].value);1378 }1379 else {1380 rollup = new Command('rollup', this.name);1381 rollup.value = to_kwargs(args);1382 }1383 rollup.replacementIndexes = replacementIndexes;1384 return rollup;1385 };1386 }1387 else {1388 this.getRollup = function(commands) {1389 var result = rollupRuleShorthand.getRollup(commands);1390 if (result) {1391 var rollup = new Command(1392 result.command1393 , result.target1394 , result.value1395 );1396 rollup.replacementIndexes = result.replacementIndexes;1397 return rollup;1398 }1399 return false;1400 };1401 }1402 1403 this.getExpandedCommands = function(kwargs) {1404 var commands = [];1405 var expandedCommands = (rollupRuleShorthand.expandedCommands1406 ? rollupRuleShorthand.expandedCommands1407 : rollupRuleShorthand.getExpandedCommands(1408 parse_kwargs(kwargs)));1409 for (var i = 0; i < expandedCommands.length; ++i) {1410 var command = expandedCommands[i];1411 commands.push(new Command(1412 command.command1413 , command.target1414 , command.value1415 ));1416 }1417 return commands;1418 };1419 };1420 1421 this.init(rollupRuleShorthand);1422}1423/**1424 *1425 */1426function RollupManager()1427{1428 // singleton pattern1429 RollupManager.self = this;1430 1431 this.init = function()1432 {1433 this.rollupRules = {};1434 if (is_IDE()) {1435 Editor.rollupManager = this;1436 }1437 };1438 /**1439 * Adds a new RollupRule to the repository. Returns true on success, or1440 * false if the rule couldn't be added.1441 *1442 * @param rollupRuleShorthand shorthand JSON specification of the new1443 * RollupRule, possibly including CommandMatcher1444 * shorthand too.1445 * @return true if the rule was added successfully,1446 * false otherwise.1447 */1448 this.addRollupRule = function(rollupRuleShorthand)1449 {1450 try {1451 var rule = new RollupRule(rollupRuleShorthand);1452 this.rollupRules[rule.name] = rule;1453 }1454 catch(e) {1455 smart_alert("Could not create RollupRule from shorthand:\n\n"1456 + e.message);1457 return false;1458 }1459 return true;1460 };1461 1462 /**1463 * Returns a RollupRule by name.1464 *1465 * @param rollupName the name of the rule to fetch1466 * @return the RollupRule, or null if it isn't found.1467 */1468 this.getRollupRule = function(rollupName)1469 {1470 return (this.rollupRules[rollupName] || null);1471 };1472 1473 /**1474 * Returns a list of name-description pairs for use in populating the1475 * auto-populated target dropdown in the IDE. Rules that have an alternate1476 * command defined are not included in the list, as they are not bona-fide1477 * rollups.1478 *1479 * @return a list of name-description pairs1480 */1481 this.getRollupRulesForDropdown = function()1482 {1483 var targets = [];1484 var names = keys(this.rollupRules).sort();1485 for (var i = 0; i < names.length; ++i) {1486 var name = names[i];1487 if (this.rollupRules[name].alternateCommand) {1488 continue;1489 }1490 targets.push([ name, this.rollupRules[name].description ]);1491 }1492 return targets;1493 };1494 1495 /**1496 * Applies all rules to the current editor commands, asking the user in1497 * each case if it's okay to perform the replacement. The rules are applied1498 * repeatedly until there are no more matches. The algorithm should1499 * remember when the user has declined a replacement, and not ask to do it1500 * again.1501 *1502 * @return the list of commands with rollup replacements performed1503 */1504 this.applyRollupRules = function()1505 {1506 var commands = editor.getTestCase().commands;1507 var blacklistedRollups = {};1508 1509 // so long as rollups were performed, we need to keep iterating through1510 // the commands starting at the beginning, because further rollups may1511 // potentially be applied on the newly created ones.1512 while (true) {1513 var performedRollup = false;1514 for (var i = 0; i < commands.length; ++i) {1515 // iterate through commands1516 for (var rollupName in this.rollupRules) {1517 var rule = this.rollupRules[rollupName];1518 var rollup = rule.getRollup(commands.slice(i));1519 if (rollup) {1520 // since we passed in a sliced version of the commands1521 // array to the getRollup() method, we need to re-add 1522 // the offset to the replacementIndexes1523 var k = 0;1524 for (; k < rollup.replacementIndexes.length; ++k) {1525 rollup.replacementIndexes[k] += i;1526 }1527 1528 // build the confirmation message1529 var msg = "Perform the following command rollup?\n\n";1530 for (k = 0; k < rollup.replacementIndexes.length; ++k) {1531 var replacementIndex = rollup.replacementIndexes[k];1532 var command = commands[replacementIndex];1533 msg += '[' + replacementIndex + ']: ';1534 msg += command + "\n";1535 }1536 msg += "\n";1537 msg += rollup;1538 1539 // check against blacklisted rollups1540 if (blacklistedRollups[msg]) {1541 continue;1542 }1543 1544 // highlight the potentially replaced rows1545 for (k = 0; k < commands.length; ++k) {1546 var command = commands[k];1547 command.result = '';1548 if (rollup.replacementIndexes.indexOf(k) != -1) {1549 command.selectedForReplacement = true;1550 }1551 editor.view.rowUpdated(replacementIndex);1552 }1553 1554 // get confirmation from user1555 if (confirm(msg)) {1556 // perform rollup1557 var deleteRanges = [];1558 var replacementIndexes = rollup.replacementIndexes;1559 for (k = 0; k < replacementIndexes.length; ++k) {1560 // this is expected to be list of ranges. A1561 // range has a start, and a list of commands.1562 // The deletion only checks the length of the1563 // command list.1564 deleteRanges.push({1565 start: replacementIndexes[k]1566 , commands: [ 1 ]1567 });1568 }1569 editor.view.executeAction(new TreeView1570 .DeleteCommandAction(editor.view,deleteRanges));1571 editor.view.insertAt(i, rollup);1572 1573 performedRollup = true;1574 }1575 else {1576 // cleverly remember not to try this rollup again1577 blacklistedRollups[msg] = true;1578 }1579 1580 // unhighlight1581 for (k = 0; k < commands.length; ++k) {1582 commands[k].selectedForReplacement = false;1583 editor.view.rowUpdated(k);1584 }1585 }1586 }1587 }1588 if (!performedRollup) {1589 break;1590 }1591 }1592 return commands;1593 };1594 1595 this.init();1596}1597RollupManager.getInstance = function() {1598 return (RollupManager.self == null)1599 ? new RollupManager()1600 : RollupManager.self;...

Full Screen

Full Screen

time.js

Source:time.js Github

copy

Full Screen

1const moment = require('moment-timezone');2const timeShorthandRegex = /^(\+\dd\s)?(\d|1[0-2]):[0-5]\d(a|p|am|pm)$/i;3const timeOffsetRegex = /^-?\d+(\.\d+)?[hms]$/;4const isoTimeRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.?\d*Z/;5class TimeUtil {6 /**7 * Get today in date form.8 */9 static getTodayDate(timezone) {10 return moment.utc().tz(timezone).format('YYYY-MM-DD');11 }12 /**13 * Interpret time shorthand (8:00am), based on a base date and a timezone,14 * into UTC time.15 *16 * Interpret +Nd H:mma by adding a N*24 hours to the date.17 */18 static convertTimeShorthandToIso(shorthand, date, timezone) {19 let addDays = 0;20 if (shorthand[0] === '+' && shorthand.indexOf(' ') > -1) {21 addDays = Number(shorthand.split(' ')[0][1]);22 shorthand = shorthand.split(' ')[1];23 }24 const localTimeString = date + ' ' + shorthand;25 const localFormat = 'YYYY-MM-DD h:mma';26 const localTime = moment27 .tz(localTimeString, localFormat, timezone)28 .add(addDays, 'days');29 return localTime.utc().toISOString();30 }31 /**32 * Convert an ISO timestamp to a human readable time. Time only if today,33 * otherwise include the day.34 */35 static humanizeIso(iso, timezone) {36 const time = moment.utc(iso).tz(timezone);37 const now = moment.utc().tz(timezone);38 const format = time.isSame(now, 'day') ? 'h:mma' : 'ddd, h:mma';39 return time.format(format);40 }41 static validateTimeShorthand(timeShorthand) {42 return timeShorthandRegex.test(timeShorthand);43 }44 /**45 * Humanize a time duration in seconds.46 */47 static humanizeDuration(seconds) {48 const mins = Math.floor(seconds / 60);49 const secs = Math.floor(seconds - (mins * 60));50 return mins + ':' + (secs < 10 ? '0' : '') + secs;51 }52 /**53 * Convert a duration shorthand like 3s or 10m into seconds.54 */55 static secondsForDurationShorthand(durShorthand) {56 if (!durShorthand) {57 return 0;58 }59 const num = Number(durShorthand.substr(0, durShorthand.length - 1));60 const unit = durShorthand.substr(durShorthand.length - 1);61 if (!num || !unit || num < 0) {62 return 0;63 }64 const multiplier = { s: 1, m: 60, h: 3600 }[unit];65 if (!multiplier) {66 return 0;67 }68 return num * multiplier;69 }70 /**71 * Allow positive or negative values for offsets.72 */73 static secondsForOffsetShorthand(offsetShorthand) {74 if (!offsetShorthand) {75 return 0;76 }77 if (offsetShorthand[0] === '-') {78 return -TimeUtil.secondsForDurationShorthand(offsetShorthand.substr(1));79 }80 return TimeUtil.secondsForDurationShorthand(offsetShorthand);81 }82}83TimeUtil.timeShorthandRegex = timeShorthandRegex;84TimeUtil.timeOffsetRegex = timeOffsetRegex;85TimeUtil.isoTimeRegex = isoTimeRegex;...

Full Screen

Full Screen

background-repeat-shorthand.js

Source:background-repeat-shorthand.js Github

copy

Full Screen

1description('Tests that correct shorthand name is returned for background-repeat-x, ' +2 'background-repeat-y, background-position-x, background-position-y, ' +3 '-webkit-mask-repeat-x,-webkit-mask-repeat-y, -webkit-mask-position-x, ' +4 '-webkit-mask-position-y when corresponding shorthand is used in the style ' +5 'declaration. It tests regression described in ' +6 '<a href="https://bugs.webkit.org/show_bug.cgi?id=28972">this bug</a>.');78function getShorthand(longhand, iconId)9{10 var iconDiv = document.getElementById(iconId);11 var rules = window.getMatchedCSSRules(iconDiv,'',false);12 return rules[1].style.getPropertyShorthand(longhand);13}1415shouldBe('getShorthand("background-repeat-x", "icon1")', '"background-repeat"');16shouldBe('getShorthand("background-repeat-y", "icon1")', '"background-repeat"');17shouldBe('getShorthand("background-repeat", "icon1")', 'null');1819shouldBe('getShorthand("background-position-x", "icon1")', '"background-position"');20shouldBe('getShorthand("background-position-y", "icon1")', '"background-position"');21shouldBe('getShorthand("background-position", "icon1")', 'null');2223shouldBe('getShorthand("-webkit-mask-repeat-x", "icon1")', '"-webkit-mask-repeat"');24shouldBe('getShorthand("-webkit-mask-repeat-y", "icon1")', '"-webkit-mask-repeat"');25shouldBe('getShorthand("-webkit-mask-repeat", "icon1")', 'null');2627shouldBe('getShorthand("-webkit-mask-position-x", "icon1")', '"-webkit-mask-position"');28shouldBe('getShorthand("-webkit-mask-position-y", "icon1")', '"-webkit-mask-position"');29shouldBe('getShorthand("-webkit-mask-repeat", "icon1")', 'null');303132debug('Test that shorthand names are null for #icon2 since its styles are declared ' +33 'with longhand properties:');34shouldBe('getShorthand("background-repeat-x", "icon2")', 'null');35shouldBe('getShorthand("background-repeat-y", "icon2")', 'null');36shouldBe('getShorthand("background-repeat", "icon2")', 'null');3738shouldBe('getShorthand("background-position-x", "icon2")', 'null');39shouldBe('getShorthand("background-position-y", "icon2")', 'null');40shouldBe('getShorthand("background-position", "icon2")', 'null');4142shouldBe('getShorthand("-webkit-mask-repeat-x", "icon2")', 'null');43shouldBe('getShorthand("-webkit-mask-repeat-y", "icon2")', 'null');44shouldBe('getShorthand("-webkit-mask-repeat", "icon2")', 'null');4546shouldBe('getShorthand("-webkit-mask-position-x", "icon2")', 'null');47shouldBe('getShorthand("-webkit-mask-position-y", "icon2")', 'null');48shouldBe('getShorthand("-webkit-mask-repeat", "icon2")', 'null');4950 ...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var wpt = new WebPageTest('www.webpagetest.org');3 if (err) return console.error(err);4 console.log('Test submitted to WebPagetest for %s', data.data.testUrl);5 console.log('Test ID: %s', data.data.testId);6});7## Run Test (with options)8var wpt = require('webpagetest');9var wpt = new WebPageTest('www.webpagetest.org');10}, function(err, data) {11 if (err) return console.error(err);12 console.log('Test submitted to WebPagetest for %s', data.data.testUrl);13 console.log('Test ID: %s', data.data.testId);14});15var wpt = require('webpagetest');16var wpt = new WebPageTest('www.webpagetest.org');17wpt.getTestStatus('140909_2B_1R', function(err, data) {18 if (err) return console.error(err);19 console.log('Test Status: %s', data.data.statusText);20});21var wpt = require('webpagetest');22var wpt = new WebPageTest('www.webpagetest.org');23wpt.getTestResults('140909_2B_1R', function(err, data) {24 if (err) return console.error(err);25 console.log('Test Status: %s', data.data.statusText);26});27## Get Test Results (with options)28var wpt = require('webpagetest');29var wpt = new WebPageTest('www.webpagetest.org');30wpt.getTestResults('140909_2B_1R', {

Full Screen

Using AI Code Generation

copy

Full Screen

1const {Builder, By, Key, until} = require('selenium-webdriver');2const driver = new Builder().forBrowser('chrome').build();3async function test() {4 await driver.findElement(By.name('q')).sendKeys('webdriver', Key.RETURN);5 await driver.wait(until.titleIs('webdriver - Google Search'), 1000);6 await driver.quit();7}8test();

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var api = new wpt('www.webpagetest.org');3 if (err) return console.error(err);4 console.log('Test Status: ' + data.statusText);5 console.log('Test ID: ' + data.data.testId);6 console.log('Test URL: ' + data.data.summary);7});8var wpt = require('webpagetest');9var api = new wpt('www.webpagetest.org');10 if (err) return console.error(err);11 console.log('Test Status: ' + data.statusText);12 console.log('Test ID: ' + data.data.testId);13 console.log('Test URL: ' + data.data.summary);14});15var wpt = require('webpagetest');16var api = new wpt('www.webpagetest.org');17 if (err) return console.error(err);18 console.log('Test Status: ' + data.statusText);19 console.log('Test ID: ' + data.data.testId);20 console.log('Test URL: ' + data.data.summary);21});22var wpt = require('webpagetest');23var api = new wpt('www.webpagetest.org');24 if (err) return console.error(err);25 console.log('Test Status: ' + data.statusText);26 console.log('Test ID: ' + data.data.testId);27 console.log('Test URL: ' + data.data.summary);28});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptools = require('wptools');2var page = wptools.page('Albert Einstein');3page.get(function(err, data) {4 console.log(data);5});6var wptools = require('wptools');7var page = wptools.page('Albert Einstein');8page.get(function(err, data) {9 console.log(data);10});11var wptools = require('wptools');12var page = wptools.page('Albert Einstein');13page.get(function(err, data) {14 console.log(data);15});16var wptools = require('wptools');17var page = wptools.page('Albert Einstein');18page.get(function(err, data) {19 console.log(data);20});21var wptools = require('wptools');22var page = wptools.page('Albert Einstein');23page.get(function(err, data) {24 console.log(data);25});26var wptools = require('wptools');27var page = wptools.page('Albert Einstein');28page.get(function(err, data) {29 console.log(data);30});31var wptools = require('wptools');32var page = wptools.page('Albert Einstein');33page.get(function(err, data) {34 console.log(data);35});36var wptools = require('wptools');37var page = wptools.page('Albert Einstein');38page.get(function(err, data) {39 console.log(data);40});41var wptools = require('wptools');42var page = wptools.page('Albert Einstein');43page.get(function(err, data) {44 console.log(data);45});

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2var client = wpt('www.webpagetest.org');3client.getLocations(function(err, locations) {4 console.log(locations);5});6 console.log(data);7});

Full Screen

Using AI Code Generation

copy

Full Screen

1var text = 'This is a test of the emergency broadcast system.';2var text2 = 'This is a test of the emergency broadcast system.';3var texturize = require('wptexturize');4console.log( texturize.wptexturize( text ) );5console.log( texturize.wptexturize( text2, true ) );6var text = 'This is a test of the emergency broadcast system.';7var text2 = 'This is a test of the emergency broadcast system.';8var texturize = require('wptexturize');9console.log( texturize.wptexturize( text ) );10console.log( texturize.wptexturize( text2, true ) );11var text = 'This is a test of the emergency broadcast system.';12var text2 = 'This is a test of the emergency broadcast system.';13var texturize = require('wptexturize');14console.log( texturize.wptexturize( text ) );15console.log( texturize.wptexturize( text2, true ) );16var text = 'This is a test of the emergency broadcast system.';17var text2 = 'This is a test of the emergency broadcast system.';18var texturize = require('wptexturize');19console.log( texturize.wptexturize( text ) );20console.log( texturize.wptexturize( text2, true ) );21var text = 'This is a test of the emergency broadcast system.';

Full Screen

Using AI Code Generation

copy

Full Screen

1var wpt = require('webpagetest');2 if (err) return console.error(err);3 console.log('Test status check: ' + data.statusText);4 console.log('Test ID: ' + data.data.testId);5 console.log('Test URL: ' + data.data.summary);6});7var wpt = require('webpagetest');8 if (err) return console.error(err);9 console.log('Test status check: ' + data.statusText);10 console.log('Test ID: ' + data.data.testId);11 console.log('Test URL: ' + data.data.summary);12 wpt.getTestStatus(data.data.testId, function(err, data) {13 if (err) return console.error(err);

Full Screen

Using AI Code Generation

copy

Full Screen

1const wpt = require('webpagetest');2const client = wpt('www.webpagetest.org', 'A.4f0f7a1c1d8b8b9f9a7c0e2e6a1c8a2d');3 console.log(data);4});5const wpt = require('webpagetest');6const client = wpt('www.webpagetest.org', 'A.4f0f7a1c1d8b8b9f9a7c0e2e6a1c8a2d');7 console.log(data);8});9const wpt = require('webpagetest');10const client = wpt('www.webpagetest.org', 'A.4f0f7a1c1d8b8b9f9a7c0e2e6a1c8a2d');11 console.log(data);12});13const wpt = require('webpagetest');14const client = wpt('www.webpagetest.org', 'A.4f0f7a1c1d8b8b9f9a7c0e2e6a1c8a2d');15 console.log(data);16});17const wpt = require('webpagetest');18const client = wpt('www.webpagetest.org', 'A.4f0f7a1c1d8b8b9f9a7c0e2e6a1c8a2d');19 console.log(data);20});21const wpt = require('webpagetest');

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful