diff --git a/.gemini.js b/.gemini.js new file mode 100644 index 00000000..94b7d27c --- /dev/null +++ b/.gemini.js @@ -0,0 +1,20 @@ +module.exports = { + rootUrl: "http://yandex.com", + + browsers: { + PhantomJS: { + desiredCapabilities: { + browserName: "phantomjs" + } + } + }, + + system: { + plugins: { + 'html-reporter': { + enabled: true, + path: 'gemini/reports' + } + } + } +}; diff --git a/gemini/reports/images/yandex-icons/plain/PhantomJS~current.png b/gemini/reports/images/yandex-icons/plain/PhantomJS~current.png new file mode 100644 index 00000000..ca695d8e Binary files /dev/null and b/gemini/reports/images/yandex-icons/plain/PhantomJS~current.png differ diff --git a/gemini/reports/images/yandex-icons/plain/PhantomJS~ref.png b/gemini/reports/images/yandex-icons/plain/PhantomJS~ref.png new file mode 100644 index 00000000..3cdb9ded Binary files /dev/null and b/gemini/reports/images/yandex-icons/plain/PhantomJS~ref.png differ diff --git a/gemini/reports/images/yandex-search/plain/PhantomJS~ref.png b/gemini/reports/images/yandex-search/plain/PhantomJS~ref.png new file mode 100644 index 00000000..b9aca6e8 Binary files /dev/null and b/gemini/reports/images/yandex-search/plain/PhantomJS~ref.png differ diff --git a/gemini/reports/images/yandex-search/with text/PhantomJS~ref.png b/gemini/reports/images/yandex-search/with text/PhantomJS~ref.png new file mode 100644 index 00000000..3581057c Binary files /dev/null and b/gemini/reports/images/yandex-search/with text/PhantomJS~ref.png differ diff --git a/gemini/reports/index.html b/gemini/reports/index.html new file mode 100644 index 00000000..017e6557 --- /dev/null +++ b/gemini/reports/index.html @@ -0,0 +1,221 @@ + + + + Gemini report + + + + +
+
Total Tests
3
+
Passed
2
+
Failed
1
+
Skipped
0
+
Retries
0
+
+ + + + + + + + + + + +
+
+ yandex-search + +
+
+ +
+
+ plain + +
+
+
+
+ PhantomJS + + +
+
+
+
+ + + +
+
+
+
+
Meta-info
+
+
{
+    "url": "/",
+    "file": "test/gemini/demo1.js",
+    "sessionId": "20cafe60-5a4f-11e7-8dde-e99d1aa2245a"
+}
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+ with text + +
+
+
+
+ PhantomJS + + +
+
+
+
+ + + +
+
+
+
+
Meta-info
+
+
{
+    "url": "/",
+    "file": "test/gemini/demo1.js",
+    "sessionId": "20cafe60-5a4f-11e7-8dde-e99d1aa2245a"
+}
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+ yandex-icons + +
+
+ +
+
+ plain + +
+
+
+
+ PhantomJS + + +
+
+
+
+ + + +
+
+
+
+
Meta-info
+
+
{
+    "url": "/foo",
+    "file": "test/gemini/demo2.js",
+    "sessionId": "20cafe60-5a4f-11e7-8dde-e99d1aa2245a"
+}
+
+
+
+
Error
+    at /home/delphin/workspaces/workspace_vis/vis/node_modules/gemini/lib/browser/client-bridge.js:42:39
+    at tryCatcher (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/util.js:16:23)
+    at Promise._settlePromiseFromHandler (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/promise.js:512:31)
+    at Promise._settlePromise (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/promise.js:569:18)
+    at Promise._settlePromise0 (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/promise.js:614:10)
+    at Promise._settlePromises (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/promise.js:693:18)
+    at Async._drainQueue (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/async.js:133:16)
+    at Async._drainQueues (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/async.js:143:10)
+    at Immediate.Async.drainQueues (/home/delphin/workspaces/workspace_vis/vis/node_modules/bluebird/js/release/async.js:17:14)
+    at runCallback (timers.js:651:20)
+    at tryOnImmediate (timers.js:624:5)
+    at processImmediate [as _immediateCallback] (timers.js:596:5)
+ +
+
+
+
+
+
+ +
+
+
+
+ + + + diff --git a/gemini/reports/report.css b/gemini/reports/report.css new file mode 100644 index 00000000..dbd3d411 --- /dev/null +++ b/gemini/reports/report.css @@ -0,0 +1,286 @@ +.report { + font: 14px Helvetica Neue, Arial, sans-serif; +} + +.summary__key { + font-weight: bold; + display: inline; +} + +.summary__key::after { + content: ':'; +} + +.summary__key_has-fails { + color: #c00; +} + +.summary__value { + margin-left: 5px; + margin-right: 20px; + display: inline; +} + +.button { + background: #fff; + border: 1px solid #ccc; + border-radius: 2px; + outline: 0; +} + +.button:hover { + border-color: #555; +} + +.button.pressed, +.button:active { + background: #eee; +} + +.button_checked { + background: #ffeba0; + border-color: #cebe7d; +} + +.image-box { + padding: 5px; + border: 1px solid #ccc; + background: #c9c9c9; +} + +.image-box__exp-with-act { + display: inline-block; +} + +.report_show-only-diff .image-box__exp-with-act { + display: none; +} + +.image-box__image { + padding: 0 5px; + display: inline-block; + vertical-align: top; +} + +.section__title { + font-weight: bold; + cursor: pointer; + + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.section__title_skipped { + color: #ccc; + cursor: default; + + -moz-user-select: text; + -webkit-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.section__title:before, .meta-info__switcher:before { + display: inline-block; + margin-right: 2px; + vertical-align: middle; + content: '\25bc'; + color: black; +} + +.section_status_success > .section__title { + color: #038035; +} + +.section_status_fail > .section__title { + color: #c00; +} + +.section_status_skip > .section__title, +.section_status_skip > .section__title:hover { + color: #ccc; + cursor: default; +} + +.section_status_skip > .section__title::before { + content: none; +} + +.section__title:hover { + color: #2d3e50; +} + +.section__body { + padding-left: 15px; +} + +.section__body_guided { + border-left: 1px dotted #ccc; +} + +.section_collapsed .section__body { + display: none; +} + +.section__icon { + display: inline-block; + width: 19px; + height: 19px; + vertical-align: top; + padding: 0 3px; + border: none; + opacity: 0.5; + cursor: pointer; +} + +.section__icon:hover { + opacity: 1; +} + +.section__icon:before { + display: block; + width: 100%; + height: 100%; + content: ''; + background-repeat: no-repeat; + background-size: 100%; + background-position: center; +} + +.section__icon_view-local:before { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTAuNzA5IC0zMi4wODEgMTQxLjczMiAxNDEuNzMyIiBoZWlnaHQ9IjE0MS43MzJweCIgaWQ9IkxpdmVsbG9fMSIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSItMC43MDkgLTMyLjA4MSAxNDEuNzMyIDE0MS43MzIiIHdpZHRoPSIxNDEuNzMycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxnIGlkPSJMaXZlbGxvXzgwIj48cGF0aCBkPSJNODkuNjY4LDM4Ljc4NmMwLTEwLjc3My04LjczMS0xOS41MTItMTkuNTEtMTkuNTEyUzUwLjY0NiwyOC4wMSw1MC42NDYsMzguNzg2YzAsMTAuNzc0LDguNzMyLDE5LjUxMSwxOS41MTIsMTkuNTExICAgQzgwLjkzNCw1OC4yOTcsODkuNjY4LDQ5LjU2MSw4OS42NjgsMzguNzg2IE0xMjguMzUyLDM4LjcyN2MtMTMuMzE1LDE3LjU5OS0zNC40MjYsMjguOTcyLTU4LjE5MywyOC45NzIgICBjLTIzLjc3LDAtNDQuODc5LTExLjM3My01OC4xOTQtMjguOTcyQzI1LjI3OSwyMS4xMjksNDYuMzg5LDkuNzU2LDcwLjE1OCw5Ljc1NkM5My45MjcsOS43NTYsMTE1LjAzNiwyMS4xMjksMTI4LjM1MiwzOC43MjcgICAgTTE0MC4zMTQsMzguNzZDMTI1LjY2NiwxNS40NzgsOTkuNzI1LDAsNzAuMTU4LDBTMTQuNjQ4LDE1LjQ3OCwwLDM4Ljc2YzE0LjY0OCwyMy4zMTIsNDAuNTkxLDM4LjgxLDcwLjE1OCwzOC44MSAgIFMxMjUuNjY2LDYyLjA3MiwxNDAuMzE0LDM4Ljc2Ii8+PC9nPjxnIGlkPSJMaXZlbGxvXzFfMV8iLz48L3N2Zz4=); +} + +.section__icon_copy-to-clipboard:before { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjwhRE9DVFlQRSBzdmcgIFBVQkxJQyAnLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4nICAnaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkJz48c3ZnIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUxMiA1MTIiIGhlaWdodD0iNTEycHgiIGlkPSJMYXllcl8xIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB3aWR0aD0iNTEycHgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxwYXRoIGQ9Ik00NjguNDkzLDEwMS42MzdMMzcxLjk1NSw1LjA5OEgxNTkuNTd2NzcuMjMxSDQzLjcyNHY0MjQuNzY5aDMwOC45MjN2LTc3LjIzMWgxMTUuODQ2VjEwMS42Mzd6ICAgTTM3MS45NTUsMzIuNDAxbDY5LjIzNiw2OS4yMzVoLTY5LjIzNlYzMi40MDF6IE02My4wMzEsNDg3Ljc5VjEwMS42MzdoMTczLjc2OXY5Ni41MzhoOTYuNTM4VjQ4Ny43OUg2My4wMzF6IE0yNTYuMTA4LDEwOS42MzIgIGw2OS4yMzYsNjkuMjM1aC02OS4yMzZWMTA5LjYzMnogTTM1Mi42NDcsNDEwLjU2VjE3OC44NjdsLTk2LjUzOC05Ni41MzhoLTc3LjIzMVYyNC40MDZoMTczLjc2OXY5Ni41MzhoOTYuNTM4VjQxMC41NkgzNTIuNjQ3eiIgZmlsbD0iIzM3NDA0RCIvPjwvc3ZnPg==); +} + +.section_collapsed .section__title:before, +.meta-info_collapsed .meta-info__switcher:before { + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + transform: rotate(-90deg); +} + +.reason { + background: #f6f5f3; + border: 1px solid #ccc; + padding: 5px; + font: 12px Consolas, Monaco, monospace; +} + +.state-button { + position: relative; + height: 22px; + display: inline-block; + box-shadow: 0 0 1px #000; + border: 1px solid #fff; + outline: none; + background: #fff; + cursor: pointer; +} + +.cswitcher__item, .tab-switcher__button { + width: 22px; +} + +.cswitcher__item_selected.cswitcher__item::before { + content: ''; + position: absolute; + top: 0; + left: 0; + background: rgba(4, 4, 4, 0.3) no-repeat 3px 2px url('data:image/svg+xml;utf8,'); + height: 20px; + width: 20px; +} + +.cswitcher_color_1 { + background: #c9c9c9; +} + +.cswitcher_color_2 { + background: #d5ff09; +} + +.cswitcher_color_3 { + background-image: url('data:image/svg+xml;utf8,'); +} + +.collapsed { + display: none; +} + +.skipped__list { + margin: 10px 0; + font-weight: bold; + color: #ccc; +} + +a:link, +a:visited { + text-decoration: none; +} + +a:hover, +a:active { + text-decoration: underline; +} + +.tab__item { + display: none; +} + +.tab__item_active { + display: block; +} + +.tab-switcher, .cswitcher { + display: inline-block; + vertical-align: top; + padding: 5px; +} + +.cswitcher:before { + content: 'Background:'; + padding-right: 4px; +} + +.tab-switcher:before { + content: 'Attempts:'; + padding-right: 4px; +} + +.tab-switcher__button_active { + background: #ffeba0; +} + +.meta-info { + margin: 5px; +} + +.meta-info__switcher { + display: inline-block; + cursor: pointer; +} + +.meta-info__content { + margin: 5px 0; + background: #f6f5f3; + padding: 5px; +} + +.meta-info_collapsed .meta-info__content { + display: none; +} + +.text-input { + outline: 0; + line-height: 14px; + padding: 2px 5px; + border: 1px solid #ccc; + border-radius: 2px; +} diff --git a/gemini/reports/report.min.js b/gemini/reports/report.min.js new file mode 100644 index 00000000..d7d3b6f5 --- /dev/null +++ b/gemini/reports/report.min.js @@ -0,0 +1,2 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o .section__body > .image-box .tab__item_active img");forEach.call(sections,function(section){if(section.classList.contains("section_status_fail")){section.classList.remove("section_collapsed")}else{section.classList.add("section_collapsed")}})}function expandRetries(){loadLazyImages(document,".has-retries > .section__body > .image-box .tab__item_active img");forEach.call(sections,function(section){if(section.classList.contains("has-retries")){section.classList.remove("section_collapsed")}else{section.classList.add("section_collapsed")}})}function handleColorSwitch(target,sources){var imageBox=findClosest(target,"image-box");sources.forEach(function(item){item.classList.remove("cswitcher__item_selected")});forEach.call(imageBox.classList,function(cls){if(/cswitcher_color_\d+/.test(cls)){imageBox.classList.remove(cls)}});target.classList.add("cswitcher__item_selected");imageBox.classList.add("cswitcher_color_"+target.dataset.id)}function handleRetriesSwitch(target){var imageBox=target.closest(".image-box");switch_(imageBox.querySelector(".tab"),"tab__item_active");switch_(imageBox.querySelector(".tab-switcher"),"tab-switcher__button_active");loadLazyImages(imageBox,".tab__item_active img");function switch_(elem,selector){forEach.call(elem.children,function(item){item.classList.remove(selector);if(target.getAttribute("data-position")===item.getAttribute("data-position")){item.classList.add(selector)}})}}function bodyClick(e){var target=e.target;if(target.classList.contains("cswitcher__item")){handleColorSwitch(target,filter.call(target.parentNode.childNodes,function(node){return node.nodeType===Node.ELEMENT_NODE}))}if(target.classList.contains("tab-switcher__button")){handleRetriesSwitch(target)}if(target.classList.contains("meta-info__switcher")){toggleMetaInfo(target)}}function toggleMetaInfo(target){target.closest(".meta-info").classList.toggle("meta-info_collapsed")}function showOnlyDiff(e){e.target.classList.toggle("button_checked");document.body.classList.toggle("report_show-only-diff")}function findClosest(context,cls){while(context=context.parentNode){if(context.classList.contains(cls)){return context}}}function loadLazyImages(elem,selector){forEach.call(elem.querySelectorAll(selector),function(img){if(img.dataset.src&&img.src!==img.dataset.src){img.src=img.dataset.src}})}function showSkippedList(){document.getElementById("showSkipped").classList.toggle("pressed");document.getElementById("skippedList").classList.toggle("collapsed")}function handleHostChange(){var textInput=document.getElementById("viewHostInput");var viewButtons=document.querySelectorAll(".section__icon_view-local");textInput.addEventListener("change",function(){setViewLinkHost(textInput.value);if(window.localStorage){window.localStorage.setItem("_gemini-replace-host",textInput.value)}});if(window.localStorage){var host=window.localStorage.getItem("_gemini-replace-host");if(host){setViewLinkHost(host);textInput.value=host}}function setViewLinkHost(host){viewButtons.forEach(function(item){var href=item.dataset.suiteViewLink,parsedHost;if(host){parsedHost=url.parse(host,false,true);href=url.format(Object.assign(url.parse(href),{host:parsedHost.slashes?parsedHost.host:host,protocol:parsedHost.slashes?parsedHost.protocol:null,hostname:null,port:null}))}item.setAttribute("href",href)})}}function handleClipboard(){forEach.call(document.querySelectorAll(".section__icon_copy-to-clipboard"),function(clipboard){new Clipboard(clipboard)})}document.addEventListener("DOMContentLoaded",function(){document.getElementById("expandAll").addEventListener("click",expandAll);document.getElementById("collapseAll").addEventListener("click",collapseAll);document.getElementById("expandErrors").addEventListener("click",expandErrors);document.getElementById("showSkipped").addEventListener("click",showSkippedList);document.getElementById("showRetries").addEventListener("click",expandRetries);document.getElementById("showOnlyDiff").addEventListener("click",showOnlyDiff);document.body.addEventListener("click",bodyClick);forEach.call(document.querySelectorAll(".section"),function(section){section.querySelector(".section__title").addEventListener("click",function(){loadLazyImages(section,":scope > .section__body > .image-box .tab__item_active img");section.classList.toggle("section_collapsed")})});forEach.call(document.querySelectorAll(".button"),function(button){button.addEventListener("click",function(e){e.stopPropagation()})})});handleClipboard();handleHostChange();expandErrors()})()},{clipboard:9,url:6}],2:[function(require,module,exports){(function(global){(function(root){var freeExports=typeof exports=="object"&&exports&&!exports.nodeType&&exports;var freeModule=typeof module=="object"&&module&&!module.nodeType&&module;var freeGlobal=typeof global=="object"&&global;if(freeGlobal.global===freeGlobal||freeGlobal.window===freeGlobal||freeGlobal.self===freeGlobal){root=freeGlobal}var punycode,maxInt=2147483647,base=36,tMin=1,tMax=26,skew=38,damp=700,initialBias=72,initialN=128,delimiter="-",regexPunycode=/^xn--/,regexNonASCII=/[^\x20-\x7E]/,regexSeparators=/[\x2E\u3002\uFF0E\uFF61]/g,errors={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},baseMinusTMin=base-tMin,floor=Math.floor,stringFromCharCode=String.fromCharCode,key;function error(type){throw new RangeError(errors[type])}function map(array,fn){var length=array.length;var result=[];while(length--){result[length]=fn(array[length])}return result}function mapDomain(string,fn){var parts=string.split("@");var result="";if(parts.length>1){result=parts[0]+"@";string=parts[1]}string=string.replace(regexSeparators,".");var labels=string.split(".");var encoded=map(labels,fn).join(".");return result+encoded}function ucs2decode(string){var output=[],counter=0,length=string.length,value,extra;while(counter=55296&&value<=56319&&counter65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value);return output}).join("")}function basicToDigit(codePoint){if(codePoint-48<10){return codePoint-22}if(codePoint-65<26){return codePoint-65}if(codePoint-97<26){return codePoint-97}return base}function digitToBasic(digit,flag){return digit+22+75*(digit<26)-((flag!=0)<<5)}function adapt(delta,numPoints,firstTime){var k=0;delta=firstTime?floor(delta/damp):delta>>1;delta+=floor(delta/numPoints);for(;delta>baseMinusTMin*tMax>>1;k+=base){delta=floor(delta/baseMinusTMin)}return floor(k+(baseMinusTMin+1)*delta/(delta+skew))}function decode(input){var output=[],inputLength=input.length,out,i=0,n=initialN,bias=initialBias,basic,j,index,oldi,w,k,digit,t,baseMinusT;basic=input.lastIndexOf(delimiter);if(basic<0){basic=0}for(j=0;j=128){error("not-basic")}output.push(input.charCodeAt(j))}for(index=basic>0?basic+1:0;index=inputLength){error("invalid-input")}digit=basicToDigit(input.charCodeAt(index++));if(digit>=base||digit>floor((maxInt-i)/w)){error("overflow")}i+=digit*w;t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(digitfloor(maxInt/baseMinusT)){error("overflow")}w*=baseMinusT}out=output.length+1;bias=adapt(i-oldi,out,oldi==0);if(floor(i/out)>maxInt-n){error("overflow")}n+=floor(i/out);i%=out;output.splice(i++,0,n)}return ucs2encode(output)}function encode(input){var n,delta,handledCPCount,basicLength,bias,j,m,q,k,t,currentValue,output=[],inputLength,handledCPCountPlusOne,baseMinusT,qMinusT;input=ucs2decode(input);inputLength=input.length;n=initialN;delta=0;bias=initialBias;for(j=0;j=n&¤tValuefloor((maxInt-delta)/handledCPCountPlusOne)){error("overflow")}delta+=(m-n)*handledCPCountPlusOne;n=m;for(j=0;jmaxInt){error("overflow")}if(currentValue==n){for(q=delta,k=base;;k+=base){t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(q0&&len>maxKeys){len=maxKeys}for(var i=0;i=0){kstr=x.substr(0,idx);vstr=x.substr(idx+1)}else{kstr=x;vstr=""}k=decodeURIComponent(kstr);v=decodeURIComponent(vstr);if(!hasOwnProperty(obj,k)){obj[k]=v}else if(isArray(obj[k])){obj[k].push(v)}else{obj[k]=[obj[k],v]}}return obj};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"}},{}],4:[function(require,module,exports){"use strict";var stringifyPrimitive=function(v){switch(typeof v){case"string":return v;case"boolean":return v?"true":"false";case"number":return isFinite(v)?v:"";default:return""}};module.exports=function(obj,sep,eq,name){sep=sep||"&";eq=eq||"=";if(obj===null){obj=undefined}if(typeof obj==="object"){return map(objectKeys(obj),function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;if(isArray(obj[k])){return map(obj[k],function(v){return ks+encodeURIComponent(stringifyPrimitive(v))}).join(sep)}else{return ks+encodeURIComponent(stringifyPrimitive(obj[k]))}}).join(sep)}if(!name)return"";return encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj))};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"};function map(xs,f){if(xs.map)return xs.map(f);var res=[];for(var i=0;i",'"',"`"," ","\r","\n","\t"],unwise=["{","}","|","\\","^","`"].concat(delims),autoEscape=["'"].concat(unwise),nonHostChars=["%","/","?",";","#"].concat(autoEscape),hostEndingChars=["/","?","#"],hostnameMaxLen=255,hostnamePartPattern=/^[+a-z0-9A-Z_-]{0,63}$/,hostnamePartStart=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,unsafeProtocol={javascript:true,"javascript:":true},hostlessProtocol={javascript:true,"javascript:":true},slashedProtocol={http:true,https:true,ftp:true,gopher:true,file:true,"http:":true,"https:":true,"ftp:":true,"gopher:":true,"file:":true},querystring=require("querystring");function urlParse(url,parseQueryString,slashesDenoteHost){if(url&&util.isObject(url)&&url instanceof Url)return url;var u=new Url;u.parse(url,parseQueryString,slashesDenoteHost);return u}Url.prototype.parse=function(url,parseQueryString,slashesDenoteHost){if(!util.isString(url)){throw new TypeError("Parameter 'url' must be a string, not "+typeof url)}var queryIndex=url.indexOf("?"),splitter=queryIndex!==-1&&queryIndex127){newpart+="x"}else{newpart+=part[j]}}if(!newpart.match(hostnamePartPattern)){var validParts=hostparts.slice(0,i);var notHost=hostparts.slice(i+1);var bit=part.match(hostnamePartStart);if(bit){validParts.push(bit[1]);notHost.unshift(bit[2])}if(notHost.length){rest="/"+notHost.join(".")+rest}this.hostname=validParts.join(".");break}}}}if(this.hostname.length>hostnameMaxLen){this.hostname=""}else{this.hostname=this.hostname.toLowerCase()}if(!ipv6Hostname){this.hostname=punycode.toASCII(this.hostname)}var p=this.port?":"+this.port:"";var h=this.hostname||"";this.host=h+p;this.href+=this.host;if(ipv6Hostname){this.hostname=this.hostname.substr(1,this.hostname.length-2);if(rest[0]!=="/"){rest="/"+rest}}}if(!unsafeProtocol[lowerProto]){for(var i=0,l=autoEscape.length;i0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}result.search=relative.search;result.query=relative.query;if(!util.isNull(result.pathname)||!util.isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.href=result.format();return result}if(!srcPath.length){result.pathname=null;if(result.search){result.path="/"+result.search}else{result.path=null}result.href=result.format();return result}var last=srcPath.slice(-1)[0];var hasTrailingSlash=(result.host||relative.host||srcPath.length>1)&&(last==="."||last==="..")||last==="";var up=0;for(var i=srcPath.length;i>=0;i--){last=srcPath[i];if(last==="."){srcPath.splice(i,1)}else if(last===".."){srcPath.splice(i,1);up++}else if(up){srcPath.splice(i,1);up--}}if(!mustEndAbs&&!removeAllDots){for(;up--;up){srcPath.unshift("..")}}if(mustEndAbs&&srcPath[0]!==""&&(!srcPath[0]||srcPath[0].charAt(0)!=="/")){srcPath.unshift("")}if(hasTrailingSlash&&srcPath.join("/").substr(-1)!=="/"){srcPath.push("")}var isAbsolute=srcPath[0]===""||srcPath[0]&&srcPath[0].charAt(0)==="/";if(psychotic){result.hostname=result.host=isAbsolute?"":srcPath.length?srcPath.shift():"";var authInHost=result.host&&result.host.indexOf("@")>0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift("")}if(!srcPath.length){result.pathname=null;result.path=null}else{result.pathname=srcPath.join("/")}if(!util.isNull(result.pathname)||!util.isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==":"){this.port=port.substr(1)}host=host.substr(0,host.length-port.length)}if(host)this.hostname=host}},{"./util":7,punycode:2,querystring:5}],7:[function(require,module,exports){"use strict";module.exports={isString:function(arg){return typeof arg==="string"},isObject:function(arg){return typeof arg==="object"&&arg!==null},isNull:function(arg){return arg===null},isNullOrUndefined:function(arg){return arg==null}}},{}],8:[function(require,module,exports){(function(global,factory){if(typeof define==="function"&&define.amd){define(["module","select"],factory)}else if(typeof exports!=="undefined"){factory(module,require("select"))}else{var mod={exports:{}};factory(mod,global.select);global.clipboardAction=mod.exports}})(this,function(module,_select){"use strict";var _select2=_interopRequireDefault(_select);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj};function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&arguments[0]!==undefined?arguments[0]:{};this.action=options.action;this.emitter=options.emitter;this.target=options.target;this.text=options.text;this.trigger=options.trigger;this.selectedText=""}},{key:"initSelection",value:function initSelection(){if(this.text){this.selectFake()}else if(this.target){this.selectTarget()}}},{key:"selectFake",value:function selectFake(){var _this=this;var isRTL=document.documentElement.getAttribute("dir")=="rtl";this.removeFake();this.fakeHandlerCallback=function(){return _this.removeFake()};this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||true;this.fakeElem=document.createElement("textarea");this.fakeElem.style.fontSize="12pt";this.fakeElem.style.border="0";this.fakeElem.style.padding="0";this.fakeElem.style.margin="0";this.fakeElem.style.position="absolute";this.fakeElem.style[isRTL?"right":"left"]="-9999px";var yPosition=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.addEventListener("focus",window.scrollTo(0,yPosition));this.fakeElem.style.top=yPosition+"px";this.fakeElem.setAttribute("readonly","");this.fakeElem.value=this.text;document.body.appendChild(this.fakeElem);this.selectedText=(0,_select2.default)(this.fakeElem);this.copyText()}},{key:"removeFake",value:function removeFake(){if(this.fakeHandler){document.body.removeEventListener("click",this.fakeHandlerCallback);this.fakeHandler=null;this.fakeHandlerCallback=null}if(this.fakeElem){document.body.removeChild(this.fakeElem);this.fakeElem=null}}},{key:"selectTarget",value:function selectTarget(){this.selectedText=(0,_select2.default)(this.target);this.copyText()}},{key:"copyText",value:function copyText(){var succeeded=void 0;try{succeeded=document.execCommand(this.action)}catch(err){succeeded=false}this.handleResult(succeeded)}},{key:"handleResult",value:function handleResult(succeeded){this.emitter.emit(succeeded?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function clearSelection(){if(this.target){this.target.blur()}window.getSelection().removeAllRanges()}},{key:"destroy",value:function destroy(){this.removeFake()}},{key:"action",set:function set(){var action=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"copy";this._action=action;if(this._action!=="copy"&&this._action!=="cut"){throw new Error('Invalid "action" value, use either "copy" or "cut"')}},get:function get(){return this._action}},{key:"target",set:function set(target){if(target!==undefined){if(target&&(typeof target==="undefined"?"undefined":_typeof(target))==="object"&&target.nodeType===1){if(this.action==="copy"&&target.hasAttribute("disabled")){throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute')}if(this.action==="cut"&&(target.hasAttribute("readonly")||target.hasAttribute("disabled"))){throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes')}this._target=target}else{throw new Error('Invalid "target" value, use a valid Element')}}},get:function get(){return this._target}}]);return ClipboardAction}();module.exports=ClipboardAction})},{select:14}],9:[function(require,module,exports){(function(global,factory){if(typeof define==="function"&&define.amd){define(["module","./clipboard-action","tiny-emitter","good-listener"],factory)}else if(typeof exports!=="undefined"){factory(module,require("./clipboard-action"),require("tiny-emitter"),require("good-listener"))}else{var mod={exports:{}};factory(mod,global.clipboardAction,global.tinyEmitter,global.goodListener);global.clipboard=mod.exports}})(this,function(module,_clipboardAction,_tinyEmitter,_goodListener){"use strict";var _clipboardAction2=_interopRequireDefault(_clipboardAction);var _tinyEmitter2=_interopRequireDefault(_tinyEmitter);var _goodListener2=_interopRequireDefault(_goodListener);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}var _createClass=function(){function defineProperties(target,props){for(var i=0;i0&&arguments[0]!==undefined?arguments[0]:{};this.action=typeof options.action==="function"?options.action:this.defaultAction;this.target=typeof options.target==="function"?options.target:this.defaultTarget;this.text=typeof options.text==="function"?options.text:this.defaultText}},{key:"listenClick",value:function listenClick(trigger){var _this2=this;this.listener=(0,_goodListener2.default)(trigger,"click",function(e){return _this2.onClick(e)})}},{key:"onClick",value:function onClick(e){var trigger=e.delegateTarget||e.currentTarget;if(this.clipboardAction){this.clipboardAction=null}this.clipboardAction=new _clipboardAction2.default({action:this.action(trigger),target:this.target(trigger),text:this.text(trigger),trigger:trigger,emitter:this})}},{key:"defaultAction",value:function defaultAction(trigger){return getAttributeValue("action",trigger)}},{key:"defaultTarget",value:function defaultTarget(trigger){var selector=getAttributeValue("target",trigger);if(selector){return document.querySelector(selector)}}},{key:"defaultText",value:function defaultText(trigger){return getAttributeValue("text",trigger)}},{key:"destroy",value:function destroy(){this.listener.destroy();if(this.clipboardAction){this.clipboardAction.destroy();this.clipboardAction=null}}}]);return Clipboard}(_tinyEmitter2.default);function getAttributeValue(suffix,element){var attribute="data-clipboard-"+suffix;if(!element.hasAttribute(attribute)){return}return element.getAttribute(attribute)}module.exports=Clipboard})},{"./clipboard-action":8,"good-listener":13,"tiny-emitter":15}],10:[function(require,module,exports){var DOCUMENT_NODE_TYPE=9;if(typeof Element!=="undefined"&&!Element.prototype.matches){var proto=Element.prototype;proto.matches=proto.matchesSelector||proto.mozMatchesSelector||proto.msMatchesSelector||proto.oMatchesSelector||proto.webkitMatchesSelector}function closest(element,selector){while(element&&element.nodeType!==DOCUMENT_NODE_TYPE){if(element.matches(selector))return element;element=element.parentNode}}module.exports=closest},{}],11:[function(require,module,exports){var closest=require("./closest");function delegate(element,selector,type,callback,useCapture){var listenerFn=listener.apply(this,arguments);element.addEventListener(type,listenerFn,useCapture);return{destroy:function(){element.removeEventListener(type,listenerFn,useCapture)}}}function listener(element,selector,type,callback){return function(e){e.delegateTarget=closest(e.target,selector);if(e.delegateTarget){callback.call(element,e)}}}module.exports=delegate},{"./closest":10}],12:[function(require,module,exports){exports.node=function(value){return value!==undefined&&value instanceof HTMLElement&&value.nodeType===1};exports.nodeList=function(value){var type=Object.prototype.toString.call(value);return value!==undefined&&(type==="[object NodeList]"||type==="[object HTMLCollection]")&&"length"in value&&(value.length===0||exports.node(value[0]))};exports.string=function(value){return typeof value==="string"||value instanceof String};exports.fn=function(value){var type=Object.prototype.toString.call(value);return type==="[object Function]"}},{}],13:[function(require,module,exports){var is=require("./is");var delegate=require("delegate");function listen(target,type,callback){if(!target&&!type&&!callback){throw new Error("Missing required arguments")}if(!is.string(type)){throw new TypeError("Second argument must be a String")}if(!is.fn(callback)){throw new TypeError("Third argument must be a Function")}if(is.node(target)){return listenNode(target,type,callback)}else if(is.nodeList(target)){return listenNodeList(target,type,callback)}else if(is.string(target)){return listenSelector(target,type,callback)}else{throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}}function listenNode(node,type,callback){node.addEventListener(type,callback);return{destroy:function(){node.removeEventListener(type,callback)}}}function listenNodeList(nodeList,type,callback){Array.prototype.forEach.call(nodeList,function(node){node.addEventListener(type,callback)});return{destroy:function(){Array.prototype.forEach.call(nodeList,function(node){node.removeEventListener(type,callback)})}}}function listenSelector(selector,type,callback){return delegate(document.body,selector,type,callback)}module.exports=listen},{"./is":12,delegate:11}],14:[function(require,module,exports){function select(element){var selectedText;if(element.nodeName==="SELECT"){element.focus();selectedText=element.value}else if(element.nodeName==="INPUT"||element.nodeName==="TEXTAREA"){var isReadOnly=element.hasAttribute("readonly");if(!isReadOnly){element.setAttribute("readonly","")}element.select();element.setSelectionRange(0,element.value.length);if(!isReadOnly){element.removeAttribute("readonly")}selectedText=element.value}else{if(element.hasAttribute("contenteditable")){element.focus()}var selection=window.getSelection();var range=document.createRange();range.selectNodeContents(element);selection.removeAllRanges();selection.addRange(range);selectedText=selection.toString()}return selectedText}module.exports=select},{}],15:[function(require,module,exports){function E(){}E.prototype={on:function(name,callback,ctx){var e=this.e||(this.e={});(e[name]||(e[name]=[])).push({fn:callback,ctx:ctx});return this},once:function(name,callback,ctx){var self=this;function listener(){self.off(name,listener);callback.apply(ctx,arguments)}listener._=callback;return this.on(name,listener,ctx)},emit:function(name){var data=[].slice.call(arguments,1);var evtArr=((this.e||(this.e={}))[name]||[]).slice();var i=0;var len=evtArr.length;for(i;i= 0) { + gutil.log("Started phantomjs webdriver"); + + var geminiProcess = spawn('gemini', ['test', 'test/gemini']); + geminiProcess.stdout.on('data', function(data) { + var msg = data.toString().replace(/\n$/g, ''); + if (msg.startsWith('✓')) { + gutil.log(gutil.colors.green(msg)); + } else if (msg.startsWith('✘')) { + hasError = true; + gutil.log(gutil.colors.red(msg)); + } else { + gutil.log(msg); + } + }); + geminiProcess.stderr.on('data', function(data) { + if (!(data.toString().indexOf('DeprecationWarning:') >= 0)) { + hasError = true; + gutil.log(gutil.colors.red(data.toString().replace(/\n$/g, + ''))); + } + }); + geminiProcess.on('close', function(code) { + completed = true; + phantomjsProcess.kill(); + }); + } + }); + phantomjsProcess.stderr.on('data', function(data) { + gutil.log(gutil.colors.red(data)); + }); + phantomjsProcess.on('close', function(code) { + if (code && !completed) { + return cb(new Error('✘ phantomjs failed with code: ' + code + + '\n' + + 'Check that port ' + phantomjsPort + + ' is free and that there are no other ' + + 'instances of phantomjs running. (`killall phantomjs`)')); + } + gutil.log("Stoped phantomjs webdriver"); + + if (hasError) { + opn('./gemini/reports/index.html'); + } + + cb(); + }); +}); + // clean the dist/img directory -gulp.task('clean', function (cb) { +gulp.task('clean', function(cb) { rimraf(DIST + '/img', cb); }); -gulp.task('bundle-js', function (cb) { +gulp.task('bundle-js', function(cb) { // update the banner contents (has a date in it which should stay up to date) bannerPlugin.banner = createBanner(); - compiler.run(function (err, stats) { + compiler.run(function(err, stats) { handleCompilerCallback(err, stats); cb(); }); }); // create individual bundles for timeline+graph2d, network, graph3d -gulp.task('bundle-js-individual', function (cb) { +gulp.task('bundle-js-individual', function(cb) { // update the banner contents (has a date in it which should stay up to date) bannerPlugin.banner = createBanner(); - async.each(INDIVIDUAL_JS_BUNDLES, function (item, callback) { + async.each(INDIVIDUAL_JS_BUNDLES, function(item, callback) { var webpackTimelineConfig = { entry: item.entry, output: { @@ -138,12 +203,12 @@ gulp.task('bundle-js-individual', function (cb) { sourcePrefix: ' ' }, module: webpackModule, - plugins: [ bannerPlugin, new webpack.optimize.UglifyJsPlugin() ], + plugins: [bannerPlugin, new webpack.optimize.UglifyJsPlugin()], cache: true }; var compiler = webpack(webpackTimelineConfig); - compiler.run(function (err, stats) { + compiler.run(function(err, stats) { handleCompilerCallback(err, stats); callback(); }); @@ -152,48 +217,51 @@ gulp.task('bundle-js-individual', function (cb) { }); // bundle and minify css -gulp.task('bundle-css', function () { +gulp.task('bundle-css', function() { return gulp.src('./lib/**/*.css') - .pipe(concat(VIS_CSS)) - .pipe(gulp.dest(DIST)) - // TODO: nicer to put minifying css in a separate task? - .pipe(cleanCSS()) - .pipe(rename(VIS_MIN_CSS)) - .pipe(gulp.dest(DIST)); + .pipe(concat(VIS_CSS)) + .pipe(gulp.dest(DIST)) + // TODO: nicer to put minifying css in a separate task? + .pipe(cleanCSS()) + .pipe(rename(VIS_MIN_CSS)) + .pipe(gulp.dest(DIST)); }); // bundle and minify individual css -gulp.task('bundle-css-individual', function (cb) { - async.each(INDIVIDUAL_CSS_BUNDLES, function (item, callback) { +gulp.task('bundle-css-individual', function(cb) { + async.each(INDIVIDUAL_CSS_BUNDLES, function(item, callback) { return gulp.src(item.entry) - .pipe(concat(item.filename)) - .pipe(cleanCSS()) - .pipe(rename(item.filename)) - .pipe(gulp.dest(DIST)) - .on('end', callback); + .pipe(concat(item.filename)) + .pipe(cleanCSS()) + .pipe(rename(item.filename)) + .pipe(gulp.dest(DIST)) + .on('end', callback); }, cb); }); -gulp.task('copy', ['clean'], function () { - var network = gulp.src('./lib/network/img/**/*') - .pipe(gulp.dest(DIST + '/img/network')); +gulp.task('copy', ['clean'], function() { + var network = gulp.src('./lib/network/img/**/*') + .pipe(gulp.dest(DIST + '/img/network')); - return network; + return network; }); -gulp.task('minify', ['bundle-js'], function (cb) { +gulp.task('minify', ['bundle-js'], function(cb) { var result = uglify.minify([DIST + '/' + VIS_JS], uglifyConfig); // note: we add a newline '\n' to the end of the minified file to prevent // any issues when concatenating the file downstream (the file ends // with a comment). fs.writeFileSync(DIST + '/' + VIS_MIN_JS, result.code + '\n'); - fs.writeFileSync(DIST + '/' + VIS_MAP, result.map.replace(/"\.\/dist\//g, '"')); + fs.writeFileSync(DIST + '/' + VIS_MAP, result.map.replace(/"\.\/dist\//g, + '"')); cb(); }); -gulp.task('bundle', ['bundle-js', 'bundle-js-individual', 'bundle-css', 'bundle-css-individual', 'copy']); +gulp.task('bundle', ['bundle-js', 'bundle-js-individual', 'bundle-css', + 'bundle-css-individual', 'copy' +]); // read command line arguments --bundle and --minify var bundle = 'bundle' in argv; @@ -204,14 +272,13 @@ if (bundle || minify) { watchTasks = []; if (bundle) watchTasks.push('bundle'); if (minify) watchTasks.push('minify'); -} -else { +} else { // by default, do both bundling and minifying watchTasks = ['bundle', 'minify']; } // The watch task (to automatically rebuild when the source code changes) -gulp.task('watch', watchTasks, function () { +gulp.task('watch', watchTasks, function() { gulp.watch(['index.js', 'lib/**/*'], watchTasks); }); diff --git a/package.json b/package.json index e1d285ee..7e936343 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "main": "./dist/vis.js", "scripts": { "test": "mocha --compilers js:babel-core/register", + "gemini": "gulp gemini-tests", "build": "gulp", "lint": "eslint lib", "watch": "gulp watch", @@ -41,15 +42,16 @@ "babel-core": "^6.6.5", "babel-eslint": "^7.1.1", "babel-loader": "^6.2.4", - "babel-polyfill": "^6.22.0", "babel-plugin-transform-es3-member-expression-literals": "^6.22.0", "babel-plugin-transform-es3-property-literals": "^6.8.0", "babel-plugin-transform-runtime": "^6.22.0", + "babel-polyfill": "^6.22.0", "babel-preset-es2015": "^6.6.0", "babel-runtime": "^6.22.0", "babelify": "^7.3.0", "clean-css": "^4.0.2", "eslint": "^3.15.0", + "gemini": "^5.0.0-alpha.3", "gulp": "^3.9.1", "gulp-clean-css": "^2.3.2", "gulp-concat": "^2.6.1", @@ -59,6 +61,7 @@ "jsdom-global": "^2.1.1", "mocha": "^3.2.0", "mocha-jsdom": "^1.1.0", + "opn": "^5.1.0", "rimraf": "^2.5.4", "uglify-js": "^2.7.5", "uuid": "^3.0.1", diff --git a/test/gemini/demo1.js b/test/gemini/demo1.js new file mode 100644 index 00000000..5c715add --- /dev/null +++ b/test/gemini/demo1.js @@ -0,0 +1,8 @@ +gemini.suite('yandex-search', function(suite) { + suite.setUrl('/') + .setCaptureElements('.main-table') + .capture('plain') + .capture('with text', function(actions, find) { + actions.sendKeys(find('.input__control'), 'hello gemini'); + }); +}); diff --git a/test/gemini/demo2.js b/test/gemini/demo2.js new file mode 100644 index 00000000..656070ec --- /dev/null +++ b/test/gemini/demo2.js @@ -0,0 +1,5 @@ +gemini.suite('yandex-icons', function(suite) { + suite.setUrl('/foo') + .setCaptureElements('.tabs') + .capture('plain'); +});