Convert test runner to headless

This commit is contained in:
toby 2017-02-24 18:50:17 -05:00
parent 04df7a51d2
commit 3a90244af0
14 changed files with 1466 additions and 318 deletions

View file

@ -25,72 +25,10 @@
<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" />
<title>CyberChef</title>
</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>
<main style="white-space: pre"></main>
<script type="application/javascript" src="tests.js"></script>
</body>
</html>

View file

@ -111,8 +111,8 @@
"SeasonalWaiter": false,
"WindowWaiter": false,
/* test */
"Vue": false,
"TestRegister": false
/* tests */
"TestRegister": false,
"TestRunner": false
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,106 +0,0 @@
/**
* 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
*/
TestRegister.prototype.getTests = function() {
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 (test.expectedError) {
test.status = "failing";
test.output = [
"Failing",
"-------",
"Expected an error but did not receive one.",
].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();
})();

View file

@ -1,95 +0,0 @@
/**
* 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 non-error when error was expected",
input: "1",
expectedError: true,
recipeConfig: [
{
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: [],
},
],
},
]);

View file

@ -1,77 +0,0 @@
/**
* 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"],
},
],
},
]);

View file

@ -1,33 +0,0 @@
/**
* 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"],
},
],
},
]);

View file

@ -1,58 +0,0 @@
/**
* 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();
},
});
})();