From ee0eff91bff6212c520e2da719250af9398aaf38 Mon Sep 17 00:00:00 2001 From: Asko Soukka Date: Fri, 17 Jan 2020 11:49:11 +0200 Subject: [PATCH] Add Binder configuration --- Examples/my_first.robot | 4 +- Examples/my_second.robot | 4 +- Examples/my_third.robot | 4 +- README.md | 72 ++++++++++-------- binder/custom.css | 31 ++++++++ binder/environment.yml | 12 +++ binder/example.md | 29 ++++++++ binder/example.robot | 29 ++++++++ binder/iframeResizer.contentWindow.min.js | 29 ++++++++ binder/jupyter_notebook_config.py | 5 ++ binder/postBuild | 14 ++++ iframeResizer.min.js | 8 ++ notebook-support.js | 90 +++++++++++++++++++++++ 13 files changed, 298 insertions(+), 33 deletions(-) create mode 100644 binder/custom.css create mode 100644 binder/environment.yml create mode 100644 binder/example.md create mode 100644 binder/example.robot create mode 100644 binder/iframeResizer.contentWindow.min.js create mode 100644 binder/jupyter_notebook_config.py create mode 100644 binder/postBuild create mode 100644 iframeResizer.min.js create mode 100644 notebook-support.js diff --git a/Examples/my_first.robot b/Examples/my_first.robot index c019396..fb842cf 100644 --- a/Examples/my_first.robot +++ b/Examples/my_first.robot @@ -1,4 +1,6 @@ +# + *** Test Cases *** My First Robot Test - Log To Console Hello Robot World! \ No newline at end of file + Log To Console Hello Robot World! +# - diff --git a/Examples/my_second.robot b/Examples/my_second.robot index ed57c9c..4c855f5 100644 --- a/Examples/my_second.robot +++ b/Examples/my_second.robot @@ -1,7 +1,9 @@ +# + *** Settings *** Library OperatingSystem ***Test Cases*** My Second Robot Test - Create File new_file.txt Hello World! \ No newline at end of file + Create File new_file.txt Hello World! +# - diff --git a/Examples/my_third.robot b/Examples/my_third.robot index 61a2e12..3d973fd 100644 --- a/Examples/my_third.robot +++ b/Examples/my_third.robot @@ -1,3 +1,4 @@ +# + *** Settings *** Library OperatingSystem @@ -14,4 +15,5 @@ My Third Robot Test My Forth Robot Test ${file_content} = Get File new_file.txt Should Be Equal ${file_content} ${GOOD_TEXT} - Should Not Be Equal ${file_content} ${BAD_TEXT} \ No newline at end of file + Should Not Be Equal ${file_content} ${BAD_TEXT} +# - diff --git a/README.md b/README.md index 2c43b3d..ac961be 100644 --- a/README.md +++ b/README.md @@ -48,40 +48,49 @@ Following example shows how to write your first robot automation case: 1. Create a new file and save it using an extension `.robot`, for example, `my_first.robot` 2. Write in file `*** Test Cases ***`. This creates [section](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#test-data-sections) for test cases. 3. Type in following (note to add the four spaces before `Log To Console`) -``` -My First Robot Test - Log To Console Hello Robot World! -``` + + ```robotframework + My First Robot Test + Log To Console Hello Robot World! + ``` + 4. First test is now ready and it should look like this: -``` -*** Test Cases *** -My First Robot Test - Log To Console Hello Robot World! -``` + ```robotframework + *** Test Cases *** + + My First Robot Test + Log To Console Hello Robot World! + ``` + +
+ 5. Open Terminal/Command Prompt. Navigate to the same folder where your `.robot` file is located and run the test by inputting command `robot my_first.robot`. For example: -``` -cd your_folder -robot my_first.robot -``` + + ``` + cd your_folder + robot my_first.robot + ``` + 6. When Robot is run, you will see this: -``` -> robot my_first.robot -============================================================================== -My First -============================================================================== -My First Robot Test Hello Robot World! -My First Robot Test | PASS | ------------------------------------------------------------------------------- -My First | PASS | -1 critical test, 1 passed, 0 failed -1 test total, 1 passed, 0 failed -============================================================================== -Output: /output.xml -Log: /log.html -Report: /report.html - -``` + + ``` + > robot my_first.robot + ============================================================================== + My First + ============================================================================== + My First Robot Test Hello Robot World! + My First Robot Test | PASS | + ------------------------------------------------------------------------------ + My First | PASS | + 1 critical test, 1 passed, 0 failed + 1 test total, 1 passed, 0 failed + ============================================================================== + Output: /output.xml + Log: /log.html + Report: /report.html + + ``` Robot has created test report files in the same folder where you run the test. You can check details of the first test run by opening report.html file. [Examples](./Examples) of this manual introduces Keyword Libraries and Variables related to Robot Framework automation. @@ -89,3 +98,6 @@ Robot has created test report files in the same folder where you run the test. Y ## More information Thank you for visiting the Beginners Guide! Hope you enjoyed learning Robot Framework. More about writing test cases: [How To Write Good Test Cases](https://github.com/robotframework/HowToWriteGoodTestCases/blob/master/HowToWriteGoodTestCases.rst). + + + diff --git a/binder/custom.css b/binder/custom.css new file mode 100644 index 0000000..f15c014 --- /dev/null +++ b/binder/custom.css @@ -0,0 +1,31 @@ +#header, +#menubar, +#maintoolbar { + display: none !important; +} +#notebook { + margin: none !important; + padding: 0 !important; +} +#notebook-container { + margin: 0 !important; + padding: 0 !important; + box-shadow: none !important; + width: auto !important; +} +#site { + height: auto !important; +} +body { + background: white !important; + bottom: auto !important; + padding-bottom: 1px; +} +.end_space { + display: none; +} +.input_prompt, +.prompt, +.prompt_container { + display: none !important; +} diff --git a/binder/environment.yml b/binder/environment.yml new file mode 100644 index 0000000..97be851 --- /dev/null +++ b/binder/environment.yml @@ -0,0 +1,12 @@ +name: robotkernel +channels: + - conda-forge +dependencies: + - python >=3.6,<3.8.0a0 + - jupyterlab >=1.2.4,<1.3 + - nodejs >=11,<12 + - pip + - pip: + - robotframework==3.1.2 + - robotkernel==1.3.0 + - jupytext==1.3.2 diff --git a/binder/example.md b/binder/example.md new file mode 100644 index 0000000..f05fb13 --- /dev/null +++ b/binder/example.md @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +--- +jupyter: + jupytext: + text_representation: + extension: .md + format_name: markdown + format_version: '1.2' + jupytext_version: 1.3.2 + kernelspec: + display_name: Robot Framework + language: robotframework + name: robotkernel +--- + +```robotframework +*** Settings *** + +Library String + +*** Variables *** + +${MESSAGE} Hello World + +*** Test Cases *** + +Message is Hello World + Should be equal ${MESSAGE} Hello World +``` diff --git a/binder/example.robot b/binder/example.robot new file mode 100644 index 0000000..18bc734 --- /dev/null +++ b/binder/example.robot @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .robot +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.3.2 +# kernelspec: +# display_name: Robot Framework +# language: robotframework +# name: robotkernel +# --- + +# + +*** Settings *** + +Library String + +*** Variables *** + +${MESSAGE} Hello World + +*** Test Cases *** + +Message is Hello World + Should be equal ${MESSAGE} Hello World +# - diff --git a/binder/iframeResizer.contentWindow.min.js b/binder/iframeResizer.contentWindow.min.js new file mode 100644 index 0000000..284356a --- /dev/null +++ b/binder/iframeResizer.contentWindow.min.js @@ -0,0 +1,29 @@ +/*! iFrame Resizer (iframeSizer.contentWindow.min.js) - v4.2.9 - 2019-12-30 + * Desc: Include this file in any page being loaded into an iframe + * to force the iframe to resize to the content size. + * Requires: iframeResizer.min.js on host page. + * Copyright: (c) 2019 David J. Bradshaw - dave@bradshaw.net + * License: MIT + */ + +!function(d){if("undefined"!=typeof window){var n=!0,o=10,i="",r=0,a="",t=null,u="",c=!1,s={resize:1,click:1},l=128,f=!0,m=1,h="bodyOffset",g=h,p=!0,v="",y={},b=32,w=null,T=!1,E="[iFrameSizer]",O=E.length,S="",M={max:1,min:1,bodyScroll:1,documentElementScroll:1},I="child",N=!0,A=window.parent,C="*",z=0,k=!1,e=null,R=16,x=1,L="scroll",F=L,P=window,D=function(){re("onMessage function not defined")},j=function(){},q=function(){},H={height:function(){return re("Custom height calculation function not defined"),document.documentElement.offsetHeight},width:function(){return re("Custom width calculation function not defined"),document.body.scrollWidth}},W={},B=!1;try{var J=Object.create({},{passive:{get:function(){B=!0}}});window.addEventListener("test",ee,J),window.removeEventListener("test",ee,J)}catch(e){}var U,V,K,Q,X,Y,G=Date.now||function(){return(new Date).getTime()},Z={bodyOffset:function(){return document.body.offsetHeight+pe("marginTop")+pe("marginBottom")},offset:function(){return Z.bodyOffset()},bodyScroll:function(){return document.body.scrollHeight},custom:function(){return H.height()},documentElementOffset:function(){return document.documentElement.offsetHeight},documentElementScroll:function(){return document.documentElement.scrollHeight},max:function(){return Math.max.apply(null,ye(Z))},min:function(){return Math.min.apply(null,ye(Z))},grow:function(){return Z.max()},lowestElement:function(){return Math.max(Z.bodyOffset()||Z.documentElementOffset(),ve("bottom",we()))},taggedElement:function(){return be("bottom","data-iframe-height")}},$={bodyScroll:function(){return document.body.scrollWidth},bodyOffset:function(){return document.body.offsetWidth},custom:function(){return H.width()},documentElementScroll:function(){return document.documentElement.scrollWidth},documentElementOffset:function(){return document.documentElement.offsetWidth},scroll:function(){return Math.max($.bodyScroll(),$.documentElementScroll())},max:function(){return Math.max.apply(null,ye($))},min:function(){return Math.min.apply(null,ye($))},rightMostElement:function(){return ve("right",we())},taggedElement:function(){return be("right","data-iframe-width")}},_=(U=Te,X=null,Y=0,function(){var e=G(),t=R-(e-(Y=Y||e));return V=this,K=arguments,t<=0||R 0) { + setTimeout(heartbeat, 1000); + } + } else { + parentIFrame.sendMessage({ + window: { + location: { + href: window.location.href + } + } + }); + setTimeout(heartbeat, 10 * 1000); + } +}; +heartbeat(); diff --git a/binder/jupyter_notebook_config.py b/binder/jupyter_notebook_config.py new file mode 100644 index 0000000..e0dcfcc --- /dev/null +++ b/binder/jupyter_notebook_config.py @@ -0,0 +1,5 @@ +c.NotebookApp.tornado_settings = { + "headers": { + "Content-Security-Policy": "" + } +} diff --git a/binder/postBuild b/binder/postBuild new file mode 100644 index 0000000..d16769c --- /dev/null +++ b/binder/postBuild @@ -0,0 +1,14 @@ +#!/bin/bash +python -m robotkernel.install --sys-prefix +jupyter nbextension install --py jupytext --sys-prefix +jupyter nbextension enable --py jupytext --sys-prefix +jupyter serverextension enable jupytext +jupyter labextension install jupyterlab_robotmode --no-build +jupyter labextension install @jupyter-widgets/jupyterlab-manager --no-build +jupyter labextension install jupyterlab-jupytext --no-build +jupyter lab build --minimize=True --dev-build=False --debug +mkdir -p .jupyter +mkdir -p .ipython/profile_default/static/custom/ +cp binder/jupyter_notebook_config.py .jupyter +cp binder/custom.css .ipython/profile_default/static/custom/ +cp binder/iframeResizer.contentWindow.min.js .ipython/profile_default/static/custom/custom.js diff --git a/iframeResizer.min.js b/iframeResizer.min.js new file mode 100644 index 0000000..4ec5e36 --- /dev/null +++ b/iframeResizer.min.js @@ -0,0 +1,8 @@ +/*! iFrame Resizer (iframeSizer.min.js ) - v4.2.9 - 2019-12-30 + * Desc: Force cross domain iframes to size to content. + * Requires: iframeResizer.contentWindow.min.js to be loaded into the target frame. + * Copyright: (c) 2019 David J. Bradshaw - dave@bradshaw.net + * License: MIT + */ + +!function(l){if("undefined"!=typeof window){var e,m=0,g=!1,o=!1,v="message".length,I="[iFrameSizer]",x=I.length,F=null,r=window.requestAnimationFrame,h={max:1,scroll:1,bodyScroll:1,documentElementScroll:1},M={},i=null,w={autoResize:!0,bodyBackground:null,bodyMargin:null,bodyMarginV1:8,bodyPadding:null,checkOrigin:!0,inPageLinks:!1,enablePublicMethods:!0,heightCalculationMethod:"bodyOffset",id:"iFrameResizer",interval:32,log:!1,maxHeight:1/0,maxWidth:1/0,minHeight:0,minWidth:0,resizeFrom:"parent",scrolling:!1,sizeHeight:!0,sizeWidth:!1,warningTimeout:5e3,tolerance:0,widthCalculationMethod:"scroll",onClose:function(){return!0},onClosed:function(){},onInit:function(){},onMessage:function(){E("onMessage function not defined")},onResized:function(){},onScroll:function(){return!0}},k={};window.jQuery&&((e=window.jQuery).fn?e.fn.iFrameResize||(e.fn.iFrameResize=function(i){return this.filter("iframe").each(function(e,n){d(n,i)}).end()}):T("","Unable to bind to jQuery, it is not fully loaded.")),"function"==typeof define&&define.amd?define([],q):"object"==typeof module&&"object"==typeof module.exports&&(module.exports=q()),window.iFrameResize=window.iFrameResize||q()}function p(){return window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver}function z(e,n,i){e.addEventListener(n,i,!1)}function O(e,n,i){e.removeEventListener(n,i,!1)}function a(e){return I+"["+function(e){var n="Host page: "+e;return window.top!==window.self&&(n=window.parentIFrame&&window.parentIFrame.getId?window.parentIFrame.getId()+": "+e:"Nested host page: "+e),n}(e)+"]"}function t(e){return M[e]?M[e].log:g}function R(e,n){s("log",e,n,t(e))}function T(e,n){s("info",e,n,t(e))}function E(e,n){s("warn",e,n,!0)}function s(e,n,i,t){!0===t&&"object"==typeof window.console&&console[e](a(n),i)}function n(n){function e(){i("Height"),i("Width"),A(function(){P(b),S(y),d("onResized",b)},b,"init")}function i(e){var n=Number(M[y]["max"+e]),i=Number(M[y]["min"+e]),t=e.toLowerCase(),o=Number(b[t]);R(y,"Checking "+t+" is in range "+i+"-"+n),oM[c]["max"+e])throw new Error("Value for min"+e+" can not be greater than max"+e)}c in M&&"iFrameResizer"in i?E(c,"Ignored iFrame, already setup."):(d=(d=e)||{},M[c]={firstRun:!0,iframe:i,remoteHost:i.src&&i.src.split("/").slice(0,3).join("/")},function(e){if("object"!=typeof e)throw new TypeError("Options is not an object")}(d),Object.keys(d).forEach(n,d),function(e){for(var n in w)Object.prototype.hasOwnProperty.call(w,n)&&(M[c][n]=Object.prototype.hasOwnProperty.call(e,n)?e[n]:w[n])}(d),M[c]&&(M[c].targetOrigin=!0===M[c].checkOrigin?function(e){return""===e||null!==e.match(/^(about:blank|javascript:|file:\/\/)/)?"*":e}(M[c].remoteHost):"*"),function(){switch(R(c,"IFrame scrolling "+(M[c]&&M[c].scrolling?"enabled":"disabled")+" for "+c),i.style.overflow=!1===(M[c]&&M[c].scrolling)?"hidden":"auto",M[c]&&M[c].scrolling){case"omit":break;case!0:i.scrolling="yes";break;case!1:i.scrolling="no";break;default:i.scrolling=M[c]?M[c].scrolling:"no"}}(),f("Height"),f("Width"),u("maxHeight"),u("minHeight"),u("maxWidth"),u("minWidth"),"number"!=typeof(M[c]&&M[c].bodyMargin)&&"0"!==(M[c]&&M[c].bodyMargin)||(M[c].bodyMarginV1=M[c].bodyMargin,M[c].bodyMargin=M[c].bodyMargin+"px"),r=L(c),(s=p())&&(a=s,i.parentNode&&new a(function(e){e.forEach(function(e){Array.prototype.slice.call(e.removedNodes).forEach(function(e){e===i&&C(i)})})}).observe(i.parentNode,{childList:!0})),z(i,"load",function(){B("iFrame.onload",r,i,l,!0),function(){var e=M[c]&&M[c].firstRun,n=M[c]&&M[c].heightCalculationMethod in h;!e&&n&&j({iframe:i,height:0,width:0,type:"init"})}()}),B("init",r,i,l,!0),M[c]&&(M[c].iframe.iFrameResizer={close:C.bind(null,M[c].iframe),removeListeners:b.bind(null,M[c].iframe),resize:B.bind(null,"Window resize","resize",M[c].iframe),moveToAnchor:function(e){B("Move to anchor","moveToAnchor:"+e,M[c].iframe,c)},sendMessage:function(e){B("Send Message","message:"+(e=JSON.stringify(e)),M[c].iframe,c)}}))}function c(e,n){null===i&&(i=setTimeout(function(){i=null,e()},n))}function u(){"hidden"!==document.visibilityState&&(R("document","Trigger event: Visiblity change"),c(function(){f("Tab Visable","resize")},16))}function f(n,i){Object.keys(M).forEach(function(e){!function(e){return M[e]&&"parent"===M[e].resizeFrom&&M[e].autoResize&&!M[e].firstRun}(e)||B(n,i,M[e].iframe,e)})}function y(){z(window,"message",n),z(window,"resize",function(){!function(e){R("window","Trigger event: "+e),c(function(){f("Window "+e,"resize")},16)}("resize")}),z(document,"visibilitychange",u),z(document,"-webkit-visibilitychange",u)}function q(){function i(e,n){n&&(function(){if(!n.tagName)throw new TypeError("Object is not a valid DOM element");if("IFRAME"!==n.tagName.toUpperCase())throw new TypeError("Expected