2018-12-29 03:58:05 +01:00
|
|
|
/**
|
2018-12-30 01:26:28 +01:00
|
|
|
* Tests to ensure that the app loads correctly in a reasonable time and that operations can be run.
|
2018-12-29 03:58:05 +01:00
|
|
|
*
|
|
|
|
* @author n1474335 [n1474335@gmail.com]
|
|
|
|
* @copyright Crown Copyright 2018
|
|
|
|
* @license Apache-2.0
|
|
|
|
*/
|
2021-01-22 13:57:21 +01:00
|
|
|
|
2023-03-06 15:53:20 +01:00
|
|
|
const utils = require("./browserUtils.js");
|
|
|
|
|
2018-12-29 03:58:05 +01:00
|
|
|
module.exports = {
|
2018-12-30 01:26:28 +01:00
|
|
|
before: browser => {
|
2018-12-29 03:58:05 +01:00
|
|
|
browser
|
|
|
|
.resizeWindow(1280, 800)
|
|
|
|
.url(browser.launchUrl);
|
|
|
|
},
|
|
|
|
|
|
|
|
"Loading screen": browser => {
|
|
|
|
// Check that the loading screen appears and then disappears within a reasonable time
|
|
|
|
browser
|
|
|
|
.waitForElementVisible("#preloader", 300)
|
|
|
|
.waitForElementNotPresent("#preloader", 10000);
|
|
|
|
},
|
|
|
|
|
|
|
|
"App loaded": browser => {
|
|
|
|
browser.useCss();
|
|
|
|
// Check that various important elements are loaded
|
|
|
|
browser.expect.element("#operations").to.be.visible;
|
|
|
|
browser.expect.element("#recipe").to.be.visible;
|
|
|
|
browser.expect.element("#input").to.be.present;
|
|
|
|
browser.expect.element("#output").to.be.present;
|
|
|
|
browser.expect.element(".op-list").to.be.present;
|
|
|
|
browser.expect.element("#rec-list").to.be.visible;
|
|
|
|
browser.expect.element("#controls").to.be.visible;
|
|
|
|
browser.expect.element("#input-text").to.be.visible;
|
|
|
|
browser.expect.element("#output-text").to.be.visible;
|
|
|
|
},
|
|
|
|
|
|
|
|
"Operations loaded": browser => {
|
|
|
|
browser.useXpath();
|
2018-12-30 01:26:28 +01:00
|
|
|
// Check that an operation in every category has been populated
|
2018-12-29 03:58:05 +01:00
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='To Base64']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='To Binary']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='AES Decrypt']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='PEM to Hex']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Power Set']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Parse IP range']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Remove Diacritics']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Sort']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='To UNIX Timestamp']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Extract dates']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Gzip']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Keccak']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='JSON Beautify']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Detect File Type']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Play Media']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Disassemble x86']").to.be.present;
|
|
|
|
browser.expect.element("//li[contains(@class, 'operation') and text()='Register']").to.be.present;
|
|
|
|
},
|
|
|
|
|
|
|
|
"Recipe can be run": browser => {
|
|
|
|
const toHex = "//li[contains(@class, 'operation') and text()='To Hex']";
|
|
|
|
const op = "#rec-list .operation .op-title";
|
|
|
|
|
|
|
|
// Check that operation is visible
|
|
|
|
browser
|
|
|
|
.useXpath()
|
|
|
|
.expect.element(toHex).to.be.visible;
|
|
|
|
|
|
|
|
// Add it to the recipe by double clicking
|
|
|
|
browser
|
|
|
|
.useXpath()
|
|
|
|
.moveToElement(toHex, 10, 10)
|
|
|
|
.useCss()
|
2018-12-30 01:47:10 +01:00
|
|
|
.waitForElementVisible(".popover-body", 1000)
|
2022-03-28 16:42:11 +02:00
|
|
|
.doubleClick("xpath", toHex);
|
2018-12-29 03:58:05 +01:00
|
|
|
|
|
|
|
// Confirm that it has been added to the recipe
|
|
|
|
browser
|
|
|
|
.useCss()
|
2019-08-30 12:43:30 +02:00
|
|
|
.waitForElementVisible(op, 100)
|
2018-12-29 03:58:05 +01:00
|
|
|
.expect.element(op).text.to.contain("To Hex");
|
|
|
|
|
|
|
|
// Enter input
|
|
|
|
browser
|
|
|
|
.useCss()
|
2023-02-27 19:21:06 +01:00
|
|
|
.sendKeys("#input-text .cm-content", "Don't Panic.")
|
2019-05-30 15:18:34 +02:00
|
|
|
.pause(1000)
|
2018-12-30 01:37:44 +01:00
|
|
|
.click("#bake");
|
2018-12-29 03:58:05 +01:00
|
|
|
|
|
|
|
// Check output
|
|
|
|
browser
|
|
|
|
.useCss()
|
2018-12-30 02:36:58 +01:00
|
|
|
.waitForElementNotVisible("#stale-indicator", 1000)
|
2023-02-27 19:30:01 +01:00
|
|
|
.expect.element("#output-text .cm-content").text.that.equals("44 6f 6e 27 74 20 50 61 6e 69 63 2e");
|
2018-12-29 03:58:05 +01:00
|
|
|
|
|
|
|
// Clear recipe
|
|
|
|
browser
|
|
|
|
.useCss()
|
|
|
|
.moveToElement(op, 10, 10)
|
2018-12-30 01:47:10 +01:00
|
|
|
.waitForElementNotPresent(".popover-body", 1000)
|
2018-12-29 03:58:05 +01:00
|
|
|
.click("#clr-recipe")
|
|
|
|
.waitForElementNotPresent(op);
|
|
|
|
},
|
|
|
|
|
|
|
|
"Test every module": browser => {
|
|
|
|
browser.useCss();
|
|
|
|
|
|
|
|
// BSON
|
|
|
|
loadOp("BSON deserialise", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
2019-08-30 12:43:30 +02:00
|
|
|
// Charts
|
|
|
|
loadOp("Entropy", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
2018-12-29 03:58:05 +01:00
|
|
|
// Ciphers
|
|
|
|
loadOp("AES Encrypt", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Code
|
|
|
|
loadOp("XPath expression", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Compression
|
|
|
|
loadOp("Gzip", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Crypto
|
|
|
|
loadOp("MD5", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Default
|
|
|
|
loadOp("Fork", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Diff
|
|
|
|
loadOp("Diff", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Encodings
|
|
|
|
loadOp("Encode text", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
2019-08-30 12:43:30 +02:00
|
|
|
// Hashing
|
|
|
|
loadOp("Streebog", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
2018-12-29 03:58:05 +01:00
|
|
|
// Image
|
|
|
|
loadOp("Extract EXIF", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// PGP
|
|
|
|
loadOp("PGP Encrypt", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// PublicKey
|
|
|
|
loadOp("Hex to PEM", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Regex
|
|
|
|
loadOp("Strings", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// Shellcode
|
|
|
|
loadOp("Disassemble x86", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// URL
|
|
|
|
loadOp("URL Encode", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
// UserAgent
|
|
|
|
loadOp("Parse User Agent", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
2019-08-30 12:43:30 +02:00
|
|
|
|
|
|
|
// YARA
|
|
|
|
loadOp("YARA Rules", browser)
|
|
|
|
.waitForElementNotVisible("#output-loader", 5000);
|
|
|
|
|
|
|
|
browser.click("#clr-recipe");
|
|
|
|
},
|
|
|
|
|
|
|
|
"Move around the UI": browser => {
|
|
|
|
const otherCat = "//a[contains(@class, 'category-title') and contains(@data-target, '#catOther')]",
|
|
|
|
genUUID = "//li[contains(@class, 'operation') and text()='Generate UUID']";
|
|
|
|
|
|
|
|
browser.useXpath();
|
|
|
|
|
|
|
|
// Scroll to a lower category
|
|
|
|
browser
|
|
|
|
.getLocationInView(otherCat)
|
|
|
|
.expect.element(otherCat).to.be.visible;
|
|
|
|
|
|
|
|
// Open category
|
|
|
|
browser
|
2024-03-26 17:10:44 +01:00
|
|
|
.useCss()
|
|
|
|
.waitForElementNotVisible("#snackbar-container", 10000)
|
|
|
|
.useXpath()
|
2019-08-30 12:43:30 +02:00
|
|
|
.click(otherCat)
|
|
|
|
.expect.element(genUUID).to.be.visible;
|
|
|
|
|
2019-08-30 16:30:30 +02:00
|
|
|
// Add op to recipe
|
|
|
|
/* mouseButtonUp drops wherever the actual cursor is, not necessarily in the right place,
|
|
|
|
so we can't test Sortable.js properly using Nightwatch. html-dnd doesn't work either.
|
|
|
|
Instead of relying on drag and drop, we double click on the op to load it. */
|
2019-08-30 12:43:30 +02:00
|
|
|
browser
|
|
|
|
.getLocationInView(genUUID)
|
|
|
|
.moveToElement(genUUID, 10, 10)
|
2022-03-28 16:42:11 +02:00
|
|
|
.doubleClick("xpath", genUUID)
|
2019-08-30 12:43:30 +02:00
|
|
|
.useCss()
|
|
|
|
.waitForElementVisible(".operation .op-title", 1000)
|
|
|
|
.waitForElementNotVisible("#stale-indicator", 1000)
|
2023-02-27 19:30:01 +01:00
|
|
|
.expect.element("#output-text .cm-content").text.which.matches(/[\da-f-]{36}/);
|
2019-08-30 12:43:30 +02:00
|
|
|
|
|
|
|
browser.click("#clr-recipe");
|
|
|
|
},
|
|
|
|
|
|
|
|
"Search": browser => {
|
|
|
|
// Search for an op
|
|
|
|
browser
|
|
|
|
.useCss()
|
|
|
|
.clearValue("#search")
|
|
|
|
.setValue("#search", "md5")
|
|
|
|
.useXpath()
|
2021-02-05 19:07:20 +01:00
|
|
|
.waitForElementVisible("//ul[@id='search-results']//b[text()='MD5']", 1000);
|
2018-12-29 03:58:05 +01:00
|
|
|
},
|
|
|
|
|
2023-03-06 15:53:20 +01:00
|
|
|
"Alert bar": browser => {
|
|
|
|
// Bake nothing to create an empty output which can be copied
|
|
|
|
utils.clear(browser);
|
|
|
|
utils.bake(browser);
|
|
|
|
|
|
|
|
// Alert bar shows and contains correct content
|
|
|
|
browser
|
2023-07-21 18:30:39 +02:00
|
|
|
.waitForElementNotVisible("#snackbar-container")
|
2023-03-06 15:53:20 +01:00
|
|
|
.click("#copy-output")
|
2024-03-26 17:10:44 +01:00
|
|
|
.waitForElementVisible("#snackbar-container .snackbar-content")
|
2023-03-06 15:53:20 +01:00
|
|
|
.expect.element("#snackbar-container .snackbar-content").text.to.equal("Copied raw output successfully.");
|
|
|
|
|
|
|
|
// Alert bar disappears after the correct amount of time
|
|
|
|
// Should disappear after 2000ms
|
|
|
|
browser
|
|
|
|
.waitForElementNotPresent("#snackbar-container .snackbar-content", 2500)
|
|
|
|
.waitForElementNotVisible("#snackbar-container");
|
|
|
|
},
|
|
|
|
|
2018-12-29 03:58:05 +01:00
|
|
|
after: browser => {
|
|
|
|
browser.end();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the current recipe and loads a new operation.
|
|
|
|
*
|
|
|
|
* @param {string} opName
|
|
|
|
* @param {Browser} browser
|
|
|
|
*/
|
|
|
|
function loadOp(opName, browser) {
|
|
|
|
return browser
|
|
|
|
.useCss()
|
|
|
|
.click("#clr-recipe")
|
|
|
|
.urlHash("op=" + opName);
|
|
|
|
}
|