diff --git a/src/web/HTMLOperation.mjs b/src/web/HTMLOperation.mjs
index 36b11519..820dd396 100755
--- a/src/web/HTMLOperation.mjs
+++ b/src/web/HTMLOperation.mjs
@@ -68,8 +68,8 @@ class HTMLOperation {
html += "check";
}
- // check if local storage has favourites at all
- const isFavourite = localStorage.favourites?.includes(this.name)
+ // check if local storage is available *and* has favourites at all ( otherwise we use the default favs )
+ const isFavourite = this.app.isLocalStorageAvailable() && localStorage.favourites?.includes(this.name);
if (window.innerWidth < this.app.breakpoint) {
html += `
diff --git a/tests/browser/00_nightwatch.js b/tests/browser/desktop-ui/00_nightwatch.js
similarity index 100%
rename from tests/browser/00_nightwatch.js
rename to tests/browser/desktop-ui/00_nightwatch.js
diff --git a/tests/browser/01_io.js b/tests/browser/desktop-ui/01_io.js
similarity index 100%
rename from tests/browser/01_io.js
rename to tests/browser/desktop-ui/01_io.js
diff --git a/tests/browser/02_ops.js b/tests/browser/desktop-ui/02_ops.js
similarity index 100%
rename from tests/browser/02_ops.js
rename to tests/browser/desktop-ui/02_ops.js
diff --git a/tests/browser/mobile-device/TODO.md b/tests/browser/mobile-device/TODO.md
new file mode 100644
index 00000000..0f04e744
--- /dev/null
+++ b/tests/browser/mobile-device/TODO.md
@@ -0,0 +1 @@
+actual mobile device tests go here
diff --git a/tests/browser/mobile/00_nightwatch.js b/tests/browser/mobile-ui/00_nightwatch.js
similarity index 94%
rename from tests/browser/mobile/00_nightwatch.js
rename to tests/browser/mobile-ui/00_nightwatch.js
index bfec3af8..3ba2a865 100644
--- a/tests/browser/mobile/00_nightwatch.js
+++ b/tests/browser/mobile-ui/00_nightwatch.js
@@ -1,9 +1,17 @@
+/**
+ * Tests to ensure that the app loads correctly in a reasonable time and that operations can be run.
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
const utils = require("./browserUtils.js");
module.exports = {
before: browser => {
browser
- .resizeWindow(412, 915) // Galaxy S20 Ultra-ish size
+ .resizeWindow(1280, 800)
.url(browser.launchUrl);
},
@@ -11,33 +19,25 @@ module.exports = {
// Check that the loading screen appears and then disappears within a reasonable time
browser
.waitForElementVisible("#preloader", 300)
- .waitForElementNotPresent("#preloader", 30000);
+ .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("#search").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 dropdown loaded": browser => {
- // browser
- // .useCss()
- // .click("#search")
- // .expect.element("#operations-dropdown").to.be.visible
- // .expect.element("#categories").to.be.visible
- // .expect.element(".op-list").to.be.present;
- // },
-
"Operations loaded": browser => {
+ browser.useXpath();
// Check that an operation in every category has been populated
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;
diff --git a/tests/browser/mobile/01_io.js b/tests/browser/mobile-ui/01_io.js
similarity index 99%
rename from tests/browser/mobile/01_io.js
rename to tests/browser/mobile-ui/01_io.js
index a3715e16..67d1fdff 100644
--- a/tests/browser/mobile/01_io.js
+++ b/tests/browser/mobile-ui/01_io.js
@@ -1,3 +1,12 @@
+/**
+ * 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,
diff --git a/tests/browser/mobile/02_ops.js b/tests/browser/mobile-ui/02_ops.js
similarity index 98%
rename from tests/browser/mobile/02_ops.js
rename to tests/browser/mobile-ui/02_ops.js
index f7e447c2..e2c8a219 100644
--- a/tests/browser/mobile/02_ops.js
+++ b/tests/browser/mobile-ui/02_ops.js
@@ -1,3 +1,18 @@
+/**
+ * Tests for operations.
+ * The primary purpose for these test is to ensure that the operations
+ * output something vaguely expected (i.e. they aren't completely broken
+ * after a dependency update or changes to the UI), rather than to confirm
+ * that this output is actually accurate. Accuracy of output and testing
+ * of edge cases should be carried out in the operations test suite found
+ * in /tests/operations as this is much faster and easier to configure
+ * than the UI tests found here.
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @copyright Crown Copyright 2021
+ * @license Apache-2.0
+ */
+
const utils = require("./browserUtils.js");
module.exports = {
diff --git a/tests/browser/mobile/browserUtils.js b/tests/browser/mobile/browserUtils.js
deleted file mode 100644
index b73dca91..00000000
--- a/tests/browser/mobile/browserUtils.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/**
- * Utility functions for browser tests.
- *
- * @author n1474335 [n1474335@gmail.com]
- * @copyright Crown Copyright 2023
- * @license Apache-2.0
- */
-
-/** @function
- * Clears the recipe and input
- *
- * @param {Browser} browser - Nightwatch client
- */
-function clear(browser) {
- browser
- .useCss()
- .click("#clr-recipe")
- .click("#clr-io")
- .waitForElementNotPresent("#rec-list li.operation")
- .expect.element("#input-text .cm-content").text.that.equals("");
-}
-
-/** @function
- * Sets the input to the desired string
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} input - The text to populate the input with
- * @param {boolean} [type=true] - Whether to type the characters in by using sendKeys,
- * or to set the value of the editor directly (useful for special characters)
- */
-function setInput(browser, input, type=true) {
- clear(browser);
- if (type) {
- browser
- .useCss()
- .sendKeys("#input-text .cm-content", input)
- .pause(100);
- } else {
- browser.execute(text => {
- window.app.setInput(text);
- }, [input]);
- }
-}
-
-/** @function
- * Triggers a bake
- *
- * @param {Browser} browser - Nightwatch client
- */
-function bake(browser) {
- browser
- .click("#bake")
- .waitForElementNotVisible("#stale-indicator", 5000)
- .waitForElementNotVisible("#output-loader", 5000);
-}
-
-/** @function
- * Sets the character encoding in the input or output
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} io - Either "input" or "output"
- * @param {string} enc - The encoding to be set
- */
-function setChrEnc(browser, io, enc) {
- io = `#${io}-text`;
- browser
- .useCss()
- .click(io + " .chr-enc-value")
- .waitForElementVisible(io + " .chr-enc-select .cm-status-bar-select-scroll")
- .click("link text", enc)
- .waitForElementNotVisible(io + " .chr-enc-select .cm-status-bar-select-scroll")
- .expect.element(io + " .chr-enc-value").text.that.equals(enc);
-}
-
-/** @function
- * Sets the end of line sequence in the input or output
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} io - Either "input" or "output"
- * @param {string} eol - The sequence to set
- */
-function setEOLSeq(browser, io, eol) {
- io = `#${io}-text`;
- browser
- .useCss()
- .click(io + " .eol-value")
- .waitForElementVisible(io + " .eol-select .cm-status-bar-select-content")
- .click(`${io} .cm-status-bar-select-content a[data-val=${eol}]`)
- .waitForElementNotVisible(io + " .eol-select .cm-status-bar-select-content")
- .expect.element(io + " .eol-value").text.that.equals(eol);
-}
-
-/** @function
- * Copies whatever is currently selected
- *
- * @param {Browser} browser - Nightwatch client
- */
-function copy(browser) {
- browser.perform(function() {
- const actions = this.actions({async: true});
-
- // Ctrl + Ins used as this works on Windows, Linux and Mac
- return actions
- .keyDown(browser.Keys.CONTROL)
- .keyDown(browser.Keys.INSERT)
- .keyUp(browser.Keys.INSERT)
- .keyUp(browser.Keys.CONTROL);
- });
-}
-
-/** @function
- * Pastes into the target element
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} el - Target element selector
- */
-function paste(browser, el) {
- browser
- .click(el)
- .perform(function() {
- const actions = this.actions({async: true});
-
- // Shift + Ins used as this works on Windows, Linux and Mac
- return actions
- .keyDown(browser.Keys.SHIFT)
- .keyDown(browser.Keys.INSERT)
- .keyUp(browser.Keys.INSERT)
- .keyUp(browser.Keys.SHIFT);
- })
- .pause(100);
-}
-
-/** @function
- * Loads a recipe and input
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string|Array} opName - name of operation to be loaded, array for multiple ops
- * @param {string} input - input text for test
- * @param {Array|Array>} args - arguments, nested if multiple ops
- */
-function loadRecipe(browser, opName, input, args) {
- let recipeConfig;
-
- if (typeof(opName) === "string") {
- recipeConfig = JSON.stringify([{
- "op": opName,
- "args": args
- }]);
- } else if (opName instanceof Array) {
- recipeConfig = JSON.stringify(
- opName.map((op, i) => {
- return {
- op: op,
- args: args.length ? args[i] : []
- };
- })
- );
- } else {
- throw new Error("Invalid operation type. Must be string or array of strings. Received: " + typeof(opName));
- }
-
- clear(browser);
- setInput(browser, input, false);
- browser
- .urlHash("recipe=" + recipeConfig)
- .waitForElementPresent("#rec-list li.operation");
-}
-
-/** @function
- * Tests whether the output matches a given value
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string|RegExp} expected - The expected output value
- */
-function expectOutput(browser, expected) {
- browser.execute(expected => {
- const output = window.app.manager.output.outputEditorView.state.doc.toString();
- if (expected instanceof RegExp) {
- return expected.test(output);
- } else {
- return expected === output;
- }
- }, [expected]);
-}
-
-/** @function
- * Uploads a file using the #open-file input
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} filename - A path to a file in the samples directory
- */
-function uploadFile(browser, filename) {
- const filepath = require("path").resolve(__dirname + "/../samples/" + filename);
-
- // The file input cannot be interacted with by nightwatch while it is hidden,
- // so we temporarily expose it for the purposes of this test.
- browser.execute(() => {
- document.getElementById("open-file").style.display = "block";
- });
- browser
- .pause(100)
- .setValue("#open-file", filepath)
- .pause(100);
- browser.execute(() => {
- document.getElementById("open-file").style.display = "none";
- });
- browser.waitForElementVisible("#input-text .cm-file-details");
-}
-
-/** @function
- * Uploads a folder using the #open-folder input
- *
- * @param {Browser} browser - Nightwatch client
- * @param {string} foldername - A path to a folder in the samples directory
- */
-function uploadFolder(browser, foldername) {
- const folderpath = require("path").resolve(__dirname + "/../samples/" + foldername);
-
- // The folder input cannot be interacted with by nightwatch while it is hidden,
- // so we temporarily expose it for the purposes of this test.
- browser.execute(() => {
- document.getElementById("open-folder").style.display = "block";
- });
- browser
- .pause(100)
- .setValue("#open-folder", folderpath)
- .pause(500);
- browser.execute(() => {
- document.getElementById("open-folder").style.display = "none";
- });
- browser.waitForElementVisible("#input-text .cm-file-details");
-}
-
-
-module.exports = {
- clear: clear,
- setInput: setInput,
- bake: bake,
- setChrEnc: setChrEnc,
- setEOLSeq: setEOLSeq,
- copy: copy,
- paste: paste,
- loadRecipe: loadRecipe,
- expectOutput: expectOutput,
- uploadFile: uploadFile,
- uploadFolder: uploadFolder
-};