Initial work on in-browser test runner

Run `grunt test` and open up the `build/test/index.html` to run the
tests.
This commit is contained in:
toby committed 2017-02-23 13:59:58 -05:00
1 parent 92bd2c921e
commit 500522bdeb
9 files changed
+535 -9

No files matched your search

+76 -7
View File
@@ -9,6 +9,10 @@ module.exports = function(grunt) {
"A persistent task which creates a development build whenever source files are modified.", "A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "concat:css", "concat:js", "copy:htmlDev", "copy:staticDev", "chmod:build", "watch"]); ["clean:dev", "concat:css", "concat:js", "copy:htmlDev", "copy:staticDev", "chmod:build", "watch"]);
grunt.registerTask("test",
"A persistent task which creates a test build whenever source files are modified.",
["clean:dev", "concat:cssTest", "concat:jsTest", "copy:htmlTest", "copy:staticTest", "chmod:build", "watch"]);
grunt.registerTask("prod", grunt.registerTask("prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.", "Creates a production-ready build. Use the --msg flag to add a compile message.",
["eslint", "exec:stats", "clean", "jsdoc", "concat", "copy:htmlDev", "copy:htmlProd", "copy:htmlInline", ["eslint", "exec:stats", "clean", "jsdoc", "concat", "copy:htmlDev", "copy:htmlProd", "copy:htmlInline",
@@ -50,7 +54,7 @@ module.exports = function(grunt) {
// JS includes // JS includes
var jsFiles = [ var jsIncludes = [
// Third party framework libraries // Third party framework libraries
"src/js/lib/jquery-2.1.1.js", "src/js/lib/jquery-2.1.1.js",
"src/js/lib/bootstrap-3.3.6.js", "src/js/lib/bootstrap-3.3.6.js",
@@ -154,10 +158,27 @@ module.exports = function(grunt) {
"src/js/views/html/*.js", "src/js/views/html/*.js",
"!src/js/views/html/main.js", "!src/js/views/html/main.js",
// Start the app!
"src/js/views/html/main.js",
]; ];
var jsAppFiles = [].concat(
jsIncludes,
[
// Start the main app!
"src/js/views/html/main.js",
]
);
var jsTestFiles = [].concat(
jsIncludes,
[
"src/js/lib/vuejs/vue.min.js",
"src/js/test/*.js",
"src/js/test/tests/**/*",
// Start the test runner app!
"src/js/test/views/html/main.js",
]
);
var banner = '/**\n\ var banner = '/**\n\
* CyberChef - The Cyber Swiss Army Knife\n\ * CyberChef - The Cyber Swiss Army Knife\n\
*\n\ *\n\
@@ -198,6 +219,7 @@ module.exports = function(grunt) {
config: ["src/js/config/**/*.js"], config: ["src/js/config/**/*.js"],
views: ["src/js/views/**/*.js"], views: ["src/js/views/**/*.js"],
operations: ["src/js/operations/**/*.js"], operations: ["src/js/operations/**/*.js"],
tests: ["src/js/test/**/*.js"],
}, },
jsdoc: { jsdoc: {
options: { options: {
@@ -239,12 +261,35 @@ module.exports = function(grunt) {
], ],
dest: "build/dev/styles.css" dest: "build/dev/styles.css"
}, },
cssTest: {
options: {
banner: banner.replace(/\/\*\*/g, "/*!"),
process: function(content, srcpath) {
// Change special comments from /** to /*! to comply with cssmin
content = content.replace(/^\/\*\* /g, "/*! ");
return grunt.template.process(content);
}
},
src: [
"src/css/lib/**/*.css",
"src/css/structure/**/*.css",
"src/css/themes/classic.css"
],
dest: "build/test/styles.css"
},
js: { js: {
options: { options: {
banner: '"use strict";\n' banner: '"use strict";\n'
}, },
src: jsFiles, src: jsAppFiles,
dest: "build/dev/scripts.js" dest: "build/dev/scripts.js"
},
jsTest: {
options: {
banner: '"use strict";\n'
},
src: jsTestFiles,
dest: "build/test/scripts.js"
} }
}, },
copy: { copy: {
@@ -257,6 +302,15 @@ module.exports = function(grunt) {
src: "src/html/index.html", src: "src/html/index.html",
dest: "build/dev/index.html" dest: "build/dev/index.html"
}, },
htmlTest: {
options: {
process: function(content, srcpath) {
return grunt.template.process(content, templateOptions);
}
},
src: "src/html/test.html",
dest: "build/test/index.html"
},
htmlProd: { htmlProd: {
options: { options: {
process: function(content, srcpath) { process: function(content, srcpath) {
@@ -294,6 +348,21 @@ module.exports = function(grunt) {
} }
] ]
}, },
staticTest: {
files: [
{
expand: true,
cwd: "src/static/",
src: [
"**/*",
"**/.*",
"!stats.txt",
"!ga.html"
],
dest: "build/test/"
}
]
},
staticProd: { staticProd: {
files: [ files: [
{ {
@@ -468,15 +537,15 @@ module.exports = function(grunt) {
}, },
js: { js: {
files: "src/js/**/*.js", files: "src/js/**/*.js",
tasks: ["concat:js", "chmod:build"] tasks: ["concat:js", "concat:jsTest", "chmod:build"]
}, },
html: { html: {
files: "src/html/**/*.html", files: "src/html/**/*.html",
tasks: ["copy:htmlDev", "chmod:build"] tasks: ["copy:htmlDev", "copy:htmlTest", "chmod:build"]
}, },
static: { static: {
files: ["src/static/**/*", "src/static/**/.*"], files: ["src/static/**/*", "src/static/**/.*"],
tasks: ["copy:staticDev", "chmod:build"] tasks: ["copy:staticDev", "copy:staticTest", "chmod:build"]
}, },
grunt: { grunt: {
files: "Gruntfile.js", files: "Gruntfile.js",
+96
View File
@@ -0,0 +1,96 @@
<!-- htmlmin:ignore --><!--
CyberChef - The Cyber Swiss Army Knife
@author tlwr [toby@toby.codes]
@copyright Crown Copyright 2017
@license Apache-2.0
Copyright 2017 Crown Copyright
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- htmlmin:ignore -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CyberChef Test Runner</title>
<link rel="icon" type="image/png" href="images/favicon.ico?__inline" />
<link href="styles.css" rel="stylesheet" />
</head>
<body>
<template id="test-status-icon-template">
<span>{{ getIcon() }}</span>
</template>
<template id="test-stats-template">
<div class="text-center row">
<div class="col-md-2"
v-for="status in ['Waiting', 'Loading', 'Erroring', 'Failing']">
<test-status-icon :status="status.toLowerCase()"></test-status-icon>
<br>
{{ status }}
<br>
{{ countTestsWithStatus(status.toLowerCase()) }}
</div>
<div class="col-md-2">
<test-status-icon status="passing"></test-status-icon>
<br>
Passing
<br>
{{ countTestsWithStatus("passing") }}
/
{{ tests.length }}
</div>
<div class="col-md-2">
<test-status-icon status="passing"></test-status-icon>
<br>
% Passing
<br>
{{ ((100.0 * countTestsWithStatus("passing")) / tests.length).toFixed(1) }}%
</div>
</div>
</template>
<template id="tests-template">
<table class="table table-striped">
<tbody>
<tr v-for="test in tests">
<td class="col-md-1 col-sm-4">
<test-status-icon :status="test.status"></test-status-icon>
</td>
<td class="col-md-4 col-sm-8">
{{ test.name }}
</td>
<td class="col-md-7 col-sm-12">
<pre v-if="test.output"><code>{{ test.output }}</code></pre>
</td>
</tr>
</tbody>
</table>
</template>
<div class="container">
<main>
<h1>CyberChef Test Runner</h1>
<hr>
<test-stats :tests="tests"></test-stats>
<hr>
<tests :tests="tests"></tests>
</main>
</div>
<script type="application/javascript" src="scripts.js"></script>
</body>
</html>
+6 -2
View File
@@ -109,6 +109,10 @@
"OutputWaiter": false, "OutputWaiter": false,
"RecipeWaiter": false, "RecipeWaiter": false,
"SeasonalWaiter": false, "SeasonalWaiter": false,
"WindowWaiter": false "WindowWaiter": false,
/* test */
"Vue": false,
"TestRegister": false
} }
} }
+8
View File
@@ -0,0 +1,8 @@
/*!
* Vue.js v2.1.10
* (c) 2014-2017 Evan You
* Released under the MIT License.
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";function e(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function t(e){var t=parseFloat(e);return isNaN(t)?e:t}function n(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function r(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function i(e,t){return ii.call(e,t)}function o(e){return"string"==typeof e||"number"==typeof e}function a(e){var t=Object.create(null);return function(n){var r=t[n];return r||(t[n]=e(n))}}function s(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function c(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function u(e,t){for(var n in t)e[n]=t[n];return e}function l(e){return null!==e&&"object"==typeof e}function f(e){return li.call(e)===fi}function p(e){for(var t={},n=0;n<e.length;n++)e[n]&&u(t,e[n]);return t}function d(){}function v(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}function h(e,t){var n=l(e),r=l(t);return n&&r?JSON.stringify(e)===JSON.stringify(t):!n&&!r&&String(e)===String(t)}function m(e,t){for(var n=0;n<e.length;n++)if(h(e[n],t))return n;return-1}function g(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function y(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function _(e){if(!hi.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function b(e){return/native code/.test(e.toString())}function $(e){Ei.target&&Ii.push(Ei.target),Ei.target=e}function w(){Ei.target=Ii.pop()}function C(e,t){e.__proto__=t}function x(e,t,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];y(e,o,t[o])}}function k(e,t){if(l(e)){var n;return i(e,"__ob__")&&e.__ob__ instanceof Di?n=e.__ob__:Mi.shouldConvert&&!xi()&&(Array.isArray(e)||f(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new Di(e)),t&&n&&n.vmCount++,n}}function A(e,t,n,r){var i=new Ei,o=Object.getOwnPropertyDescriptor(e,t);if(!o||o.configurable!==!1){var a=o&&o.get,s=o&&o.set,c=k(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=a?a.call(e):n;return Ei.target&&(i.depend(),c&&c.dep.depend(),Array.isArray(t)&&T(t)),t},set:function(t){var r=a?a.call(e):n;t===r||t!==t&&r!==r||(s?s.call(e,t):n=t,c=k(t),i.notify())}})}}function O(e,t,n){if(Array.isArray(e))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(i(e,t))return void(e[t]=n);var r=e.__ob__;if(!(e._isVue||r&&r.vmCount))return r?(A(r.value,t,n),r.dep.notify(),n):void(e[t]=n)}function S(e,t){var n=e.__ob__;e._isVue||n&&n.vmCount||i(e,t)&&(delete e[t],n&&n.dep.notify())}function T(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Array.isArray(t)&&T(t)}function E(e,t){if(!t)return e;for(var n,r,o,a=Object.keys(t),s=0;s<a.length;s++)n=a[s],r=e[n],o=t[n],i(e,n)?f(r)&&f(o)&&E(r,o):O(e,n,o);return e}function I(e,t){return t?e?e.concat(t):Array.isArray(t)?t:[t]:e}function j(e,t){var n=Object.create(e||null);return t?u(n,t):n}function N(e){var t=e.props;if(t){var n,r,i,o={};if(Array.isArray(t))for(n=t.length;n--;)r=t[n],"string"==typeof r&&(i=ai(r),o[i]={type:null});else if(f(t))for(var a in t)r=t[a],i=ai(a),o[i]=f(r)?r:{type:r};e.props=o}}function L(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function M(e,t,n){function r(r){var i=Pi[r]||Ri;l[r]=i(e[r],t[r],n,r)}N(t),L(t);var o=t.extends;if(o&&(e="function"==typeof o?M(e,o.options,n):M(e,o,n)),t.mixins)for(var a=0,s=t.mixins.length;a<s;a++){var c=t.mixins[a];c.prototype instanceof Ue&&(c=c.options),e=M(e,c,n)}var u,l={};for(u in e)r(u);for(u in t)i(e,u)||r(u);return l}function D(e,t,n,r){if("string"==typeof n){var o=e[t];if(i(o,n))return o[n];var a=ai(n);if(i(o,a))return o[a];var s=si(a);if(i(o,s))return o[s];var c=o[n]||o[a]||o[s];return c}}function P(e,t,n,r){var o=t[e],a=!i(n,e),s=n[e];if(H(Boolean,o.type)&&(a&&!i(o,"default")?s=!1:H(String,o.type)||""!==s&&s!==ui(e)||(s=!0)),void 0===s){s=R(r,o,e);var c=Mi.shouldConvert;Mi.shouldConvert=!0,k(s),Mi.shouldConvert=c}return s}function R(e,t,n){if(i(t,"default")){var r=t.default;return l(r),e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e[n]?e[n]:"function"==typeof r&&t.type!==Function?r.call(e):r}}function F(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t&&t[1]}function H(e,t){if(!Array.isArray(t))return F(t)===F(e);for(var n=0,r=t.length;n<r;n++)if(F(t[n])===F(e))return!0;return!1}function U(e){return new Hi(void 0,void 0,void 0,String(e))}function B(e){var t=new Hi(e.tag,e.data,e.children,e.text,e.elm,e.context,e.componentOptions);return t.ns=e.ns,t.isStatic=e.isStatic,t.keyLine truncated
return Gt(t)+Gt(e[n])}))}function Gt(e){return 1e3*Number(e.slice(0,-1))}function Yt(e,t){var n=e.elm;n._leaveCb&&(n._leaveCb.cancelled=!0,n._leaveCb());var r=Xt(e.data.transition);if(r&&!n._enterCb&&1===n.nodeType){for(var i=r.css,o=r.type,a=r.enterClass,s=r.enterToClass,c=r.enterActiveClass,u=r.appearClass,l=r.appearToClass,f=r.appearActiveClass,p=r.beforeEnter,d=r.enter,v=r.afterEnter,h=r.enterCancelled,m=r.beforeAppear,g=r.appear,y=r.afterAppear,_=r.appearCancelled,b=Zi,$=Zi.$vnode;$&&$.parent;)$=$.parent,b=$.context;var w=!b._isMounted||!e.isRootInsert;if(!w||g||""===g){var C=w?u:a,x=w?f:c,k=w?l:s,A=w?m||p:p,O=w&&"function"==typeof g?g:d,S=w?y||v:v,T=w?_||h:h,E=i!==!1&&!bi,I=O&&(O._length||O.length)>1,j=n._enterCb=en(function(){E&&(Kt(n,k),Kt(n,x)),j.cancelled?(E&&Kt(n,C),T&&T(n)):S&&S(n),n._enterCb=null});e.data.show||ne(e.data.hook||(e.data.hook={}),"insert",function(){var t=n.parentNode,r=t&&t._pending&&t._pending[e.key];r&&r.tag===e.tag&&r.elm._leaveCb&&r.elm._leaveCb(),O&&O(n,j)},"transition-insert"),A&&A(n),E&&(Jt(n,C),Jt(n,x),Vt(function(){Jt(n,k),Kt(n,C),j.cancelled||I||qt(n,o,j)})),e.data.show&&(t&&t(),O&&O(n,j)),E||I||j()}}}function Qt(e,t){function n(){g.cancelled||(e.data.show||((r.parentNode._pending||(r.parentNode._pending={}))[e.key]=e),l&&l(r),h&&(Jt(r,s),Jt(r,u),Vt(function(){Jt(r,c),Kt(r,s),g.cancelled||m||qt(r,a,g)})),f&&f(r,g),h||m||g())}var r=e.elm;r._enterCb&&(r._enterCb.cancelled=!0,r._enterCb());var i=Xt(e.data.transition);if(!i)return t();if(!r._leaveCb&&1===r.nodeType){var o=i.css,a=i.type,s=i.leaveClass,c=i.leaveToClass,u=i.leaveActiveClass,l=i.beforeLeave,f=i.leave,p=i.afterLeave,d=i.leaveCancelled,v=i.delayLeave,h=o!==!1&&!bi,m=f&&(f._length||f.length)>1,g=r._leaveCb=en(function(){r.parentNode&&r.parentNode._pending&&(r.parentNode._pending[e.key]=null),h&&(Kt(r,c),Kt(r,u)),g.cancelled?(h&&Kt(r,s),d&&d(r)):(t(),p&&p(r)),r._leaveCb=null});v?v(n):n()}}function Xt(e){if(e){if("object"==typeof e){var t={};return e.css!==!1&&u(t,Xo(e.name||"v")),u(t,e),t}return"string"==typeof e?Xo(e):void 0}}function en(e){var t=!1;return function(){t||(t=!0,e())}}function tn(e,t){t.data.show||Yt(t)}function nn(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],i)o=m(r,on(a))>-1,a.selected!==o&&(a.selected=o);else if(h(on(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function rn(e,t){for(var n=0,r=t.length;n<r;n++)if(h(on(t[n]),e))return!1;return!0}function on(e){return"_value"in e?e._value:e.value}function an(e){e.target.composing=!0}function sn(e){e.target.composing=!1,cn(e.target,"input")}function cn(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function un(e){return!e.componentInstance||e.data&&e.data.transition?e:un(e.componentInstance._vnode)}function ln(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?ln(ce(t.children)):e}function fn(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[ai(o)]=i[o].fn;return t}function pn(e,t){return/\d-keep-alive$/.test(t.tag)?e("keep-alive"):null}function dn(e){for(;e=e.parent;)if(e.data.transition)return!0}function vn(e,t){return t.key===e.key&&t.tag===e.tag}function hn(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function mn(e){e.data.newPos=e.elm.getBoundingClientRect()}function gn(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}function yn(e,t){var n=document.createElement("div");return n.innerHTML='<div a="'+e+'">',n.innerHTML.indexOf(t)>0}function _n(e){return pa=pa||document.createElement("div"),pa.innerHTML=e,pa.textContent}function bn(e,t){return t&&(e=e.replace(os,"\n")),e.replace(rs,"<").replace(is,">").replace(as,"&").replace(ss,'"')}function $n(e,t){function n(t){f+=t,e=e.substring(t)}function r(){var t=e.match(Ca);if(t){var r={tagName:t[1],attrs:[],start:f};n(t[0].length);for(var i,o;!(i=e.match(xa))&&(o=e.match(ba));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=f,r}}function i(e){var n=e.tagName,r=e.unarySlash;u&&("p"===s&&ma(n)&&o(s),ha(n)&&s===n&&o(n));for(var i=l(n)||"html"===n&&"head"===s||!!r,a=e.attrs.length,f=new Array(a),p=0;p<a;p++){var d=e.attrs[p];Ta&&d[0].indexOf('""')===-1&&(""===d[3]&&delete d[3],""===d[4]&&delete d[4],""===d[5]&&delete d[5]);var v=d[3]||d[4]||d[5]||"";f[p]={name:d[1],value:bn(v,t.shouldDecodeNewlines)}}i||(c.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:f}),s=n,r=""),t.start&&t.start(n,f,i,e.start,e.end)}function o(e,n,r){var i,o;if(null==n&&(n=f),null==r&&(r=f),e&&(o=e.toLowerCase()),e)for(i=c.length-1;i>=0&&c[i].lowerCasedTag!==o;i--);else i=0;if(i>=0){for(var a=c.length-1;a>=i;a--)t.end&&t.end(c[a].tag,n,r);c.length=i,s=i&&c[i-1].tag}else"br"===o?t.start&&t.start(e,[],!0,n,r):"p"===o&&(t.staLine truncated
update:Ct,destroy:function(e){Ct(e,So)}},Io=Object.create(null),jo=[Oo,Eo],No={create:St,update:St},Lo={create:Et,update:Et},Mo={create:Nt,update:Nt},Do={create:Lt,update:Lt},Po=a(function(e){var t={},n=/;(?![^(]*\))/g,r=/:(.+)/;return e.split(n).forEach(function(e){if(e){var n=e.split(r);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}),Ro=/^--/,Fo=/\s*!important$/,Ho=function(e,t,n){Ro.test(t)?e.style.setProperty(t,n):Fo.test(n)?e.style.setProperty(t,n.replace(Fo,""),"important"):e.style[Bo(t)]=n},Uo=["Webkit","Moz","ms"],Bo=a(function(e){if(lo=lo||document.createElement("div"),e=ai(e),"filter"!==e&&e in lo.style)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<Uo.length;n++){var r=Uo[n]+t;if(r in lo.style)return r}}),zo={create:Ut,update:Ut},Vo=gi&&!bi,Jo="transition",Ko="animation",qo="transition",Wo="transitionend",Zo="animation",Go="animationend";Vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(qo="WebkitTransition",Wo="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Zo="WebkitAnimation",Go="webkitAnimationEnd"));var Yo=gi&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout,Qo=/\b(transform|all)(,|$)/,Xo=a(function(e){return{enterClass:e+"-enter",leaveClass:e+"-leave",appearClass:e+"-enter",enterToClass:e+"-enter-to",leaveToClass:e+"-leave-to",appearToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveActiveClass:e+"-leave-active",appearActiveClass:e+"-enter-active"}}),ea=gi?{create:tn,activate:tn,remove:function(e,t){e.data.show?t():Qt(e,t)}}:{},ta=[No,Lo,Mo,Do,zo,ea],na=ta.concat(jo),ra=wt({nodeOps:Ao,modules:na});bi&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&cn(e,"input")});var ia={inserted:function(e,t,n){if("select"===n.tag){var r=function(){nn(e,t,n.context)};r(),(_i||$i)&&setTimeout(r,0)}else"textarea"!==n.tag&&"text"!==e.type||(e._vModifiers=t.modifiers,t.modifiers.lazy||(wi||(e.addEventListener("compositionstart",an),e.addEventListener("compositionend",sn)),bi&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){nn(e,t,n.context);var r=e.multiple?t.value.some(function(t){return rn(t,e.options)}):t.value!==t.oldValue&&rn(t.value,e.options);r&&cn(e,"change")}}},oa={bind:function(e,t,n){var r=t.value;n=un(n);var i=n.data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i&&!bi?(n.data.show=!0,Yt(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value,i=t.oldValue;if(r!==i){n=un(n);var o=n.data&&n.data.transition;o&&!bi?(n.data.show=!0,r?Yt(n,function(){e.style.display=e.__vOriginalDisplay}):Qt(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none"}},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}},aa={model:ia,show:oa},sa={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String},ca={name:"transition",props:sa,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(function(e){return e.tag}),n.length)){var r=this.mode,i=n[0];if(dn(this.$vnode))return i;var a=ln(i);if(!a)return i;if(this._leaving)return pn(e,i);var s="__transition-"+this._uid+"-",c=a.key=null==a.key?s+a.tag:o(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key,l=(a.data||(a.data={})).transition=fn(this),f=this._vnode,p=ln(f);if(a.data.directives&&a.data.directives.some(function(e){return"show"===e.name})&&(a.data.show=!0),p&&p.data&&!vn(a,p)){var d=p&&(p.data.transition=u({},l));if("out-in"===r)return this._leaving=!0,ne(d,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()},c),pn(e,i);if("in-out"===r){var v,h=function(){v()};ne(l,"afterEnter",h,c),ne(l,"enterCancelled",h,c),ne(d,"delayLeave",function(e){v=e},c)}}return i}}},ua=u({tag:String,moveClass:String},sa);delete ua.mode;var la={props:ua,render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=fn(this),s=0;s<i.length;s++){var c=i[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(o.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],l=[],f=0;f<r.length;f++){var p=r[f];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?u.push(p):l.push(p)}this.kept=e(t,null,u),this.removed=l}return e(t,null,o)},beforeUpdate:function(){this.__patch__(this._vnode,this.kept,!1,!0),this._vnode=this.kept},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";if(e.length&&this.hasMove(e[0].elm,t)){e.forEach(hn),e.forEach(mn),e.forEach(gn);document.body.offsetHeight;e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;Jt(n,t),r.transform=r.WebkLine truncated
+97
View File
@@ -0,0 +1,97 @@
/**
* TestRegister.js
*
* This is so individual files can register their tests in one place, and
* ensure that they will get run by the frontend.
*
* @author tlwr [toby@toby.codes
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
*/
(function() {
/**
* Add a list of tests to the register.
*
* @class
*/
function TestRegister() {
this.tests = [];
}
/**
* Add a list of tests to the register.
*
* @param {Object[]} tests
*/
TestRegister.prototype.addTests = function(tests) {
this.tests = this.tests.concat(tests.map(function(test) {
test.status = "waiting";
test.output = "";
return test;
}));
};
/**
* Returns the list of tests.
*
* @returns {Object[]} tests
return this.tests;
};
/**
* Runs all the tests in the register and updates the state of each test.
*
*/
TestRegister.prototype.runTests = function() {
this.tests.forEach(function(test, i) {
var chef = new Chef();
// This resolve is to not instantly break when async operations are
// supported. Marked as TODO.
Promise.resolve(chef.bake(
test.input,
test.recipeConfig,
{},
0,
0
))
.then(function(result) {
if (result.error) {
if (test.expectedError) {
test.status = "passing";
} else {
test.status = "erroring";
test.output = [
"Erroring",
"-------",
result.error.displayStr,
].join("\n");
}
} else {
if (result.result === test.expectedOutput) {
test.status = "passing";
} else {
test.status = "failing";
test.output = [
"Failing",
"-------",
"Expected",
"-------",
test.expectedOutput,
"Actual",
"-------",
result.result,
].join("\n");
}
}
});
});
};
// Singleton TestRegister, keeping things simple and obvious.
window.TestRegister = new TestRegister();
})();
+84
View File
@@ -0,0 +1,84 @@
/**
* Core tests.
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
*/
TestRegister.addTests([
{
name: "Example error",
input: "1\n2\na\n4",
expectedOutput: "1\n2\n3\n4",
recipeConfig: [
{
op: "Fork",
args: ["\n", "\n", false],
},
{
op: "To Base",
args: [16],
},
],
},
{
name: "Example fail",
input: "1\n2\na\n4",
expectedOutput: "1\n2\n3\n4",
recipeConfig: [
{
op: "Fork",
args: ["\n", "\n", true],
},
{
op: "To Base",
args: [16],
},
],
},
{
name: "Fork: nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "Fork",
args: ["\n", "\n", false],
},
],
},
{
name: "Fork, Merge: nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "Fork",
args: ["\n", "\n", false],
},
{
op: "Merge",
args: [],
},
],
},
{
name: "Fork, (expect) Error, Merge",
input: "1\n2\na\n4",
expectedError: true,
recipeConfig: [
{
op: "Fork",
args: ["\n", "\n", false],
},
{
op: "To Base",
args: [16],
},
{
op: "Merge",
args: [],
},
],
},
]);
+77
View File
@@ -0,0 +1,77 @@
/**
* Base58 tests.
*
* @author tlwr [toby@toby.codes
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
*/
TestRegister.addTests([
{
name: "To Base58 (Bitcoin): nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "To Base58",
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
},
],
},
{
name: "To Base58 (Ripple): nothing",
input: "",
expectedOutput: "",
recipeConfig: [
{
op: "To Base58",
args: ["rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"],
},
],
},
{
name: "To Base58 (Bitcoin): 'hello world'",
input: "hello world",
expectedOutput: "StV1DL6CwTryKyV",
recipeConfig: [
{
op: "To Base58",
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
},
],
},
{
name: "To Base58 (Ripple): 'hello world'",
input: "hello world",
expectedOutput: "StVrDLaUATiyKyV",
recipeConfig: [
{
op: "To Base58",
args: ["rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"],
},
],
},
{
name: "From Base58 (Bitcoin): 'StV1DL6CwTryKyV'",
input: "StV1DL6CwTryKyV",
expectedOutput: "hello world",
recipeConfig: [
{
op: "From Base58",
args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
},
],
},
{
name: "From Base58 (Ripple): 'StVrDLaUATiyKyV'",
input: "StVrDLaUATiyKyV",
expectedOutput: "hello world",
recipeConfig: [
{
op: "From Base58",
args: ["rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"],
},
],
},
]);
+33
View File
@@ -0,0 +1,33 @@
/**
* Base58 tests.
*
* @author tlwr [toby@toby.codes
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
*/
TestRegister.addTests([
{
name: "To Morse Code: 'SOS'",
input: "SOS",
expectedOutput: "... --- ...",
recipeConfig: [
{
op: "To Morse Code",
args: ["-/.", "Space", "Line feed"],
},
],
},
{
name: "From Morse Code '... --- ...'",
input: "... --- ...",
expectedOutput: "SOS",
recipeConfig: [
{
op: "From Morse Code",
args: ["Space", "Line feed"],
},
],
},
]);
+58
View File
@@ -0,0 +1,58 @@
/**
* main.js
*
* Simple VueJS app for running all the tests and displaying some basic stats.
* @author tlwr [toby@toby.codes]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
*/
(function() {
Vue.component("test-status-icon", {
template: "#test-status-icon-template",
props: ["status"],
methods: {
getIcon: function() {
var icons = {
waiting: "⌚",
loading: "⚡",
passing: "✔️️",
failing: "❌",
erroring: "☠️",
};
return icons[this.status];
}
},
});
Vue.component("test-stats", {
template: "#test-stats-template",
props: ["tests"],
methods: {
countTestsWithStatus: function(status) {
return this.tests.filter(function(test) {
return test.status === status;
}).length;
},
},
});
Vue.component("tests", {
template: "#tests-template",
props: ["tests"],
});
window.TestRunner = new Vue({
el: "main",
data: {
tests: TestRegister.getTests(),
},
mounted: function() {
TestRegister.runTests();
},
});
})();