diff --git a/tests/browser/00_nightwatch_mobile.js b/tests/browser/00_nightwatch_mobile.js index 048f223d..996cf1c8 100644 --- a/tests/browser/00_nightwatch_mobile.js +++ b/tests/browser/00_nightwatch_mobile.js @@ -43,28 +43,6 @@ module.exports = { browser.expect.element("#output-text").to.be.visible; }, - "Operations loaded": browser => { - browser.useXpath(); - // Check that an operation in every category has been populated - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='To Base64']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='To Binary']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='AES Decrypt']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='PEM to Hex']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Power Set']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Parse IP range']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Remove Diacritics']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Sort']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='To UNIX Timestamp']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Extract dates']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Gzip']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Keccak']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='JSON Beautify']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Detect File Type']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Play Media']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Disassemble x86']").to.be.present; - browser.expect.element("//li[contains(@class, 'operation')]/span[text()='Register']").to.be.present; - }, - "Recipe can be run": browser => { const toHex = "//li[contains(@class, 'operation')]/span[text()='To Hex']"; const op = "#rec-list .operation .op-title"; @@ -118,84 +96,6 @@ module.exports = { .waitForElementNotPresent(op); }, - "Test every module": browser => { - browser.useCss(); - - // BSON - loadOp("BSON deserialise", browser) - .waitForElementNotVisible("#output-loader", 5000); - - // Charts - loadOp("Entropy", browser) - .waitForElementNotVisible("#output-loader", 5000); - - // 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); - - // Hashing - loadOp("Streebog", browser) - .waitForElementNotVisible("#output-loader", 5000); - - // 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); - - // 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')]/span[text()='Generate UUID']"; @@ -250,25 +150,6 @@ module.exports = { }, - "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 - .click("#copy-output") - .waitForElementVisible("#snackbar-container") - .waitForElementVisible("#snackbar-container .snackbar-content") - .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"); - }, - after: browser => { browser.end(); } diff --git a/tests/browser/01_io_mobile.js b/tests/browser/01_io_mobile.js deleted file mode 100644 index b26853d7..00000000 --- a/tests/browser/01_io_mobile.js +++ /dev/null @@ -1,679 +0,0 @@ -/** - * Tests for input and output of various types to ensure the editors work as expected - * and retain data integrity, especially when it comes to special characters. - * - * @author n1474335 [n1474335@gmail.com] - * @copyright Crown Copyright 2023 - * @license Apache-2.0 - */ - -// import { -// clear, -// utils.setInput, -// bake, -// setChrEnc, -// setEOLSeq, -// copy, -// paste, -// loadRecipe, -// expectOutput, -// uploadFile, -// uploadFolder -// } from "./browserUtils.js"; - -const utils = require("./browserUtils.js"); - -const SPECIAL_CHARS = [ - "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f", - "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f", - "\u007f", - "\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008a\u008b\u008c\u008d\u008e\u008f", - "\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009a\u009b\u009c\u009d\u009e\u009f", - "\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9\ufffa\ufffb\ufffc" -].join(""); - -const ALL_BYTES = [ - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", - "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f", - "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f", - "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", - "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f", - "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f", - "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f", - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f", - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef", - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", -].join(""); - -const PUA_CHARS = "\ue000\ue001\uf8fe\uf8ff"; - -const MULTI_LINE_STRING =`"You know," said Arthur, "it's at times like this, when I'm trapped in a Vogon airlock with a man from Betelgeuse, and about to die of asphyxiation in deep space that I really wish I'd listened to what my mother told me when I was young." -"Why, what did she tell you?" -"I don't know, I didn't listen."`; - -const SELECTABLE_STRING = `ONE -two -ONE -three -ONE -four -ONE`; - -// Descriptions for named control characters -const CONTROL_CHAR_NAMES = { - 0: "null", - 7: "bell", - 8: "backspace", - 10: "line feed", - 11: "vertical tab", - 13: "carriage return", - 27: "escape", - 8203: "zero width space", - 8204: "zero width non-joiner", - 8205: "zero width joiner", - 8206: "left-to-right mark", - 8207: "right-to-left mark", - 8232: "line separator", - 8237: "left-to-right override", - 8238: "right-to-left override", - 8294: "left-to-right isolate", - 8295: "right-to-left isolate", - 8297: "pop directional isolate", - 8233: "paragraph separator", - 65279: "zero width no-break space", - 65532: "object replacement" -}; - -module.exports = { - before: browser => { - browser - .resizeWindow(500, 800) - .url(browser.launchUrl) - .useCss() - .waitForElementNotPresent("#preloader", 10000) - .click("#auto-bake-label"); - }, - - "CodeMirror has loaded correctly": browser => { - /* Editor has initialised */ - browser - .useCss() - // Input - .waitForElementVisible("#input-text") - .waitForElementVisible("#input-text .cm-editor") - .waitForElementVisible("#input-text .cm-editor .cm-scroller") - .waitForElementVisible("#input-text .cm-editor .cm-scroller .cm-content") - .waitForElementVisible("#input-text .cm-editor .cm-scroller .cm-content .cm-line") - // Output - .waitForElementVisible("#output-text") - .waitForElementVisible("#output-text .cm-editor") - .waitForElementVisible("#output-text .cm-editor .cm-scroller") - .waitForElementVisible("#output-text .cm-editor .cm-scroller .cm-content") - .waitForElementVisible("#output-text .cm-editor .cm-scroller .cm-content .cm-line"); - - /* Status bar is showing and has correct values */ - browser // Input - .waitForElementVisible("#input-text .cm-status-bar") - .waitForElementVisible("#input-text .cm-status-bar .stats-length-value") - .expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("0"); - browser.waitForElementVisible("#input-text .cm-status-bar .stats-lines-value") - .expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - browser.waitForElementVisible("#input-text .cm-status-bar .chr-enc-value") - .expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes"); - browser.waitForElementVisible("#input-text .cm-status-bar .eol-value") - .expect.element("#input-text .cm-status-bar .eol-value").text.to.equal("LF"); - - browser // Output - .waitForElementVisible("#output-text .cm-status-bar") - .waitForElementVisible("#output-text .cm-status-bar .stats-length-value") - .expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("0"); - browser.waitForElementVisible("#output-text .cm-status-bar .stats-lines-value") - .expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - browser.waitForElementVisible("#output-text .cm-status-bar .baking-time-info") - .expect.element("#output-text .cm-status-bar .baking-time-info").text.to.contain("ms"); - browser.waitForElementVisible("#output-text .cm-status-bar .chr-enc-value") - .expect.element("#output-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes"); - browser.waitForElementVisible("#output-text .cm-status-bar .eol-value") - .expect.element("#output-text .cm-status-bar .eol-value").text.to.equal("LF"); - }, - - "Adding content": browser => { - /* Status bar updates correctly */ - utils.setInput(browser, MULTI_LINE_STRING); - - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("3"); - browser.expect.element("#input-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes"); - browser.expect.element("#input-text .cm-status-bar .eol-value").text.to.equal("LF"); - - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("0"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - browser.expect.element("#output-text .cm-status-bar .baking-time-info").text.to.contain("ms"); - browser.expect.element("#output-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes"); - browser.expect.element("#output-text .cm-status-bar .eol-value").text.to.equal("LF"); - - /* Output updates correctly */ - utils.bake(browser); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("3"); - browser.expect.element("#output-text .cm-status-bar .baking-time-info").text.to.contain("ms"); - browser.expect.element("#output-text .cm-status-bar .chr-enc-value").text.to.equal("Raw Bytes"); - browser.expect.element("#output-text .cm-status-bar .eol-value").text.to.equal("LF"); - }, - - "Special content": browser => { - /* Special characters are rendered correctly */ - utils.setInput(browser, SPECIAL_CHARS, false); - - // First line - for (let i = 0x0; i <= 0x8; i++) { - browser.expect.element(`#input-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(${i+1})`) - .to.have.property("title").equals(`Control character ${CONTROL_CHAR_NAMES[i] || "0x" + i.toString(16)}`); - browser.expect.element(`#input-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(${i+1})`) - .text.to.equal(String.fromCharCode(0x2400 + i)); - } - - // Tab \u0009 - browser.expect.element(`#input-text .cm-line:nth-of-type(1)`).to.have.property("textContent").match(/\u0009$/); - - // Line feed \u000a - browser.expect.element(`#input-text .cm-line:nth-of-type(1)`).to.have.property("textContent").match(/^.{10}$/); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - // Second line - for (let i = 0x0b; i < SPECIAL_CHARS.length; i++) { - const index = SPECIAL_CHARS.charCodeAt(i); - const name = CONTROL_CHAR_NAMES[index] || "0x" + index.toString(16); - const value = index >= 32 ? "\u2022" : String.fromCharCode(0x2400 + index); - - browser.expect.element(`#input-text .cm-line:nth-of-type(2) .cm-specialChar:nth-of-type(${i-10})`) - .to.have.property("title").equals(`Control character ${name}`); - browser.expect.element(`#input-text .cm-line:nth-of-type(2) .cm-specialChar:nth-of-type(${i-10})`) - .text.to.equal(value); - } - - /* Output renders correctly */ - utils.setChrEnc(browser, "output", "UTF-8"); - utils.bake(browser); - - // First line - for (let i = 0x0; i <= 0x8; i++) { - browser.expect.element(`#output-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(${i+1})`) - .to.have.property("title").equals(`Control character ${CONTROL_CHAR_NAMES[i] || "0x" + i.toString(16)}`); - browser.expect.element(`#output-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(${i+1})`) - .text.to.equal(String.fromCharCode(0x2400 + i)); - } - - // Tab \u0009 - browser.expect.element(`#output-text .cm-line:nth-of-type(1)`).to.have.property("textContent").match(/\u0009$/); - - // Line feed \u000a - browser.expect.element(`#output-text .cm-line:nth-of-type(1)`).to.have.property("textContent").match(/^.{10}$/); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - // Second line - for (let i = 0x0b; i < SPECIAL_CHARS.length; i++) { - const index = SPECIAL_CHARS.charCodeAt(i); - const name = CONTROL_CHAR_NAMES[index] || "0x" + index.toString(16); - const value = index >= 32 ? "\u2022" : String.fromCharCode(0x2400 + index); - - browser.expect.element(`#output-text .cm-content .cm-line:nth-of-type(2) .cm-specialChar:nth-of-type(${i-10})`) - .to.have.property("title").equals(`Control character ${name}`); - browser.expect.element(`#output-text .cm-content .cm-line:nth-of-type(2) .cm-specialChar:nth-of-type(${i-10})`) - .text.to.equal(value); - } - - /* Bytes are rendered correctly */ - utils.setInput(browser, ALL_BYTES, false); - // Expect length to be 255, since one character is creating a newline - browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{255}$/); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("256"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - - /* PUA \ue000-\uf8ff */ - utils.setInput(browser, PUA_CHARS, false); - utils.setChrEnc(browser, "output", "UTF-8"); - utils.bake(browser); - - // Confirm input and output as expected - /* In order to render whitespace characters as control character pictures in the output, even - when they are the designated line separator, CyberChef sometimes chooses to represent them - internally using the Unicode Private Use Area (https://en.wikipedia.org/wiki/Private_Use_Areas). - See `Utils.escapeWhitespace()` for an example of this. - Therefore, PUA characters should be rendered normally in the Input but as control character - pictures in the output. - */ - browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^\ue000\ue001\uf8fe\uf8ff$/); - browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^\u2400\u2401\u3cfe\u3cff$/); - - /* Can be copied */ - utils.setInput(browser, SPECIAL_CHARS, false); - utils.setChrEnc(browser, "output", "UTF-8"); - utils.bake(browser); - - // Manual copy - browser - .doubleClick("#output-text .cm-content .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(1)") - .waitForElementVisible("#output-text .cm-selectionBackground"); - utils.copy(browser); - utils.paste(browser, "#search"); // Paste into search box as this won't mess with the values - - // Ensure that the values are as expected - browser.expect.element("#search").to.have.value.that.equals("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008"); - browser.clearValue("#search"); - browser.click("#close-ops-dropdown-icon"); - browser.waitForElementNotVisible("#categories", 1000); - - // Raw copy - browser - .click("#copy-output") - .pause(100); - utils.paste(browser, "#search"); // Paste into search box as this won't mess with the values - - // Ensure that the values are as expected - browser.expect.element("#search").to.have.value.that.matches(/^\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009/); - browser.clearValue("#search"); - browser.click("#close-ops-dropdown-icon"); - browser.waitForElementNotVisible("#categories", 1000); - - }, - - "HTML output": browser => { - /* Displays correctly */ - utils.loadRecipe(browser, "Entropy", ALL_BYTES); - utils.bake(browser); - - browser - .waitForElementVisible("#output-html") - .waitForElementVisible("#output-html #chart-area"); - - /* Status bar widgets are disabled */ - browser.expect.element("#output-text .cm-status-bar .disabled .stats-length-value").to.be.visible; - browser.expect.element("#output-text .cm-status-bar .disabled .stats-lines-value").to.be.visible; - browser.expect.element("#output-text .cm-status-bar .disabled .chr-enc-value").to.be.visible; - browser.expect.element("#output-text .cm-status-bar .disabled .eol-value").to.be.visible; - - /* Displays special chars correctly */ - utils.loadRecipe(browser, "To Table", ",\u0000\u0001\u0002\u0003\u0004", [",", "\\r\\n", false, "HTML"]); - utils.bake(browser); - - for (let i = 0x0; i <= 0x4; i++) { - browser.expect.element(`#output-html .cm-specialChar:nth-of-type(${i+1})`) - .to.have.property("title").equals(`Control character ${CONTROL_CHAR_NAMES[i] || "0x" + i.toString(16)}`); - browser.expect.element(`#output-html .cm-specialChar:nth-of-type(${i+1})`) - .text.to.equal(String.fromCharCode(0x2400 + i)); - } - - /* Can be copied */ - // Raw copy - browser - .click("#copy-output") - .pause(100); - utils.paste(browser, "#search"); // Paste into search box as this won't mess with the values - - // Ensure that the values are as expected - browser.expect.element("#search").to.have.value.that.matches(/\u0000\u0001\u0002\u0003\u0004/); - browser.clearValue("#search"); - browser.click("#close-ops-dropdown-icon"); - browser.waitForElementNotVisible("#categories", 1000); - }, - - "Highlighting": browser => { - utils.setInput(browser, SELECTABLE_STRING); - utils.bake(browser); - - /* Selecting input text also selects other instances in input and output */ - browser // Input - .click("#auto-bake-label") - .doubleClick("#input-text .cm-content .cm-line:nth-of-type(1)") - .waitForElementVisible("#input-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(1) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(2) .cm-selectionMatch") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(3) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(4) .cm-selectionMatch") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(5) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(6) .cm-selectionMatch") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(7) .cm-selectionMatch"); - - browser // Output - .waitForElementVisible("#output-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(1) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(2) .cm-selectionMatch") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(3) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(4) .cm-selectionMatch") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(5) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(6) .cm-selectionMatch") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(7) .cm-selectionMatch"); - - /* Selecting output text highlights in input */ - browser // Output - .click("#output-text") - .waitForElementNotPresent("#input-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementNotPresent("#output-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementNotPresent("#input-text .cm-content .cm-line .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line .cm-selectionMatch") - .doubleClick("#output-text .cm-content .cm-line:nth-of-type(7)") - .waitForElementVisible("#output-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(1) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(2) .cm-selectionMatch") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(3) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(4) .cm-selectionMatch") - .waitForElementVisible("#output-text .cm-content .cm-line:nth-of-type(5) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(6) .cm-selectionMatch") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(7) .cm-selectionMatch"); - - browser // Input - .waitForElementVisible("#input-text .cm-selectionLayer .cm-selectionBackground") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(1) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(2) .cm-selectionMatch") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(3) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(4) .cm-selectionMatch") - .waitForElementVisible("#input-text .cm-content .cm-line:nth-of-type(5) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(6) .cm-selectionMatch") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(7) .cm-selectionMatch"); - - // Turn autobake off again - browser.click("#auto-bake-label"); - }, - - "Character encoding": browser => { - const CHINESE_CHARS = "不要恐慌。"; - /* Dropup works */ - /* Selecting changes output correctly */ - utils.setInput(browser, CHINESE_CHARS, false); - utils.setChrEnc(browser, "input", "UTF-8"); - utils.bake(browser); - utils.expectOutput(browser, "\u00E4\u00B8\u008D\u00E8\u00A6\u0081\u00E6\u0081\u0090\u00E6\u0085\u008C\u00E3\u0080\u0082"); - - /* Changing output to match input works as expected */ - utils.setChrEnc(browser, "output", "UTF-8"); - utils.bake(browser); - utils.expectOutput(browser, CHINESE_CHARS); - - /* Encodings appear in the URL */ - browser.assert.urlContains("ienc=65001"); - browser.assert.urlContains("oenc=65001"); - - /* Try various encodings */ - // These are not meant to be realistic encodings for this data - utils.setInput(browser, CHINESE_CHARS, false); - utils.setChrEnc(browser, "input", "UTF-8"); - utils.setChrEnc(browser, "output", "UTF-16LE"); - utils.bake(browser); - utils.expectOutput(browser, "\uB8E4\uE88D\u81A6\u81E6\uE690\u8C85\u80E3"); - - utils.setChrEnc(browser, "output", "Simplified Chinese GBK"); - utils.bake(browser); - utils.expectOutput(browser, "\u6D93\u5D88\uFDFF\u93AD\u612D\u53A1\u9286\u0000"); - - utils.setChrEnc(browser, "input", "UTF-7"); - utils.bake(browser); - utils.expectOutput(browser, "+Tg0-+iYE-+YFA-+YUw-"); - - utils.setChrEnc(browser, "input", "Traditional Chinese Big5"); - utils.bake(browser); - utils.expectOutput(browser, "\u3043\u74B6\uFDFF\u7A3A\uFDFF"); - - utils.setChrEnc(browser, "output", "Windows-1251 Cyrillic"); - utils.bake(browser); - utils.expectOutput(browser, "\u00A4\u0408\u00ADn\u00AE\u0408\u00B7W\u040EC"); - }, - - "Line endings": browser => { - /* Dropup works */ - /* Selecting changes view in input */ - utils.setInput(browser, MULTI_LINE_STRING); - - // Line endings: LF - - // Input - browser - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(3)") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(4)") - .waitForElementNotPresent("#input-text .cm-content .cm-specialChar"); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("3"); - - // Output - utils.bake(browser); - browser - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(3)") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(4)") - .waitForElementNotPresent("#output-text .cm-content .cm-specialChar"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("3"); - - // Input EOL: VT - utils.setEOLSeq(browser, "input", "VT"); - - // Input - browser - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(1)") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementPresent("#input-text .cm-content .cm-specialChar"); - browser.expect.element("#input-text .cm-content .cm-specialChar").text.to.equal("␊"); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - - // Output - utils.bake(browser); - browser - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(3)") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(4)") - .waitForElementNotPresent("#output-text .cm-content .cm-specialChar"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("3"); - - // Output EOL: VT - utils.setEOLSeq(browser, "output", "VT"); - - // Input - browser - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(1)") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementPresent("#input-text .cm-content .cm-specialChar"); - browser.expect.element("#input-text .cm-content .cm-specialChar").text.to.equal("␊"); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - - // Output - browser - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(1)") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementPresent("#output-text .cm-content .cm-specialChar"); - browser.expect.element("#output-text .cm-content .cm-specialChar").text.to.equal("␊"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("301"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - - /* Adding new line ending changes output correctly */ - browser.sendKeys("#input-text .cm-content", browser.Keys.RETURN); - - // Input - browser - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(3)"); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("302"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - // Output - utils.bake(browser); - browser - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(3)"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("302"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - // Input EOL: CRLF - utils.setEOLSeq(browser, "input", "CRLF"); - // Output EOL: CR - utils.setEOLSeq(browser, "output", "CR"); - browser.sendKeys("#input-text .cm-content", browser.Keys.RETURN); - - // Input - browser - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementNotPresent("#input-text .cm-content .cm-line:nth-of-type(3)") - .waitForElementPresent("#input-text .cm-content .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(3)"); - browser.expect.element("#input-text .cm-content .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(3)").text.to.equal("␋"); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("304"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - // Output - utils.bake(browser); - browser - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(2)") - .waitForElementNotPresent("#output-text .cm-content .cm-line:nth-of-type(3)") - .waitForElementPresent("#output-text .cm-content .cm-line:nth-of-type(2) .cm-specialChar"); - browser.expect.element("#output-text .cm-content .cm-line:nth-of-type(2) .cm-specialChar").text.to.equal("␊"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("304"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - /* Line endings appear in the URL */ - browser.assert.urlContains("ieol=%0D%0A"); - browser.assert.urlContains("oeol=%0D"); - }, - - "File inputs": browser => { - utils.clear(browser); - - /* Side panel displays correct info */ - utils.uploadFile(browser, "files/TowelDay.jpeg"); - - browser - .waitForElementVisible("#input-text .cm-file-details") - .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown") - .waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail") - .waitForElementVisible("#input-text .cm-file-details .file-details-name") - .waitForElementVisible("#input-text .cm-file-details .file-details-size") - .waitForElementVisible("#input-text .cm-file-details .file-details-type") - .waitForElementVisible("#input-text .cm-file-details .file-details-loaded"); - browser.expect.element("#input-text .cm-file-details .file-details-name").text.that.equals("TowelDay.jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-size").text.that.equals("61,379 bytes"); - browser.expect.element("#input-text .cm-file-details .file-details-type").text.that.equals("image/jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-loaded").text.that.equals("100%"); - - /* Side panel can be hidden */ - browser - .click("#input-text .cm-file-details .file-details-toggle-shown") - .waitForElementNotPresent("#input-text .cm-file-details .file-details-toggle-shown") - .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-hidden") - .expect.element("#input-text .cm-file-details").to.have.css("width").which.equals("1px"); - - browser - .click("#input-text .cm-file-details .file-details-toggle-hidden") - .waitForElementNotPresent("#input-text .cm-file-details .file-details-toggle-hidden") - .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown") - .expect.element("#input-text .cm-file-details").to.have.css("width").which.equals("200px"); - }, - - "Folder inputs": browser => { - utils.clear(browser); - - /* Side panel displays correct info */ - utils.uploadFolder(browser, "files"); - - // Loop through tabs - for (let i = 1; i < 3; i++) { - browser - .click(`#input-tabs li:nth-of-type(${i})`) - .waitForElementVisible(`#input-tabs li:nth-of-type(${i}).active-input-tab`); - - browser - .waitForElementVisible("#input-text .cm-file-details") - .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown") - .waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail") - .waitForElementVisible("#input-text .cm-file-details .file-details-name") - .waitForElementVisible("#input-text .cm-file-details .file-details-size") - .waitForElementVisible("#input-text .cm-file-details .file-details-type") - .waitForElementVisible("#input-text .cm-file-details .file-details-loaded"); - - browser.getText("#input-text .cm-file-details .file-details-name", function(result) { - switch (result.value) { - case "TowelDay.jpeg": - browser.expect.element("#input-text .cm-file-details .file-details-name").text.that.equals("TowelDay.jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-size").text.that.equals("61,379 bytes"); - browser.expect.element("#input-text .cm-file-details .file-details-type").text.that.equals("image/jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-loaded").text.that.equals("100%"); - break; - case "Hitchhikers_Guide.jpeg": - browser.expect.element("#input-text .cm-file-details .file-details-name").text.that.equals("Hitchhikers_Guide.jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-size").text.that.equals("36,595 bytes"); - browser.expect.element("#input-text .cm-file-details .file-details-type").text.that.equals("image/jpeg"); - browser.expect.element("#input-text .cm-file-details .file-details-loaded").text.that.equals("100%"); - break; - default: - break; - } - }); - } - }, - - "Loading from URL": browser => { - /* Complex deep link populates the input correctly (encoding, eol, input) */ - browser - .urlHash("recipe=To_Base64('A-Za-z0-9%2B/%3D')&input=VGhlIHNoaXBzIGh1bmcgaW4gdGhlIHNreSBpbiBtdWNoIHRoZSBzYW1lIHdheSB0aGF0IGJyaWNrcyBkb24ndC4M&ienc=21866&oenc=1201&ieol=%0C&oeol=%E2%80%A9") - .waitForElementVisible("#rec-list li.operation"); - - browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{65}$/); - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("66"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - - browser.expect.element("#input-text .chr-enc-value").text.that.equals("KOI8-U Ukrainian Cyrillic"); - browser.expect.element("#output-text .chr-enc-value").text.that.equals("UTF-16BE"); - - browser.expect.element("#input-text .eol-value").text.that.equals("FF"); - browser.expect.element("#output-text .eol-value").text.that.equals("PS"); - - utils.bake(browser); - - browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^.{44}$/); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("44"); - browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - }, - - "Replace input with output": browser => { - /* Input is correctly populated */ - utils.loadRecipe(browser, "XOR", "The ships hung in the sky in much the same way that bricks don't.", [{ "option": "Hex", "string": "65" }, "Standard", false]); - utils.setChrEnc(browser, "input", "UTF-32LE"); - utils.setChrEnc(browser, "output", "UTF-7"); - utils.setEOLSeq(browser, "input", "CRLF"); - utils.setEOLSeq(browser, "output", "LS"); - - browser - .sendKeys("#input-text .cm-content", browser.Keys.RETURN) - .expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - utils.bake(browser); - - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("67"); - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); - browser.expect.element("#input-text .chr-enc-value").text.that.equals("UTF-32LE"); - browser.expect.element("#input-text .eol-value").text.that.equals("CRLF"); - browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("268"); - - browser - .click("#switch") - .waitForElementVisible("#stale-indicator"); - - browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("268"); - - /* Special characters, encodings and line endings all as expected */ - browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("1"); - browser.expect.element("#input-text .chr-enc-value").text.that.equals("UTF-7"); - browser.expect.element("#input-text .eol-value").text.that.equals("LS"); - browser.expect.element("#input-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(1)").text.to.equal("␍"); - browser.expect.element("#input-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(49)").text.to.equal("␑"); - browser.waitForElementNotPresent("#input-text .cm-line:nth-of-type(1) .cm-specialChar:nth-of-type(50)"); - }, - - - after: browser => { - browser.end(); - } -};