From 94a6d1acbdf9caee3faa99d113e7d612db842b45 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Wed, 13 Nov 2024 07:17:44 +0200 Subject: [PATCH 01/12] dbs review --- mod/utils/dbs.js | 144 +- public/js/tests/_mapp.test.js | 2546 +++++++++++++++++++++++++++++ public/js/tests/_mapp.test.js.map | 8 + 3 files changed, 2670 insertions(+), 28 deletions(-) create mode 100644 public/js/tests/_mapp.test.js create mode 100644 public/js/tests/_mapp.test.js.map diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 9150160af3..f429a55afb 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -1,47 +1,135 @@ /** -@module /utils/dbs + * @module /utils/dbs + * @description Database connection and query management module that creates connection pools for multiple databases + * based on environment variables prefixed with 'DBS_'. */ const { Pool } = require('pg'); - const logger = require('./logger'); +/** @type {Object.} Object containing database query functions */ const dbs = {}; -Object.keys(process.env) +/** @constant {number} RETRY_LIMIT Maximum number of retry attempts for failed queries */ +const RETRY_LIMIT = 3; - // Filter keys which start with DBS - .filter(key => key.startsWith('DBS_')) +/** @constant {number} INITIAL_RETRY_DELAY Base delay in milliseconds between retry attempts */ +const INITIAL_RETRY_DELAY = 1000; +/** + * Helper function to pause execution + * @param {number} ms - Time to sleep in milliseconds + * @returns {Promise} + * @private + */ +const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +// Initialize database pools and create query functions +Object.keys(process.env) + .filter(key => key.startsWith('DBS_')) .forEach(key => { - + /** + * @type {Pool} + * @private + */ const pool = new Pool({ connectionString: process.env[key], - keepAlive: true + keepAlive: true, + connectionTimeoutMillis: 5000, // 5 seconds + idleTimeoutMillis: 30000, // 30 seconds + max: 20 // Maximum number of clients in the pool }); - dbs[key.split('_')[1]] = async (query, variables, timeout) => { - - try { - - const client = await pool.connect() + // Handle pool errors + pool.on('error', (err, client) => { + logger({ + err, + message: 'Unexpected error on idle client', + pool: key.split('_')[1] + }); + }); - if (timeout || process.env.STATEMENT_TIMEOUT) { - await client.query(`SET statement_timeout = ${parseInt(timeout) || parseInt(process.env.STATEMENT_TIMEOUT)}`) + /** + * Executes a database query with retry logic + * @async + * @param {string} query - SQL query to execute + * @param {Array} [variables] - Parameters for the SQL query + * @param {number} [timeout] - Statement timeout in milliseconds + * @returns {Promise} Query results or error object + * @throws {Error} Database connection or query errors + */ + dbs[key.split('_')[1]] = async (query, variables, timeout) => { + let retryCount = 0; + let lastError; + + while (retryCount < RETRY_LIMIT) { + /** @type {import('pg').PoolClient} */ + let client; + + try { + client = await pool.connect(); + + // Set statement timeout if specified + if (timeout || process.env.STATEMENT_TIMEOUT) { + await client.query(`SET statement_timeout = ${parseInt(timeout) || parseInt(process.env.STATEMENT_TIMEOUT) + }`); + } + + const { rows } = await client.query(query, variables); + return rows; + + } catch (err) { + lastError = err; + + // Log the error with retry information + logger({ + err, + query, + variables, + retry: retryCount + 1, + pool: key.split('_')[1] + }); + + /** + * Determine if error is retryable + * @type {boolean} + * @private + */ + const isRetryable = ( + err.code === 'ECONNRESET' || // Connection reset by peer + err.code === 'ECONNREFUSED' || // Connection refused + err.code === '57P01' || // Admin shutdown + err.code === '57P02' || // Crash shutdown + err.code === '57P03' || // Cannot connect now + err.message.includes('Connection terminated unexpectedly') + ); + + if (!isRetryable) { + return err; + } + + retryCount++; + + if (retryCount < RETRY_LIMIT) { + // Exponential backoff + const delay = INITIAL_RETRY_DELAY * Math.pow(2, retryCount - 1); + await sleep(delay); + } + + } finally { + if (client) { + client.release(true); // Force release in case of errors + } } - - const { rows } = await client.query(query, variables) - - client.release() - - return rows - - } catch (err) { - - logger({ err, query, variables }) - return err; } - } - }) -module.exports = dbs \ No newline at end of file + // If we've exhausted all retries, return the last error + return lastError; + }; + }); + +/** + * Database interface object containing query functions for each configured database + * @type {Object.>} + */ +module.exports = dbs; \ No newline at end of file diff --git a/public/js/tests/_mapp.test.js b/public/js/tests/_mapp.test.js new file mode 100644 index 0000000000..114ae9ba82 --- /dev/null +++ b/public/js/tests/_mapp.test.js @@ -0,0 +1,2546 @@ +(() => { + // public/tests/_base.test.mjs + async function base() { + let mapview = {}; + await codi.describe("Mapview test", async () => { + console.log(`MAPP v${mapp.version}`); + const OL = document.getElementById("OL"); + const locationsTab = document.getElementById("locations"); + const layersTab = document.getElementById("layers"); + const tabs = document.querySelectorAll("#ctrl-tabs > div"); + const tabPanels = document.querySelectorAll("#ctrl-panel > div"); + const tabview = document.getElementById("Tabview"); + await codi.it("should merge dictionaries correctly", () => { + const initialLength = Object.keys(mapp.dictionaries.en).length; + mapp.utils.merge(mapp.dictionaries, { + en: { + toolbar_zoom_in: "Zoom in", + toolbar_zoom_out: "Zoom out", + toolbar_zoom_to_area: "Zoom to area", + toolbar_current_location: "Current location", + toolbar_fullscreen: "Fullscreen mapview", + toolbar_admin: "Open account admin view", + toolbar_login: "Log in", + toolbar_logout: "Log out", + layers: "Layers", + locations: "Locations", + no_locales: "Your account has been verified and approved, but you do not have access to any locales. This is likely as an administrator has not given you the required roles. Please contact an administrator to resolve this.", + no_layers: "No accessible layers in locale." + }, + de: { + toolbar_zoom_in: "Zoom rein", + toolbar_zoom_out: "Zoom raus", + toolbar_zoom_to_area: "Zoom Rechteck", + toolbar_current_location: "Standort", + toolbar_fullscreen: "Vollbild", + toolbar_admin: "Benutzerkontenverwaltung", + toolbar_login: "Einloggen", + toolbar_logout: "Ausloggen", + layers: "Ebenen", + locations: "Orte" + }, + zh: { + toolbar_zoom_in: "\u653E\u5927", + toolbar_zoom_out: "\u7F29\u5C0F", + toolbar_zoom_to_area: "\u7F29\u653E\u81F3\u533A\u57DF", + toolbar_current_location: "\u5F53\u524D\u4F4D\u7F6E", + toolbar_fullscreen: "\u5168\u5C4F\u5730\u56FE\u89C6\u56FE", + toolbar_admin: "\u6253\u5F00\u5E10\u6237\u7BA1\u7406\u89C6\u56FE", + toolbar_login: "\u767B\u5F55", + toolbar_logout: "\u767B\u51FA", + layers: "\u56FE\u5C42", + locations: "\u5730\u70B9" + }, + zh_tw: { + toolbar_zoom_in: "\u653E\u5927", + toolbar_zoom_out: "\u7E2E\u5C0F", + toolbar_zoom_to_area: "\u7E2E\u653E\u81F3\u5340\u57DF", + toolbar_current_location: "\u7576\u524D\u4F4D\u7F6E", + toolbar_fullscreen: "\u5168\u5C4F\u5730\u5716\u8996\u5716", + toolbar_admin: "\u6253\u958B\u5E33\u6236\u7BA1\u7406\u8996\u5716", + toolbar_login: "\u767B\u9304", + toolbar_logout: "\u767B\u51FA", + layers: "\u5716\u5C64", + locations: "\u5730\u9EDE" + }, + pl: { + toolbar_zoom_in: "Przybli\u017C", + toolbar_zoom_out: "Oddal", + toolbar_zoom_to_area: "Przybli\u017C do obszaru", + toolbar_current_location: "Obezha lokalizcja", + toolbar_fullscreen: "Mapa na ca\u0142ym ekranie", + toolbar_admin: "Otw\xF3rz widok administratora", + toolbar_login: "Zaloguj si\u0119", + toolbar_logout: "Wyloguj si\u0119", + layers: "Warstwy", + locations: "Lokalizacje" + }, + fr: { + toolbar_zoom_in: "Zoom +", + toolbar_zoom_out: "Zoom -", + toolbar_zoom_to_area: "Zoomer sur la zone", + toolbar_current_location: "Emplacement actuel", + toolbar_fullscreen: "Carte en plein \xE9cran", + toolbar_admin: "Ouvrir le menu administrateur", + toolbar_login: "Se connecter", + toolbar_logout: "D\xE9connexion", + layers: "Couches cartographiques", + locations: "Sites" + }, + ja: { + toolbar_zoom_in: "\u30BA\u30FC\u30E0\u30A4\u30F3", + toolbar_zoom_out: "\u30BA\u30FC\u30E0\u30A2\u30A6\u30C8", + toolbar_zoom_to_area: "\u30A8\u30EA\u30A2\u3092\u30BA\u30FC\u30E0\u306B", + toolbar_current_location: "\u73FE\u5730", + toolbar_fullscreen: "\u30D5\u30EB\u30B9\u30AF\u30EA\u30FC\u30F3 \u30DE\u30C3\u30D7\u30D3\u30E5\u30FC", + toolbar_admin: "\u30A2\u30AB\u30A6\u30F3\u30C8\u30A2\u30C9\u30DF\u30F3\u30D3\u30E5\u30FC\u3092\u958B\u304F", + toolbar_login: "\u30ED\u30B0\u30A4\u30F3", + toolbar_logout: "\u30ED\u30B0\u30A2\u30A6\u30C8", + layers: "\u30EC\u30A4\u30E4\u30FC", + locations: "\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3" + }, + esp: { + toolbar_zoom_in: "Zoom +", + toolbar_zoom_out: "Zoom -", + toolbar_zoom_to_area: "Zoom al \xE1rea", + toolbar_current_location: "Ubicaci\xF3n actual", + toolbar_fullscreen: "Vista de mapa en pantalla completa", + toolbar_admin: "Abrir vista de administrador de cuenta", + toolbar_login: "Iniciar sesi\xF3n", + toolbar_logout: "Desconexi\xF3n", + layers: "Capas", + locations: "Ubicaciones" + }, + tr: { + toolbar_zoom_in: "Yaklas", + toolbar_zoom_out: "Uzaklas", + toolbar_zoom_to_area: "Bolgeye yaklas", + toolbar_current_location: "Mevcut konum", + toolbar_fullscreen: "Tam ekran harita", + toolbar_admin: "Hesap yoneticisini ac", + toolbar_login: "Oturum ac", + toolbar_logout: "Oturumu kapat", + layers: "Katmanlar", + locations: "Konumlar" + }, + it: { + toolbar_zoom_in: "Ingrandisci", + toolbar_zoom_out: "Rimpicciolisci", + toolbar_zoom_to_area: "Zoom nell'area", + toolbar_current_location: "Posizione attuale", + toolbar_fullscreen: "Mappa a schermo intero", + toolbar_admin: "Apri il men\xF9 amministratore", + toolbar_login: "Log in", + toolbar_logout: "Log out", + layers: "Layers", + locations: "Localit\xE0" + }, + th: { + toolbar_zoom_in: "\u0E02\u0E22\u0E32\u0E22\u0E40\u0E02\u0E49\u0E32", + toolbar_zoom_out: "\u0E0B\u0E39\u0E21\u0E2D\u0E2D\u0E01", + toolbar_zoom_to_area: "\u0E0B\u0E39\u0E21\u0E44\u0E1B\u0E17\u0E35\u0E48\u0E1E\u0E37\u0E49\u0E19\u0E17\u0E35\u0E48", + toolbar_current_location: "\u0E2A\u0E16\u0E32\u0E19\u0E17\u0E35\u0E48\u0E1B\u0E31\u0E08\u0E08\u0E38\u0E1A\u0E31\u0E19", + toolbar_fullscreen: "\u0E21\u0E38\u0E21\u0E21\u0E2D\u0E07\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48\u0E41\u0E1A\u0E1A\u0E40\u0E15\u0E47\u0E21\u0E2B\u0E19\u0E49\u0E32\u0E08\u0E2D", + toolbar_admin: "\u0E40\u0E1B\u0E34\u0E14\u0E21\u0E38\u0E21\u0E21\u0E2D\u0E07\u0E1C\u0E39\u0E49\u0E14\u0E39\u0E41\u0E25\u0E23\u0E30\u0E1A\u0E1A", + toolbar_login: "\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A", + toolbar_logout: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A", + layers: "\u0E0A\u0E31\u0E49\u0E19", + locations: "\u0E2A\u0E16\u0E32\u0E19\u0E17\u0E35\u0E48" + } + }); + const updatedLength = Object.keys(mapp.dictionaries.en).length; + codi.assertTrue(updatedLength > initialLength, "English dictionary should have new entries"); + codi.assertEqual(mapp.dictionaries.en.toolbar_zoom_in, "Zoom in", "English dictionary should have the correct value for toolbar_zoom_in"); + codi.assertEqual(mapp.dictionaries.de.toolbar_zoom_in, "Zoom rein", "German dictionary should have the correct value for toolbar_zoom_in"); + }); + await codi.it("should refresh cookie and get user with updated credentials", async () => { + const currentUser = mapp.user; + mapp.user = await mapp.utils.xhr(`${mapp.host}/api/user/cookie`); + if (mapp.user !== null) { + codi.assertNotEqual(mapp.user, currentUser, "User object should be updated after refreshing cookie"); + codi.assertTrue(mapp.user.hasOwnProperty("email"), 'User object should have the "email" property'); + codi.assertTrue(mapp.user.hasOwnProperty("language"), 'User object should have the "language" property'); + codi.assertTrue(mapp.user.hasOwnProperty("roles"), 'User object should have the "roles" property'); + } + }); + await codi.it("should set the language correctly", () => { + const currentLanguage = mapp.language; + mapp.language = mapp.hooks.current.language || mapp.user?.language || mapp.language; + if (mapp.hooks.current.language) { + codi.assertEqual(mapp.language, mapp.hooks.current.language, "Language should be set to the value from mapp.hooks.current.language"); + } else if (mapp.user?.language) { + codi.assertEqual(mapp.language, mapp.user.language, "Language should be set to the value from mapp.user.language"); + } else { + codi.assertEqual(mapp.language, currentLanguage, "Language should remain unchanged if no overrides are present"); + } + }); + await codi.it("should restore scroll if supported", () => { + if ("scrollRestoration" in history) { + history.scrollRestoration = "auto"; + codi.assertEqual(history.scrollRestoration, "auto", 'Scroll restoration should be set to "auto"'); + } else { + codi.assertFalse("scrollRestoration" in history, "Scroll restoration is not supported"); + } + }); + document.body.addEventListener("scroll", () => { + OL.style["marginTop"] = `-${parseInt(window.pageYOffset / 2)}px`; + if (document.body.scrollTop > window.innerHeight) { + document.body.scrollTop = window.innerHeight; + } + }); + mapp.ui.utils.resizeHandler({ + target: document.getElementById("ctrls-divider"), + resizeEvent: (e) => { + let pageX = e.touches && e.touches[0].pageX || e.pageX; + if (pageX < 350) + return; + if (pageX > window.innerWidth / 2) + pageX = window.innerWidth / 2; + document.body.style.gridTemplateColumns = `${pageX}px 10px auto`; + } + }); + mapp.ui.utils.resizeHandler({ + target: document.getElementById("tabview-divider"), + resizeEvent: (e) => { + const pageY = e.touches && e.touches[0].pageY || e.pageY; + if (pageY < 0) + return; + let height = window.innerHeight - pageY; + if (height < 65) + height = 50; + if (height > window.innerHeight - 10) + height = window.innerHeight; + document.body.style.gridTemplateRows = `auto 10px ${height}px`; + OL.style.marginTop = `-${height / 2}px`; + } + }); + tabs.forEach((tab) => { + tab.title = mapp.dictionary[tab.dataset.id]; + tab.onclick = (e) => { + tabs.forEach((el) => el.classList.remove("active")); + e.target.classList.add("active"); + tabPanels.forEach((el) => el.classList.remove("active")); + document.getElementById(e.target.dataset.id).classList.add("active"); + if (e.target.dataset.id === "locations") { + const gazetteerInput = document.getElementById("gazetteerInput"); + gazetteerInput && window.innerWidth > 768 && gazetteerInput.focus(); + } + }; + }); + await codi.it("should set help text from dictionary", () => { + tabs.forEach((tab) => { + tab.title = mapp.dictionary[tab.dataset.id]; + codi.assertEqual(tab.title, mapp.dictionary[tab.dataset.id], "Title should be set from the dictionary"); + }); + }); + await codi.it("should handle tab click events", () => { + tabs.forEach((tab) => { + tab.click(); + codi.assertTrue(tab.classList.contains("active"), "Clicked tab should have the active class"); + tabs.forEach((otherTab) => { + if (otherTab !== tab) { + codi.assertFalse(otherTab.classList.contains("active"), "Other tabs should not have the active class"); + } + }); + const panel = document.getElementById(tab.dataset.id); + codi.assertTrue(panel.classList.contains("active"), "Corresponding panel should have the active class"); + tabPanels.forEach((otherPanel) => { + if (otherPanel !== panel) { + codi.assertFalse(otherPanel.classList.contains("active"), "Other panels should not have the active class"); + } + }); + }); + const layersTab2 = Array.from(tabs).find((tab) => tab.dataset.id === "layers"); + layersTab2.click(); + }); + const testTabView = mapp.ui.Tabview({ + node: tabview, + id: "tabview", + showTab: () => { + if (tabview.classList.contains("desktop-display-none")) { + tabview.classList.remove("desktop-display-none"); + document.body.style.gridTemplateRows = "auto 10px 50px"; + } + }, + removeLastTab: () => { + tabview.classList.add("desktop-display-none"); + document.body.style.gridTemplateRows = "auto 0 0"; + mapview.Map.getTargetElement().style.marginTop = 0; + } + }); + const btnColumn = document.getElementById("mapButton"); + const locales = await mapp.utils.xhr(`${mapp.host}/api/workspace/locales`); + const locale = await mapp.utils.xhr( + `${mapp.host}/api/workspace/locale?locale=${mapp.hooks.current.locale || locales[0]?.key}&layers=true` + ); + if (locale instanceof Error) { + mapp.ui.elements.dialog({ + css_style: "padding: 1em; border-color: #000", + content: mapp.dictionary.no_locales, + top: "50%", + left: "10%" + }); + } + if (locales.length > 1) { + const localesDropdown = mapp.ui.elements.dropdown({ + data_id: "locales-dropdown", + span: locale.name || locale.key, + entries: locales.map((locale2) => ({ + title: locale2.name || locale2.key, + key: locale2.key + })), + callback: (e, entry) => { + window.location.assign(`${mapp.host}?template=test_view&integrity=true&locale=${entry.key}`); + } + }); + layersTab.appendChild(mapp.utils.html.node`${localesDropdown}`); + } + await codi.it("should retrieve accessible locales from Workspace API", async () => { + codi.assertTrue(Array.isArray(locales), "Locales should be an array"); + codi.assertNotEqual(locales.length, 0, "Locales array should not be empty"); + }); + await codi.it("should retrieve locale with list of layers from Workspace API", async () => { + codi.assertFalse(locale instanceof Error, "Locale should not be an instance of Error"); + codi.assertTrue(locale.hasOwnProperty("name"), 'Locale should have a "name" property'); + codi.assertTrue(locale.hasOwnProperty("key"), 'Locale should have a "key" property'); + codi.assertTrue(locale.hasOwnProperty("layers"), 'Locale should have a "layers" property'); + }); + if (locale instanceof Error) { + await codi.it("should display an error dialog if locale is an instance of Error", async () => { + const errorDialog = document.querySelector(".dialog-modal"); + codi.assertNotEqual(errorDialog, null, "Error dialog should be appended to the document body"); + codi.assertEqual(errorDialog.textContent.trim(), mapp.dictionary.no_locales, "Error dialog should display the correct message"); + }); + } + if (locales.length > 1) { + await codi.it("should add locale dropdown to layers panel if multiple locales are accessible", async () => { + const dropdown = layersTab.querySelector('[data-id="locales-dropdown"]'); + codi.assertNotEqual(dropdown, null, "Locale dropdown should be appended to the layers tab"); + }); + } + if (!window.ol) + await mapp.utils.olScript(); + locale.syncPlugins ??= ["zoomBtn", "admin", "login"]; + mapview = await mapp.Mapview({ + host: mapp.host, + target: OL, + locale, + hooks: false, + scrollWheelZoom: true, + attribution: { + target: document.getElementById("Map"), + logo: mapp.utils.html.node` +
\n `,\n links: {\n [`XYZ v${mapp.version}`]: 'https://github.com/GEOLYTIX/xyz',\n ['SHA']: `https://github.com/GEOLYTIX/xyz/commit/${mapp.hash}`,\n Openlayers: 'https://openlayers.org',\n }\n },\n syncPlugins: locale.syncPlugins,\n svgTemplates: locale.svg_templates\n });\n\n\n if (!locale.layers?.length) {\n\n mapp.ui.elements.dialog({\n css_style: 'padding: 1em; border-color: #000;',\n content: mapp.dictionary.no_layers,\n target: document.getElementById('Map'),\n top: '50%',\n left: '50%'\n });\n\n }\n\n // Add layers to mapview.\n await mapview.addLayer(locale.layers);\n\n if (mapview.locale.gazetteer) {\n\n mapp.ui.Gazetteer(Object.assign(mapview.locale.gazetteer, {\n mapview,\n target: locationsTab.appendChild(mapp.utils.html.node`
`),\n }));\n\n } else {\n\n document.querySelector('[data-id=locations]').style.display = 'none'\n }\n\n // Create layers listview.\n mapp.ui.layers.listview({\n target: layersTab,\n mapview: mapview,\n });\n\n // Create locations listview.\n mapp.ui.locations.listview({\n target: locationsTab,\n mapview: mapview,\n });\n\n // Begin highlight interaction.\n mapview.interactions.highlight();\n\n // Select locations from hooks.\n mapp.hooks.current.locations.forEach((_hook) => {\n\n // Split location hook into layer key and id.\n const hook = _hook.split('!');\n\n // Get the location.\n // Will be added to listview in location panel.\n mapp.location.get({\n layer: mapview.layers[decodeURIComponent(hook[0])],\n id: hook[1],\n });\n });\n\n //Testcase: Create mapview\n await codi.it('should create a mapview', async () => {\n // Assert that mapview is created\n codi.assertNotEqual(mapview, undefined, 'Mapview should be created');\n\n // Assert that mapview has the expected properties\n codi.assertTrue(mapview.hasOwnProperty('host'), 'Mapview should have a \"host\" property');\n codi.assertTrue(mapview.hasOwnProperty('target'), 'Mapview should have a \"target\" property');\n codi.assertTrue(mapview.hasOwnProperty('locale'), 'Mapview should have a \"locale\" property');\n codi.assertTrue(mapview.hasOwnProperty('hooks'), 'Mapview should have a \"hooks\" property');\n codi.assertTrue(mapview.hasOwnProperty('scrollWheelZoom'), 'Mapview should have a \"scrollWheelZoom\" property');\n codi.assertTrue(mapview.hasOwnProperty('attribution'), 'Mapview should have an \"attribution\" property');\n });\n\n //Testcase: Add layers to mapview\n await codi.it('should add layers to mapview', async () => {\n // Assert that layers are added to mapview\n codi.assertTrue(Object.keys(mapview.layers).length > 0, 'Mapview should have layers');\n });\n\n //Testcase: Create a gazetteer if in locale\n await codi.it('should create a gazetteer if available in the locale', async () => {\n if (mapview.locale.gazetteer) {\n const gazetteer = locationsTab.querySelector('div');\n codi.assertNotEqual(gazetteer, null, 'Gazetteer should be created');\n } else {\n // Assert that the locations tab is hidden\n const locationsTabElement = document.querySelector('[data-id=locations]');\n codi.assertEqual(locationsTabElement.style.display, 'none', 'Locations tab should be hidden');\n }\n });\n\n //Testcase: Should create a layers listview\n await codi.it('should create a layers listview', async () => {\n // Assert that the layers listview is created\n const listview = layersTab.querySelector('div');\n codi.assertNotEqual(listview, null, 'Layers listview should be created');\n });\n\n //Testcase: Check for locations list view if gazetteer is present or if there is a selection\n if (mapview.locale.gazetteer) {\n await codi.it('should create a locations listview', async () => {\n // Assert that the locations listview is created\n const listview = locationsTab.querySelector('div');\n codi.assertNotEqual(listview, null, 'Locations listview should be created');\n });\n }\n\n //Testcase: Ensure mapview has highlight interaction.\n await codi.it('should begin highlight interaction', async () => {\n // Assert that highlight interaction is added to mapview\n codi.assertTrue(mapview.interactions.hasOwnProperty('highlight'), 'Mapview should have a \"highlight\" interaction');\n });\n\n // Configure idle mask if set in locale.\n mapp.user &&\n mapview.locale.idle &&\n mapp.ui.utils.idleLogout({\n host: mapp.host,\n idle: mapview.locale.idle,\n });\n\n // Append spacer for tableview\n btnColumn.appendChild(mapp.utils.html.node`\n
`);\n\n //Tests that have to run after everything else.\n\n //Testcase: Should show the tabview.\n await codi.it('should show the tabview when showTab is called', () => {\n // Add the 'desktop-display-none' class to the tabview\n tabview.classList.add('desktop-display-none');\n\n // Call the showTab function\n testTabView.showTab();\n\n // Assert that the 'desktop-display-none' class is removed from the tabview\n codi.assertFalse(tabview.classList.contains('desktop-display-none'), 'Tabview should not have the \"desktop-display-none\" class after showTab is called');\n\n // Assert that the grid template rows of the document body are set correctly\n codi.assertEqual(document.body.style.gridTemplateRows, 'auto 10px 50px', 'Grid template rows should be set to \"auto 10px 50px\" after showTab is called');\n });\n\n //Testcase: Should hide the tabview\n await codi.it('should hide the tabview when removeLastTab is called', () => {\n // Remove the 'desktop-display-none' class from the tabview\n tabview.classList.remove('desktop-display-none');\n\n // Call the removeLastTab function\n testTabView.removeLastTab();\n\n // Assert that the 'desktop-display-none' class is added to the tabview\n codi.assertTrue(tabview.classList.contains('desktop-display-none'), 'Tabview should have the \"desktop-display-none\" class after removeLastTab is called');\n\n\n\n // Assert that the grid template rows of the document body are set correctly\n codi.assertEqual(document.body.style.gridTemplateRows, 'auto 0px 0px', 'Grid template rows should be set to \"auto 0 0\" after removeLastTab is called');\n\n // Assert that the margin top of the map target element is set to 0\n codi.assertEqual(mapview.Map.getTargetElement().style.marginTop, '0px', 'Margin top of the map target element should be set to 0 after removeLastTab is called');\n });\n\n });\n\n return mapview;\n}", "export async function coreTest() {\n //API Tests\n await _mappTest.workspaceTest();\n await _mappTest.queryTest();\n const mapview = await _mappTest.base();\n await runAllTests(_mappTest.userTest);\n //Run Map Object test\n await runAllTests(_mappTest.mappTest);\n // Run the dictionary Tests\n await runAllTests(_mappTest.dictionaryTest, mapview);\n //Plugins Tests\n await runAllTests(_mappTest.pluginsTest);\n //Layer Tests\n await runAllTests(_mappTest.layerTest, mapview);\n //Location Tests\n await runAllTests(_mappTest.locationTest, mapview);\n //Mapview Tests\n await runAllTests(_mappTest.mapviewTest, mapview);\n //UI Elements Tests\n await runAllTests(_mappTest.ui_elementsTest, mapview);\n //Entries Tests\n await runAllTests(_mappTest.entriesTest, mapview);\n //UI Layers Tests\n await runAllTests(_mappTest.ui_layers, mapview);\n //UI tests\n await runAllTests(_mappTest.uiTest);\n //Format Tests\n await runAllTests(_mappTest.formatTest, mapview);\n //UI Locations Tests\n await runAllTests(_mappTest.ui_locations, mapview);\n //Utils Tests\n await runAllTests(_mappTest.utilsTest, mapview);\n}\n\n/**\n * This function is used to execute all the test functions on the exported test object. \n * @function runAllTests\n * @param {object} tests \n * @param {object} mapview \n */\nasync function runAllTests(tests, mapview) {\n const testFunctions = Object.values(tests).filter(item => typeof item === 'function');\n\n for (const testFn of testFunctions) {\n try {\n await testFn(mapview);\n } catch (error) {\n console.error(`Error in test ${testFn.name}:`, error);\n }\n }\n}", "export const mappTest = {\n base\n}\n\n/**\n * Function used to test the mapp objct to see if all the base objects * properties are present\n * @function base\n */\nfunction base() {\n codi.describe('Mapp base object test', () => {\n codi.it('Mapp: Ensure we have base objects', () => {\n codi.assertTrue(Object.hasOwn(mapp, 'ol', 'The mapp object needs to have an ol object'));\n codi.assertTrue(Object.hasOwn(mapp, 'version', 'The mapp object needs to have an version object'));\n codi.assertTrue(Object.hasOwn(mapp, 'hash', 'The mapp object needs to have an hash object'));\n codi.assertTrue(Object.hasOwn(mapp, 'host', 'The mapp object needs to have an host object'));\n codi.assertTrue(Object.hasOwn(mapp, 'language', 'The mapp object needs to have an language object'));\n codi.assertTrue(Object.hasOwn(mapp, 'dictionaries', 'The mapp object needs to have an dictionaries object'));\n codi.assertTrue(Object.hasOwn(mapp, 'dictionary', 'The mapp object needs to have an dictionary object'));\n codi.assertTrue(Object.hasOwn(mapp, 'hooks', 'The mapp object needs to have an hooks object'));\n codi.assertTrue(Object.hasOwn(mapp, 'layer', 'The mapp object needs to have an layer object'));\n codi.assertTrue(Object.hasOwn(mapp, 'location', 'The mapp object needs to have an location object'));\n codi.assertTrue(Object.hasOwn(mapp, 'Mapview', 'The mapp object needs to have an Mapview object'));\n codi.assertTrue(Object.hasOwn(mapp, 'utils', 'The mapp object needs to have an utils object'));\n codi.assertTrue(Object.hasOwn(mapp, 'plugins', 'The mapp object needs to have an plugins object'));\n });\n });\n}", "const views =\n{\n 'default': {\n lat: '0',\n long: '-7.081154551613622e-10'\n },\n 'london': {\n lat: '-14035.161399215933',\n long: '6708600.902178298'\n },\n 'sandton': {\n lat: '3123319.665346',\n long: '-3012437.111737'\n }\n}\n\nexport async function setView(mapview, z, view) {\n await mapview.Map.getView().setZoom(z);\n await mapview.Map.getView().setCenter([views[view].lat, views[view].long])\n}", "{\n \"group\": \"layer\",\n \"format\": \"wkt\",\n \"dbs\": \"NEON\",\n \"table\": \"test.scratch\",\n \"srid\": \"3857\",\n \"geom\": \"geom_3857\",\n \"qID\": \"id\"\n}", "{\n \"infoj\": [\n {\n \"title\": \"qID\",\n \"field\": \"id\",\n \"inline\": true\n },\n {\n \"type\": \"key\"\n },\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n },\n {\n \"title\": \"textarea\",\n \"field\": \"textarea\",\n \"edit\": true\n },\n {\n \"title\": \"char_field\",\n \"field\": \"char_field\"\n }\n ]\n}", "{\n \"style\": {\n \"default\": {\n \"strokeColor\": \"#333\",\n \"fillColor\": \"#fff9\",\n \"icon\": {\n \"type\": \"dot\"\n }\n },\n \"cluster\": {\n \"clusterScale\": 1\n },\n \"highlight\": {\n \"scale\": 1.3,\n \"strokeColor\": \"#090\"\n }\n }\n}", "/**\n * ## layer.decorateTest()\n * @module layer/decorateTest\n */\nimport { setView } from '../../utils/view.js';\nimport wkt_layer_default from '../../assets/layers/wkt/layer.json'\nimport wkt_infoj_default from '../../assets/layers/wkt/infoj.json'\nimport wkt_style_default from '../../assets/layers/wkt/style.json'\n\n/**\n * This function is used as an entry point for the decorateTest\n * - The main function of the test is to see how a layer is decorated from the raw .json of a workspace. \n * - The test setups with the following\n * 1. The layer gets the decorated_layer from the mapview.\n * 2. Then we get the workspace json from the test directory. \n * 3. We then assign a mapview to the layer.\n * 4. Then we perform the decorate on the layer.\n * @function decorateTest \n * @param {Object} mapview \n*/\nexport async function decorateTest(mapview, layer, infoj, style) {\n\n layer ??= wkt_layer_default;\n infoj ??= wkt_infoj_default;\n style ??= wkt_style_default;\n\n await setView(mapview, 2, 'default');\n\n await codi.describe('Layer: decorateTest', async () => {\n\n const infoj_skip = [\n 'textarea'\n ]\n\n layer = {\n mapview: mapview,\n ...infoj,\n infoj_skip: infoj_skip,\n ...style,\n ...layer\n }\n\n await mapp.layer.decorate(layer);\n\n /**\n * ### Should have a draw object\n * We check if the layer has a draw object\n * @function it\n */\n await codi.it('Should have a draw object', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'draw'), 'The layer should have a draw object by default')\n });\n\n /**\n * ### Should have a show function\n * 1. We check if a decorated layer has a show function\n * 2. We then execute the show() function on a layer.\n * 3. We expect the layer.display to now be true\n * @function it\n */\n await codi.it('Should have a show function', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'show'), 'The layer should have a show method by default');\n codi.assertTrue(typeof layer.display === 'undefined', 'The layer shouldn\\'t have a display flag');\n layer.show();\n codi.assertTrue(layer.display, 'The layer should now display true after displaying');\n });\n\n /**\n * ### Should have a hide function\n * 1. We check if the decorated layer has a hide function\n * 2. We execute the hide() function\n * 3. We check if the display is false\n * @function it\n */\n await codi.it('Should have a hide function', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'hide'), 'The layer should have a hide method by default')\n layer.hide();\n codi.assertFalse(layer.display, 'The layer should display as false');\n });\n\n /**\n * ### Should not have an edit object\n * - The layer should not have an edit object as it's deprecated.\n * @function it\n */\n await codi.it('Should not have an edit object', async () => {\n codi.assertTrue(!layer.edit, 'The layer should not have an edit object as its been deprecated.')\n });\n\n /**\n * ### Should add the `skipEntry` flag to the textArea entry\n * - We check if the textArea entry on the decorate layer has the skipEntry flag.\n * @function it\n */\n await codi.it('Should add the skipEntry flag to the textArea entry', async () => {\n layer.infoj.filter(entry => entry.field === 'textarea').forEach(entry => {\n codi.assertTrue(entry.skipEntry, 'The layer should have a hide method by default')\n });\n });\n\n await setView(mapview, 11, 'london');\n\n /**\n * ### Should get `test.public` table at zoom level 11.\n * 1. We call the `tableCurrent()` function.\n * 2. We assert that the table returned is zool level 11.\n */\n await codi.it('Should get test.public table at zoom level 11', async () => {\n const table = layer.tableCurrent();\n codi.assertTrue(typeof table === 'string');\n });\n\n /**\n * ### Should get `geom_3857` at zoom level 11\n * 1. We call the `geomCurrent()` function.\n * 2. We then assert that the name of the geometry is geom_3857\n * @function it\n */\n await codi.it('Should get geom_3857 geom at zoom level 11', async () => {\n const geom = layer.geomCurrent();\n codi.assertTrue(typeof geom === 'string', 'The geometry should be returned from the layer')\n });\n\n /**\n * ### Should be able to zoomToExtent\n * 1. We call the `zoomToExtent()` function.\n * 2. We assert that the return is a success.\n */\n await codi.it('Should be able to zoomToExtent', async () => {\n const success = await layer.zoomToExtent();\n codi.assertTrue(success, 'We should see the layer zoom to extent')\n });\n\n });\n}", "import { setView } from '../../utils/view.js';\nexport async function fadeTest(mapview) {\n await setView(mapview, 2, 'default');\n await codi.describe('TODO: Layer: fadeTest', async () => {\n await codi.it('Should should test for something', () => {\n console.warn('The Fade module needs to be re-reviewed.')\n });\n });\n}", "export async function featureFieldsTest() {\n await codi.describe('TODO: Layer: featureFieldsTest', async () => {\n await codi.it('The fields array on on a theme should not be duplicated', () => {\n\n const layer = {\n params: {\n default_fields: ['zIndex']\n },\n style: {\n theme: {\n field: 'field_22',\n fields: [\n 'field_00',\n 'field_01',\n 'field_02',\n 'field_03',\n 'field_04',\n 'field_05',\n 'field_06',\n 'field_07',\n 'field_08',\n 'field_09',\n 'field_10',\n 'field_11',\n 'field_12',\n 'field_13',\n 'field_14',\n 'field_15',\n 'field_16',\n 'field_17',\n 'field_18',\n 'field_19',\n 'field_20',\n 'field_21',\n 'field_22',\n 'field_22',\n 'field_23'\n ]\n },\n label: { field: 'another_field' },\n icon_scaling: {\n field: 'another_field'\n },\n cluser: {\n label: 'another_field'\n }\n }\n }\n\n const featureArray = mapp.layer.featureFields.fieldsArray(layer);\n\n codi.assertNoDuplicates(featureArray);\n\n });\n });\n}", "export async function featureFormatsTest() {\n codi.describe('Layer: featureFormatsTest', () => {\n const mapview = {\n srid: '3857'\n }\n\n const layer = {\n format: 'wkt',\n params: {\n fields: [\n 'size'\n ]\n },\n style: {\n icon_scaling: {\n field: 'size'\n },\n hover: {\n field: 'id'\n }\n },\n mapview\n }\n\n const wktFeatures = [\n [\n 1,\n 'POINT(-14400 6710852)',\n null\n ],\n [\n 2,\n 'POINT(-14920 6711046)',\n 10\n ],\n [\n 3,\n 'POINT(-15322 6710796)',\n 15\n ]\n ]\n\n const geojsonFeatures = [\n {\n 'type': 'Feature',\n 'id': 1,\n 'properties': {\n 'id': 1,\n 'name': 'Central Park',\n 'type': 'Park',\n 'city': 'New York',\n 'size': 100\n },\n 'geometry': {\n 'type': 'Polygon',\n 'coordinates': [[\n [-73.968285, 40.785091],\n [-73.968285, 40.764891],\n [-73.949318, 40.764891],\n [-73.949318, 40.785091],\n [-73.968285, 40.785091]\n ]]\n }\n },\n {\n 'type': 'Feature',\n 'id': 2,\n 'properties': {\n 'id': 2,\n 'name': 'Empire State Building',\n 'type': 'Building',\n 'size': 200\n },\n 'geometry': {\n 'type': 'Point',\n 'coordinates': [-73.985428, 40.748817]\n }\n },\n {\n 'type': 'Feature',\n 'id': 3,\n 'properties': {\n 'id': 3,\n 'name': 'Broadway',\n 'type': 'Road',\n 'size': 300\n },\n 'geometry': {\n 'type': 'LineString',\n 'coordinates': [\n [-73.987381, 40.758896],\n [-73.986030, 40.757355],\n [-73.984442, 40.755823],\n [-73.982940, 40.754274]\n ]\n }\n }\n ]\n\n /**\n * @description WKT: Test style.icon_scaling\n * @function it\n */\n codi.it('WKT: Test style.icon_scaling', () => {\n\n mapp.layer.featureFormats[layer.format](layer, wktFeatures)\n\n codi.assertEqual(layer.style.icon_scaling.max, 15, 'The Icon scaling max should equal to 15')\n });\n\n /**\n * @description WKT: featureFormats test\n * @function it\n */\n codi.it('WKT: featureFormats test', () => {\n\n const assertIDArray = [1, 2, 3];\n const assertSizeArray = [null, 10, 15];\n const features = mapp.layer.featureFormats[layer.format](layer, wktFeatures)\n\n //Check id's and size values are correct\n features.forEach((feature, index) => {\n codi.assertEqual(feature.values_.id, assertIDArray[index]);\n codi.assertEqual(feature.values_.size, assertSizeArray[index]);\n });\n\n });\n\n /**\n * @description geojson: featureFormats test\n * @function it\n */\n codi.it('geojson: featureFormats test', () => {\n layer.format = 'geojson';\n\n const assertIDArray = [1, 2, 3];\n const assertSizeArray = [100, 200, 300];\n const features = mapp.layer.featureFormats[layer.format](layer, geojsonFeatures)\n\n //Check id's and size values are correct\n features.forEach((feature, index) => {\n codi.assertEqual(feature.values_.id, assertIDArray[index]);\n codi.assertEqual(feature.values_.size, assertSizeArray[index]);\n });\n\n });\n });\n}\n", "export async function featureHoverTest() {\n codi.describe('TODO: Layer: featureHoverTest', () => {\n codi.it('Should should test for something', () => {\n //TODO\n });\n });\n}\n", "/**\n * ## queryTest()\n * @module lib/layer/featureStyle\n */\n\n/**\n * This function is used to test the query API endpoint\n * @function featureStyleTest\n * @param {Object} mapview \n*/\nexport async function featureStyleTest(mapview) {\n await codi.describe('TODO: Layer: featureStyleTest', async () => {\n //TODO\n });\n}", "export async function styleParserTest(mapview) {\n await codi.describe('TODO: Layer: styleParserTest', async () => {\n // const workspace = await mapp.utils.xhr(`/test/tests/workspace.json`);\n // const layer = workspace.locale.layers['styleParser'];\n // layer.key = 'Style Parser Test';\n // await mapp.layer.styleParser(layer);\n\n // await codi.it('The Layer should have a default object', () => {\n // codi.assertTrue(!!layer.style.default, 'The Layer should always have a default object')\n // });\n\n // await codi.it('The parser should remove the hover object, and add it into the layer.style object', () => {\n // codi.assertTrue(!layer.hover, 'The layer shouldnt have a layer.hover object')\n // codi.assertTrue(!!layer.style.hover, 'The layer should have a layer.style.hover object')\n // });\n\n // await codi.it('The parse should remove the label property if both labels and label are present', () => {\n // codi.assertTrue(!layer.style.label, 'The layer shouldnt have a layer.style.label object')\n // codi.assertTrue(!!layer.style.labels, 'The layer should have a layer.style.labels object')\n // });\n\n console.warn('The Style parse modules need to be broken up and exported for easier testability');\n });\n}", "/**\n * ## layerTest{}\n * The layer test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module layer \n */\n\n/**\n * @typedef {Object} layerTest\n * @property {decorateTest} decorateTest\n * @property {Function} fadeTest\n * @property {Function} featureFieldsTest\n * @property {Function} featureFormatsTest\n * @property {Function} featureHoverTest\n * @property {Function} featureStyleTest\n * @property {Function} styleParserTest\n */\nimport { decorateTest } from './decorate.test.mjs';\nimport { fadeTest } from './fade.test.mjs';\nimport { featureFieldsTest } from './featureFields.test.mjs';\nimport { featureFormatsTest } from './featureFormats.test.mjs';\nimport { featureHoverTest } from './featureHover.test.mjs';\nimport { featureStyleTest } from './featureStyle.test.mjs';\nimport { styleParserTest } from './styleParser.test.mjs';\n\nexport const layerTest = {\n decorateTest,\n fadeTest,\n featureFieldsTest,\n featureFormatsTest,\n featureHoverTest,\n featureStyleTest,\n styleParserTest\n};", "\n/**\n * This test is used to see if all the language options at least have all of these base entries.\n * @function baseDictionaryTest\n */\nexport async function baseDictionaryTest() {\n await codi.describe('All languages should have the same base language entries', async () => {\n\n const base_dictionary = {\n save: '',\n cancel: '',\n confirm_delete: '',\n invalid_geometry: '',\n no_results: '',\n };\n\n for (const language of Object.keys(mapp.dictionaries)) {\n await codi.it(`${language} dictionary should have all the base keys`, () => {\n for (const key of Object.keys(base_dictionary)) {\n codi.assertTrue(!!mapp.dictionaries[language][key], `${language} should have ${key}`);\n }\n });\n }\n });\n}", "\n/**\n * @description This test is used to see if the key value dictionary is working correctly\n * @function keyValueDictionaryTest\n */\nexport async function keyValueDictionaryTest(mapview) {\n await codi.describe('Key Value Dictionary Tests', async () => {\n\n await codi.it('should replace the key value dictionary for default value on a layer', () => {\n // Get the OSM layer from the mapview\n const osm = mapview.locale.layers.find(layer => layer.key === 'OSM');\n // Check the OSM layer has the correct name\n codi.assertEqual(osm.name, 'OpenStreetMap KeyValue Dictionary');\n });\n\n await codi.it('should replace the key value dictionary for default value in an infoj', () => {\n // Get the changeEnd layer from the mapview\n const changeEnd = mapview.locale.layers.find(layer => layer.key === 'changeEnd');\n // Check the changeEnd infoj entry of field textarea has the correct title\n const entry = changeEnd.infoj.find(entry => entry.field === 'textarea');\n // Check the changeEnd infoj entry of field textarea has the correct title\n codi.assertEqual(entry.title, 'TextArea KeyValue Dictionary');\n\n });\n\n await codi.it('should not replace the key value dictionary for an array', () => {\n // Get the changeEnd layer from the mapview\n const changeEnd = mapview.locale.layers.find(layer => layer.key === 'changeEnd');\n // Check the changeEnd test_array has the correct value\n const array = changeEnd.test_array\n const expected = ['TEST KEYVALUE'];\n\n // Check the changeEnd infoj entry of field textarea has the correct array value\n codi.assertEqual(array, expected);\n });\n });\n}\n", "/**\n * This test is used to see if the mapp.language exists in the dictionaries object.\n * If not, it should return a warning and default to 'en'.\n * @function unknownLanguageTest\n */\nexport async function unknownLanguageTest() {\n // Describe the test\n await codi.describe('Language TEST should default language to English', async () => {\n\n // The language was set to 'TEST' in _test.html, which is not a valid language\n\n // Assert that the language has been reset to 'en'\n await codi.it('Should default to English', () => {\n codi.assertEqual(mapp.language, 'en');\n });\n });\n}\n", "/**\n * ## dictionaryTest{}\n * The dictionary test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module dictionaries \n */\n\n/**\n * @typedef {Object} dictionaryTest\n * @property {baseDictionaryTest} baseDictionaryTest \n * @property {keyValueDictionaryTest} keyValueDictionaryTest\n */\nimport { baseDictionaryTest } from './baseDictionary.test.mjs';\nimport { keyValueDictionaryTest } from './keyValueDictionary.test.mjs';\nimport { unknownLanguageTest } from './unknownLanguageTest.test.mjs';\n\nexport const dictionaryTest = {\n baseDictionaryTest,\n keyValueDictionaryTest,\n unknownLanguageTest\n};", "export async function createTest() {\n\n // codi.describe('TODO: Location: createTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "/**\n * This test is used to test the mapp.location.get function\n * @function getTest \n * @param {object} mapview \n */\nexport async function getTest(mapview) {\n await codi.describe('Location: getTest', async () => {\n\n const location_layer = mapview.layers['location_get_test'];\n\n const location_layer_no_infoj = mapview.layers['location_get_test_no_infoj'];\n\n /**\n * This tests the functionality to mock a location by passing in a template that returns values from the query\n * @function it\n */\n await codi.it('We should be able to mock a location get.', async () => {\n\n //Get the location with the id returned from the query above\n const location = await mapp.location.get({\n layer: location_layer,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertEqual(location.infoj.length, 4, 'We expect to see three infoj entries');\n codi.assertEqual(location.record.hook, 'location_get_test!6', 'We expect a hook made up of layer key and id');\n codi.assertTrue(location.layer instanceof Object, 'The location needs a layer object');\n\n // Push removeCallback method to remove callback methods.\n location.removeCallbacks.push(_this => delete _this.removeCallbacks)\n\n location.remove()\n\n codi.assertTrue(!location.record.hook, 'The hook should be removed from the location record.');\n\n codi.assertTrue(!location.removeCallbacks, 'removeCallbacks should have removed themselves.');\n });\n\n /**\n * This tests that no location is returned if no infoj is provided\n * @function it\n */\n await codi.it('Location get should return undefined if location.layer.info is undefined.', async () => {\n\n //Get the location with the id returned from the query above\n const location = await mapp.location.get({\n layer: location_layer_no_infoj,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertEqual(location, undefined, 'The Location should be undefined');\n\n });\n\n /**\n * This tests that no location is returned if no infoj is provided\n * @function it\n */\n await codi.it('The getInfoj method should return an infoj if none is provided on the layer present.', async () => {\n\n //Get the location with the id returned from the query above\n const infoj = await mapp.location.getInfoj({\n layer: location_layer_no_infoj,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertTrue(infoj !== undefined, 'The Location should be undefined');\n });\n });\n}", "export async function nnearestTest() {\n codi.describe('TODO: Location: nnearestTest', () => {\n codi.it('Should should test for something', () => {\n //TODO\n });\n });\n}\n\n", "import { createTest } from './create.test.mjs';\nimport { getTest } from './get.test.mjs';\nimport { nnearestTest } from './nnearest.test.mjs';\n\nexport const locationTest = {\n createTest,\n getTest,\n nnearestTest\n};", "\n/**\n* This is the add layer test module for the mapview. \n * @module lib/mapview/addLayer\n*/\n\n/**\n * The entry point test that is used to test the add layer module for a mapview. \n * @param {Object} mapview \n * @function addLayerTest\n */\nexport async function addLayerTest(mapview) {\n await codi.describe('Mapview: addLayerTest', async () => {\n\n /**\n * This test is used to check if we can add a single layer to the mapview.\n * @function it\n */\n await codi.it('Add single layer to mapview.', async () => {\n\n const layer = {\n 'format': 'tiles',\n 'URI': 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'\n }\n\n const layers = await mapview.addLayer(layer)\n\n codi.assertEqual(layers.length, 1, 'We expect to see 1 layer being returned from getLayers method.');\n codi.assertTrue(layers[0].show instanceof Function, 'The decorated layer has a show method.');\n codi.assertTrue(Object.hasOwn(mapview.layers, layers[0].key), 'The layer has been added to the mapview.');\n });\n\n /**\n * This test is used to check if we can add multiple layers to the mapview.\n * @function it\n */\n await codi.it('Add multiple layer to mapview.', async () => {\n\n const layer = {\n 'format': 'tiles',\n 'URI': 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'\n }\n\n const layers = await mapview.addLayer([layer, layer])\n\n codi.assertEqual(layers.length, 2, 'We expect to see 2 layer being returned from getLayers method.');\n codi.assertTrue(layers[0].show instanceof Function, 'The first decorated layer has a show method.');\n codi.assertTrue(Object.hasOwn(mapview.layers, layers[0].key), 'The first layer has been added to the mapview.');\n });\n });\n}", "export async function allfeaturesTest() {\n // await codi.describe('TODO: Mapview: allfeaturesTest', async () => {\n // await codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n}\n", "export async function attributionTest() {\n\n // codi.describe('TODO: Mapview: attributionTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function fitViewTest() {\n\n // codi.describe('TODO: Mapview: fitViewTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function geoJSONTest() {\n\n // codi.describe('TODO: Mapview: geoJSONTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function geometryTest() {\n\n // codi.describe('TODO: Mapview: geometryTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function getBoundsTest() {\n\n // codi.describe('TODO: Mapview: getBoundsTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function infotipTest() {\n\n // codi.describe('TODO: Mapview: infotipTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function locateTest() {\n\n // codi.describe('TODO: Mapview: locateTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // })\n\n}\n", "export async function popupTest() {\n\n // codi.describe('TODO: Mapview: popupTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "\nexport async function olControlsTest(mapview) {\n await codi.describe('Mapview', async () => {\n await codi.it('The Mapview should have controls', () => {\n codi.assertTrue(mapview.controls.length >= 1, 'The ol controls array should be greater or equal to 1');\n });\n });\n};", "import { addLayerTest } from './addLayer.test.mjs';\nimport { allfeaturesTest } from './allfeatures.test.mjs';\nimport { attributionTest } from './attribution.test.mjs';\nimport { fitViewTest } from './fitView.test.mjs';\nimport { geoJSONTest } from './geojson.test.mjs';\nimport { geometryTest } from './geometry.test.mjs';\nimport { getBoundsTest } from './getBounds.test.mjs';\nimport { infotipTest } from './infotip.test.mjs';\nimport { locateTest } from './locate.test.mjs';\nimport { popupTest } from './popup.test.mjs';\nimport { olControlsTest } from './olcontrols.test.mjs';\n\nexport const mapviewTest = {\n olControlsTest,\n addLayerTest,\n allfeaturesTest,\n attributionTest,\n fitViewTest,\n geoJSONTest,\n geometryTest,\n getBoundsTest,\n infotipTest,\n locateTest,\n popupTest\n}", "\n/**\n * This test is used to see if the link_button plugin is working as expected.\n * @function linkButtonTest\n */\nexport function linkButtonTest() {\n codi.describe('Link Button Test', () => {\n codi.it('Should add a link button to the mapButton panel', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"TITLE HERE\")\n const linkButton = mapButton.querySelector('a[title=\"TITLE HERE\"]');\n\n // Check if the linkButton has the correct href\n codi.assertEqual(linkButton.getAttribute('href'), '/url/url');\n });\n\n codi.it('Should not add a button if no href is provided', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"SHOULD NOT BE ADDED AS NO HREF\")\n const linkButton = mapButton.querySelector('a[title=\"SHOULD NOT BE ADDED AS NO HREF\"]');\n\n // Check if the linkButton does not exist\n codi.assertTrue(!linkButton);\n });\n\n codi.it('Should add multiple buttons if the link_button config is an array', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"TITLE HERE\")\n const linkButton = mapButton.querySelector('a[title=\"TITLE HERE\"]');\n\n const linkButton2 = mapButton.querySelector('a[title=\"WILL BE ADDED AS HREF\"]');\n\n // Check if the linkButton has the correct href\n codi.assertEqual(linkButton.getAttribute('href'), '/url/url');\n\n // Check if the linkButton2 has the correct href\n codi.assertEqual(linkButton2.getAttribute('href'), '/url/url2');\n });\n\n });\n}", "/**\n * ## pluginsTest{}\n * The plugins test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module plugins \n */\n\n/**\n * @typedef {Object} pluginsTest\n * @property {linkButtonTest} linkButtonTest \n */\nimport { linkButtonTest } from './link_button.test.mjs';\n\nexport const pluginsTest = {\n linkButtonTest\n};", "/**\n * ## workspaceTest()\n * @module mod/workspace\n */\n\n/**\n * This function is used as an entry point for the changeEndTest\n * This function is also in a function as to not execute in the CLI environment and only execute in a browser.\n * @function workspaceTest \n * @param {Object} mapview \n*/\nexport async function workspaceTest(mapview) {\n\n await codi.describe('Workspace: Testing Workspace API', async () => {\n\n await codi.it('Workspace: Getting Locales', async () => {\n const locales = await mapp.utils.xhr(`/test/api/workspace/locales`);\n codi.assertEqual(locales[0].key, 'locale', 'Ensure that we are getting a locale back from the API')\n });\n\n await codi.it('Workspace: Getting a Locale', async () => {\n const locale = await mapp.utils.xhr(`/test/api/workspace/locale?locale=locale`);\n codi.assertTrue(!!locale.key, 'The locale should have a key property');\n codi.assertTrue(!!locale.layers, 'The locale should have layers');\n codi.assertTrue(!!locale.name, 'The locale should have a name');\n codi.assertTrue(!!locale.plugins, 'The locale should have plugins');\n codi.assertTrue(!!locale.syncPlugins, 'The locale should have syncPlugins');\n });\n\n await codi.it('Workspace: Getting template_test Layer', async () => {\n let layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test`);\n codi.assertEqual(layer.key, 'template_test', 'Ensure that we get the template_test layer from the API')\n codi.assertTrue(!!layer.table, 'Ensure that the layer has a table');\n codi.assertTrue(!!layer.geom, 'Ensure that the layer has a geom');\n codi.assertTrue(!!layer.group, 'Ensure that the layer has a group');\n codi.assertEqual(layer.infoj.length, 7, 'The infoj should always have 7 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n\n layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test`);\n codi.assertEqual(layer.infoj.length, 7, 'The infoj should always have 7 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n codi.assertTrue(!!layer.err, 'The layer should have a error array')\n codi.assertEqual(layer.err.length, 1, 'There should be on failure on the layer');\n });\n\n await codi.it('Workspace: Getting template_test_vanilla Layer', async () => {\n const layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test_vanilla`);\n codi.assertEqual(layer.key, 'template_test_vanilla', 'Ensure that we get the template_test_vanilla layer from the API')\n codi.assertEqual(layer.infoj.length, 6, 'The infoj should always have 6 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n });\n\n await codi.it('Workspace: Getting Roles', async () => {\n const roles = await mapp.utils.xhr(`/test/api/workspace/roles`);\n\n const expected_roles = ['A', 'B', 'C', 'test', 'super_test']\n codi.assertEqual(roles, expected_roles, 'Ensure that we get the correct roles from the API')\n });\n\n await codi.it('Should return an array of roles as defined in the workspace', async () => {\n const response = await fetch('api/workspace/roles');\n const roles = await response.json();\n // Check the response is an array\n codi.assertTrue(Array.isArray(roles));\n\n // Check the response contains 'A', 'B', 'C'\n await codi.it('Roles should contain A', async () => {\n codi.assertTrue(roles.includes('A'));\n });\n\n await codi.it('Roles should contain B', async () => {\n\n codi.assertTrue(roles.includes('B'));\n });\n\n await codi.it('Roles should contain C', async () => {\n codi.assertTrue(roles.includes('C'));\n\n });\n\n // Check the response does not contain the reserved role '*'\n await codi.it('Roles should not contain *', async () => {\n codi.assertTrue(!roles.includes('*'));\n });\n });\n\n await codi.it('Should return an object of workspace roles with definitions', async () => {\n const response = await fetch('api/workspace/roles?detail=true');\n const roles = await response.json();\n // Check the response is an object\n codi.assertTrue(typeof roles === 'object');\n\n await codi.it('Roles object should contain A with value = Text about A', async () => {\n // Check the object contains 'A' role with text' Text about A'\n codi.assertTrue(roles.A === 'Text about A');\n });\n\n await codi.it('Roles object should contain B with value = Text about A', async () => {\n // Check the object contains 'B' role with text' Text about B'\n codi.assertTrue(roles.B === 'Text about B');\n });\n\n await codi.it('Roles object should contain C with value = {}', async () => {\n // Check the object contains 'C' role as an object\n // this is as its not added to the roles object in the workspace\n // So it gets added as an object \n codi.assertTrue(typeof roles.C === 'object');\n });\n\n await codi.it('Roles object should not contain *', async () => {\n // Check the reserved role '*' is not included in the object\n codi.assertTrue(!roles['*']);\n });\n });\n\n await codi.it('Workspace: Testing the test endpoint', async () => {\n let workspace_test = await mapp.utils.xhr(`/test/api/workspace/test`);\n\n const counts = {\n errors: workspace_test.errors.length,\n overwritten_templates: workspace_test.overwritten_templates.length,\n unused_templates: workspace_test.unused_templates.length,\n usage: Object.keys(workspace_test.usage).length\n }\n\n codi.assertTrue(workspace_test.errors.length > 0, 'The errors array needs to have more than 1 entry')\n codi.assertTrue(workspace_test.overwritten_templates.length > 0, 'The overwritten templates array needs to have more than 1 entry')\n codi.assertTrue(workspace_test.unused_templates.length > 0, 'The unsused templates array needs to have more than 1 entry')\n codi.assertTrue(Object.keys(workspace_test.usage).length > 0, 'The usage object needs to have keys')\n\n workspace_test = await mapp.utils.xhr(`/test/api/workspace/test`);\n\n codi.assertEqual(workspace_test.errors.length, counts.errors, 'The errors array needs to have the same number of entries we did the first run')\n codi.assertEqual(workspace_test.overwritten_templates.length, counts.overwritten_templates, 'The overwritten templates array needs to have the same number of entries we did the first run')\n codi.assertEqual(workspace_test.unused_templates.length, counts.unused_templates, 'The unused templates array needs to have the same number of entries we did the first run')\n codi.assertEqual(Object.keys(workspace_test.usage).length, counts.usage, 'The usage templates object needs to have the same number of entries we did the first run')\n });\n });\n}", "\n/**\n * ## queryTest()\n * @module mod/query\n */\n\n/**\n * This function is used to test the query API endpoint\n * @function querytest \n * @param {Object} mapview \n*/\nexport async function queryTest() {\n\n\n await codi.describe('Query: Testing Query API', async () => {\n /**\n * @description Query: Testing Query defined on infoj entry\n * @function it \n */\n await codi.it('Query: Testing Query defined on infoj entry', async () => {\n const expected_result = [1, 2, 5, 3, 4];\n const results = await mapp.utils.xhr(`/test/api/query?template=data_array`);\n codi.assertEqual(results, expected_result, 'We should be able to just call the template even if its not part of the workspace.templates object in configuration');\n });\n /**\n * @description Query: Testing Module defined in templates\n * @function it \n */\n await codi.it('Query: Testing Module defined in templates', async () => {\n const expected_result = {\n 'bar': 'foo'\n }\n const results = await mapp.utils.xhr(`/test/api/query?template=module_test`);\n codi.assertEqual(results, expected_result, 'The Module should return the basic query');\n });\n\n /**\n * @description Query: Testing a query with a bogus dbs string via the req params\n * @function it \n */\n await codi.it('Query: Testing a query with a bogus dbs string via the req params', async () => {\n const expected_result = {\n 'bar': 'foo'\n }\n const results = await mapp.utils.xhr(`/test/api/query?template=module_test&dbs=bogus`);\n codi.assertEqual(results, expected_result, 'The Module should return the basic query');\n });\n\n /**\n * @description Query: Testing a query with a bogus dbs on the template\n * @function it \n */\n await codi.it('Query: Testing a query with a bogus dbs on the template', async () => {\n const results = await mapp.utils.xhr(`/test/api/query?template=bogus_data_array`);\n codi.assertTrue(results instanceof Error, 'We should return an error for a bogus DBS connection');\n });\n });\n}", "\n/**\n * ## user.updateTest()\n * @module user/update\n */\n\n/**\n * This function is used as an entry point for the changeEndTest\n * @function updateTest \n*/\nexport async function updateTest() {\n\n if (mapp.user) {\n await codi.describe('User: update', async () => {\n\n /**\n * ### update endpoint should be able to process a body\n * The user update endpoint should be able to take a body as the request.\n * @function it\n */\n await codi.it('update endpoint should be able to process a body', async () => {\n\n let params = {\n url: '/test/api/user/update',\n body: JSON.stringify(\n {\n email: 'test@geolytix.co.uk',\n admin: false,\n approved: false,\n verified: false\n }\n )\n };\n\n await mapp.utils.xhr(params);\n\n params = {\n url: '/test/api/user/update',\n body: JSON.stringify(\n {\n email: 'test@geolytix.co.uk',\n admin: true,\n approved: true,\n verified: false\n }\n )\n }\n\n await mapp.utils.xhr(params);\n\n const acl = await mapp.utils.xhr('/test/api/user/list');\n const test_user = acl.filter(user => user.email === 'test@geolytix.co.uk')[0];\n\n await codi.assertEqual(test_user.email, 'test@geolytix.co.uk', 'The users email address should be test@geolytix.co.uk')\n await codi.assertFalse(test_user.verified, 'The user should be not verified')\n await codi.assertTrue(test_user.admin, 'The user should an admin')\n await codi.assertTrue(test_user.approved, 'The user should be approved')\n\n });\n\n /**\n ### update endpoint should be able to be just params\n * The user update endpoint should be able to take a body as the request.\n * @function it\n */\n await codi.it('update endpoint should be able to be just params', async () => {\n\n const url = `/test/api/user/update?email=test@geolytix.co.uk&field=admin&value=false`\n await mapp.utils.xhr(url);\n\n const acl = await mapp.utils.xhr('/test/api/user/list');\n const test_user = acl.filter(user => user.email === 'test@geolytix.co.uk')[0];\n\n await codi.assertEqual(test_user.email, 'test@geolytix.co.uk', 'The users email address should be test@geolytix.co.uk')\n await codi.assertFalse(test_user.verified, 'The user should be not verified')\n await codi.assertFalse(test_user.admin, 'The user should an admin')\n await codi.assertTrue(test_user.approved, 'The user should be approved')\n\n });\n\n });\n }\n}", "import { updateTest } from './update.test.mjs';\n\nexport const userTest = {\n updateTest\n}", "/**\n * ## layer.decorateTest()\n * @module ui/elements/slider\n */\n/**\n * This function is used as an entry point for the sliderTest\n * This test is used to test the creation of the slider ui element.\n * **Note: I still want to figure out event management for these elements to trigger the oninput function to simulate sliding the element**\n * @function sliderTest \n*/\nexport async function sliderTest() {\n await codi.describe('UI elements: slider', async () => {\n await codi.it('Should return the slider', async () => {\n //get the workspace from the local files\n const workspace = await mapp.utils.xhr(`/test/tests/workspace.json`);\n const layer = workspace.locale.layers['input_slider'];//Get the input slider layer that we can get the params for.\n\n const input_slider_params = layer.infoj.filter(entry => entry.field === 'integer_field');\n //Getting the params for the slider\n const input_slider = mapp.ui.elements.slider(input_slider_params[0]);\n\n //Getting the creating input slider element and asserting the exected value\n const input_slider_element = input_slider.getElementsByTagName('input')[1];\n const assert_input = ``;\n codi.assertEqual(input_slider_element.outerHTML, assert_input, 'We expect to see the input defined in the test');\n });\n });\n}", "\n/**\n * ## layer.layerStyleTest()\n * @module ui/elements/layerStyle\n */\n/**\n * This function is used as an entry point for the layerStyleTest\n * This test is used to test the creation of the style panel ui elements.\n * @function layerStyleTest \n*/\nexport async function layerStyleTest(mapview) {\n await codi.describe('UI elements: layerStyle', async () => {\n //Style object that we will use to create the entire panel\n const style = {\n opacitySlider: true,\n cluster: {\n clusterScale: 5\n },\n icon_scaling: {\n field: 'size',\n icon: true,\n clusterScale: true,\n zoomInScale: true,\n zoomOutScale: true\n },\n hover: {\n display: true,\n title: 'Hover title',\n field: 'hover_1',\n label: 'I am a hover label'\n },\n hovers: {\n hover_1: {\n title: 'Hover title',\n field: 'hover_1',\n display: true,\n label: 'I am a hover label'\n },\n hover_2: {\n title: 'Hover title 2',\n field: 'hover_2',\n display: true,\n label: 'I am a hover label'\n }\n },\n label: 'label_2',\n labels: {\n label_1: {\n title: 'Label title',\n display: true,\n field: 'label_1',\n label: 'I am labels label'\n },\n label_2: {\n title: 'Label title 2',\n display: true,\n field: 'label_2',\n label: 'I am a labels label'\n }\n },\n theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n },\n themes: {\n first_theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n },\n second_theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n }\n }\n };\n\n //get the workspace from the local files\n const layer = await mapview.layers['location_get_test'];\n\n //This will be defaulted on decorated layers. \n //We need to remove this for new elements to be passed in on the panel function.\n delete layer.style.elements;\n\n //spreading the style to the layer style object\n layer.style = { ...layer.style, ...style };\n\n //Calling the panel function to create the panel with the layers style\n const panel = await mapp.ui.elements.layerStyle.panel(layer);\n\n //Opacity Slider\n await codi.it('The panel function should return a opacitySlider', async () => {\n const opacitySlider = panel.querySelector('[data-id=\"opacitySlider\"]')\n codi.assertTrue(!!opacitySlider, 'The panel should have a opacitySlider');\n });\n\n //Hover checkbox \n await codi.it('The panel function should return a hover check box', () => {\n const hoverCheckBox = panel.querySelector('[data-id=\"hoverCheckbox\"]');\n codi.assertTrue(!!hoverCheckBox, 'The panel should have a hoverCheckBox');\n });\n\n //hovers dropdown\n await codi.it('The panel function should return a hovers dropdown', () => {\n const hoversDropDown = panel.querySelector('[data-id=\"hoversDropdown\"]');\n codi.assertTrue(!!hoversDropDown, 'The panel should have a hoversDropdown');\n });\n\n //layer theme\n await codi.it('The panel function should return a layerTheme', () => {\n const layerTheme = panel.querySelector('[data-id=\"layerTheme\"]');\n codi.assertTrue(!!layerTheme, 'The panel should have a layerTheme');\n });\n\n //Themes dropdown\n await codi.it('The panel function should return a themes dropdown', () => {\n const themesDropdown = panel.querySelector('[data-id=\"themesDropdown\"]');\n codi.assertTrue(!!themesDropdown, 'The panel should have a themes dropdown');\n });\n\n //icon scaling checkbox\n await codi.it('The panel function should return an icon scaling field checkbox', () => {\n const iconScalingFieldCheckBox = panel.querySelector('[data-id=\"iconScalingFieldCheckbox\"]');\n codi.assertTrue(!!iconScalingFieldCheckBox, 'The panel should have an icon scaling field check box');\n });\n\n //icon scaling slider\n await codi.it('The panel function should return an icon scaling slider', () => {\n const iconScalingSlider = panel.querySelector('[data-id=\"iconScalingSlider\"]');\n codi.assertTrue(!!iconScalingSlider, 'The panel should have an icon scaling slider');\n });\n\n //icon scaling cluster slider\n await codi.it('The panel function should return an icon scaling cluster slider', () => {\n const iconScalingClusterSlider = panel.querySelector('[data-id=\"iconScalingClusterSlider\"]');\n codi.assertTrue(!!iconScalingClusterSlider, 'The panel should have an icon scaling cluser slider');\n });\n\n //icon scaling zoom in slider\n await codi.it('The panel function should return an icon scaling zoom in slider', () => {\n const iconScalingZoomInSlider = panel.querySelector('[data-id=\"iconScalingZoomInSlider\"]');\n codi.assertTrue(!!iconScalingZoomInSlider, 'The panel should have an icon scaling zoom in slider');\n });\n\n //icon scaling zoom out slider\n await codi.it('The panel function should return an icon scaling zoom out slider', () => {\n const iconScalingZoomOutSlider = panel.querySelector('[data-id=\"iconScalingZoomOutSlider\"]');\n codi.assertTrue(!!iconScalingZoomOutSlider, 'The panel should have an icon scaling zoom out slider');\n });\n });\n}", "/**\n * ## layer.changeEndTest()\n * @module ui/elements/pills\n */\n\n\n/**\n * This is the entry function for the pills test.\n * @function pillsTest\n */\nexport async function pillsTest() {\n await codi.describe('UI Elements: Pills', async () => {\n //creating the pills component without any params\n const pillsComponent = mapp.ui.elements.pills();\n\n /**\n * We should be able to create a pills component with 0 params\n * We check if there is an add/remove function on the returned componenent.\n * We also check if we have a pills set\n * @fucntion it\n */\n await codi.it('Should create pills', () => {\n codi.assertTrue(typeof pillsComponent.add === 'function', 'The pills needs to have an add function');\n codi.assertTrue(typeof pillsComponent.remove === 'function', 'The pills needs to have an add function');\n codi.assertTrue(typeof pillsComponent.pills === 'object', 'The pills needs to have a pills object');\n });\n\n /**\n * Testing if we can add pills with the add function.\n * @function it\n */\n await codi.it('We should be able to add pills', () => {\n pillsComponent.add('pill');\n codi.assertTrue(pillsComponent.pills.size === 1, 'We should have 1 pill in the pills set');\n });\n\n /**\n * Testing if we can remove a pill with the remove function.\n * @function it \n */\n await codi.it('We should be able to remove pills', () => {\n pillsComponent.remove('pill');\n codi.assertTrue(pillsComponent.pills.size === 0, 'We should have 1 pill in the pills set');\n });\n\n });\n}\n", "/**\n * ## layer.decorateTest()\n * @module ui/elements/alert\n */\n/**\n * This function is used to test the alert method\n * @function alertTest \n*/\nexport async function alertTest() {\n await codi.describe('UI elements: Alert', async () => {\n\n // Test providing params\n await codi.describe('Should create an alert with params provided', async () => {\n const alert = await mapp.ui.elements.alert({ title: 'ALERT TITLE', text: 'ALERT TEXT' });\n\n codi.assertTrue(alert !== undefined, 'We expect to see the alert element');\n\n await codi.it('Should have a title of ALERT TITLE', async () => {\n // Get the alert title\n const alert_title = alert.title;\n codi.assertEqual(alert_title, 'ALERT TITLE', 'We expect to see the alert title');\n\n });\n\n await codi.it('Should have a text of ALERT TEXT', async () => {\n // Get the alert text\n const alert_text = alert.text;\n codi.assertEqual(alert_text, 'ALERT TEXT', 'We expect to see the alert text');\n })\n // Close the alert \n alert.close();\n\n });\n\n // Test providing no params\n await codi.describe('Should create an alert with no params provided', async () => {\n const alert = await mapp.ui.elements.alert({});\n\n codi.assertTrue(alert !== undefined, 'We expect to see the alert element');\n\n await codi.it('Should have a title of Information', async () => {\n // Get the alert title\n const alert_title = alert.title;\n codi.assertEqual(alert_title, 'Information', 'We expect to see the alert title');\n\n });\n\n await codi.it('Should have no text', async () => {\n // Get the alert text\n const alert_text = alert.text;\n codi.assertEqual(alert_text, undefined, 'We expect to see no alert text');\n })\n // Close the alert \n alert.close();\n\n });\n\n });\n}", "/**\n * ## layer.decorateTest()\n * @module ui/elements/confirm\n */\n/**\n * This function is used to test the confirm method\n * @function confirmTest \n*/\nexport async function confirmTest() {\n await codi.describe('UI elements: Confirm', async () => {\n\n // Test providing params\n await codi.describe('Should create a confirm dialog with params provided', async () => {\n mapp.ui.elements.confirm({ title: 'CONFIRM TITLE', text: 'CONFIRM TEXT', data_id: 'confirm-test' });\n\n // Get the confirm element\n\n const confirm = document.querySelector('[data-id=confirm-test]');\n codi.assertTrue(confirm !== undefined, 'We expect to see the confirm element');\n\n await codi.it('Should have a title of CONFIRM TITLE', async () => {\n // Get the confirm title\n const confirm_title = confirm.querySelector('h4').textContent;\n codi.assertEqual(confirm_title, 'CONFIRM TITLE', 'We expect to see the confirm title');\n\n });\n\n await codi.it('Should have a text of CONFIRM TEXT', async () => {\n // Get the confirm text\n const confirm_text = confirm.querySelector('p').textContent;\n codi.assertEqual(confirm_text, 'CONFIRM TEXT', 'We expect to see the confirm text');\n })\n\n // Get the confirm buttons\n const confirm_buttons = confirm.querySelectorAll('button');\n\n await codi.it('Should have an OK button', async () => {\n codi.assertEqual(confirm_buttons[0].innerText, 'OK', 'We expect to see the OK button');\n })\n\n await codi.it('Should have a Cancel button', async () => {\n codi.assertEqual(confirm_buttons[1].innerText, 'Cancel', 'We expect to see the Cancel button');\n });\n\n // Close the confirm \n confirm.remove();\n\n });\n\n // Test providing no params\n await codi.describe('Should create a confirm dialog with no params provided', async () => {\n mapp.ui.elements.confirm({ data_id: 'confirm-test' });\n\n // Get the confirm element\n const confirm = document.querySelector('[data-id=confirm-test]');\n codi.assertTrue(confirm !== undefined, 'We expect to see the confirm element');\n\n await codi.it('Should have a title of Information', async () => {\n // Get the confirm title\n const confirm_title = confirm.querySelector('h4').textContent;\n codi.assertEqual(confirm_title, 'Confirm', 'We expect to see the confirm title');\n\n });\n\n await codi.it('Should have no text', async () => {\n // Get the confirm text\n const confirm_text = confirm.querySelector('p').textContent;\n codi.assertEqual(confirm_text, '', 'We expect to see no confirm text');\n })\n\n // Get the confirm buttons\n const confirm_buttons = confirm.querySelectorAll('button');\n\n await codi.it('Should have an OK button', async () => {\n codi.assertEqual(confirm_buttons[0].innerText, 'OK', 'We expect to see the OK button');\n })\n\n await codi.it('Should have a Cancel button', async () => {\n codi.assertEqual(confirm_buttons[1].innerText, 'Cancel', 'We expect to see the Cancel button');\n });\n\n // Close the confirm \n confirm.remove();\n\n });\n\n });\n}", "\n/**\n * This function is used to test the dialog ui element.\n * @function dialogTest\n */\nexport function dialogTest() {\n codi.describe('UI Elements: dialog/modal', () => {\n\n const params = {\n target: document.getElementById('Map'),\n closeBtn: true,\n data_id: 'dialog-test',\n headerDrag: true,\n header: 'I am a header',\n content: 'I am so content',\n top: '5em',\n left: '5em',\n contained: true\n };\n\n /**\n * We should be able to create a basic dialog with some params\n * @function it\n */\n codi.it('Should create a basic dialog', () => {\n\n const dialog = mapp.ui.elements.dialog({ ...params });\n\n /**\n * The dialog should be able to close\n * @function it\n */\n codi.it('Dialog should be able to close', () => {\n dialog.close();\n const dialog_element = document.querySelector('[data-id=\"dialog-test\"]')\n codi.assertEqual(dialog_element, null, 'The dialog should be removed from the DOM on close');\n });\n\n /**\n * The dialog should be able to be shown again\n * @function it\n */\n codi.it('Dialog should be able to be shown again', () => {\n dialog.show();\n const dialog_element = document.querySelector('[data-id=\"dialog-test\"]')\n codi.assertEqual(dialog_element, dialog.node, 'The dialog should be in the DOM again');\n });\n\n dialog.close();\n });\n\n /**\n * Created dialog should not call show method\n * @function it\n */\n codi.it('Should recreate a basic dialog', () => {\n\n params.new = true;\n const new_params = { ...params }\n\n const dialog = mapp.ui.elements.dialog(new_params);\n dialog.close();\n\n const new_dialog = mapp.ui.elements.dialog(new_params);\n\n codi.assertEqual(dialog, new_dialog, 'The dialog should be recreated');\n\n new_dialog.close();\n });\n\n /**\n * Created dialog should have minimize/maximize functionality\n * @function it\n */\n codi.it('Should create a dialog that can minimize/maximize', () => {\n\n params.minimizeBtn = true;\n const new_params = { ...params }\n\n const dialog = mapp.ui.elements.dialog(new_params);\n\n dialog.node.querySelector('header > button.mask-icon.minimize-btn').dispatchEvent(new Event('click'))\n let minimized = dialog.node.classList.contains('minimized');\n codi.assertTrue(minimized, 'The dialog content should not be visible');\n\n dialog.node.querySelector('header > button.mask-icon.minimize-btn').dispatchEvent(new Event('click'))\n minimized = dialog.node.classList.contains('minimized');\n codi.assertFalse(minimized, 'The dialog content should not be visible');\n\n dialog.close();\n });\n\n });\n}", "import { sliderTest } from './slider.test.mjs';\nimport { layerStyleTest } from './layerStyle.test.mjs'\nimport { pillsTest } from './pills.test.mjs';\nimport { alertTest } from './alert.test.mjs';\nimport { confirmTest } from './confirm.test.mjs';\nimport { dialogTest } from './dialog.test.mjs';\n\nexport const ui_elementsTest = {\n sliderTest,\n layerStyleTest,\n pillsTest,\n alertTest,\n confirmTest,\n dialogTest\n};", "/**\n * This is the entry point function for the ui/layers/filters test\n * @function filtersTest \n * @param {object} mapview \n */\nexport async function filtersTest(mapview) {\n await codi.describe('UI Layers: Filters test', async () => {\n\n //Creating the filter to be used in other tests\n const filter = {\n field: 'id',\n minmax_query: 'minmax_query'\n };\n\n //Getting a layer\n const layer = mapview.layers['location_get_test'];\n\n /**\n * This function is used to test a custom minmax query\n * This query is by design returning 100 & 500 as min max\n * @function it\n */\n await codi.it('Numeric Filter: minmax_query test', async () => {\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '100', 'The min should return 100.');\n codi.assertEqual(maxInput.value, '500', 'The max should return 500');\n });\n\n /**\n * Testing providing an explicit min value on the filter.\n * @function it\n */\n await codi.it('Numeric Filter: min value specified', async () => {\n\n filter['min'] = 200;\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '200', 'The min should return 200.');\n codi.assertEqual(maxInput.value, '500', 'The max should return 500');\n\n //Delete the lte value of the current filter otherwise it will not be changed in the next test\n await mapp.ui.layers.filters.removeFilter(layer, filter);\n\n //Delete the min value from the filter\n delete filter.min;\n });\n\n /**\n * Testing providing an explicit max value on the filter.\n * @function it\n */\n await codi.it('Numeric Filter: max value specified', async () => {\n\n filter['max'] = 1000;\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '100', 'The min should return 100.');\n codi.assertEqual(maxInput.value, '1000', 'The max should return 1000');\n });\n\n /**\n * Testing providing a layer.current as explicit values.\n * @function it\n */\n await codi.it('Numeric Filter: layer.current specified as `lte: 200` and `gte: 800`', async () => {\n\n layer.filter.current[filter.field].lte = 800\n layer.filter.current[filter.field].gte = 200\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '200', 'The min should return 200.');\n codi.assertEqual(maxInput.value, '800', 'The max should return 800');\n\n await mapp.ui.layers.filters.removeFilter(layer, filter)\n\n codi.assertEqual(layer.filter.current, {}, 'The filter of the layer should be cleared');\n\n });\n });\n}", "/**\r\n * @module lib/ui/elements/layers/panels/filters\r\n */\r\n/**\r\n * This is the entry point function for the ui/layers/panels/filter test\r\n * @function panelFilterTest\r\n */\r\nexport function panelFilterTest() {\r\n\r\n codi.describe('UI Layers Panels: Filter', () => {\r\n /**\r\n * This function is used to test the creation of a filter panel\r\n * @function it\r\n */\r\n codi.it('Create a filter panel', () => {\r\n const layer = {\r\n reload: () => { },\r\n mapview: {\r\n Map: {\r\n getTargetElement: () => { return document.getElementById('Map') }\r\n }\r\n },\r\n key: 'panel_test',\r\n filter: {\r\n current: {}\r\n },\r\n infoj: [\r\n {\r\n 'field': 'field_1',\r\n 'filter': 'like',\r\n 'type': 'text'\r\n },\r\n {\r\n 'field': 'field_2',\r\n 'type': 'numeric',\r\n 'filter': {\r\n 'type': 'integer'\r\n }\r\n }\r\n ]\r\n }\r\n\r\n const filterPanel = mapp.ui.layers.panels.filter(layer)\r\n\r\n const filterPanelDropDown = filterPanel.querySelector('[data-id=panel_test-filter-dropdown]')\r\n\r\n const drop_down_elements = filterPanelDropDown.querySelector('ul');\r\n\r\n codi.assertEqual(drop_down_elements.children.length, 2, 'We expect two entries into the dropdown from the infoj')\r\n\r\n filterPanel.querySelector('ul').children[0].dispatchEvent(new Event('click'))\r\n\r\n codi.assertEqual(filterPanel.querySelector('ul').children[0].classList.contains('selected'), true, 'Expect an element to be selected')\r\n\r\n const resetButton = filterPanel.querySelector('[data-id=resetall]')\r\n\r\n layer.filter.current['field_1'] ??= { 'like': 'a' }\r\n\r\n resetButton.dispatchEvent(new Event('click'))\r\n\r\n codi.assertEqual(layer.filter.current, {}, ' `layer.current.filter` should be empty')\r\n\r\n });\r\n });\r\n}", "export function delayFunction(delay) {\n return new Promise(resolve => {\n setTimeout(resolve, delay);\n });\n}", "\n/**\n * \n * @module /ui/layers/view\n */\n\nimport { setView } from '../../../utils/view.js';\nimport { delayFunction } from '../../../utils/delay.js';\n\n/**\n * This function is used as an entry point for the changeEndTest\n * @function viewTest \n * @param {Object} mapview \n*/\nexport async function viewTest(mapview) {\n\n await setView(mapview, 2, 'default');\n\n await codi.describe('UI Layers: viewTest', async () => {\n\n /**\n * ### should dispatch the event and the layer should not display\n * 1. We create the `changeEnd` event and dispatch it.\n * 2. We assert that the `layer.display` is not set to true.\n * @function it\n */\n await codi.it('should dispatch the event and the layer should not display.', async () => {\n const layer = mapview.layers['changeEnd'];\n const changeEndEvent = new Event('changeEnd');\n const target = layer.mapview.Map.getTargetElement();\n\n target.dispatchEvent(changeEndEvent);\n\n await codi.assertFalse(layer.display, 'The changeEnd() layer should not display at the default zoom level.')\n\n await delayFunction(1000);\n });\n\n /**\n * ### should display at zoom level 6.\n * 1. The Test sets the mapview to London at zoom level 11.\n * 2. Creates the `changeEnd` event and dispatches it.\n * 3. And asserts that the `layer.display` is true.\n * @function it\n */\n await codi.it('should display at zoom level 6', async () => {\n await setView(mapview, 11, 'london')\n const layer = mapview.layers['changeEnd'];\n const changeEndEvent = new Event('changeEnd');\n const target = layer.mapview.Map.getTargetElement();\n\n target.dispatchEvent(changeEndEvent);\n codi.assertTrue(layer.display, 'The changeEnd() layer should display at zoom level 6');\n await delayFunction(1000);\n });\n });\n}", "import { filtersTest } from './filters.test.mjs';\nimport { panelFilterTest } from './panels/filter.test.mjs'\nimport { viewTest } from './view.test.mjs';\n\nexport const ui_layers = {\n filtersTest,\n panelFilterTest,\n viewTest\n}", "export async function mockLocation(mapview) {\n const locationLayer = mapview.layers['location_get_test'];\n return await mapp.location.get({\n layer: locationLayer,\n getTemplate: 'get_location_mock',\n id: 999,\n });\n}", "import { mockLocation } from '../../../../utils/location.js';\n/**\n * ## locations.entries.pinTest()\n * @module ui/elements/pinTest\n */\n/**\n * This test is used to test the creation of the pin ui element.\n * @function pinTest \n*/\nexport async function pinTest(mapview) {\n await codi.describe('UI elements: pin', async () => {\n await codi.it('Needs to be able to create a pin element with a scale of 4', async () => {\n\n //Set the one pin style to have a scale of 4\n mapview.layers['location_get_test'].infoj.find(entry => entry.type === 'pin').style ??= { icon: { scale: 4 } };\n\n //Mock the location\n const location = await mockLocation(mapview);\n\n //Get the pinEntry from the location\n const pinEntry = location.infoj.filter(entry => entry.type === 'pin')[0];\n\n codi.assertTrue(!!pinEntry.style, 'The pinEntry needs to have a style object');\n codi.assertTrue(!!pinEntry.style.icon, 'The pinEntry needs to have an icon assigned to the style');\n codi.assertEqual(pinEntry.style.icon.scale, 4, 'The pinEntry needs to have an scale property on the icon set to 4');\n\n //remove the location\n location.removeCallbacks.push(_this => delete _this.removeCallbacks);\n location.remove();\n });\n });\n}", "/**\n * @module lib/ui/locations/entries/geometries \n */\n\n/**\n * Entry point for the geometry test module\n * @function geometryTest \n * @param {object} mapview \n */\nexport async function geometryTest(mapview) {\n await codi.describe('UI Entries: Geometry', async () => {\n const entry = {\n mapview: mapview,\n key: 'geometry-test',\n value: {\n type: 'Point',\n coordinates: '0101000020110F000065D98262C7490CC10DF78253F7B75D41',\n },\n srid: 3856,\n display: true,\n location: {\n layer: {\n mapview: mapview\n },\n Layers: []\n }\n }\n\n /**\n * @description Should return geometry checkbox\n * @function it\n */\n await codi.it('Should return geometry checkbox', async () => {\n\n const geometryCheckBox = mapp.ui.locations.entries.geometry(entry);\n codi.assertTrue(!!geometryCheckBox, 'A checkbox needs to be returned');\n });\n\n /**\n * @description Should return 0 if no entry value is provided\n * @function it\n */\n await codi.it('Should return 0 if no entry value is provided', async () => {\n entry.value = null;\n const geometryCheckBox = await mapp.ui.locations.entries.geometry(entry);\n codi.assertTrue(typeof geometryCheckBox === 'undefined', 'We need to get no geometry checkbox returned');\n });\n })\n}", "import { delayFunction } from '../../../../utils/delay.js';\n\n/**\n * @description Test module for the ui/locations/entries/layer module\n * @module lib/ui/locations/entries/layer\n */\n\n/**\n * @description Entry point for the entries layer test module\n * @function layerTest\n */\n\nimport { setView } from '../../../../utils/view.js';\n\nexport async function layerTest(mapview) {\n await codi.describe('Layer Entry Test', async () => {\n const entry = {\n mapview: mapview,\n zIndex: 99,\n location: {\n hook: 'entry_layer!23',\n removeCallbacks: []\n },\n 'key': 'test_layer',\n 'label': 'entry_layer',\n 'type': 'layer',\n 'display': 'true',\n 'layer': 'mvt_test'\n };\n\n /**\n * @function it\n * A basic layer should be created from a entry.type = layer\n */\n await codi.it('We should get a basic layer entry', async () => {\n await mapp.ui.locations.entries.layer(entry);\n //Need to delay for async functions \n await delayFunction(1000);\n codi.assertTrue(Object.keys(mapview.layers[entry.key]).length > 0, 'We should see the unique layer being added to the mapview')\n entry.location.removeCallbacks?.forEach(fn => fn instanceof Function && fn(this));\n //Need to delay for async functions \n await delayFunction(1000);\n codi.assertTrue(typeof mapview.layers[entry.key] === 'undefined', 'We should see the unique layer being removed from the mapview')\n });\n\n /**\n * @function it\n * The layer entry should fail, with warning if the layer doesnt exist in the mapview\n */\n await codi.it('Layer entry should fail with warning', async () => {\n entry.layer = 'bogus_layer'\n await mapp.ui.locations.entries.layer(entry);\n //Need to delay for async functions \n codi.assertTrue(!mapview.layers[entry.key], 'Should warn about an undefined layer')\n\n entry.layer = 'mvt_test'\n });\n\n /**\n * @function it\n * The entry.layer should have a layer toggle if tables is defined\n * \n */\n await codi.it('Layer entry should adhere to zoom restrictions', async () => {\n\n const newEntry = {\n mapview: mapview,\n zIndex: 99,\n location: {\n hook: 'entry_layer!23',\n removeCallbacks: []\n },\n 'key': 'test_layer',\n 'label': 'entry_layer',\n 'type': 'layer',\n 'display': 'true',\n 'layer': 'mvt_test',\n 'tables': {\n '12': null,\n '13': 'test.mvt_test'\n }\n };\n\n //Zoom out\n await setView(mapview, 11, 'london');\n\n await mapp.ui.locations.entries.layer(newEntry);\n\n //Need to delay for async functions \n await delayFunction(1000);\n\n codi.assertTrue(mapview.layers[newEntry.key].display_toggle.classList.contains('disabled'), 'Toggle should be disabled')\n\n //Zoom in\n await setView(mapview, 14, 'london');\n\n codi.assertFalse(!mapview.layers[newEntry.key].display_toggle.classList.contains('disabled'), 'Toggle should be enabled')\n\n });\n });\n}", "import { pinTest } from './pin.test.mjs';\nimport { geometryTest } from './geometry.test.mjs';\nimport { layerTest } from './layer.test.mjs';\n\nexport const entriesTest = {\n pinTest,\n geometryTest,\n layerTest\n}", "/**\n * This test is used to test the tabview functions\n * @function Tabview \n */\nexport async function Tabview() {\n // await codi.describe('UI Test: Tabview', async () => {\n // console.warn('These tests need to be rewritten');\n // });\n};", "import { Tabview } from './Tabview.test.mjs';\n\nexport const uiTest = {\n Tabview\n}", "/**\n * @module utils/numericFormatter\n */\n\n/**\n * This function is used as an entry point for the numericFormatter Test\n * @function numericFormatterTest\n */\nexport function numericFormatterTest() {\n\n codi.describe('Utils: numericFormatter Test', () => {\n const params = {\n value: 654321.987,\n prefix: '$',\n formatterParams: {\n locale: 'en-UK'\n }\n };\n\n const expected_unformated_value = 654321.99\n let expected_formated_value = '$654,321.99'\n /**\n * ### Should format UK locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised UK string.\n * @function it\n */\n codi.it('Should format UK locale Numeric Values', () => {\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n /**\n * ### Should unformat UK locale string\n * This test is used to check if a localised string to UK returns the correct string.\n * @function it\n */\n codi.it('Should unformat UK locale strings', () => {\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n /**\n * ### Should format DE locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised DE string.\n * @function it\n */\n codi.it('Should format DE locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'DE';\n expected_formated_value = '$654.321,99'\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n /**\n * ### Should unformat DE locale string\n * This test is used to check if a localised string to DE returns the correct string.\n * @function it\n */\n codi.it('Should unformat DE locale strings', () => {\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n\n /**\n * ### Should format PL locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised PL string.\n * @function it\n */\n codi.it('Should format PL locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'PL';\n expected_formated_value = '$654\u00A0321,99'\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n\n codi.it('Should unformat PL locale strings', () => {\n mapp.utils.formatNumericValue(params);\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n\n /**\n * ### Should format RUB locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised PL string.\n * @function it\n */\n codi.it('Should format RUB locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'RUB';\n expected_formated_value = '$654,321.99';\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n\n codi.it('Should unformat RUB locale strings', () => {\n mapp.utils.formatNumericValue(params);\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n });\n}", "/**\n * @module utils/merge\n */\n\n/**\n * This function is used to test the merge function\n * @function mergeTest\n */\nexport async function mergeTest() {\n\n await codi.describe('Utils: mergeTest Test', async () => {\n\n await codi.it('Hobbies should be overwritten in the merge', async () => {\n const target = {\n name: 'Rob',\n age: 28,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['squash', 'guitar'],\n };\n\n const source = {\n name: 'Rob',\n age: 26,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['cooking'],\n };\n\n const expected = {\n name: 'Rob',\n age: 26,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['cooking'],\n };\n\n const mergedObj = mapp.utils.merge(target, source);\n\n codi.assertEqual(mergedObj, expected)\n });\n\n await codi.it('should handle merging with null or undefined values', async () => {\n const target = {\n name: 'John',\n age: 30,\n };\n\n const source1 = null;\n const source2 = undefined;\n\n const expected = {\n name: 'John',\n age: 30,\n };\n\n const mergedObj1 = mapp.utils.merge(target, source1);\n const mergedObj2 = mapp.utils.merge(target, source2);\n\n codi.assertEqual(mergedObj1, expected);\n codi.assertEqual(mergedObj2, expected);\n });\n\n await codi.it('should prevent _proto merging', async () => {\n const target = {\n current: {\n 'country': {\n 'in': ['ROI']\n }\n }\n };\n\n const source = {\n current: {\n 'country': {\n 'in': ['UK']\n }\n },\n __proto__: {\n 'polluted': 'polluted'\n }\n };\n\n const expected = {\n current: {\n 'country': {\n 'in': ['ROI']\n }\n }\n };\n\n const mergedObj1 = mapp.utils.merge(target, source);\n codi.assertEqual(mergedObj1, expected, 'The merge should not happen if a __proto__ is found on an object');\n });\n\n });\n}", "/**\r\n * @module utils/paramString\r\n */\r\n\r\n/**\r\n * This function is used as an entry point for the paramString Test\r\n * @function paramStringTest\r\n */\r\nexport async function paramStringTest() {\r\n\r\n await codi.describe('Utils: paramString Test', async () => {\r\n\r\n /**\r\n * ### Should Return an empty string as nothing is in params\r\n * This test is used to check that paramString returns an empty string if no params are supplied\r\n * @function it\r\n */\r\n await codi.it('Should return empty param string', async () => {\r\n\r\n const params = null;\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, '', `We expect the value to equal '', we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return an urlencoded string with the given params\r\n * This test is used to check that paramString returns a correctly urlencoded string containing the provided params\r\n * @function it\r\n */\r\n await codi.it('Should return urlencoded string', async () => {\r\n\r\n const params = {\r\n id: 1,\r\n name: 'test',\r\n age: '29 ',\r\n viewport: true,\r\n template: {'in': {'id':1}}\r\n }\r\n\r\n const expectedValue = 'id=1&name=test&age=29%20&viewport=true&template=%7B%22in%22%3A%7B%22id%22%3A1%7D%7D'\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, expectedValue, `We expect the value to equal ${expectedValue}, we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return an urlencoded string with the given params, excluding failing parameters\r\n * This test is used to check that paramString returns a correctly urlencoded string containing the provided params,\r\n * without the params that are invalid\r\n * @function it\r\n */\r\n await codi.it('Should return urlencoded string, excluding null and undefined values', async () => {\r\n\r\n const params = {\r\n id: null,\r\n name: undefined,\r\n age: '29 ',\r\n viewport: [],\r\n template: {}\r\n }\r\n\r\n const expectedValue = 'age=29%20'\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, expectedValue, `We expect the value to equal ${expectedValue}, we received ${formattedValue}`)\r\n });\r\n \r\n });\r\n}", "/**\r\n * @module utils/queryParams\r\n */\r\n\r\nimport { setView } from '../../utils/view.js';\r\n\r\n/**\r\n * This function is used as an entry point for the queryParams Test\r\n * @function queryParamsTest\r\n */\r\nexport async function queryParamsTest(mapview) {\r\n\r\n await codi.describe('Utils: queryParams Test', async () => {\r\n\r\n const location_layer = mapview.layers['query_params_layer'];\r\n\r\n //Get the location\r\n const location = await mapp.location.get({\r\n layer: location_layer,\r\n getTemplate: 'get_location_mock',\r\n id: 6,\r\n });\r\n\r\n const params = {\r\n layer: location_layer,\r\n queryparams: {\r\n layer: location_layer,\r\n table: 'fake_table',\r\n },\r\n };\r\n\r\n await setView(mapview, 2, 'default');\r\n\r\n /**\r\n * ### Should Return undefined\r\n * This test is used to check that queryParams returns undefined if queryparams is null/undefined\r\n * @function it\r\n */\r\n await codi.it('Should return undefined with null queryparams', async () => {\r\n\r\n const null_params = {};\r\n const formattedValue = mapp.utils.queryParams(null_params);\r\n codi.assertEqual(formattedValue, undefined, `We expect the value to equal undefined, we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return qID and id \r\n * This test is used to check that queryParams returns the correct field values for id and qID when supplied.\r\n * @function it\r\n */\r\n await codi.it('Should return id, qID', async () => {\r\n\r\n params.queryparams.id = true\r\n params.queryparams.qID = true\r\n params.location = location\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.id, 6, `We expect the value to equal 6, we received ${queryParams.id}`)\r\n codi.assertEqual(queryParams.qID, '_id', `We expect the value to equal id, we received ${queryParams.qID}`)\r\n });\r\n\r\n /**\r\n * ### Should Return lat, lng and z parameters in the response\r\n * This test is used to check that queryParams returns latitude, longitude and zoom level when requested.\r\n * @function it\r\n */\r\n await codi.it('Should return lat, lng, z', async () => {\r\n\r\n params.queryparams.center = true\r\n params.queryparams.z = true\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.lng, 0, `We expect the value to equal 0, we received ${queryParams.lng}`)\r\n codi.assertEqual(queryParams.lat, 0, `We expect the value to equal 0, we received ${queryParams.lat}`)\r\n codi.assertTrue(!!queryParams.z, `We expect the zoom level to be returned from the method`)\r\n });\r\n\r\n /**\r\n * ### Should Return locale, template and layer parameters in the response\r\n * This test is used to check that queryParams returns locale, template and layer when requested.\r\n * @function it\r\n */\r\n await codi.it('Should return locale, template, layer', async () => {\r\n\r\n params.query = 'not_real'\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.template, params.query, `We expect the value to equal ${params.query}, we received ${queryParams.template}`)\r\n codi.assertEqual(queryParams.locale, 'locale', `We expect the value to equal 0, we received ${queryParams.locale}`)\r\n codi.assertEqual(queryParams.layer, location_layer.key, `We expect the value to equal ${location_layer.key}, we received ${queryParams.layer}`)\r\n });\r\n\r\n /**\r\n * ### Should Return viewport and filter\r\n * This test is used to check that queryParams returns viewport and filter when requested\r\n * @function it\r\n */\r\n await codi.it('Should return viewport, filter', async () => {\r\n\r\n params.viewport = true\r\n params.queryparams.filter = true\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.viewport.length, 5, `We expect the value to have 5 params, we received ${queryParams.viewport.length}`)\r\n codi.assertEqual(queryParams.filter, {}, `We expect the value to equal {'id':{}}, we received ${JSON.stringify(queryParams.filter)}`)\r\n });\r\n\r\n // Push removeCallback method to remove callback methods.\r\n location.removeCallbacks.push(_this => delete _this.removeCallbacks)\r\n\r\n location.remove()\r\n\r\n });\r\n}", "/**\n * @module lib/utility/compose\n */\n\n/**\n * @description This is used as an entry point for the compose utility test\n * @function composeTest \n */\nexport function composeTest() {\n codi.describe('Compose Test', () => {\n\n /**\n * ### Should compose functions from left to right\n * @function it\n */\n codi.it('Should compose functions from left to right', () => {\n //Different functions to use\n const addOne = x => x + 1;\n const double = x => x * 2;\n const square = x => x * x;\n\n //Creating the compose chain\n const composed = mapp.utils.compose(addOne, double, square);\n\n codi.assertEqual(composed(3), 64, 'We expect this order of opperation when composing functions left to right : ((3 + 1) * 2)^2 = 64');\n });\n\n /**\n * ### Should work with a single function\n * @function it\n */\n codi.it('Should work with a single function', () => {\n const addTwo = x => x + 2;\n\n //Creating the compose chain\n const composed = mapp.utils.compose(addTwo);\n\n codi.assertEqual(composed(5), 7, 'Compose should also work with a single function');\n });\n\n /**\n * ### Should return the input if no functions are provided\n * @function it\n */\n codi.it('Should return the input if no functions are provided', () => {\n //Creating the compose chain\n const composed = mapp.utils.compose();\n\n codi.assertEqual(composed(10), 10, 'We should get the input as a return if no functions are provided');\n });\n\n /**\n * ### Should handle different data types\n * @function it\n */\n codi.it('Should handle different data types', () => {\n const toUpperCase = str => str.toUpperCase();\n const addExclamation = str => str + '!';\n const composed = mapp.utils.compose(addExclamation, toUpperCase);\n\n codi.assertEqual(composed('hello'), 'HELLO!', 'We expect the string to change in the chain given.');\n });\n\n\n });\n}", "/**\n * @description This module is used to test the svgTemplates util\n * @module /lib/utils/svgTemplates\n */\n\n/**\n * @description This is used as an entry point for the test module\n * @function svgTemplatesTest\n */\nexport async function svgTemplatesTest() {\n await codi.describe('Utils: SVG Templates', async () => {\n\n /**\n * ### We shouldn't be able to replace already existing templates\n * @function it\n */\n await codi.it('We should load new svg templates once', async () => {\n\n const svgTemplates = {\n 'dot_test': 'I am a bogus svg and shouldnt be loaded',\n };\n\n await mapp.utils.svgTemplates(svgTemplates);\n const dot_test_svg = await mapp.utils.svgSymbols.templates['dot_test'];\n codi.assertNotEqual(dot_test_svg, '', 'The svg template should not be overwriten');\n\n });\n });\n}", "/**\n * @module utils/versionCheck\n */\n\n/**\n * This function is used to test the versionCheck function\n * @function versionCheck\n */\nexport async function versionCheck() {\n\n await codi.describe('Utils: versionCheck Test', async () => {\n\n await codi.it('should return false if the major and minor are the same but version patch exceeds', async () => {\n\n mapp.version = '4.11.1';\n\n const result = await mapp.utils.versionCheck('4.11');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return true if the major version is more than', async () => {\n\n mapp.version = '4.9.1';\n\n const result = mapp.utils.versionCheck('3.9');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return false if the major version is the same and the minor version is less', async () => {\n\n mapp.version = '4.9.0';\n\n const result = mapp.utils.versionCheck('4.10.0');\n\n codi.assertEqual(result, false);\n });\n\n await codi.it('should return true if the major version is the same and the minor version is more', async () => {\n\n mapp.version = '4.11.0';\n\n const result = await mapp.utils.versionCheck('4.10.0');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return true if the major version is the same and the minor version is the same', async () => {\n\n mapp.version = '4.11.2';\n\n const result = await mapp.utils.versionCheck('4.11.1');\n\n codi.assertEqual(result, true);\n });\n });\n}\n", "import { numericFormatterTest } from './numericFormatter.test.mjs';\nimport { mergeTest } from './merge.test.mjs';\nimport { paramStringTest } from './paramString.test.mjs';\nimport { queryParamsTest } from './queryParams.test.mjs';\nimport { composeTest } from './compose.test.mjs';\nimport { svgTemplatesTest } from './svgTemplates.test.mjs';\nimport { versionCheck } from './versionCheck.mjs';\nexport const utilsTest = {\n numericFormatterTest,\n mergeTest,\n paramStringTest,\n queryParamsTest,\n composeTest,\n svgTemplatesTest,\n versionCheck\n}", "{\n \"key\": \"cluster_test\",\n \"display\": true,\n \"group\": \"layer\",\n \"format\": \"wkt\",\n \"dbs\": \"NEON\",\n \"table\": \"test.scratch\",\n \"srid\": \"3857\",\n \"geom\": \"geom_3857\",\n \"qID\": \"id\",\n \"cluster\": {\n \"resolution\": 0.005,\n \"hexgrid\": true\n },\n \"infoj\": [\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n }\n ],\n \"style\": {\n \"default\": {\n \"icon\": {\n \"type\": \"dot\",\n \"fillColor\": \"#13336B\"\n }\n },\n \"cluster\": {\n \"icon\": {\n \"type\": \"target\",\n \"fillColor\": \"#E6FFFF\",\n \"layers\": {\n \"1\": \"#13336B\",\n \"0.85\": \"#E6FFFF\"\n }\n }\n },\n \"highlight\": {\n \"scale\": 1.3\n },\n \"theme\": {\n \"title\": \"theme_1\",\n \"type\": \"graduated\",\n \"field\": \"test_template_style\",\n \"graduated_breaks\": \"greater_than\",\n \"template\": {\n \"key\": \"test_template_style\",\n \"template\": \"100-99\",\n \"value_only\": true\n },\n \"cat_arr\": [\n {\n \"value\": 0,\n \"label\": \"0 to 5%\",\n \"style\": {\n \"icon\": {\n \"fillColor\": \"#ffffcc\",\n \"fillOpacity\": 0.8\n }\n }\n }\n ]\n }\n }\n}", "/**\n * This is the vector module used to test /lib/layer/format/vector\n * @module layer/format/vector\n */\n\nimport cluster_layer_default from '../../../assets/layers/cluster/layer.json';\n\n/**\n * This is the entry point function for the vector test module.\n * @function vectorTest \n * @param {object} mapview \n */\nexport async function vectorTest(mapview, layer) {\n\n layer ??= cluster_layer_default;\n\n await codi.describe('Layer Format: Vector', async () => {\n\n /**\n * ### Should be able to create a cluster layer\n * 1. It takes layer params.\n * 2. Decorates the layer.\n * 3. We then give the vector function the layer.\n * 4. We expect the format of the layer to change to 'cluster'\n * @function it\n */\n await codi.it('Should create a cluster layer', async () => {\n\n const layer_params = {\n mapview: mapview,\n ...layer\n }\n\n //Decorating layer\n const clusterLayer = await mapp.layer.decorate(layer_params);\n\n //Passing the layer to the format method\n mapp.layer.formats.vector(clusterLayer);\n\n //Showing the layer\n clusterLayer.show();\n codi.assertTrue(typeof clusterLayer.show === 'function', 'The layer should have a show function');\n codi.assertTrue(typeof clusterLayer.reload === 'function', 'The layer should have a reload function');\n codi.assertTrue(typeof clusterLayer.setSource === 'function', 'The layer should have a setSource function');\n codi.assertTrue(clusterLayer.format === 'cluster', 'The layer should have the format cluster');\n clusterLayer.hide();\n });\n });\n}", "{\n \"group\": \"layer\",\n \"name\": \"mvt_test\",\n \"format\": \"mvt\",\n \"table\": \"test.mvt_test\",\n \"geom\": \"geom_3857\",\n \"srid\": \"3857\",\n \"qID\": \"id\",\n \"infoj\": [\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n }\n ],\n \"style\": {\n \"default\": {\n \"strokeWidth\": \"0\",\n \"fillColor\": \"#fff\",\n \"fillOpacity\": 0.4,\n \"strokeColor\": null\n },\n \"themes\": {\n \"theme_1\": {\n \"title\": \"theme_1\",\n \"type\": \"categorized\",\n \"field\": \"numeric_field\",\n \"cat\": {\n \"1\": {\n \"label\": \"Lowest\",\n \"style\": {\n \"fillColor\": \"#3193ED\"\n }\n },\n \"2\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#5DC29A\"\n }\n },\n \"3\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#8FE15A\"\n }\n },\n \"4\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#D8D758\"\n }\n },\n \"5\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FFB956\"\n }\n },\n \"6\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FE8355\"\n }\n },\n \"7\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FA5652\"\n }\n },\n \"8\": {\n \"label\": \"Highest\",\n \"style\": {\n \"fillColor\": \"#F0304D\"\n }\n }\n }\n },\n \"theme_2\": {\n \"title\": \"theme_2\",\n \"type\": \"categorized\",\n \"field\": \"numeric_field\",\n \"cat\": {\n \"1\": {\n \"label\": \"Lowest\",\n \"style\": {\n \"fillColor\": \"#6B2E94\"\n }\n },\n \"2\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#8B44B8\"\n }\n },\n \"3\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#9B6FCD\"\n }\n },\n \"4\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#89A7D6\"\n }\n },\n \"5\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#70C1C9\"\n }\n },\n \"6\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#52C4A3\"\n }\n },\n \"7\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#38B77C\"\n }\n },\n \"8\": {\n \"label\": \"Highest\",\n \"style\": {\n \"fillColor\": \"#1FA855\"\n }\n }\n }\n }\n }\n }\n}", "import mvt_layer_default from '../../../assets/layers/mvt/layer.json';\n\nexport function mvtTest(mapview, layer) {\n\n layer ??= mvt_layer_default;\n\n codi.describe('Layer Format: MVT', () => {\n /**\n * @description MVT: Create basic layer\n * @function it\n */\n codi.it('MVT: Create basic layer', () => {\n mapp.layer.formats[layer.format]?.(layer);\n\n codi.assertTrue(Object.hasOwn(layer, 'reload'), 'The mvt layer needs to have a reload function')\n codi.assertTrue(Object.hasOwn(layer, 'featureSource'), 'The mvt layer needs to have a featureSource')\n codi.assertTrue(Object.hasOwn(layer, 'source'), 'The mvt layer needs to have a source')\n codi.assertTrue(Object.hasOwn(layer, 'L'), 'The mvt layer needs to have an openlayer object')\n });\n\n /**\n * @description MVT: Reload should remove sourceTiles\n * @function it\n */\n codi.it('MVT: Reload should remove sourceTiles', () => {\n mapp.layer.formats[layer.format]?.(layer);\n\n layer.source.sourceTiles_ = { tile: 'foo' };\n layer.reload();\n codi.assertEqual(layer.source.sourceTiles_, {}, 'The sourceTiles needs to be cleared');\n });\n });\n}", "import { vectorTest } from './vector.test.mjs';\nimport { mvtTest } from './mvt.test.mjs';\n\nexport const formatTest = {\n vectorTest,\n mvtTest\n} ", "/**\n * This function is used as an entry point for the infoj test\n * @function injojTest\n */\nexport function infojTest() {\n codi.describe('UI Locations: infojTest', () => {\n /**\n * ### It should create an infoj with a correct order\n * 1. We define an infoj with a combination of different entries with keys, fields and queries\n * 2. We assert against the order\n * @function it\n */\n codi.it('It should create an infoj with certain order', () => {\n\n const location = {\n infoj: [\n {\n field: 'field_1',\n key: 'key_1',\n label: 'test_1',\n value: 'test 1 value'\n },\n {\n field: 'field_2',\n label: 'test_2',\n value: 'value_2'\n },\n {\n field: 'field_3',\n label: 'test_3',\n value: 'value_3'\n },\n {\n key: 'key_4',\n value: 'value_4'\n },\n {\n query: 'query_5',\n value: 'value_5',\n location: {}\n }\n ]\n };\n\n const infoj_order = [\n '_field_1',\n 'field_2',\n 'field_3',\n 'key_4',\n 'query_5',\n {\n field: 'field6',\n value: 'value_6'\n }\n ];\n\n // Get listview element from the infoj object\n const infoj = mapp.ui.locations.infoj(location, infoj_order);\n\n // Get textvalues from location listview elements.\n const results = Array.from(infoj.children)\n .map(el => el.firstChild.innerText.trim())\n\n // Expected results\n const expected = [\n 'value_2',\n 'value_3',\n 'value_4',\n 'value_5',\n 'value_6'\n ];\n\n // Asserting we get the expected results and order\n codi.assertEqual(results, expected, 'The infoj order needs to be as defined in the expected');\n\n });\n });\n}\n", "import { infojTest } from './infoj.test.mjs';\n\nexport const ui_locations = { infojTest };", "import { base } from '../public/tests/_base.test.mjs';\nimport { coreTest } from './browser/local.test.mjs';\nimport { mappTest } from './lib/mapp.test.mjs';\nimport { layerTest } from './lib/layer/_layer.test.mjs';\nimport { dictionaryTest } from './lib/dictionaries/_dictionaries.test.mjs';\nimport { locationTest } from './lib/location/_location.test.mjs';\nimport { mapviewTest } from './lib/mapview/_mapview.test.mjs';\nimport { pluginsTest } from './plugins/_plugins.test.mjs';\nimport { workspaceTest } from './mod/workspace/_workspace.test.mjs';\nimport { queryTest } from './mod/query.test.mjs';\nimport { userTest } from './mod/user/_user.test.js';\nimport { ui_elementsTest } from './lib/ui/elements/_elements.test.mjs';\nimport { ui_layers } from './lib/ui/layers/_layers.test.mjs';\nimport { entriesTest } from './lib/ui/locations/entries/_entries.test.mjs';\nimport { uiTest } from './lib/ui/_ui.test.mjs';\nimport { utilsTest } from './lib/utils/_utils.test.mjs';\nimport { formatTest } from './lib/layer/format/_format.test.mjs';\nimport { ui_locations } from './lib/ui/locations/_locations.test.mjs';\n\nself._mappTest = {\n base,\n coreTest,\n mappTest,\n layerTest,\n dictionaryTest,\n locationTest,\n mapviewTest,\n pluginsTest,\n workspaceTest,\n queryTest,\n userTest,\n ui_elementsTest,\n ui_layers,\n entriesTest,\n uiTest,\n utilsTest,\n formatTest,\n ui_locations,\n}"], + "mappings": "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", + "names": ["layersTab", "locale", "base", "entry", "geometryTest", "layerTest", "geometryTest", "layerTest", "layer_default", "layer_default", "layer_default", "layer_default"] +} From 8e90147abcdbc95cbeff275f19de194a54b8360b Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 14 Nov 2024 12:47:14 +0200 Subject: [PATCH 02/12] Fix docs --- mod/utils/dbs.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index f429a55afb..e9e760626f 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -1,6 +1,9 @@ /** + * @module /utils/dbs - * @description Database connection and query management module that creates connection pools for multiple databases + * @description + * ## /utils/dbs + * Database connection and query management module that creates connection pools for multiple databases * based on environment variables prefixed with 'DBS_'. */ From 6571745936a76acdcb8cbf30072cc10dc63849ba Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 14 Nov 2024 12:49:50 +0200 Subject: [PATCH 03/12] Remove test bundles --- public/js/tests/_mapp.test.js | 2546 ----------------------------- public/js/tests/_mapp.test.js.map | 8 - 2 files changed, 2554 deletions(-) delete mode 100644 public/js/tests/_mapp.test.js delete mode 100644 public/js/tests/_mapp.test.js.map diff --git a/public/js/tests/_mapp.test.js b/public/js/tests/_mapp.test.js deleted file mode 100644 index 114ae9ba82..0000000000 --- a/public/js/tests/_mapp.test.js +++ /dev/null @@ -1,2546 +0,0 @@ -(() => { - // public/tests/_base.test.mjs - async function base() { - let mapview = {}; - await codi.describe("Mapview test", async () => { - console.log(`MAPP v${mapp.version}`); - const OL = document.getElementById("OL"); - const locationsTab = document.getElementById("locations"); - const layersTab = document.getElementById("layers"); - const tabs = document.querySelectorAll("#ctrl-tabs > div"); - const tabPanels = document.querySelectorAll("#ctrl-panel > div"); - const tabview = document.getElementById("Tabview"); - await codi.it("should merge dictionaries correctly", () => { - const initialLength = Object.keys(mapp.dictionaries.en).length; - mapp.utils.merge(mapp.dictionaries, { - en: { - toolbar_zoom_in: "Zoom in", - toolbar_zoom_out: "Zoom out", - toolbar_zoom_to_area: "Zoom to area", - toolbar_current_location: "Current location", - toolbar_fullscreen: "Fullscreen mapview", - toolbar_admin: "Open account admin view", - toolbar_login: "Log in", - toolbar_logout: "Log out", - layers: "Layers", - locations: "Locations", - no_locales: "Your account has been verified and approved, but you do not have access to any locales. This is likely as an administrator has not given you the required roles. Please contact an administrator to resolve this.", - no_layers: "No accessible layers in locale." - }, - de: { - toolbar_zoom_in: "Zoom rein", - toolbar_zoom_out: "Zoom raus", - toolbar_zoom_to_area: "Zoom Rechteck", - toolbar_current_location: "Standort", - toolbar_fullscreen: "Vollbild", - toolbar_admin: "Benutzerkontenverwaltung", - toolbar_login: "Einloggen", - toolbar_logout: "Ausloggen", - layers: "Ebenen", - locations: "Orte" - }, - zh: { - toolbar_zoom_in: "\u653E\u5927", - toolbar_zoom_out: "\u7F29\u5C0F", - toolbar_zoom_to_area: "\u7F29\u653E\u81F3\u533A\u57DF", - toolbar_current_location: "\u5F53\u524D\u4F4D\u7F6E", - toolbar_fullscreen: "\u5168\u5C4F\u5730\u56FE\u89C6\u56FE", - toolbar_admin: "\u6253\u5F00\u5E10\u6237\u7BA1\u7406\u89C6\u56FE", - toolbar_login: "\u767B\u5F55", - toolbar_logout: "\u767B\u51FA", - layers: "\u56FE\u5C42", - locations: "\u5730\u70B9" - }, - zh_tw: { - toolbar_zoom_in: "\u653E\u5927", - toolbar_zoom_out: "\u7E2E\u5C0F", - toolbar_zoom_to_area: "\u7E2E\u653E\u81F3\u5340\u57DF", - toolbar_current_location: "\u7576\u524D\u4F4D\u7F6E", - toolbar_fullscreen: "\u5168\u5C4F\u5730\u5716\u8996\u5716", - toolbar_admin: "\u6253\u958B\u5E33\u6236\u7BA1\u7406\u8996\u5716", - toolbar_login: "\u767B\u9304", - toolbar_logout: "\u767B\u51FA", - layers: "\u5716\u5C64", - locations: "\u5730\u9EDE" - }, - pl: { - toolbar_zoom_in: "Przybli\u017C", - toolbar_zoom_out: "Oddal", - toolbar_zoom_to_area: "Przybli\u017C do obszaru", - toolbar_current_location: "Obezha lokalizcja", - toolbar_fullscreen: "Mapa na ca\u0142ym ekranie", - toolbar_admin: "Otw\xF3rz widok administratora", - toolbar_login: "Zaloguj si\u0119", - toolbar_logout: "Wyloguj si\u0119", - layers: "Warstwy", - locations: "Lokalizacje" - }, - fr: { - toolbar_zoom_in: "Zoom +", - toolbar_zoom_out: "Zoom -", - toolbar_zoom_to_area: "Zoomer sur la zone", - toolbar_current_location: "Emplacement actuel", - toolbar_fullscreen: "Carte en plein \xE9cran", - toolbar_admin: "Ouvrir le menu administrateur", - toolbar_login: "Se connecter", - toolbar_logout: "D\xE9connexion", - layers: "Couches cartographiques", - locations: "Sites" - }, - ja: { - toolbar_zoom_in: "\u30BA\u30FC\u30E0\u30A4\u30F3", - toolbar_zoom_out: "\u30BA\u30FC\u30E0\u30A2\u30A6\u30C8", - toolbar_zoom_to_area: "\u30A8\u30EA\u30A2\u3092\u30BA\u30FC\u30E0\u306B", - toolbar_current_location: "\u73FE\u5730", - toolbar_fullscreen: "\u30D5\u30EB\u30B9\u30AF\u30EA\u30FC\u30F3 \u30DE\u30C3\u30D7\u30D3\u30E5\u30FC", - toolbar_admin: "\u30A2\u30AB\u30A6\u30F3\u30C8\u30A2\u30C9\u30DF\u30F3\u30D3\u30E5\u30FC\u3092\u958B\u304F", - toolbar_login: "\u30ED\u30B0\u30A4\u30F3", - toolbar_logout: "\u30ED\u30B0\u30A2\u30A6\u30C8", - layers: "\u30EC\u30A4\u30E4\u30FC", - locations: "\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3" - }, - esp: { - toolbar_zoom_in: "Zoom +", - toolbar_zoom_out: "Zoom -", - toolbar_zoom_to_area: "Zoom al \xE1rea", - toolbar_current_location: "Ubicaci\xF3n actual", - toolbar_fullscreen: "Vista de mapa en pantalla completa", - toolbar_admin: "Abrir vista de administrador de cuenta", - toolbar_login: "Iniciar sesi\xF3n", - toolbar_logout: "Desconexi\xF3n", - layers: "Capas", - locations: "Ubicaciones" - }, - tr: { - toolbar_zoom_in: "Yaklas", - toolbar_zoom_out: "Uzaklas", - toolbar_zoom_to_area: "Bolgeye yaklas", - toolbar_current_location: "Mevcut konum", - toolbar_fullscreen: "Tam ekran harita", - toolbar_admin: "Hesap yoneticisini ac", - toolbar_login: "Oturum ac", - toolbar_logout: "Oturumu kapat", - layers: "Katmanlar", - locations: "Konumlar" - }, - it: { - toolbar_zoom_in: "Ingrandisci", - toolbar_zoom_out: "Rimpicciolisci", - toolbar_zoom_to_area: "Zoom nell'area", - toolbar_current_location: "Posizione attuale", - toolbar_fullscreen: "Mappa a schermo intero", - toolbar_admin: "Apri il men\xF9 amministratore", - toolbar_login: "Log in", - toolbar_logout: "Log out", - layers: "Layers", - locations: "Localit\xE0" - }, - th: { - toolbar_zoom_in: "\u0E02\u0E22\u0E32\u0E22\u0E40\u0E02\u0E49\u0E32", - toolbar_zoom_out: "\u0E0B\u0E39\u0E21\u0E2D\u0E2D\u0E01", - toolbar_zoom_to_area: "\u0E0B\u0E39\u0E21\u0E44\u0E1B\u0E17\u0E35\u0E48\u0E1E\u0E37\u0E49\u0E19\u0E17\u0E35\u0E48", - toolbar_current_location: "\u0E2A\u0E16\u0E32\u0E19\u0E17\u0E35\u0E48\u0E1B\u0E31\u0E08\u0E08\u0E38\u0E1A\u0E31\u0E19", - toolbar_fullscreen: "\u0E21\u0E38\u0E21\u0E21\u0E2D\u0E07\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48\u0E41\u0E1A\u0E1A\u0E40\u0E15\u0E47\u0E21\u0E2B\u0E19\u0E49\u0E32\u0E08\u0E2D", - toolbar_admin: "\u0E40\u0E1B\u0E34\u0E14\u0E21\u0E38\u0E21\u0E21\u0E2D\u0E07\u0E1C\u0E39\u0E49\u0E14\u0E39\u0E41\u0E25\u0E23\u0E30\u0E1A\u0E1A", - toolbar_login: "\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A", - toolbar_logout: "\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A", - layers: "\u0E0A\u0E31\u0E49\u0E19", - locations: "\u0E2A\u0E16\u0E32\u0E19\u0E17\u0E35\u0E48" - } - }); - const updatedLength = Object.keys(mapp.dictionaries.en).length; - codi.assertTrue(updatedLength > initialLength, "English dictionary should have new entries"); - codi.assertEqual(mapp.dictionaries.en.toolbar_zoom_in, "Zoom in", "English dictionary should have the correct value for toolbar_zoom_in"); - codi.assertEqual(mapp.dictionaries.de.toolbar_zoom_in, "Zoom rein", "German dictionary should have the correct value for toolbar_zoom_in"); - }); - await codi.it("should refresh cookie and get user with updated credentials", async () => { - const currentUser = mapp.user; - mapp.user = await mapp.utils.xhr(`${mapp.host}/api/user/cookie`); - if (mapp.user !== null) { - codi.assertNotEqual(mapp.user, currentUser, "User object should be updated after refreshing cookie"); - codi.assertTrue(mapp.user.hasOwnProperty("email"), 'User object should have the "email" property'); - codi.assertTrue(mapp.user.hasOwnProperty("language"), 'User object should have the "language" property'); - codi.assertTrue(mapp.user.hasOwnProperty("roles"), 'User object should have the "roles" property'); - } - }); - await codi.it("should set the language correctly", () => { - const currentLanguage = mapp.language; - mapp.language = mapp.hooks.current.language || mapp.user?.language || mapp.language; - if (mapp.hooks.current.language) { - codi.assertEqual(mapp.language, mapp.hooks.current.language, "Language should be set to the value from mapp.hooks.current.language"); - } else if (mapp.user?.language) { - codi.assertEqual(mapp.language, mapp.user.language, "Language should be set to the value from mapp.user.language"); - } else { - codi.assertEqual(mapp.language, currentLanguage, "Language should remain unchanged if no overrides are present"); - } - }); - await codi.it("should restore scroll if supported", () => { - if ("scrollRestoration" in history) { - history.scrollRestoration = "auto"; - codi.assertEqual(history.scrollRestoration, "auto", 'Scroll restoration should be set to "auto"'); - } else { - codi.assertFalse("scrollRestoration" in history, "Scroll restoration is not supported"); - } - }); - document.body.addEventListener("scroll", () => { - OL.style["marginTop"] = `-${parseInt(window.pageYOffset / 2)}px`; - if (document.body.scrollTop > window.innerHeight) { - document.body.scrollTop = window.innerHeight; - } - }); - mapp.ui.utils.resizeHandler({ - target: document.getElementById("ctrls-divider"), - resizeEvent: (e) => { - let pageX = e.touches && e.touches[0].pageX || e.pageX; - if (pageX < 350) - return; - if (pageX > window.innerWidth / 2) - pageX = window.innerWidth / 2; - document.body.style.gridTemplateColumns = `${pageX}px 10px auto`; - } - }); - mapp.ui.utils.resizeHandler({ - target: document.getElementById("tabview-divider"), - resizeEvent: (e) => { - const pageY = e.touches && e.touches[0].pageY || e.pageY; - if (pageY < 0) - return; - let height = window.innerHeight - pageY; - if (height < 65) - height = 50; - if (height > window.innerHeight - 10) - height = window.innerHeight; - document.body.style.gridTemplateRows = `auto 10px ${height}px`; - OL.style.marginTop = `-${height / 2}px`; - } - }); - tabs.forEach((tab) => { - tab.title = mapp.dictionary[tab.dataset.id]; - tab.onclick = (e) => { - tabs.forEach((el) => el.classList.remove("active")); - e.target.classList.add("active"); - tabPanels.forEach((el) => el.classList.remove("active")); - document.getElementById(e.target.dataset.id).classList.add("active"); - if (e.target.dataset.id === "locations") { - const gazetteerInput = document.getElementById("gazetteerInput"); - gazetteerInput && window.innerWidth > 768 && gazetteerInput.focus(); - } - }; - }); - await codi.it("should set help text from dictionary", () => { - tabs.forEach((tab) => { - tab.title = mapp.dictionary[tab.dataset.id]; - codi.assertEqual(tab.title, mapp.dictionary[tab.dataset.id], "Title should be set from the dictionary"); - }); - }); - await codi.it("should handle tab click events", () => { - tabs.forEach((tab) => { - tab.click(); - codi.assertTrue(tab.classList.contains("active"), "Clicked tab should have the active class"); - tabs.forEach((otherTab) => { - if (otherTab !== tab) { - codi.assertFalse(otherTab.classList.contains("active"), "Other tabs should not have the active class"); - } - }); - const panel = document.getElementById(tab.dataset.id); - codi.assertTrue(panel.classList.contains("active"), "Corresponding panel should have the active class"); - tabPanels.forEach((otherPanel) => { - if (otherPanel !== panel) { - codi.assertFalse(otherPanel.classList.contains("active"), "Other panels should not have the active class"); - } - }); - }); - const layersTab2 = Array.from(tabs).find((tab) => tab.dataset.id === "layers"); - layersTab2.click(); - }); - const testTabView = mapp.ui.Tabview({ - node: tabview, - id: "tabview", - showTab: () => { - if (tabview.classList.contains("desktop-display-none")) { - tabview.classList.remove("desktop-display-none"); - document.body.style.gridTemplateRows = "auto 10px 50px"; - } - }, - removeLastTab: () => { - tabview.classList.add("desktop-display-none"); - document.body.style.gridTemplateRows = "auto 0 0"; - mapview.Map.getTargetElement().style.marginTop = 0; - } - }); - const btnColumn = document.getElementById("mapButton"); - const locales = await mapp.utils.xhr(`${mapp.host}/api/workspace/locales`); - const locale = await mapp.utils.xhr( - `${mapp.host}/api/workspace/locale?locale=${mapp.hooks.current.locale || locales[0]?.key}&layers=true` - ); - if (locale instanceof Error) { - mapp.ui.elements.dialog({ - css_style: "padding: 1em; border-color: #000", - content: mapp.dictionary.no_locales, - top: "50%", - left: "10%" - }); - } - if (locales.length > 1) { - const localesDropdown = mapp.ui.elements.dropdown({ - data_id: "locales-dropdown", - span: locale.name || locale.key, - entries: locales.map((locale2) => ({ - title: locale2.name || locale2.key, - key: locale2.key - })), - callback: (e, entry) => { - window.location.assign(`${mapp.host}?template=test_view&integrity=true&locale=${entry.key}`); - } - }); - layersTab.appendChild(mapp.utils.html.node`${localesDropdown}`); - } - await codi.it("should retrieve accessible locales from Workspace API", async () => { - codi.assertTrue(Array.isArray(locales), "Locales should be an array"); - codi.assertNotEqual(locales.length, 0, "Locales array should not be empty"); - }); - await codi.it("should retrieve locale with list of layers from Workspace API", async () => { - codi.assertFalse(locale instanceof Error, "Locale should not be an instance of Error"); - codi.assertTrue(locale.hasOwnProperty("name"), 'Locale should have a "name" property'); - codi.assertTrue(locale.hasOwnProperty("key"), 'Locale should have a "key" property'); - codi.assertTrue(locale.hasOwnProperty("layers"), 'Locale should have a "layers" property'); - }); - if (locale instanceof Error) { - await codi.it("should display an error dialog if locale is an instance of Error", async () => { - const errorDialog = document.querySelector(".dialog-modal"); - codi.assertNotEqual(errorDialog, null, "Error dialog should be appended to the document body"); - codi.assertEqual(errorDialog.textContent.trim(), mapp.dictionary.no_locales, "Error dialog should display the correct message"); - }); - } - if (locales.length > 1) { - await codi.it("should add locale dropdown to layers panel if multiple locales are accessible", async () => { - const dropdown = layersTab.querySelector('[data-id="locales-dropdown"]'); - codi.assertNotEqual(dropdown, null, "Locale dropdown should be appended to the layers tab"); - }); - } - if (!window.ol) - await mapp.utils.olScript(); - locale.syncPlugins ??= ["zoomBtn", "admin", "login"]; - mapview = await mapp.Mapview({ - host: mapp.host, - target: OL, - locale, - hooks: false, - scrollWheelZoom: true, - attribution: { - target: document.getElementById("Map"), - logo: mapp.utils.html.node` -
\n `,\n links: {\n [`XYZ v${mapp.version}`]: 'https://github.com/GEOLYTIX/xyz',\n ['SHA']: `https://github.com/GEOLYTIX/xyz/commit/${mapp.hash}`,\n Openlayers: 'https://openlayers.org',\n }\n },\n syncPlugins: locale.syncPlugins,\n svgTemplates: locale.svg_templates\n });\n\n\n if (!locale.layers?.length) {\n\n mapp.ui.elements.dialog({\n css_style: 'padding: 1em; border-color: #000;',\n content: mapp.dictionary.no_layers,\n target: document.getElementById('Map'),\n top: '50%',\n left: '50%'\n });\n\n }\n\n // Add layers to mapview.\n await mapview.addLayer(locale.layers);\n\n if (mapview.locale.gazetteer) {\n\n mapp.ui.Gazetteer(Object.assign(mapview.locale.gazetteer, {\n mapview,\n target: locationsTab.appendChild(mapp.utils.html.node`
`),\n }));\n\n } else {\n\n document.querySelector('[data-id=locations]').style.display = 'none'\n }\n\n // Create layers listview.\n mapp.ui.layers.listview({\n target: layersTab,\n mapview: mapview,\n });\n\n // Create locations listview.\n mapp.ui.locations.listview({\n target: locationsTab,\n mapview: mapview,\n });\n\n // Begin highlight interaction.\n mapview.interactions.highlight();\n\n // Select locations from hooks.\n mapp.hooks.current.locations.forEach((_hook) => {\n\n // Split location hook into layer key and id.\n const hook = _hook.split('!');\n\n // Get the location.\n // Will be added to listview in location panel.\n mapp.location.get({\n layer: mapview.layers[decodeURIComponent(hook[0])],\n id: hook[1],\n });\n });\n\n //Testcase: Create mapview\n await codi.it('should create a mapview', async () => {\n // Assert that mapview is created\n codi.assertNotEqual(mapview, undefined, 'Mapview should be created');\n\n // Assert that mapview has the expected properties\n codi.assertTrue(mapview.hasOwnProperty('host'), 'Mapview should have a \"host\" property');\n codi.assertTrue(mapview.hasOwnProperty('target'), 'Mapview should have a \"target\" property');\n codi.assertTrue(mapview.hasOwnProperty('locale'), 'Mapview should have a \"locale\" property');\n codi.assertTrue(mapview.hasOwnProperty('hooks'), 'Mapview should have a \"hooks\" property');\n codi.assertTrue(mapview.hasOwnProperty('scrollWheelZoom'), 'Mapview should have a \"scrollWheelZoom\" property');\n codi.assertTrue(mapview.hasOwnProperty('attribution'), 'Mapview should have an \"attribution\" property');\n });\n\n //Testcase: Add layers to mapview\n await codi.it('should add layers to mapview', async () => {\n // Assert that layers are added to mapview\n codi.assertTrue(Object.keys(mapview.layers).length > 0, 'Mapview should have layers');\n });\n\n //Testcase: Create a gazetteer if in locale\n await codi.it('should create a gazetteer if available in the locale', async () => {\n if (mapview.locale.gazetteer) {\n const gazetteer = locationsTab.querySelector('div');\n codi.assertNotEqual(gazetteer, null, 'Gazetteer should be created');\n } else {\n // Assert that the locations tab is hidden\n const locationsTabElement = document.querySelector('[data-id=locations]');\n codi.assertEqual(locationsTabElement.style.display, 'none', 'Locations tab should be hidden');\n }\n });\n\n //Testcase: Should create a layers listview\n await codi.it('should create a layers listview', async () => {\n // Assert that the layers listview is created\n const listview = layersTab.querySelector('div');\n codi.assertNotEqual(listview, null, 'Layers listview should be created');\n });\n\n //Testcase: Check for locations list view if gazetteer is present or if there is a selection\n if (mapview.locale.gazetteer) {\n await codi.it('should create a locations listview', async () => {\n // Assert that the locations listview is created\n const listview = locationsTab.querySelector('div');\n codi.assertNotEqual(listview, null, 'Locations listview should be created');\n });\n }\n\n //Testcase: Ensure mapview has highlight interaction.\n await codi.it('should begin highlight interaction', async () => {\n // Assert that highlight interaction is added to mapview\n codi.assertTrue(mapview.interactions.hasOwnProperty('highlight'), 'Mapview should have a \"highlight\" interaction');\n });\n\n // Configure idle mask if set in locale.\n mapp.user &&\n mapview.locale.idle &&\n mapp.ui.utils.idleLogout({\n host: mapp.host,\n idle: mapview.locale.idle,\n });\n\n // Append spacer for tableview\n btnColumn.appendChild(mapp.utils.html.node`\n
`);\n\n //Tests that have to run after everything else.\n\n //Testcase: Should show the tabview.\n await codi.it('should show the tabview when showTab is called', () => {\n // Add the 'desktop-display-none' class to the tabview\n tabview.classList.add('desktop-display-none');\n\n // Call the showTab function\n testTabView.showTab();\n\n // Assert that the 'desktop-display-none' class is removed from the tabview\n codi.assertFalse(tabview.classList.contains('desktop-display-none'), 'Tabview should not have the \"desktop-display-none\" class after showTab is called');\n\n // Assert that the grid template rows of the document body are set correctly\n codi.assertEqual(document.body.style.gridTemplateRows, 'auto 10px 50px', 'Grid template rows should be set to \"auto 10px 50px\" after showTab is called');\n });\n\n //Testcase: Should hide the tabview\n await codi.it('should hide the tabview when removeLastTab is called', () => {\n // Remove the 'desktop-display-none' class from the tabview\n tabview.classList.remove('desktop-display-none');\n\n // Call the removeLastTab function\n testTabView.removeLastTab();\n\n // Assert that the 'desktop-display-none' class is added to the tabview\n codi.assertTrue(tabview.classList.contains('desktop-display-none'), 'Tabview should have the \"desktop-display-none\" class after removeLastTab is called');\n\n\n\n // Assert that the grid template rows of the document body are set correctly\n codi.assertEqual(document.body.style.gridTemplateRows, 'auto 0px 0px', 'Grid template rows should be set to \"auto 0 0\" after removeLastTab is called');\n\n // Assert that the margin top of the map target element is set to 0\n codi.assertEqual(mapview.Map.getTargetElement().style.marginTop, '0px', 'Margin top of the map target element should be set to 0 after removeLastTab is called');\n });\n\n });\n\n return mapview;\n}", "export async function coreTest() {\n //API Tests\n await _mappTest.workspaceTest();\n await _mappTest.queryTest();\n const mapview = await _mappTest.base();\n await runAllTests(_mappTest.userTest);\n //Run Map Object test\n await runAllTests(_mappTest.mappTest);\n // Run the dictionary Tests\n await runAllTests(_mappTest.dictionaryTest, mapview);\n //Plugins Tests\n await runAllTests(_mappTest.pluginsTest);\n //Layer Tests\n await runAllTests(_mappTest.layerTest, mapview);\n //Location Tests\n await runAllTests(_mappTest.locationTest, mapview);\n //Mapview Tests\n await runAllTests(_mappTest.mapviewTest, mapview);\n //UI Elements Tests\n await runAllTests(_mappTest.ui_elementsTest, mapview);\n //Entries Tests\n await runAllTests(_mappTest.entriesTest, mapview);\n //UI Layers Tests\n await runAllTests(_mappTest.ui_layers, mapview);\n //UI tests\n await runAllTests(_mappTest.uiTest);\n //Format Tests\n await runAllTests(_mappTest.formatTest, mapview);\n //UI Locations Tests\n await runAllTests(_mappTest.ui_locations, mapview);\n //Utils Tests\n await runAllTests(_mappTest.utilsTest, mapview);\n}\n\n/**\n * This function is used to execute all the test functions on the exported test object. \n * @function runAllTests\n * @param {object} tests \n * @param {object} mapview \n */\nasync function runAllTests(tests, mapview) {\n const testFunctions = Object.values(tests).filter(item => typeof item === 'function');\n\n for (const testFn of testFunctions) {\n try {\n await testFn(mapview);\n } catch (error) {\n console.error(`Error in test ${testFn.name}:`, error);\n }\n }\n}", "export const mappTest = {\n base\n}\n\n/**\n * Function used to test the mapp objct to see if all the base objects * properties are present\n * @function base\n */\nfunction base() {\n codi.describe('Mapp base object test', () => {\n codi.it('Mapp: Ensure we have base objects', () => {\n codi.assertTrue(Object.hasOwn(mapp, 'ol', 'The mapp object needs to have an ol object'));\n codi.assertTrue(Object.hasOwn(mapp, 'version', 'The mapp object needs to have an version object'));\n codi.assertTrue(Object.hasOwn(mapp, 'hash', 'The mapp object needs to have an hash object'));\n codi.assertTrue(Object.hasOwn(mapp, 'host', 'The mapp object needs to have an host object'));\n codi.assertTrue(Object.hasOwn(mapp, 'language', 'The mapp object needs to have an language object'));\n codi.assertTrue(Object.hasOwn(mapp, 'dictionaries', 'The mapp object needs to have an dictionaries object'));\n codi.assertTrue(Object.hasOwn(mapp, 'dictionary', 'The mapp object needs to have an dictionary object'));\n codi.assertTrue(Object.hasOwn(mapp, 'hooks', 'The mapp object needs to have an hooks object'));\n codi.assertTrue(Object.hasOwn(mapp, 'layer', 'The mapp object needs to have an layer object'));\n codi.assertTrue(Object.hasOwn(mapp, 'location', 'The mapp object needs to have an location object'));\n codi.assertTrue(Object.hasOwn(mapp, 'Mapview', 'The mapp object needs to have an Mapview object'));\n codi.assertTrue(Object.hasOwn(mapp, 'utils', 'The mapp object needs to have an utils object'));\n codi.assertTrue(Object.hasOwn(mapp, 'plugins', 'The mapp object needs to have an plugins object'));\n });\n });\n}", "const views =\n{\n 'default': {\n lat: '0',\n long: '-7.081154551613622e-10'\n },\n 'london': {\n lat: '-14035.161399215933',\n long: '6708600.902178298'\n },\n 'sandton': {\n lat: '3123319.665346',\n long: '-3012437.111737'\n }\n}\n\nexport async function setView(mapview, z, view) {\n await mapview.Map.getView().setZoom(z);\n await mapview.Map.getView().setCenter([views[view].lat, views[view].long])\n}", "{\n \"group\": \"layer\",\n \"format\": \"wkt\",\n \"dbs\": \"NEON\",\n \"table\": \"test.scratch\",\n \"srid\": \"3857\",\n \"geom\": \"geom_3857\",\n \"qID\": \"id\"\n}", "{\n \"infoj\": [\n {\n \"title\": \"qID\",\n \"field\": \"id\",\n \"inline\": true\n },\n {\n \"type\": \"key\"\n },\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n },\n {\n \"title\": \"textarea\",\n \"field\": \"textarea\",\n \"edit\": true\n },\n {\n \"title\": \"char_field\",\n \"field\": \"char_field\"\n }\n ]\n}", "{\n \"style\": {\n \"default\": {\n \"strokeColor\": \"#333\",\n \"fillColor\": \"#fff9\",\n \"icon\": {\n \"type\": \"dot\"\n }\n },\n \"cluster\": {\n \"clusterScale\": 1\n },\n \"highlight\": {\n \"scale\": 1.3,\n \"strokeColor\": \"#090\"\n }\n }\n}", "/**\n * ## layer.decorateTest()\n * @module layer/decorateTest\n */\nimport { setView } from '../../utils/view.js';\nimport wkt_layer_default from '../../assets/layers/wkt/layer.json'\nimport wkt_infoj_default from '../../assets/layers/wkt/infoj.json'\nimport wkt_style_default from '../../assets/layers/wkt/style.json'\n\n/**\n * This function is used as an entry point for the decorateTest\n * - The main function of the test is to see how a layer is decorated from the raw .json of a workspace. \n * - The test setups with the following\n * 1. The layer gets the decorated_layer from the mapview.\n * 2. Then we get the workspace json from the test directory. \n * 3. We then assign a mapview to the layer.\n * 4. Then we perform the decorate on the layer.\n * @function decorateTest \n * @param {Object} mapview \n*/\nexport async function decorateTest(mapview, layer, infoj, style) {\n\n layer ??= wkt_layer_default;\n infoj ??= wkt_infoj_default;\n style ??= wkt_style_default;\n\n await setView(mapview, 2, 'default');\n\n await codi.describe('Layer: decorateTest', async () => {\n\n const infoj_skip = [\n 'textarea'\n ]\n\n layer = {\n mapview: mapview,\n ...infoj,\n infoj_skip: infoj_skip,\n ...style,\n ...layer\n }\n\n await mapp.layer.decorate(layer);\n\n /**\n * ### Should have a draw object\n * We check if the layer has a draw object\n * @function it\n */\n await codi.it('Should have a draw object', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'draw'), 'The layer should have a draw object by default')\n });\n\n /**\n * ### Should have a show function\n * 1. We check if a decorated layer has a show function\n * 2. We then execute the show() function on a layer.\n * 3. We expect the layer.display to now be true\n * @function it\n */\n await codi.it('Should have a show function', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'show'), 'The layer should have a show method by default');\n codi.assertTrue(typeof layer.display === 'undefined', 'The layer shouldn\\'t have a display flag');\n layer.show();\n codi.assertTrue(layer.display, 'The layer should now display true after displaying');\n });\n\n /**\n * ### Should have a hide function\n * 1. We check if the decorated layer has a hide function\n * 2. We execute the hide() function\n * 3. We check if the display is false\n * @function it\n */\n await codi.it('Should have a hide function', async () => {\n codi.assertTrue(Object.hasOwn(layer, 'hide'), 'The layer should have a hide method by default')\n layer.hide();\n codi.assertFalse(layer.display, 'The layer should display as false');\n });\n\n /**\n * ### Should not have an edit object\n * - The layer should not have an edit object as it's deprecated.\n * @function it\n */\n await codi.it('Should not have an edit object', async () => {\n codi.assertTrue(!layer.edit, 'The layer should not have an edit object as its been deprecated.')\n });\n\n /**\n * ### Should add the `skipEntry` flag to the textArea entry\n * - We check if the textArea entry on the decorate layer has the skipEntry flag.\n * @function it\n */\n await codi.it('Should add the skipEntry flag to the textArea entry', async () => {\n layer.infoj.filter(entry => entry.field === 'textarea').forEach(entry => {\n codi.assertTrue(entry.skipEntry, 'The layer should have a hide method by default')\n });\n });\n\n await setView(mapview, 11, 'london');\n\n /**\n * ### Should get `test.public` table at zoom level 11.\n * 1. We call the `tableCurrent()` function.\n * 2. We assert that the table returned is zool level 11.\n */\n await codi.it('Should get test.public table at zoom level 11', async () => {\n const table = layer.tableCurrent();\n codi.assertTrue(typeof table === 'string');\n });\n\n /**\n * ### Should get `geom_3857` at zoom level 11\n * 1. We call the `geomCurrent()` function.\n * 2. We then assert that the name of the geometry is geom_3857\n * @function it\n */\n await codi.it('Should get geom_3857 geom at zoom level 11', async () => {\n const geom = layer.geomCurrent();\n codi.assertTrue(typeof geom === 'string', 'The geometry should be returned from the layer')\n });\n\n /**\n * ### Should be able to zoomToExtent\n * 1. We call the `zoomToExtent()` function.\n * 2. We assert that the return is a success.\n */\n await codi.it('Should be able to zoomToExtent', async () => {\n const success = await layer.zoomToExtent();\n codi.assertTrue(success, 'We should see the layer zoom to extent')\n });\n\n });\n}", "import { setView } from '../../utils/view.js';\nexport async function fadeTest(mapview) {\n await setView(mapview, 2, 'default');\n await codi.describe('TODO: Layer: fadeTest', async () => {\n await codi.it('Should should test for something', () => {\n console.warn('The Fade module needs to be re-reviewed.')\n });\n });\n}", "export async function featureFieldsTest() {\n await codi.describe('TODO: Layer: featureFieldsTest', async () => {\n await codi.it('The fields array on on a theme should not be duplicated', () => {\n\n const layer = {\n params: {\n default_fields: ['zIndex']\n },\n style: {\n theme: {\n field: 'field_22',\n fields: [\n 'field_00',\n 'field_01',\n 'field_02',\n 'field_03',\n 'field_04',\n 'field_05',\n 'field_06',\n 'field_07',\n 'field_08',\n 'field_09',\n 'field_10',\n 'field_11',\n 'field_12',\n 'field_13',\n 'field_14',\n 'field_15',\n 'field_16',\n 'field_17',\n 'field_18',\n 'field_19',\n 'field_20',\n 'field_21',\n 'field_22',\n 'field_22',\n 'field_23'\n ]\n },\n label: { field: 'another_field' },\n icon_scaling: {\n field: 'another_field'\n },\n cluser: {\n label: 'another_field'\n }\n }\n }\n\n const featureArray = mapp.layer.featureFields.fieldsArray(layer);\n\n codi.assertNoDuplicates(featureArray);\n\n });\n });\n}", "export async function featureFormatsTest() {\n codi.describe('Layer: featureFormatsTest', () => {\n const mapview = {\n srid: '3857'\n }\n\n const layer = {\n format: 'wkt',\n params: {\n fields: [\n 'size'\n ]\n },\n style: {\n icon_scaling: {\n field: 'size'\n },\n hover: {\n field: 'id'\n }\n },\n mapview\n }\n\n const wktFeatures = [\n [\n 1,\n 'POINT(-14400 6710852)',\n null\n ],\n [\n 2,\n 'POINT(-14920 6711046)',\n 10\n ],\n [\n 3,\n 'POINT(-15322 6710796)',\n 15\n ]\n ]\n\n const geojsonFeatures = [\n {\n 'type': 'Feature',\n 'id': 1,\n 'properties': {\n 'id': 1,\n 'name': 'Central Park',\n 'type': 'Park',\n 'city': 'New York',\n 'size': 100\n },\n 'geometry': {\n 'type': 'Polygon',\n 'coordinates': [[\n [-73.968285, 40.785091],\n [-73.968285, 40.764891],\n [-73.949318, 40.764891],\n [-73.949318, 40.785091],\n [-73.968285, 40.785091]\n ]]\n }\n },\n {\n 'type': 'Feature',\n 'id': 2,\n 'properties': {\n 'id': 2,\n 'name': 'Empire State Building',\n 'type': 'Building',\n 'size': 200\n },\n 'geometry': {\n 'type': 'Point',\n 'coordinates': [-73.985428, 40.748817]\n }\n },\n {\n 'type': 'Feature',\n 'id': 3,\n 'properties': {\n 'id': 3,\n 'name': 'Broadway',\n 'type': 'Road',\n 'size': 300\n },\n 'geometry': {\n 'type': 'LineString',\n 'coordinates': [\n [-73.987381, 40.758896],\n [-73.986030, 40.757355],\n [-73.984442, 40.755823],\n [-73.982940, 40.754274]\n ]\n }\n }\n ]\n\n /**\n * @description WKT: Test style.icon_scaling\n * @function it\n */\n codi.it('WKT: Test style.icon_scaling', () => {\n\n mapp.layer.featureFormats[layer.format](layer, wktFeatures)\n\n codi.assertEqual(layer.style.icon_scaling.max, 15, 'The Icon scaling max should equal to 15')\n });\n\n /**\n * @description WKT: featureFormats test\n * @function it\n */\n codi.it('WKT: featureFormats test', () => {\n\n const assertIDArray = [1, 2, 3];\n const assertSizeArray = [null, 10, 15];\n const features = mapp.layer.featureFormats[layer.format](layer, wktFeatures)\n\n //Check id's and size values are correct\n features.forEach((feature, index) => {\n codi.assertEqual(feature.values_.id, assertIDArray[index]);\n codi.assertEqual(feature.values_.size, assertSizeArray[index]);\n });\n\n });\n\n /**\n * @description geojson: featureFormats test\n * @function it\n */\n codi.it('geojson: featureFormats test', () => {\n layer.format = 'geojson';\n\n const assertIDArray = [1, 2, 3];\n const assertSizeArray = [100, 200, 300];\n const features = mapp.layer.featureFormats[layer.format](layer, geojsonFeatures)\n\n //Check id's and size values are correct\n features.forEach((feature, index) => {\n codi.assertEqual(feature.values_.id, assertIDArray[index]);\n codi.assertEqual(feature.values_.size, assertSizeArray[index]);\n });\n\n });\n });\n}\n", "export async function featureHoverTest() {\n codi.describe('TODO: Layer: featureHoverTest', () => {\n codi.it('Should should test for something', () => {\n //TODO\n });\n });\n}\n", "/**\n * ## queryTest()\n * @module lib/layer/featureStyle\n */\n\n/**\n * This function is used to test the query API endpoint\n * @function featureStyleTest\n * @param {Object} mapview \n*/\nexport async function featureStyleTest(mapview) {\n await codi.describe('TODO: Layer: featureStyleTest', async () => {\n //TODO\n });\n}", "export async function styleParserTest(mapview) {\n await codi.describe('TODO: Layer: styleParserTest', async () => {\n // const workspace = await mapp.utils.xhr(`/test/tests/workspace.json`);\n // const layer = workspace.locale.layers['styleParser'];\n // layer.key = 'Style Parser Test';\n // await mapp.layer.styleParser(layer);\n\n // await codi.it('The Layer should have a default object', () => {\n // codi.assertTrue(!!layer.style.default, 'The Layer should always have a default object')\n // });\n\n // await codi.it('The parser should remove the hover object, and add it into the layer.style object', () => {\n // codi.assertTrue(!layer.hover, 'The layer shouldnt have a layer.hover object')\n // codi.assertTrue(!!layer.style.hover, 'The layer should have a layer.style.hover object')\n // });\n\n // await codi.it('The parse should remove the label property if both labels and label are present', () => {\n // codi.assertTrue(!layer.style.label, 'The layer shouldnt have a layer.style.label object')\n // codi.assertTrue(!!layer.style.labels, 'The layer should have a layer.style.labels object')\n // });\n\n console.warn('The Style parse modules need to be broken up and exported for easier testability');\n });\n}", "/**\n * ## layerTest{}\n * The layer test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module layer \n */\n\n/**\n * @typedef {Object} layerTest\n * @property {decorateTest} decorateTest\n * @property {Function} fadeTest\n * @property {Function} featureFieldsTest\n * @property {Function} featureFormatsTest\n * @property {Function} featureHoverTest\n * @property {Function} featureStyleTest\n * @property {Function} styleParserTest\n */\nimport { decorateTest } from './decorate.test.mjs';\nimport { fadeTest } from './fade.test.mjs';\nimport { featureFieldsTest } from './featureFields.test.mjs';\nimport { featureFormatsTest } from './featureFormats.test.mjs';\nimport { featureHoverTest } from './featureHover.test.mjs';\nimport { featureStyleTest } from './featureStyle.test.mjs';\nimport { styleParserTest } from './styleParser.test.mjs';\n\nexport const layerTest = {\n decorateTest,\n fadeTest,\n featureFieldsTest,\n featureFormatsTest,\n featureHoverTest,\n featureStyleTest,\n styleParserTest\n};", "\n/**\n * This test is used to see if all the language options at least have all of these base entries.\n * @function baseDictionaryTest\n */\nexport async function baseDictionaryTest() {\n await codi.describe('All languages should have the same base language entries', async () => {\n\n const base_dictionary = {\n save: '',\n cancel: '',\n confirm_delete: '',\n invalid_geometry: '',\n no_results: '',\n };\n\n for (const language of Object.keys(mapp.dictionaries)) {\n await codi.it(`${language} dictionary should have all the base keys`, () => {\n for (const key of Object.keys(base_dictionary)) {\n codi.assertTrue(!!mapp.dictionaries[language][key], `${language} should have ${key}`);\n }\n });\n }\n });\n}", "\n/**\n * @description This test is used to see if the key value dictionary is working correctly\n * @function keyValueDictionaryTest\n */\nexport async function keyValueDictionaryTest(mapview) {\n await codi.describe('Key Value Dictionary Tests', async () => {\n\n await codi.it('should replace the key value dictionary for default value on a layer', () => {\n // Get the OSM layer from the mapview\n const osm = mapview.locale.layers.find(layer => layer.key === 'OSM');\n // Check the OSM layer has the correct name\n codi.assertEqual(osm.name, 'OpenStreetMap KeyValue Dictionary');\n });\n\n await codi.it('should replace the key value dictionary for default value in an infoj', () => {\n // Get the changeEnd layer from the mapview\n const changeEnd = mapview.locale.layers.find(layer => layer.key === 'changeEnd');\n // Check the changeEnd infoj entry of field textarea has the correct title\n const entry = changeEnd.infoj.find(entry => entry.field === 'textarea');\n // Check the changeEnd infoj entry of field textarea has the correct title\n codi.assertEqual(entry.title, 'TextArea KeyValue Dictionary');\n\n });\n\n await codi.it('should not replace the key value dictionary for an array', () => {\n // Get the changeEnd layer from the mapview\n const changeEnd = mapview.locale.layers.find(layer => layer.key === 'changeEnd');\n // Check the changeEnd test_array has the correct value\n const array = changeEnd.test_array\n const expected = ['TEST KEYVALUE'];\n\n // Check the changeEnd infoj entry of field textarea has the correct array value\n codi.assertEqual(array, expected);\n });\n });\n}\n", "/**\n * This test is used to see if the mapp.language exists in the dictionaries object.\n * If not, it should return a warning and default to 'en'.\n * @function unknownLanguageTest\n */\nexport async function unknownLanguageTest() {\n // Describe the test\n await codi.describe('Language TEST should default language to English', async () => {\n\n // The language was set to 'TEST' in _test.html, which is not a valid language\n\n // Assert that the language has been reset to 'en'\n await codi.it('Should default to English', () => {\n codi.assertEqual(mapp.language, 'en');\n });\n });\n}\n", "/**\n * ## dictionaryTest{}\n * The dictionary test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module dictionaries \n */\n\n/**\n * @typedef {Object} dictionaryTest\n * @property {baseDictionaryTest} baseDictionaryTest \n * @property {keyValueDictionaryTest} keyValueDictionaryTest\n */\nimport { baseDictionaryTest } from './baseDictionary.test.mjs';\nimport { keyValueDictionaryTest } from './keyValueDictionary.test.mjs';\nimport { unknownLanguageTest } from './unknownLanguageTest.test.mjs';\n\nexport const dictionaryTest = {\n baseDictionaryTest,\n keyValueDictionaryTest,\n unknownLanguageTest\n};", "export async function createTest() {\n\n // codi.describe('TODO: Location: createTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "/**\n * This test is used to test the mapp.location.get function\n * @function getTest \n * @param {object} mapview \n */\nexport async function getTest(mapview) {\n await codi.describe('Location: getTest', async () => {\n\n const location_layer = mapview.layers['location_get_test'];\n\n const location_layer_no_infoj = mapview.layers['location_get_test_no_infoj'];\n\n /**\n * This tests the functionality to mock a location by passing in a template that returns values from the query\n * @function it\n */\n await codi.it('We should be able to mock a location get.', async () => {\n\n //Get the location with the id returned from the query above\n const location = await mapp.location.get({\n layer: location_layer,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertEqual(location.infoj.length, 4, 'We expect to see three infoj entries');\n codi.assertEqual(location.record.hook, 'location_get_test!6', 'We expect a hook made up of layer key and id');\n codi.assertTrue(location.layer instanceof Object, 'The location needs a layer object');\n\n // Push removeCallback method to remove callback methods.\n location.removeCallbacks.push(_this => delete _this.removeCallbacks)\n\n location.remove()\n\n codi.assertTrue(!location.record.hook, 'The hook should be removed from the location record.');\n\n codi.assertTrue(!location.removeCallbacks, 'removeCallbacks should have removed themselves.');\n });\n\n /**\n * This tests that no location is returned if no infoj is provided\n * @function it\n */\n await codi.it('Location get should return undefined if location.layer.info is undefined.', async () => {\n\n //Get the location with the id returned from the query above\n const location = await mapp.location.get({\n layer: location_layer_no_infoj,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertEqual(location, undefined, 'The Location should be undefined');\n\n });\n\n /**\n * This tests that no location is returned if no infoj is provided\n * @function it\n */\n await codi.it('The getInfoj method should return an infoj if none is provided on the layer present.', async () => {\n\n //Get the location with the id returned from the query above\n const infoj = await mapp.location.getInfoj({\n layer: location_layer_no_infoj,\n getTemplate: 'get_location_mock',\n id: 6,\n });\n\n codi.assertTrue(infoj !== undefined, 'The Location should be undefined');\n });\n });\n}", "export async function nnearestTest() {\n codi.describe('TODO: Location: nnearestTest', () => {\n codi.it('Should should test for something', () => {\n //TODO\n });\n });\n}\n\n", "import { createTest } from './create.test.mjs';\nimport { getTest } from './get.test.mjs';\nimport { nnearestTest } from './nnearest.test.mjs';\n\nexport const locationTest = {\n createTest,\n getTest,\n nnearestTest\n};", "\n/**\n* This is the add layer test module for the mapview. \n * @module lib/mapview/addLayer\n*/\n\n/**\n * The entry point test that is used to test the add layer module for a mapview. \n * @param {Object} mapview \n * @function addLayerTest\n */\nexport async function addLayerTest(mapview) {\n await codi.describe('Mapview: addLayerTest', async () => {\n\n /**\n * This test is used to check if we can add a single layer to the mapview.\n * @function it\n */\n await codi.it('Add single layer to mapview.', async () => {\n\n const layer = {\n 'format': 'tiles',\n 'URI': 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'\n }\n\n const layers = await mapview.addLayer(layer)\n\n codi.assertEqual(layers.length, 1, 'We expect to see 1 layer being returned from getLayers method.');\n codi.assertTrue(layers[0].show instanceof Function, 'The decorated layer has a show method.');\n codi.assertTrue(Object.hasOwn(mapview.layers, layers[0].key), 'The layer has been added to the mapview.');\n });\n\n /**\n * This test is used to check if we can add multiple layers to the mapview.\n * @function it\n */\n await codi.it('Add multiple layer to mapview.', async () => {\n\n const layer = {\n 'format': 'tiles',\n 'URI': 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'\n }\n\n const layers = await mapview.addLayer([layer, layer])\n\n codi.assertEqual(layers.length, 2, 'We expect to see 2 layer being returned from getLayers method.');\n codi.assertTrue(layers[0].show instanceof Function, 'The first decorated layer has a show method.');\n codi.assertTrue(Object.hasOwn(mapview.layers, layers[0].key), 'The first layer has been added to the mapview.');\n });\n });\n}", "export async function allfeaturesTest() {\n // await codi.describe('TODO: Mapview: allfeaturesTest', async () => {\n // await codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n}\n", "export async function attributionTest() {\n\n // codi.describe('TODO: Mapview: attributionTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function fitViewTest() {\n\n // codi.describe('TODO: Mapview: fitViewTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function geoJSONTest() {\n\n // codi.describe('TODO: Mapview: geoJSONTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function geometryTest() {\n\n // codi.describe('TODO: Mapview: geometryTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function getBoundsTest() {\n\n // codi.describe('TODO: Mapview: getBoundsTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function infotipTest() {\n\n // codi.describe('TODO: Mapview: infotipTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "export async function locateTest() {\n\n // codi.describe('TODO: Mapview: locateTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // })\n\n}\n", "export async function popupTest() {\n\n // codi.describe('TODO: Mapview: popupTest', () => {\n // codi.it('Should should test for something', () => {\n // //TODO\n // });\n // });\n\n}\n", "\nexport async function olControlsTest(mapview) {\n await codi.describe('Mapview', async () => {\n await codi.it('The Mapview should have controls', () => {\n codi.assertTrue(mapview.controls.length >= 1, 'The ol controls array should be greater or equal to 1');\n });\n });\n};", "import { addLayerTest } from './addLayer.test.mjs';\nimport { allfeaturesTest } from './allfeatures.test.mjs';\nimport { attributionTest } from './attribution.test.mjs';\nimport { fitViewTest } from './fitView.test.mjs';\nimport { geoJSONTest } from './geojson.test.mjs';\nimport { geometryTest } from './geometry.test.mjs';\nimport { getBoundsTest } from './getBounds.test.mjs';\nimport { infotipTest } from './infotip.test.mjs';\nimport { locateTest } from './locate.test.mjs';\nimport { popupTest } from './popup.test.mjs';\nimport { olControlsTest } from './olcontrols.test.mjs';\n\nexport const mapviewTest = {\n olControlsTest,\n addLayerTest,\n allfeaturesTest,\n attributionTest,\n fitViewTest,\n geoJSONTest,\n geometryTest,\n getBoundsTest,\n infotipTest,\n locateTest,\n popupTest\n}", "\n/**\n * This test is used to see if the link_button plugin is working as expected.\n * @function linkButtonTest\n */\nexport function linkButtonTest() {\n codi.describe('Link Button Test', () => {\n codi.it('Should add a link button to the mapButton panel', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"TITLE HERE\")\n const linkButton = mapButton.querySelector('a[title=\"TITLE HERE\"]');\n\n // Check if the linkButton has the correct href\n codi.assertEqual(linkButton.getAttribute('href'), '/url/url');\n });\n\n codi.it('Should not add a button if no href is provided', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"SHOULD NOT BE ADDED AS NO HREF\")\n const linkButton = mapButton.querySelector('a[title=\"SHOULD NOT BE ADDED AS NO HREF\"]');\n\n // Check if the linkButton does not exist\n codi.assertTrue(!linkButton);\n });\n\n codi.it('Should add multiple buttons if the link_button config is an array', () => {\n // Get the mapButton element\n const mapButton = document.getElementById('mapButton');\n // Get the link_button from the mapButton (a tag with the title=\"TITLE HERE\")\n const linkButton = mapButton.querySelector('a[title=\"TITLE HERE\"]');\n\n const linkButton2 = mapButton.querySelector('a[title=\"WILL BE ADDED AS HREF\"]');\n\n // Check if the linkButton has the correct href\n codi.assertEqual(linkButton.getAttribute('href'), '/url/url');\n\n // Check if the linkButton2 has the correct href\n codi.assertEqual(linkButton2.getAttribute('href'), '/url/url2');\n });\n\n });\n}", "/**\n * ## pluginsTest{}\n * The plugins test modules are exported as an object to be used in the local.test.mjs module in the browser tests\n * @module plugins \n */\n\n/**\n * @typedef {Object} pluginsTest\n * @property {linkButtonTest} linkButtonTest \n */\nimport { linkButtonTest } from './link_button.test.mjs';\n\nexport const pluginsTest = {\n linkButtonTest\n};", "/**\n * ## workspaceTest()\n * @module mod/workspace\n */\n\n/**\n * This function is used as an entry point for the changeEndTest\n * This function is also in a function as to not execute in the CLI environment and only execute in a browser.\n * @function workspaceTest \n * @param {Object} mapview \n*/\nexport async function workspaceTest(mapview) {\n\n await codi.describe('Workspace: Testing Workspace API', async () => {\n\n await codi.it('Workspace: Getting Locales', async () => {\n const locales = await mapp.utils.xhr(`/test/api/workspace/locales`);\n codi.assertEqual(locales[0].key, 'locale', 'Ensure that we are getting a locale back from the API')\n });\n\n await codi.it('Workspace: Getting a Locale', async () => {\n const locale = await mapp.utils.xhr(`/test/api/workspace/locale?locale=locale`);\n codi.assertTrue(!!locale.key, 'The locale should have a key property');\n codi.assertTrue(!!locale.layers, 'The locale should have layers');\n codi.assertTrue(!!locale.name, 'The locale should have a name');\n codi.assertTrue(!!locale.plugins, 'The locale should have plugins');\n codi.assertTrue(!!locale.syncPlugins, 'The locale should have syncPlugins');\n });\n\n await codi.it('Workspace: Getting template_test Layer', async () => {\n let layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test`);\n codi.assertEqual(layer.key, 'template_test', 'Ensure that we get the template_test layer from the API')\n codi.assertTrue(!!layer.table, 'Ensure that the layer has a table');\n codi.assertTrue(!!layer.geom, 'Ensure that the layer has a geom');\n codi.assertTrue(!!layer.group, 'Ensure that the layer has a group');\n codi.assertEqual(layer.infoj.length, 7, 'The infoj should always have 7 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n\n layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test`);\n codi.assertEqual(layer.infoj.length, 7, 'The infoj should always have 7 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n codi.assertTrue(!!layer.err, 'The layer should have a error array')\n codi.assertEqual(layer.err.length, 1, 'There should be on failure on the layer');\n });\n\n await codi.it('Workspace: Getting template_test_vanilla Layer', async () => {\n const layer = await mapp.utils.xhr(`/test/api/workspace/layer?layer=template_test_vanilla`);\n codi.assertEqual(layer.key, 'template_test_vanilla', 'Ensure that we get the template_test_vanilla layer from the API')\n codi.assertEqual(layer.infoj.length, 6, 'The infoj should always have 6 infoj entries')\n codi.assertTrue(!!layer.style, 'The layer needs to have a style object from another template')\n });\n\n await codi.it('Workspace: Getting Roles', async () => {\n const roles = await mapp.utils.xhr(`/test/api/workspace/roles`);\n\n const expected_roles = ['A', 'B', 'C', 'test', 'super_test']\n codi.assertEqual(roles, expected_roles, 'Ensure that we get the correct roles from the API')\n });\n\n await codi.it('Should return an array of roles as defined in the workspace', async () => {\n const response = await fetch('api/workspace/roles');\n const roles = await response.json();\n // Check the response is an array\n codi.assertTrue(Array.isArray(roles));\n\n // Check the response contains 'A', 'B', 'C'\n await codi.it('Roles should contain A', async () => {\n codi.assertTrue(roles.includes('A'));\n });\n\n await codi.it('Roles should contain B', async () => {\n\n codi.assertTrue(roles.includes('B'));\n });\n\n await codi.it('Roles should contain C', async () => {\n codi.assertTrue(roles.includes('C'));\n\n });\n\n // Check the response does not contain the reserved role '*'\n await codi.it('Roles should not contain *', async () => {\n codi.assertTrue(!roles.includes('*'));\n });\n });\n\n await codi.it('Should return an object of workspace roles with definitions', async () => {\n const response = await fetch('api/workspace/roles?detail=true');\n const roles = await response.json();\n // Check the response is an object\n codi.assertTrue(typeof roles === 'object');\n\n await codi.it('Roles object should contain A with value = Text about A', async () => {\n // Check the object contains 'A' role with text' Text about A'\n codi.assertTrue(roles.A === 'Text about A');\n });\n\n await codi.it('Roles object should contain B with value = Text about A', async () => {\n // Check the object contains 'B' role with text' Text about B'\n codi.assertTrue(roles.B === 'Text about B');\n });\n\n await codi.it('Roles object should contain C with value = {}', async () => {\n // Check the object contains 'C' role as an object\n // this is as its not added to the roles object in the workspace\n // So it gets added as an object \n codi.assertTrue(typeof roles.C === 'object');\n });\n\n await codi.it('Roles object should not contain *', async () => {\n // Check the reserved role '*' is not included in the object\n codi.assertTrue(!roles['*']);\n });\n });\n\n await codi.it('Workspace: Testing the test endpoint', async () => {\n let workspace_test = await mapp.utils.xhr(`/test/api/workspace/test`);\n\n const counts = {\n errors: workspace_test.errors.length,\n overwritten_templates: workspace_test.overwritten_templates.length,\n unused_templates: workspace_test.unused_templates.length,\n usage: Object.keys(workspace_test.usage).length\n }\n\n codi.assertTrue(workspace_test.errors.length > 0, 'The errors array needs to have more than 1 entry')\n codi.assertTrue(workspace_test.overwritten_templates.length > 0, 'The overwritten templates array needs to have more than 1 entry')\n codi.assertTrue(workspace_test.unused_templates.length > 0, 'The unsused templates array needs to have more than 1 entry')\n codi.assertTrue(Object.keys(workspace_test.usage).length > 0, 'The usage object needs to have keys')\n\n workspace_test = await mapp.utils.xhr(`/test/api/workspace/test`);\n\n codi.assertEqual(workspace_test.errors.length, counts.errors, 'The errors array needs to have the same number of entries we did the first run')\n codi.assertEqual(workspace_test.overwritten_templates.length, counts.overwritten_templates, 'The overwritten templates array needs to have the same number of entries we did the first run')\n codi.assertEqual(workspace_test.unused_templates.length, counts.unused_templates, 'The unused templates array needs to have the same number of entries we did the first run')\n codi.assertEqual(Object.keys(workspace_test.usage).length, counts.usage, 'The usage templates object needs to have the same number of entries we did the first run')\n });\n });\n}", "\n/**\n * ## queryTest()\n * @module mod/query\n */\n\n/**\n * This function is used to test the query API endpoint\n * @function querytest \n * @param {Object} mapview \n*/\nexport async function queryTest() {\n\n\n await codi.describe('Query: Testing Query API', async () => {\n /**\n * @description Query: Testing Query defined on infoj entry\n * @function it \n */\n await codi.it('Query: Testing Query defined on infoj entry', async () => {\n const expected_result = [1, 2, 5, 3, 4];\n const results = await mapp.utils.xhr(`/test/api/query?template=data_array`);\n codi.assertEqual(results, expected_result, 'We should be able to just call the template even if its not part of the workspace.templates object in configuration');\n });\n /**\n * @description Query: Testing Module defined in templates\n * @function it \n */\n await codi.it('Query: Testing Module defined in templates', async () => {\n const expected_result = {\n 'bar': 'foo'\n }\n const results = await mapp.utils.xhr(`/test/api/query?template=module_test`);\n codi.assertEqual(results, expected_result, 'The Module should return the basic query');\n });\n\n /**\n * @description Query: Testing a query with a bogus dbs string via the req params\n * @function it \n */\n await codi.it('Query: Testing a query with a bogus dbs string via the req params', async () => {\n const expected_result = {\n 'bar': 'foo'\n }\n const results = await mapp.utils.xhr(`/test/api/query?template=module_test&dbs=bogus`);\n codi.assertEqual(results, expected_result, 'The Module should return the basic query');\n });\n\n /**\n * @description Query: Testing a query with a bogus dbs on the template\n * @function it \n */\n await codi.it('Query: Testing a query with a bogus dbs on the template', async () => {\n const results = await mapp.utils.xhr(`/test/api/query?template=bogus_data_array`);\n codi.assertTrue(results instanceof Error, 'We should return an error for a bogus DBS connection');\n });\n });\n}", "\n/**\n * ## user.updateTest()\n * @module user/update\n */\n\n/**\n * This function is used as an entry point for the changeEndTest\n * @function updateTest \n*/\nexport async function updateTest() {\n\n if (mapp.user) {\n await codi.describe('User: update', async () => {\n\n /**\n * ### update endpoint should be able to process a body\n * The user update endpoint should be able to take a body as the request.\n * @function it\n */\n await codi.it('update endpoint should be able to process a body', async () => {\n\n let params = {\n url: '/test/api/user/update',\n body: JSON.stringify(\n {\n email: 'test@geolytix.co.uk',\n admin: false,\n approved: false,\n verified: false\n }\n )\n };\n\n await mapp.utils.xhr(params);\n\n params = {\n url: '/test/api/user/update',\n body: JSON.stringify(\n {\n email: 'test@geolytix.co.uk',\n admin: true,\n approved: true,\n verified: false\n }\n )\n }\n\n await mapp.utils.xhr(params);\n\n const acl = await mapp.utils.xhr('/test/api/user/list');\n const test_user = acl.filter(user => user.email === 'test@geolytix.co.uk')[0];\n\n await codi.assertEqual(test_user.email, 'test@geolytix.co.uk', 'The users email address should be test@geolytix.co.uk')\n await codi.assertFalse(test_user.verified, 'The user should be not verified')\n await codi.assertTrue(test_user.admin, 'The user should an admin')\n await codi.assertTrue(test_user.approved, 'The user should be approved')\n\n });\n\n /**\n ### update endpoint should be able to be just params\n * The user update endpoint should be able to take a body as the request.\n * @function it\n */\n await codi.it('update endpoint should be able to be just params', async () => {\n\n const url = `/test/api/user/update?email=test@geolytix.co.uk&field=admin&value=false`\n await mapp.utils.xhr(url);\n\n const acl = await mapp.utils.xhr('/test/api/user/list');\n const test_user = acl.filter(user => user.email === 'test@geolytix.co.uk')[0];\n\n await codi.assertEqual(test_user.email, 'test@geolytix.co.uk', 'The users email address should be test@geolytix.co.uk')\n await codi.assertFalse(test_user.verified, 'The user should be not verified')\n await codi.assertFalse(test_user.admin, 'The user should an admin')\n await codi.assertTrue(test_user.approved, 'The user should be approved')\n\n });\n\n });\n }\n}", "import { updateTest } from './update.test.mjs';\n\nexport const userTest = {\n updateTest\n}", "/**\n * ## layer.decorateTest()\n * @module ui/elements/slider\n */\n/**\n * This function is used as an entry point for the sliderTest\n * This test is used to test the creation of the slider ui element.\n * **Note: I still want to figure out event management for these elements to trigger the oninput function to simulate sliding the element**\n * @function sliderTest \n*/\nexport async function sliderTest() {\n await codi.describe('UI elements: slider', async () => {\n await codi.it('Should return the slider', async () => {\n //get the workspace from the local files\n const workspace = await mapp.utils.xhr(`/test/tests/workspace.json`);\n const layer = workspace.locale.layers['input_slider'];//Get the input slider layer that we can get the params for.\n\n const input_slider_params = layer.infoj.filter(entry => entry.field === 'integer_field');\n //Getting the params for the slider\n const input_slider = mapp.ui.elements.slider(input_slider_params[0]);\n\n //Getting the creating input slider element and asserting the exected value\n const input_slider_element = input_slider.getElementsByTagName('input')[1];\n const assert_input = ``;\n codi.assertEqual(input_slider_element.outerHTML, assert_input, 'We expect to see the input defined in the test');\n });\n });\n}", "\n/**\n * ## layer.layerStyleTest()\n * @module ui/elements/layerStyle\n */\n/**\n * This function is used as an entry point for the layerStyleTest\n * This test is used to test the creation of the style panel ui elements.\n * @function layerStyleTest \n*/\nexport async function layerStyleTest(mapview) {\n await codi.describe('UI elements: layerStyle', async () => {\n //Style object that we will use to create the entire panel\n const style = {\n opacitySlider: true,\n cluster: {\n clusterScale: 5\n },\n icon_scaling: {\n field: 'size',\n icon: true,\n clusterScale: true,\n zoomInScale: true,\n zoomOutScale: true\n },\n hover: {\n display: true,\n title: 'Hover title',\n field: 'hover_1',\n label: 'I am a hover label'\n },\n hovers: {\n hover_1: {\n title: 'Hover title',\n field: 'hover_1',\n display: true,\n label: 'I am a hover label'\n },\n hover_2: {\n title: 'Hover title 2',\n field: 'hover_2',\n display: true,\n label: 'I am a hover label'\n }\n },\n label: 'label_2',\n labels: {\n label_1: {\n title: 'Label title',\n display: true,\n field: 'label_1',\n label: 'I am labels label'\n },\n label_2: {\n title: 'Label title 2',\n display: true,\n field: 'label_2',\n label: 'I am a labels label'\n }\n },\n theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n },\n themes: {\n first_theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n },\n second_theme: {\n title: 'Theme title',\n type: 'categorized',\n field: 'foo',\n other: true,\n categories: [\n {\n key: 'category_1',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_2',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n },\n {\n key: 'category_3',\n style: {\n strokeColor: '#000',\n fillColor: '#000',\n fillOpacity: 0.5,\n strokeWidth: 3\n }\n }\n ]\n }\n }\n };\n\n //get the workspace from the local files\n const layer = await mapview.layers['location_get_test'];\n\n //This will be defaulted on decorated layers. \n //We need to remove this for new elements to be passed in on the panel function.\n delete layer.style.elements;\n\n //spreading the style to the layer style object\n layer.style = { ...layer.style, ...style };\n\n //Calling the panel function to create the panel with the layers style\n const panel = await mapp.ui.elements.layerStyle.panel(layer);\n\n //Opacity Slider\n await codi.it('The panel function should return a opacitySlider', async () => {\n const opacitySlider = panel.querySelector('[data-id=\"opacitySlider\"]')\n codi.assertTrue(!!opacitySlider, 'The panel should have a opacitySlider');\n });\n\n //Hover checkbox \n await codi.it('The panel function should return a hover check box', () => {\n const hoverCheckBox = panel.querySelector('[data-id=\"hoverCheckbox\"]');\n codi.assertTrue(!!hoverCheckBox, 'The panel should have a hoverCheckBox');\n });\n\n //hovers dropdown\n await codi.it('The panel function should return a hovers dropdown', () => {\n const hoversDropDown = panel.querySelector('[data-id=\"hoversDropdown\"]');\n codi.assertTrue(!!hoversDropDown, 'The panel should have a hoversDropdown');\n });\n\n //layer theme\n await codi.it('The panel function should return a layerTheme', () => {\n const layerTheme = panel.querySelector('[data-id=\"layerTheme\"]');\n codi.assertTrue(!!layerTheme, 'The panel should have a layerTheme');\n });\n\n //Themes dropdown\n await codi.it('The panel function should return a themes dropdown', () => {\n const themesDropdown = panel.querySelector('[data-id=\"themesDropdown\"]');\n codi.assertTrue(!!themesDropdown, 'The panel should have a themes dropdown');\n });\n\n //icon scaling checkbox\n await codi.it('The panel function should return an icon scaling field checkbox', () => {\n const iconScalingFieldCheckBox = panel.querySelector('[data-id=\"iconScalingFieldCheckbox\"]');\n codi.assertTrue(!!iconScalingFieldCheckBox, 'The panel should have an icon scaling field check box');\n });\n\n //icon scaling slider\n await codi.it('The panel function should return an icon scaling slider', () => {\n const iconScalingSlider = panel.querySelector('[data-id=\"iconScalingSlider\"]');\n codi.assertTrue(!!iconScalingSlider, 'The panel should have an icon scaling slider');\n });\n\n //icon scaling cluster slider\n await codi.it('The panel function should return an icon scaling cluster slider', () => {\n const iconScalingClusterSlider = panel.querySelector('[data-id=\"iconScalingClusterSlider\"]');\n codi.assertTrue(!!iconScalingClusterSlider, 'The panel should have an icon scaling cluser slider');\n });\n\n //icon scaling zoom in slider\n await codi.it('The panel function should return an icon scaling zoom in slider', () => {\n const iconScalingZoomInSlider = panel.querySelector('[data-id=\"iconScalingZoomInSlider\"]');\n codi.assertTrue(!!iconScalingZoomInSlider, 'The panel should have an icon scaling zoom in slider');\n });\n\n //icon scaling zoom out slider\n await codi.it('The panel function should return an icon scaling zoom out slider', () => {\n const iconScalingZoomOutSlider = panel.querySelector('[data-id=\"iconScalingZoomOutSlider\"]');\n codi.assertTrue(!!iconScalingZoomOutSlider, 'The panel should have an icon scaling zoom out slider');\n });\n });\n}", "/**\n * ## layer.changeEndTest()\n * @module ui/elements/pills\n */\n\n\n/**\n * This is the entry function for the pills test.\n * @function pillsTest\n */\nexport async function pillsTest() {\n await codi.describe('UI Elements: Pills', async () => {\n //creating the pills component without any params\n const pillsComponent = mapp.ui.elements.pills();\n\n /**\n * We should be able to create a pills component with 0 params\n * We check if there is an add/remove function on the returned componenent.\n * We also check if we have a pills set\n * @fucntion it\n */\n await codi.it('Should create pills', () => {\n codi.assertTrue(typeof pillsComponent.add === 'function', 'The pills needs to have an add function');\n codi.assertTrue(typeof pillsComponent.remove === 'function', 'The pills needs to have an add function');\n codi.assertTrue(typeof pillsComponent.pills === 'object', 'The pills needs to have a pills object');\n });\n\n /**\n * Testing if we can add pills with the add function.\n * @function it\n */\n await codi.it('We should be able to add pills', () => {\n pillsComponent.add('pill');\n codi.assertTrue(pillsComponent.pills.size === 1, 'We should have 1 pill in the pills set');\n });\n\n /**\n * Testing if we can remove a pill with the remove function.\n * @function it \n */\n await codi.it('We should be able to remove pills', () => {\n pillsComponent.remove('pill');\n codi.assertTrue(pillsComponent.pills.size === 0, 'We should have 1 pill in the pills set');\n });\n\n });\n}\n", "/**\n * ## layer.decorateTest()\n * @module ui/elements/alert\n */\n/**\n * This function is used to test the alert method\n * @function alertTest \n*/\nexport async function alertTest() {\n await codi.describe('UI elements: Alert', async () => {\n\n // Test providing params\n await codi.describe('Should create an alert with params provided', async () => {\n const alert = await mapp.ui.elements.alert({ title: 'ALERT TITLE', text: 'ALERT TEXT' });\n\n codi.assertTrue(alert !== undefined, 'We expect to see the alert element');\n\n await codi.it('Should have a title of ALERT TITLE', async () => {\n // Get the alert title\n const alert_title = alert.title;\n codi.assertEqual(alert_title, 'ALERT TITLE', 'We expect to see the alert title');\n\n });\n\n await codi.it('Should have a text of ALERT TEXT', async () => {\n // Get the alert text\n const alert_text = alert.text;\n codi.assertEqual(alert_text, 'ALERT TEXT', 'We expect to see the alert text');\n })\n // Close the alert \n alert.close();\n\n });\n\n // Test providing no params\n await codi.describe('Should create an alert with no params provided', async () => {\n const alert = await mapp.ui.elements.alert({});\n\n codi.assertTrue(alert !== undefined, 'We expect to see the alert element');\n\n await codi.it('Should have a title of Information', async () => {\n // Get the alert title\n const alert_title = alert.title;\n codi.assertEqual(alert_title, 'Information', 'We expect to see the alert title');\n\n });\n\n await codi.it('Should have no text', async () => {\n // Get the alert text\n const alert_text = alert.text;\n codi.assertEqual(alert_text, undefined, 'We expect to see no alert text');\n })\n // Close the alert \n alert.close();\n\n });\n\n });\n}", "/**\n * ## layer.decorateTest()\n * @module ui/elements/confirm\n */\n/**\n * This function is used to test the confirm method\n * @function confirmTest \n*/\nexport async function confirmTest() {\n await codi.describe('UI elements: Confirm', async () => {\n\n // Test providing params\n await codi.describe('Should create a confirm dialog with params provided', async () => {\n mapp.ui.elements.confirm({ title: 'CONFIRM TITLE', text: 'CONFIRM TEXT', data_id: 'confirm-test' });\n\n // Get the confirm element\n\n const confirm = document.querySelector('[data-id=confirm-test]');\n codi.assertTrue(confirm !== undefined, 'We expect to see the confirm element');\n\n await codi.it('Should have a title of CONFIRM TITLE', async () => {\n // Get the confirm title\n const confirm_title = confirm.querySelector('h4').textContent;\n codi.assertEqual(confirm_title, 'CONFIRM TITLE', 'We expect to see the confirm title');\n\n });\n\n await codi.it('Should have a text of CONFIRM TEXT', async () => {\n // Get the confirm text\n const confirm_text = confirm.querySelector('p').textContent;\n codi.assertEqual(confirm_text, 'CONFIRM TEXT', 'We expect to see the confirm text');\n })\n\n // Get the confirm buttons\n const confirm_buttons = confirm.querySelectorAll('button');\n\n await codi.it('Should have an OK button', async () => {\n codi.assertEqual(confirm_buttons[0].innerText, 'OK', 'We expect to see the OK button');\n })\n\n await codi.it('Should have a Cancel button', async () => {\n codi.assertEqual(confirm_buttons[1].innerText, 'Cancel', 'We expect to see the Cancel button');\n });\n\n // Close the confirm \n confirm.remove();\n\n });\n\n // Test providing no params\n await codi.describe('Should create a confirm dialog with no params provided', async () => {\n mapp.ui.elements.confirm({ data_id: 'confirm-test' });\n\n // Get the confirm element\n const confirm = document.querySelector('[data-id=confirm-test]');\n codi.assertTrue(confirm !== undefined, 'We expect to see the confirm element');\n\n await codi.it('Should have a title of Information', async () => {\n // Get the confirm title\n const confirm_title = confirm.querySelector('h4').textContent;\n codi.assertEqual(confirm_title, 'Confirm', 'We expect to see the confirm title');\n\n });\n\n await codi.it('Should have no text', async () => {\n // Get the confirm text\n const confirm_text = confirm.querySelector('p').textContent;\n codi.assertEqual(confirm_text, '', 'We expect to see no confirm text');\n })\n\n // Get the confirm buttons\n const confirm_buttons = confirm.querySelectorAll('button');\n\n await codi.it('Should have an OK button', async () => {\n codi.assertEqual(confirm_buttons[0].innerText, 'OK', 'We expect to see the OK button');\n })\n\n await codi.it('Should have a Cancel button', async () => {\n codi.assertEqual(confirm_buttons[1].innerText, 'Cancel', 'We expect to see the Cancel button');\n });\n\n // Close the confirm \n confirm.remove();\n\n });\n\n });\n}", "\n/**\n * This function is used to test the dialog ui element.\n * @function dialogTest\n */\nexport function dialogTest() {\n codi.describe('UI Elements: dialog/modal', () => {\n\n const params = {\n target: document.getElementById('Map'),\n closeBtn: true,\n data_id: 'dialog-test',\n headerDrag: true,\n header: 'I am a header',\n content: 'I am so content',\n top: '5em',\n left: '5em',\n contained: true\n };\n\n /**\n * We should be able to create a basic dialog with some params\n * @function it\n */\n codi.it('Should create a basic dialog', () => {\n\n const dialog = mapp.ui.elements.dialog({ ...params });\n\n /**\n * The dialog should be able to close\n * @function it\n */\n codi.it('Dialog should be able to close', () => {\n dialog.close();\n const dialog_element = document.querySelector('[data-id=\"dialog-test\"]')\n codi.assertEqual(dialog_element, null, 'The dialog should be removed from the DOM on close');\n });\n\n /**\n * The dialog should be able to be shown again\n * @function it\n */\n codi.it('Dialog should be able to be shown again', () => {\n dialog.show();\n const dialog_element = document.querySelector('[data-id=\"dialog-test\"]')\n codi.assertEqual(dialog_element, dialog.node, 'The dialog should be in the DOM again');\n });\n\n dialog.close();\n });\n\n /**\n * Created dialog should not call show method\n * @function it\n */\n codi.it('Should recreate a basic dialog', () => {\n\n params.new = true;\n const new_params = { ...params }\n\n const dialog = mapp.ui.elements.dialog(new_params);\n dialog.close();\n\n const new_dialog = mapp.ui.elements.dialog(new_params);\n\n codi.assertEqual(dialog, new_dialog, 'The dialog should be recreated');\n\n new_dialog.close();\n });\n\n /**\n * Created dialog should have minimize/maximize functionality\n * @function it\n */\n codi.it('Should create a dialog that can minimize/maximize', () => {\n\n params.minimizeBtn = true;\n const new_params = { ...params }\n\n const dialog = mapp.ui.elements.dialog(new_params);\n\n dialog.node.querySelector('header > button.mask-icon.minimize-btn').dispatchEvent(new Event('click'))\n let minimized = dialog.node.classList.contains('minimized');\n codi.assertTrue(minimized, 'The dialog content should not be visible');\n\n dialog.node.querySelector('header > button.mask-icon.minimize-btn').dispatchEvent(new Event('click'))\n minimized = dialog.node.classList.contains('minimized');\n codi.assertFalse(minimized, 'The dialog content should not be visible');\n\n dialog.close();\n });\n\n });\n}", "import { sliderTest } from './slider.test.mjs';\nimport { layerStyleTest } from './layerStyle.test.mjs'\nimport { pillsTest } from './pills.test.mjs';\nimport { alertTest } from './alert.test.mjs';\nimport { confirmTest } from './confirm.test.mjs';\nimport { dialogTest } from './dialog.test.mjs';\n\nexport const ui_elementsTest = {\n sliderTest,\n layerStyleTest,\n pillsTest,\n alertTest,\n confirmTest,\n dialogTest\n};", "/**\n * This is the entry point function for the ui/layers/filters test\n * @function filtersTest \n * @param {object} mapview \n */\nexport async function filtersTest(mapview) {\n await codi.describe('UI Layers: Filters test', async () => {\n\n //Creating the filter to be used in other tests\n const filter = {\n field: 'id',\n minmax_query: 'minmax_query'\n };\n\n //Getting a layer\n const layer = mapview.layers['location_get_test'];\n\n /**\n * This function is used to test a custom minmax query\n * This query is by design returning 100 & 500 as min max\n * @function it\n */\n await codi.it('Numeric Filter: minmax_query test', async () => {\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '100', 'The min should return 100.');\n codi.assertEqual(maxInput.value, '500', 'The max should return 500');\n });\n\n /**\n * Testing providing an explicit min value on the filter.\n * @function it\n */\n await codi.it('Numeric Filter: min value specified', async () => {\n\n filter['min'] = 200;\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '200', 'The min should return 200.');\n codi.assertEqual(maxInput.value, '500', 'The max should return 500');\n\n //Delete the lte value of the current filter otherwise it will not be changed in the next test\n await mapp.ui.layers.filters.removeFilter(layer, filter);\n\n //Delete the min value from the filter\n delete filter.min;\n });\n\n /**\n * Testing providing an explicit max value on the filter.\n * @function it\n */\n await codi.it('Numeric Filter: max value specified', async () => {\n\n filter['max'] = 1000;\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '100', 'The min should return 100.');\n codi.assertEqual(maxInput.value, '1000', 'The max should return 1000');\n });\n\n /**\n * Testing providing a layer.current as explicit values.\n * @function it\n */\n await codi.it('Numeric Filter: layer.current specified as `lte: 200` and `gte: 800`', async () => {\n\n layer.filter.current[filter.field].lte = 800\n layer.filter.current[filter.field].gte = 200\n\n const numericFilter = await mapp.ui.layers.filters.numeric(layer, filter);\n const minInput = numericFilter.querySelector('div > input[type=range]:nth-child(3)');\n const maxInput = numericFilter.querySelector('div > input[type=range]:nth-child(4)');\n\n codi.assertEqual(minInput.value, '200', 'The min should return 200.');\n codi.assertEqual(maxInput.value, '800', 'The max should return 800');\n\n await mapp.ui.layers.filters.removeFilter(layer, filter)\n\n codi.assertEqual(layer.filter.current, {}, 'The filter of the layer should be cleared');\n\n });\n });\n}", "/**\r\n * @module lib/ui/elements/layers/panels/filters\r\n */\r\n/**\r\n * This is the entry point function for the ui/layers/panels/filter test\r\n * @function panelFilterTest\r\n */\r\nexport function panelFilterTest() {\r\n\r\n codi.describe('UI Layers Panels: Filter', () => {\r\n /**\r\n * This function is used to test the creation of a filter panel\r\n * @function it\r\n */\r\n codi.it('Create a filter panel', () => {\r\n const layer = {\r\n reload: () => { },\r\n mapview: {\r\n Map: {\r\n getTargetElement: () => { return document.getElementById('Map') }\r\n }\r\n },\r\n key: 'panel_test',\r\n filter: {\r\n current: {}\r\n },\r\n infoj: [\r\n {\r\n 'field': 'field_1',\r\n 'filter': 'like',\r\n 'type': 'text'\r\n },\r\n {\r\n 'field': 'field_2',\r\n 'type': 'numeric',\r\n 'filter': {\r\n 'type': 'integer'\r\n }\r\n }\r\n ]\r\n }\r\n\r\n const filterPanel = mapp.ui.layers.panels.filter(layer)\r\n\r\n const filterPanelDropDown = filterPanel.querySelector('[data-id=panel_test-filter-dropdown]')\r\n\r\n const drop_down_elements = filterPanelDropDown.querySelector('ul');\r\n\r\n codi.assertEqual(drop_down_elements.children.length, 2, 'We expect two entries into the dropdown from the infoj')\r\n\r\n filterPanel.querySelector('ul').children[0].dispatchEvent(new Event('click'))\r\n\r\n codi.assertEqual(filterPanel.querySelector('ul').children[0].classList.contains('selected'), true, 'Expect an element to be selected')\r\n\r\n const resetButton = filterPanel.querySelector('[data-id=resetall]')\r\n\r\n layer.filter.current['field_1'] ??= { 'like': 'a' }\r\n\r\n resetButton.dispatchEvent(new Event('click'))\r\n\r\n codi.assertEqual(layer.filter.current, {}, ' `layer.current.filter` should be empty')\r\n\r\n });\r\n });\r\n}", "export function delayFunction(delay) {\n return new Promise(resolve => {\n setTimeout(resolve, delay);\n });\n}", "\n/**\n * \n * @module /ui/layers/view\n */\n\nimport { setView } from '../../../utils/view.js';\nimport { delayFunction } from '../../../utils/delay.js';\n\n/**\n * This function is used as an entry point for the changeEndTest\n * @function viewTest \n * @param {Object} mapview \n*/\nexport async function viewTest(mapview) {\n\n await setView(mapview, 2, 'default');\n\n await codi.describe('UI Layers: viewTest', async () => {\n\n /**\n * ### should dispatch the event and the layer should not display\n * 1. We create the `changeEnd` event and dispatch it.\n * 2. We assert that the `layer.display` is not set to true.\n * @function it\n */\n await codi.it('should dispatch the event and the layer should not display.', async () => {\n const layer = mapview.layers['changeEnd'];\n const changeEndEvent = new Event('changeEnd');\n const target = layer.mapview.Map.getTargetElement();\n\n target.dispatchEvent(changeEndEvent);\n\n await codi.assertFalse(layer.display, 'The changeEnd() layer should not display at the default zoom level.')\n\n await delayFunction(1000);\n });\n\n /**\n * ### should display at zoom level 6.\n * 1. The Test sets the mapview to London at zoom level 11.\n * 2. Creates the `changeEnd` event and dispatches it.\n * 3. And asserts that the `layer.display` is true.\n * @function it\n */\n await codi.it('should display at zoom level 6', async () => {\n await setView(mapview, 11, 'london')\n const layer = mapview.layers['changeEnd'];\n const changeEndEvent = new Event('changeEnd');\n const target = layer.mapview.Map.getTargetElement();\n\n target.dispatchEvent(changeEndEvent);\n codi.assertTrue(layer.display, 'The changeEnd() layer should display at zoom level 6');\n await delayFunction(1000);\n });\n });\n}", "import { filtersTest } from './filters.test.mjs';\nimport { panelFilterTest } from './panels/filter.test.mjs'\nimport { viewTest } from './view.test.mjs';\n\nexport const ui_layers = {\n filtersTest,\n panelFilterTest,\n viewTest\n}", "export async function mockLocation(mapview) {\n const locationLayer = mapview.layers['location_get_test'];\n return await mapp.location.get({\n layer: locationLayer,\n getTemplate: 'get_location_mock',\n id: 999,\n });\n}", "import { mockLocation } from '../../../../utils/location.js';\n/**\n * ## locations.entries.pinTest()\n * @module ui/elements/pinTest\n */\n/**\n * This test is used to test the creation of the pin ui element.\n * @function pinTest \n*/\nexport async function pinTest(mapview) {\n await codi.describe('UI elements: pin', async () => {\n await codi.it('Needs to be able to create a pin element with a scale of 4', async () => {\n\n //Set the one pin style to have a scale of 4\n mapview.layers['location_get_test'].infoj.find(entry => entry.type === 'pin').style ??= { icon: { scale: 4 } };\n\n //Mock the location\n const location = await mockLocation(mapview);\n\n //Get the pinEntry from the location\n const pinEntry = location.infoj.filter(entry => entry.type === 'pin')[0];\n\n codi.assertTrue(!!pinEntry.style, 'The pinEntry needs to have a style object');\n codi.assertTrue(!!pinEntry.style.icon, 'The pinEntry needs to have an icon assigned to the style');\n codi.assertEqual(pinEntry.style.icon.scale, 4, 'The pinEntry needs to have an scale property on the icon set to 4');\n\n //remove the location\n location.removeCallbacks.push(_this => delete _this.removeCallbacks);\n location.remove();\n });\n });\n}", "/**\n * @module lib/ui/locations/entries/geometries \n */\n\n/**\n * Entry point for the geometry test module\n * @function geometryTest \n * @param {object} mapview \n */\nexport async function geometryTest(mapview) {\n await codi.describe('UI Entries: Geometry', async () => {\n const entry = {\n mapview: mapview,\n key: 'geometry-test',\n value: {\n type: 'Point',\n coordinates: '0101000020110F000065D98262C7490CC10DF78253F7B75D41',\n },\n srid: 3856,\n display: true,\n location: {\n layer: {\n mapview: mapview\n },\n Layers: []\n }\n }\n\n /**\n * @description Should return geometry checkbox\n * @function it\n */\n await codi.it('Should return geometry checkbox', async () => {\n\n const geometryCheckBox = mapp.ui.locations.entries.geometry(entry);\n codi.assertTrue(!!geometryCheckBox, 'A checkbox needs to be returned');\n });\n\n /**\n * @description Should return 0 if no entry value is provided\n * @function it\n */\n await codi.it('Should return 0 if no entry value is provided', async () => {\n entry.value = null;\n const geometryCheckBox = await mapp.ui.locations.entries.geometry(entry);\n codi.assertTrue(typeof geometryCheckBox === 'undefined', 'We need to get no geometry checkbox returned');\n });\n })\n}", "import { delayFunction } from '../../../../utils/delay.js';\n\n/**\n * @description Test module for the ui/locations/entries/layer module\n * @module lib/ui/locations/entries/layer\n */\n\n/**\n * @description Entry point for the entries layer test module\n * @function layerTest\n */\n\nimport { setView } from '../../../../utils/view.js';\n\nexport async function layerTest(mapview) {\n await codi.describe('Layer Entry Test', async () => {\n const entry = {\n mapview: mapview,\n zIndex: 99,\n location: {\n hook: 'entry_layer!23',\n removeCallbacks: []\n },\n 'key': 'test_layer',\n 'label': 'entry_layer',\n 'type': 'layer',\n 'display': 'true',\n 'layer': 'mvt_test'\n };\n\n /**\n * @function it\n * A basic layer should be created from a entry.type = layer\n */\n await codi.it('We should get a basic layer entry', async () => {\n await mapp.ui.locations.entries.layer(entry);\n //Need to delay for async functions \n await delayFunction(1000);\n codi.assertTrue(Object.keys(mapview.layers[entry.key]).length > 0, 'We should see the unique layer being added to the mapview')\n entry.location.removeCallbacks?.forEach(fn => fn instanceof Function && fn(this));\n //Need to delay for async functions \n await delayFunction(1000);\n codi.assertTrue(typeof mapview.layers[entry.key] === 'undefined', 'We should see the unique layer being removed from the mapview')\n });\n\n /**\n * @function it\n * The layer entry should fail, with warning if the layer doesnt exist in the mapview\n */\n await codi.it('Layer entry should fail with warning', async () => {\n entry.layer = 'bogus_layer'\n await mapp.ui.locations.entries.layer(entry);\n //Need to delay for async functions \n codi.assertTrue(!mapview.layers[entry.key], 'Should warn about an undefined layer')\n\n entry.layer = 'mvt_test'\n });\n\n /**\n * @function it\n * The entry.layer should have a layer toggle if tables is defined\n * \n */\n await codi.it('Layer entry should adhere to zoom restrictions', async () => {\n\n const newEntry = {\n mapview: mapview,\n zIndex: 99,\n location: {\n hook: 'entry_layer!23',\n removeCallbacks: []\n },\n 'key': 'test_layer',\n 'label': 'entry_layer',\n 'type': 'layer',\n 'display': 'true',\n 'layer': 'mvt_test',\n 'tables': {\n '12': null,\n '13': 'test.mvt_test'\n }\n };\n\n //Zoom out\n await setView(mapview, 11, 'london');\n\n await mapp.ui.locations.entries.layer(newEntry);\n\n //Need to delay for async functions \n await delayFunction(1000);\n\n codi.assertTrue(mapview.layers[newEntry.key].display_toggle.classList.contains('disabled'), 'Toggle should be disabled')\n\n //Zoom in\n await setView(mapview, 14, 'london');\n\n codi.assertFalse(!mapview.layers[newEntry.key].display_toggle.classList.contains('disabled'), 'Toggle should be enabled')\n\n });\n });\n}", "import { pinTest } from './pin.test.mjs';\nimport { geometryTest } from './geometry.test.mjs';\nimport { layerTest } from './layer.test.mjs';\n\nexport const entriesTest = {\n pinTest,\n geometryTest,\n layerTest\n}", "/**\n * This test is used to test the tabview functions\n * @function Tabview \n */\nexport async function Tabview() {\n // await codi.describe('UI Test: Tabview', async () => {\n // console.warn('These tests need to be rewritten');\n // });\n};", "import { Tabview } from './Tabview.test.mjs';\n\nexport const uiTest = {\n Tabview\n}", "/**\n * @module utils/numericFormatter\n */\n\n/**\n * This function is used as an entry point for the numericFormatter Test\n * @function numericFormatterTest\n */\nexport function numericFormatterTest() {\n\n codi.describe('Utils: numericFormatter Test', () => {\n const params = {\n value: 654321.987,\n prefix: '$',\n formatterParams: {\n locale: 'en-UK'\n }\n };\n\n const expected_unformated_value = 654321.99\n let expected_formated_value = '$654,321.99'\n /**\n * ### Should format UK locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised UK string.\n * @function it\n */\n codi.it('Should format UK locale Numeric Values', () => {\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n /**\n * ### Should unformat UK locale string\n * This test is used to check if a localised string to UK returns the correct string.\n * @function it\n */\n codi.it('Should unformat UK locale strings', () => {\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n /**\n * ### Should format DE locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised DE string.\n * @function it\n */\n codi.it('Should format DE locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'DE';\n expected_formated_value = '$654.321,99'\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n /**\n * ### Should unformat DE locale string\n * This test is used to check if a localised string to DE returns the correct string.\n * @function it\n */\n codi.it('Should unformat DE locale strings', () => {\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n\n /**\n * ### Should format PL locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised PL string.\n * @function it\n */\n codi.it('Should format PL locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'PL';\n expected_formated_value = '$654\u00A0321,99'\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n\n codi.it('Should unformat PL locale strings', () => {\n mapp.utils.formatNumericValue(params);\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n\n /**\n * ### Should format RUB locale Numeric Values\n * This test is used to check if a numeric value gets formatted to the correct localised PL string.\n * @function it\n */\n codi.it('Should format RUB locale Numeric Values', () => {\n //Settings the locale to 'DE'\n params.formatterParams.locale = 'RUB';\n expected_formated_value = '$654,321.99';\n\n const formattedValue = mapp.utils.formatNumericValue(params);\n codi.assertEqual(formattedValue, expected_formated_value, `We expect the value to equal ${expected_formated_value}, we received ${formattedValue}`)\n });\n\n codi.it('Should unformat RUB locale strings', () => {\n mapp.utils.formatNumericValue(params);\n\n const unformattedString = mapp.utils.unformatStringValue(params)\n codi.assertEqual(unformattedString, expected_unformated_value, `We expect the value to equal ${expected_unformated_value}, we received ${unformattedString}`)\n });\n });\n}", "/**\n * @module utils/merge\n */\n\n/**\n * This function is used to test the merge function\n * @function mergeTest\n */\nexport async function mergeTest() {\n\n await codi.describe('Utils: mergeTest Test', async () => {\n\n await codi.it('Hobbies should be overwritten in the merge', async () => {\n const target = {\n name: 'Rob',\n age: 28,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['squash', 'guitar'],\n };\n\n const source = {\n name: 'Rob',\n age: 26,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['cooking'],\n };\n\n const expected = {\n name: 'Rob',\n age: 26,\n address: {\n street: '6 fourteenth street',\n city: 'Johannesburg',\n },\n hobbies: ['cooking'],\n };\n\n const mergedObj = mapp.utils.merge(target, source);\n\n codi.assertEqual(mergedObj, expected)\n });\n\n await codi.it('should handle merging with null or undefined values', async () => {\n const target = {\n name: 'John',\n age: 30,\n };\n\n const source1 = null;\n const source2 = undefined;\n\n const expected = {\n name: 'John',\n age: 30,\n };\n\n const mergedObj1 = mapp.utils.merge(target, source1);\n const mergedObj2 = mapp.utils.merge(target, source2);\n\n codi.assertEqual(mergedObj1, expected);\n codi.assertEqual(mergedObj2, expected);\n });\n\n await codi.it('should prevent _proto merging', async () => {\n const target = {\n current: {\n 'country': {\n 'in': ['ROI']\n }\n }\n };\n\n const source = {\n current: {\n 'country': {\n 'in': ['UK']\n }\n },\n __proto__: {\n 'polluted': 'polluted'\n }\n };\n\n const expected = {\n current: {\n 'country': {\n 'in': ['ROI']\n }\n }\n };\n\n const mergedObj1 = mapp.utils.merge(target, source);\n codi.assertEqual(mergedObj1, expected, 'The merge should not happen if a __proto__ is found on an object');\n });\n\n });\n}", "/**\r\n * @module utils/paramString\r\n */\r\n\r\n/**\r\n * This function is used as an entry point for the paramString Test\r\n * @function paramStringTest\r\n */\r\nexport async function paramStringTest() {\r\n\r\n await codi.describe('Utils: paramString Test', async () => {\r\n\r\n /**\r\n * ### Should Return an empty string as nothing is in params\r\n * This test is used to check that paramString returns an empty string if no params are supplied\r\n * @function it\r\n */\r\n await codi.it('Should return empty param string', async () => {\r\n\r\n const params = null;\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, '', `We expect the value to equal '', we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return an urlencoded string with the given params\r\n * This test is used to check that paramString returns a correctly urlencoded string containing the provided params\r\n * @function it\r\n */\r\n await codi.it('Should return urlencoded string', async () => {\r\n\r\n const params = {\r\n id: 1,\r\n name: 'test',\r\n age: '29 ',\r\n viewport: true,\r\n template: {'in': {'id':1}}\r\n }\r\n\r\n const expectedValue = 'id=1&name=test&age=29%20&viewport=true&template=%7B%22in%22%3A%7B%22id%22%3A1%7D%7D'\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, expectedValue, `We expect the value to equal ${expectedValue}, we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return an urlencoded string with the given params, excluding failing parameters\r\n * This test is used to check that paramString returns a correctly urlencoded string containing the provided params,\r\n * without the params that are invalid\r\n * @function it\r\n */\r\n await codi.it('Should return urlencoded string, excluding null and undefined values', async () => {\r\n\r\n const params = {\r\n id: null,\r\n name: undefined,\r\n age: '29 ',\r\n viewport: [],\r\n template: {}\r\n }\r\n\r\n const expectedValue = 'age=29%20'\r\n const formattedValue = mapp.utils.paramString(params);\r\n codi.assertEqual(formattedValue, expectedValue, `We expect the value to equal ${expectedValue}, we received ${formattedValue}`)\r\n });\r\n \r\n });\r\n}", "/**\r\n * @module utils/queryParams\r\n */\r\n\r\nimport { setView } from '../../utils/view.js';\r\n\r\n/**\r\n * This function is used as an entry point for the queryParams Test\r\n * @function queryParamsTest\r\n */\r\nexport async function queryParamsTest(mapview) {\r\n\r\n await codi.describe('Utils: queryParams Test', async () => {\r\n\r\n const location_layer = mapview.layers['query_params_layer'];\r\n\r\n //Get the location\r\n const location = await mapp.location.get({\r\n layer: location_layer,\r\n getTemplate: 'get_location_mock',\r\n id: 6,\r\n });\r\n\r\n const params = {\r\n layer: location_layer,\r\n queryparams: {\r\n layer: location_layer,\r\n table: 'fake_table',\r\n },\r\n };\r\n\r\n await setView(mapview, 2, 'default');\r\n\r\n /**\r\n * ### Should Return undefined\r\n * This test is used to check that queryParams returns undefined if queryparams is null/undefined\r\n * @function it\r\n */\r\n await codi.it('Should return undefined with null queryparams', async () => {\r\n\r\n const null_params = {};\r\n const formattedValue = mapp.utils.queryParams(null_params);\r\n codi.assertEqual(formattedValue, undefined, `We expect the value to equal undefined, we received ${formattedValue}`)\r\n });\r\n\r\n /**\r\n * ### Should Return qID and id \r\n * This test is used to check that queryParams returns the correct field values for id and qID when supplied.\r\n * @function it\r\n */\r\n await codi.it('Should return id, qID', async () => {\r\n\r\n params.queryparams.id = true\r\n params.queryparams.qID = true\r\n params.location = location\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.id, 6, `We expect the value to equal 6, we received ${queryParams.id}`)\r\n codi.assertEqual(queryParams.qID, '_id', `We expect the value to equal id, we received ${queryParams.qID}`)\r\n });\r\n\r\n /**\r\n * ### Should Return lat, lng and z parameters in the response\r\n * This test is used to check that queryParams returns latitude, longitude and zoom level when requested.\r\n * @function it\r\n */\r\n await codi.it('Should return lat, lng, z', async () => {\r\n\r\n params.queryparams.center = true\r\n params.queryparams.z = true\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.lng, 0, `We expect the value to equal 0, we received ${queryParams.lng}`)\r\n codi.assertEqual(queryParams.lat, 0, `We expect the value to equal 0, we received ${queryParams.lat}`)\r\n codi.assertTrue(!!queryParams.z, `We expect the zoom level to be returned from the method`)\r\n });\r\n\r\n /**\r\n * ### Should Return locale, template and layer parameters in the response\r\n * This test is used to check that queryParams returns locale, template and layer when requested.\r\n * @function it\r\n */\r\n await codi.it('Should return locale, template, layer', async () => {\r\n\r\n params.query = 'not_real'\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.template, params.query, `We expect the value to equal ${params.query}, we received ${queryParams.template}`)\r\n codi.assertEqual(queryParams.locale, 'locale', `We expect the value to equal 0, we received ${queryParams.locale}`)\r\n codi.assertEqual(queryParams.layer, location_layer.key, `We expect the value to equal ${location_layer.key}, we received ${queryParams.layer}`)\r\n });\r\n\r\n /**\r\n * ### Should Return viewport and filter\r\n * This test is used to check that queryParams returns viewport and filter when requested\r\n * @function it\r\n */\r\n await codi.it('Should return viewport, filter', async () => {\r\n\r\n params.viewport = true\r\n params.queryparams.filter = true\r\n\r\n const queryParams = mapp.utils.queryParams(params)\r\n codi.assertEqual(queryParams.viewport.length, 5, `We expect the value to have 5 params, we received ${queryParams.viewport.length}`)\r\n codi.assertEqual(queryParams.filter, {}, `We expect the value to equal {'id':{}}, we received ${JSON.stringify(queryParams.filter)}`)\r\n });\r\n\r\n // Push removeCallback method to remove callback methods.\r\n location.removeCallbacks.push(_this => delete _this.removeCallbacks)\r\n\r\n location.remove()\r\n\r\n });\r\n}", "/**\n * @module lib/utility/compose\n */\n\n/**\n * @description This is used as an entry point for the compose utility test\n * @function composeTest \n */\nexport function composeTest() {\n codi.describe('Compose Test', () => {\n\n /**\n * ### Should compose functions from left to right\n * @function it\n */\n codi.it('Should compose functions from left to right', () => {\n //Different functions to use\n const addOne = x => x + 1;\n const double = x => x * 2;\n const square = x => x * x;\n\n //Creating the compose chain\n const composed = mapp.utils.compose(addOne, double, square);\n\n codi.assertEqual(composed(3), 64, 'We expect this order of opperation when composing functions left to right : ((3 + 1) * 2)^2 = 64');\n });\n\n /**\n * ### Should work with a single function\n * @function it\n */\n codi.it('Should work with a single function', () => {\n const addTwo = x => x + 2;\n\n //Creating the compose chain\n const composed = mapp.utils.compose(addTwo);\n\n codi.assertEqual(composed(5), 7, 'Compose should also work with a single function');\n });\n\n /**\n * ### Should return the input if no functions are provided\n * @function it\n */\n codi.it('Should return the input if no functions are provided', () => {\n //Creating the compose chain\n const composed = mapp.utils.compose();\n\n codi.assertEqual(composed(10), 10, 'We should get the input as a return if no functions are provided');\n });\n\n /**\n * ### Should handle different data types\n * @function it\n */\n codi.it('Should handle different data types', () => {\n const toUpperCase = str => str.toUpperCase();\n const addExclamation = str => str + '!';\n const composed = mapp.utils.compose(addExclamation, toUpperCase);\n\n codi.assertEqual(composed('hello'), 'HELLO!', 'We expect the string to change in the chain given.');\n });\n\n\n });\n}", "/**\n * @description This module is used to test the svgTemplates util\n * @module /lib/utils/svgTemplates\n */\n\n/**\n * @description This is used as an entry point for the test module\n * @function svgTemplatesTest\n */\nexport async function svgTemplatesTest() {\n await codi.describe('Utils: SVG Templates', async () => {\n\n /**\n * ### We shouldn't be able to replace already existing templates\n * @function it\n */\n await codi.it('We should load new svg templates once', async () => {\n\n const svgTemplates = {\n 'dot_test': 'I am a bogus svg and shouldnt be loaded',\n };\n\n await mapp.utils.svgTemplates(svgTemplates);\n const dot_test_svg = await mapp.utils.svgSymbols.templates['dot_test'];\n codi.assertNotEqual(dot_test_svg, '', 'The svg template should not be overwriten');\n\n });\n });\n}", "/**\n * @module utils/versionCheck\n */\n\n/**\n * This function is used to test the versionCheck function\n * @function versionCheck\n */\nexport async function versionCheck() {\n\n await codi.describe('Utils: versionCheck Test', async () => {\n\n await codi.it('should return false if the major and minor are the same but version patch exceeds', async () => {\n\n mapp.version = '4.11.1';\n\n const result = await mapp.utils.versionCheck('4.11');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return true if the major version is more than', async () => {\n\n mapp.version = '4.9.1';\n\n const result = mapp.utils.versionCheck('3.9');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return false if the major version is the same and the minor version is less', async () => {\n\n mapp.version = '4.9.0';\n\n const result = mapp.utils.versionCheck('4.10.0');\n\n codi.assertEqual(result, false);\n });\n\n await codi.it('should return true if the major version is the same and the minor version is more', async () => {\n\n mapp.version = '4.11.0';\n\n const result = await mapp.utils.versionCheck('4.10.0');\n\n codi.assertEqual(result, true);\n });\n\n await codi.it('should return true if the major version is the same and the minor version is the same', async () => {\n\n mapp.version = '4.11.2';\n\n const result = await mapp.utils.versionCheck('4.11.1');\n\n codi.assertEqual(result, true);\n });\n });\n}\n", "import { numericFormatterTest } from './numericFormatter.test.mjs';\nimport { mergeTest } from './merge.test.mjs';\nimport { paramStringTest } from './paramString.test.mjs';\nimport { queryParamsTest } from './queryParams.test.mjs';\nimport { composeTest } from './compose.test.mjs';\nimport { svgTemplatesTest } from './svgTemplates.test.mjs';\nimport { versionCheck } from './versionCheck.mjs';\nexport const utilsTest = {\n numericFormatterTest,\n mergeTest,\n paramStringTest,\n queryParamsTest,\n composeTest,\n svgTemplatesTest,\n versionCheck\n}", "{\n \"key\": \"cluster_test\",\n \"display\": true,\n \"group\": \"layer\",\n \"format\": \"wkt\",\n \"dbs\": \"NEON\",\n \"table\": \"test.scratch\",\n \"srid\": \"3857\",\n \"geom\": \"geom_3857\",\n \"qID\": \"id\",\n \"cluster\": {\n \"resolution\": 0.005,\n \"hexgrid\": true\n },\n \"infoj\": [\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n }\n ],\n \"style\": {\n \"default\": {\n \"icon\": {\n \"type\": \"dot\",\n \"fillColor\": \"#13336B\"\n }\n },\n \"cluster\": {\n \"icon\": {\n \"type\": \"target\",\n \"fillColor\": \"#E6FFFF\",\n \"layers\": {\n \"1\": \"#13336B\",\n \"0.85\": \"#E6FFFF\"\n }\n }\n },\n \"highlight\": {\n \"scale\": 1.3\n },\n \"theme\": {\n \"title\": \"theme_1\",\n \"type\": \"graduated\",\n \"field\": \"test_template_style\",\n \"graduated_breaks\": \"greater_than\",\n \"template\": {\n \"key\": \"test_template_style\",\n \"template\": \"100-99\",\n \"value_only\": true\n },\n \"cat_arr\": [\n {\n \"value\": 0,\n \"label\": \"0 to 5%\",\n \"style\": {\n \"icon\": {\n \"fillColor\": \"#ffffcc\",\n \"fillOpacity\": 0.8\n }\n }\n }\n ]\n }\n }\n}", "/**\n * This is the vector module used to test /lib/layer/format/vector\n * @module layer/format/vector\n */\n\nimport cluster_layer_default from '../../../assets/layers/cluster/layer.json';\n\n/**\n * This is the entry point function for the vector test module.\n * @function vectorTest \n * @param {object} mapview \n */\nexport async function vectorTest(mapview, layer) {\n\n layer ??= cluster_layer_default;\n\n await codi.describe('Layer Format: Vector', async () => {\n\n /**\n * ### Should be able to create a cluster layer\n * 1. It takes layer params.\n * 2. Decorates the layer.\n * 3. We then give the vector function the layer.\n * 4. We expect the format of the layer to change to 'cluster'\n * @function it\n */\n await codi.it('Should create a cluster layer', async () => {\n\n const layer_params = {\n mapview: mapview,\n ...layer\n }\n\n //Decorating layer\n const clusterLayer = await mapp.layer.decorate(layer_params);\n\n //Passing the layer to the format method\n mapp.layer.formats.vector(clusterLayer);\n\n //Showing the layer\n clusterLayer.show();\n codi.assertTrue(typeof clusterLayer.show === 'function', 'The layer should have a show function');\n codi.assertTrue(typeof clusterLayer.reload === 'function', 'The layer should have a reload function');\n codi.assertTrue(typeof clusterLayer.setSource === 'function', 'The layer should have a setSource function');\n codi.assertTrue(clusterLayer.format === 'cluster', 'The layer should have the format cluster');\n clusterLayer.hide();\n });\n });\n}", "{\n \"group\": \"layer\",\n \"name\": \"mvt_test\",\n \"format\": \"mvt\",\n \"table\": \"test.mvt_test\",\n \"geom\": \"geom_3857\",\n \"srid\": \"3857\",\n \"qID\": \"id\",\n \"infoj\": [\n {\n \"type\": \"pin\",\n \"label\": \"ST_PointOnSurface\",\n \"field\": \"pin\",\n \"fieldfx\": \"ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]\"\n }\n ],\n \"style\": {\n \"default\": {\n \"strokeWidth\": \"0\",\n \"fillColor\": \"#fff\",\n \"fillOpacity\": 0.4,\n \"strokeColor\": null\n },\n \"themes\": {\n \"theme_1\": {\n \"title\": \"theme_1\",\n \"type\": \"categorized\",\n \"field\": \"numeric_field\",\n \"cat\": {\n \"1\": {\n \"label\": \"Lowest\",\n \"style\": {\n \"fillColor\": \"#3193ED\"\n }\n },\n \"2\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#5DC29A\"\n }\n },\n \"3\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#8FE15A\"\n }\n },\n \"4\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#D8D758\"\n }\n },\n \"5\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FFB956\"\n }\n },\n \"6\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FE8355\"\n }\n },\n \"7\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#FA5652\"\n }\n },\n \"8\": {\n \"label\": \"Highest\",\n \"style\": {\n \"fillColor\": \"#F0304D\"\n }\n }\n }\n },\n \"theme_2\": {\n \"title\": \"theme_2\",\n \"type\": \"categorized\",\n \"field\": \"numeric_field\",\n \"cat\": {\n \"1\": {\n \"label\": \"Lowest\",\n \"style\": {\n \"fillColor\": \"#6B2E94\"\n }\n },\n \"2\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#8B44B8\"\n }\n },\n \"3\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#9B6FCD\"\n }\n },\n \"4\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#89A7D6\"\n }\n },\n \"5\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#70C1C9\"\n }\n },\n \"6\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#52C4A3\"\n }\n },\n \"7\": {\n \"label\": \"-\",\n \"style\": {\n \"fillColor\": \"#38B77C\"\n }\n },\n \"8\": {\n \"label\": \"Highest\",\n \"style\": {\n \"fillColor\": \"#1FA855\"\n }\n }\n }\n }\n }\n }\n}", "import mvt_layer_default from '../../../assets/layers/mvt/layer.json';\n\nexport function mvtTest(mapview, layer) {\n\n layer ??= mvt_layer_default;\n\n codi.describe('Layer Format: MVT', () => {\n /**\n * @description MVT: Create basic layer\n * @function it\n */\n codi.it('MVT: Create basic layer', () => {\n mapp.layer.formats[layer.format]?.(layer);\n\n codi.assertTrue(Object.hasOwn(layer, 'reload'), 'The mvt layer needs to have a reload function')\n codi.assertTrue(Object.hasOwn(layer, 'featureSource'), 'The mvt layer needs to have a featureSource')\n codi.assertTrue(Object.hasOwn(layer, 'source'), 'The mvt layer needs to have a source')\n codi.assertTrue(Object.hasOwn(layer, 'L'), 'The mvt layer needs to have an openlayer object')\n });\n\n /**\n * @description MVT: Reload should remove sourceTiles\n * @function it\n */\n codi.it('MVT: Reload should remove sourceTiles', () => {\n mapp.layer.formats[layer.format]?.(layer);\n\n layer.source.sourceTiles_ = { tile: 'foo' };\n layer.reload();\n codi.assertEqual(layer.source.sourceTiles_, {}, 'The sourceTiles needs to be cleared');\n });\n });\n}", "import { vectorTest } from './vector.test.mjs';\nimport { mvtTest } from './mvt.test.mjs';\n\nexport const formatTest = {\n vectorTest,\n mvtTest\n} ", "/**\n * This function is used as an entry point for the infoj test\n * @function injojTest\n */\nexport function infojTest() {\n codi.describe('UI Locations: infojTest', () => {\n /**\n * ### It should create an infoj with a correct order\n * 1. We define an infoj with a combination of different entries with keys, fields and queries\n * 2. We assert against the order\n * @function it\n */\n codi.it('It should create an infoj with certain order', () => {\n\n const location = {\n infoj: [\n {\n field: 'field_1',\n key: 'key_1',\n label: 'test_1',\n value: 'test 1 value'\n },\n {\n field: 'field_2',\n label: 'test_2',\n value: 'value_2'\n },\n {\n field: 'field_3',\n label: 'test_3',\n value: 'value_3'\n },\n {\n key: 'key_4',\n value: 'value_4'\n },\n {\n query: 'query_5',\n value: 'value_5',\n location: {}\n }\n ]\n };\n\n const infoj_order = [\n '_field_1',\n 'field_2',\n 'field_3',\n 'key_4',\n 'query_5',\n {\n field: 'field6',\n value: 'value_6'\n }\n ];\n\n // Get listview element from the infoj object\n const infoj = mapp.ui.locations.infoj(location, infoj_order);\n\n // Get textvalues from location listview elements.\n const results = Array.from(infoj.children)\n .map(el => el.firstChild.innerText.trim())\n\n // Expected results\n const expected = [\n 'value_2',\n 'value_3',\n 'value_4',\n 'value_5',\n 'value_6'\n ];\n\n // Asserting we get the expected results and order\n codi.assertEqual(results, expected, 'The infoj order needs to be as defined in the expected');\n\n });\n });\n}\n", "import { infojTest } from './infoj.test.mjs';\n\nexport const ui_locations = { infojTest };", "import { base } from '../public/tests/_base.test.mjs';\nimport { coreTest } from './browser/local.test.mjs';\nimport { mappTest } from './lib/mapp.test.mjs';\nimport { layerTest } from './lib/layer/_layer.test.mjs';\nimport { dictionaryTest } from './lib/dictionaries/_dictionaries.test.mjs';\nimport { locationTest } from './lib/location/_location.test.mjs';\nimport { mapviewTest } from './lib/mapview/_mapview.test.mjs';\nimport { pluginsTest } from './plugins/_plugins.test.mjs';\nimport { workspaceTest } from './mod/workspace/_workspace.test.mjs';\nimport { queryTest } from './mod/query.test.mjs';\nimport { userTest } from './mod/user/_user.test.js';\nimport { ui_elementsTest } from './lib/ui/elements/_elements.test.mjs';\nimport { ui_layers } from './lib/ui/layers/_layers.test.mjs';\nimport { entriesTest } from './lib/ui/locations/entries/_entries.test.mjs';\nimport { uiTest } from './lib/ui/_ui.test.mjs';\nimport { utilsTest } from './lib/utils/_utils.test.mjs';\nimport { formatTest } from './lib/layer/format/_format.test.mjs';\nimport { ui_locations } from './lib/ui/locations/_locations.test.mjs';\n\nself._mappTest = {\n base,\n coreTest,\n mappTest,\n layerTest,\n dictionaryTest,\n locationTest,\n mapviewTest,\n pluginsTest,\n workspaceTest,\n queryTest,\n userTest,\n ui_elementsTest,\n ui_layers,\n entriesTest,\n uiTest,\n utilsTest,\n formatTest,\n ui_locations,\n}"], - "mappings": "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", - "names": ["layersTab", "locale", "base", "entry", "geometryTest", "layerTest", "geometryTest", "layerTest", "layer_default", "layer_default", "layer_default", "layer_default"] -} From 49cb7318721d98be2492a7aa49ee90d011ced283 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 14 Nov 2024 13:00:11 +0200 Subject: [PATCH 04/12] Clean up --- db.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++ mod/utils/dbs.js | 1 - 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 db.md diff --git a/db.md b/db.md new file mode 100644 index 0000000000..31897f1706 --- /dev/null +++ b/db.md @@ -0,0 +1,107 @@ +# Database Connection Management Enhancement + +## Overview + +This PR implements robust database connection handling with retry logic, better error management, and connection pooling optimizations for our PostgreSQL connections. + +## Key Changes + +1. Implemented retry logic with exponential backoff +2. Enhanced connection pool configuration +3. Added comprehensive error handling +4. Improved resource management +5. Added detailed logging +6. Added JSDoc documentation + +## Detailed Implementation + +### 1. Retry Logic + +- Maximum of 3 retry attempts +- Exponential backoff delay between retries +- Initial delay of 1 second, doubling with each retry +- Retries only on specific, recoverable errors: + - ECONNRESET (Connection reset by peer) + - ECONNREFUSED (Connection refused) + - 57P01 (Admin shutdown) + - 57P02 (Crash shutdown) + - 57P03 (Cannot connect now) + - Unexpected connection termination + +### 2. Connection Pool Configuration + +```javascript +const pool = new Pool({ + connectionString: process.env[key], + keepAlive: true, + connectionTimeoutMillis: 5000, // 5 second timeout for connection attempts + idleTimeoutMillis: 30000, // 30 second timeout for idle connections + max: 20 // Maximum pool size +}); +``` + +### 3. Error Handling + +- Pool-level error handler for idle client issues +- Per-query error handling with retry information +- Proper error classification for retry decisions +- Error logging with context information + +### 4. Resource Management + +- Guaranteed client release using finally block +- Force release flag for error cases +- Statement timeout handling + +### 5. Logging Enhancements + +- Query context in error logs +- Retry attempt counting +- Pool identification +- Error details and stack traces + +## Usage Example + +```javascript +// Example database query with retry logic +const results = await dbs.YOUR_DB( + 'SELECT * FROM table WHERE id = $1', + [123], + 5000 // Optional timeout in milliseconds +); +``` + +## Testing + +- Unit tests should be updated to include: + - Retry behavior verification + - Error handling scenarios + - Connection timeout scenarios + - Pool management + +## Performance Impact + +- Minimal impact on successful queries +- Improved handling of transient failures +- Better resource utilization through connection pooling +- Controlled retry behavior prevents cascade failures + +## Documentation + +JSDoc documentation has been added. + +## Testing Checklist + +- [ ] Verify retry behavior with simulated network failures +- [ ] Test connection pool limits +- [ ] Verify error logging format +- [ ] Test statement timeout functionality +- [ ] Verify resource cleanup +- [ ] Load test under high concurrency +- [ ] Test with different database configurations + +## Security Considerations + +- No new security implications +- Maintains existing connection string security +- No exposure of sensitive information in logs diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index e9e760626f..7b455b526b 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -1,5 +1,4 @@ /** - * @module /utils/dbs * @description * ## /utils/dbs From 2ad111f496d591e2a3f5df65566b41aaa5fb41b5 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 14 Nov 2024 13:02:30 +0200 Subject: [PATCH 05/12] Remove .md --- db.md | 107 ---------------------------------------------------------- 1 file changed, 107 deletions(-) delete mode 100644 db.md diff --git a/db.md b/db.md deleted file mode 100644 index 31897f1706..0000000000 --- a/db.md +++ /dev/null @@ -1,107 +0,0 @@ -# Database Connection Management Enhancement - -## Overview - -This PR implements robust database connection handling with retry logic, better error management, and connection pooling optimizations for our PostgreSQL connections. - -## Key Changes - -1. Implemented retry logic with exponential backoff -2. Enhanced connection pool configuration -3. Added comprehensive error handling -4. Improved resource management -5. Added detailed logging -6. Added JSDoc documentation - -## Detailed Implementation - -### 1. Retry Logic - -- Maximum of 3 retry attempts -- Exponential backoff delay between retries -- Initial delay of 1 second, doubling with each retry -- Retries only on specific, recoverable errors: - - ECONNRESET (Connection reset by peer) - - ECONNREFUSED (Connection refused) - - 57P01 (Admin shutdown) - - 57P02 (Crash shutdown) - - 57P03 (Cannot connect now) - - Unexpected connection termination - -### 2. Connection Pool Configuration - -```javascript -const pool = new Pool({ - connectionString: process.env[key], - keepAlive: true, - connectionTimeoutMillis: 5000, // 5 second timeout for connection attempts - idleTimeoutMillis: 30000, // 30 second timeout for idle connections - max: 20 // Maximum pool size -}); -``` - -### 3. Error Handling - -- Pool-level error handler for idle client issues -- Per-query error handling with retry information -- Proper error classification for retry decisions -- Error logging with context information - -### 4. Resource Management - -- Guaranteed client release using finally block -- Force release flag for error cases -- Statement timeout handling - -### 5. Logging Enhancements - -- Query context in error logs -- Retry attempt counting -- Pool identification -- Error details and stack traces - -## Usage Example - -```javascript -// Example database query with retry logic -const results = await dbs.YOUR_DB( - 'SELECT * FROM table WHERE id = $1', - [123], - 5000 // Optional timeout in milliseconds -); -``` - -## Testing - -- Unit tests should be updated to include: - - Retry behavior verification - - Error handling scenarios - - Connection timeout scenarios - - Pool management - -## Performance Impact - -- Minimal impact on successful queries -- Improved handling of transient failures -- Better resource utilization through connection pooling -- Controlled retry behavior prevents cascade failures - -## Documentation - -JSDoc documentation has been added. - -## Testing Checklist - -- [ ] Verify retry behavior with simulated network failures -- [ ] Test connection pool limits -- [ ] Verify error logging format -- [ ] Test statement timeout functionality -- [ ] Verify resource cleanup -- [ ] Load test under high concurrency -- [ ] Test with different database configurations - -## Security Considerations - -- No new security implications -- Maintains existing connection string security -- No exposure of sensitive information in logs From a8ada70dbb81fbae0c12bf5e44248d96f062fc0e Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Thu, 14 Nov 2024 13:36:35 +0200 Subject: [PATCH 06/12] reduce complexity --- mod/utils/dbs.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 7b455b526b..d90232df84 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -18,6 +18,17 @@ const RETRY_LIMIT = 3; /** @constant {number} INITIAL_RETRY_DELAY Base delay in milliseconds between retry attempts */ const INITIAL_RETRY_DELAY = 1000; +/** + * Error codes that are safe to retry + * @constant {Set}*/ +const RETRYABLE_ERROR_CODES = new Set([ + err.code === 'ECONNRESET' || // Connection reset by peer + err.code === 'ECONNREFUSED' || // Connection refused + err.code === '57P01' || // Admin shutdown + err.code === '57P02' || // Crash shutdown + err.code === '57P03' // Cannot connect now +]); + /** * Helper function to pause execution * @param {number} ms - Time to sleep in milliseconds @@ -97,12 +108,8 @@ Object.keys(process.env) * @type {boolean} * @private */ - const isRetryable = ( - err.code === 'ECONNRESET' || // Connection reset by peer - err.code === 'ECONNREFUSED' || // Connection refused - err.code === '57P01' || // Admin shutdown - err.code === '57P02' || // Crash shutdown - err.code === '57P03' || // Cannot connect now + const isRetryable = (err) => ( + RETRYABLE_ERROR_CODES.has(err.code) || err.message.includes('Connection terminated unexpectedly') ); From 94e639295bbae77445827b7aeb4509f7004c2bbf Mon Sep 17 00:00:00 2001 From: dbauszus-glx Date: Fri, 15 Nov 2024 15:14:30 +0000 Subject: [PATCH 07/12] update requires; node-pg --- mod/utils/dbs.js | 15 ++++++++++----- package.json | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index d90232df84..cf6eab443b 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -1,9 +1,13 @@ /** - * @module /utils/dbs - * @description - * ## /utils/dbs - * Database connection and query management module that creates connection pools for multiple databases - * based on environment variables prefixed with 'DBS_'. +@module /utils/dbs +@description +## /utils/dbs +Database connection and query management module that creates connection pools for multiple databases based on environment variables prefixed with 'DBS_'. + +The [node-postgres]{@link https://www.npmjs.com/package/pg} package is required to create a [new connection Pool]{@link https://node-postgres.com/apis/pool} for DBS connections. + +@requires pg +@requires /utils/logger */ const { Pool } = require('pg'); @@ -21,6 +25,7 @@ const INITIAL_RETRY_DELAY = 1000; /** * Error codes that are safe to retry * @constant {Set}*/ + const RETRYABLE_ERROR_CODES = new Set([ err.code === 'ECONNRESET' || // Connection reset by peer err.code === 'ECONNREFUSED' || // Connection refused diff --git a/package.json b/package.json index dddebad17c..a777402214 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@aws-sdk/s3-request-presigner": "^3.621.0", "jsonwebtoken": "^9.0.2", "nodemailer": "^6.9.7", - "pg": "^8.7.3", + "pg": "^8.13.1", "simple-statistics": "^7.8.3" }, "devDependencies": { @@ -43,4 +43,4 @@ "nodemon": "^3.1.7", "uhtml": "^3.1.0" } -} \ No newline at end of file +} From 9f6e366b409d8428d59599755d06e1676fd89b2c Mon Sep 17 00:00:00 2001 From: dbauszus-glx Date: Fri, 15 Nov 2024 16:18:46 +0000 Subject: [PATCH 08/12] update dbs module --- mod/utils/dbs.js | 200 ++++++++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 105 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index cf6eab443b..53994ef695 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -11,10 +11,8 @@ The [node-postgres]{@link https://www.npmjs.com/package/pg} package is required */ const { Pool } = require('pg'); -const logger = require('./logger'); -/** @type {Object.} Object containing database query functions */ -const dbs = {}; +const logger = require('./logger'); /** @constant {number} RETRY_LIMIT Maximum number of retry attempts for failed queries */ const RETRY_LIMIT = 3; @@ -22,40 +20,24 @@ const RETRY_LIMIT = 3; /** @constant {number} INITIAL_RETRY_DELAY Base delay in milliseconds between retry attempts */ const INITIAL_RETRY_DELAY = 1000; -/** - * Error codes that are safe to retry - * @constant {Set}*/ - -const RETRYABLE_ERROR_CODES = new Set([ - err.code === 'ECONNRESET' || // Connection reset by peer - err.code === 'ECONNREFUSED' || // Connection refused - err.code === '57P01' || // Admin shutdown - err.code === '57P02' || // Crash shutdown - err.code === '57P03' // Cannot connect now -]); - -/** - * Helper function to pause execution - * @param {number} ms - Time to sleep in milliseconds - * @returns {Promise} - * @private - */ -const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); +/** @constant {Object.} dbs containing database query functions */ +const dbs = {}; // Initialize database pools and create query functions Object.keys(process.env) .filter(key => key.startsWith('DBS_')) .forEach(key => { - /** - * @type {Pool} - * @private - */ + + /** + @type {Pool} @private + */ const pool = new Pool({ + dbs: key.split('_')[1], connectionString: process.env[key], keepAlive: true, - connectionTimeoutMillis: 5000, // 5 seconds - idleTimeoutMillis: 30000, // 30 seconds - max: 20 // Maximum number of clients in the pool + connectionTimeoutMillis: 5000, // 5 seconds + idleTimeoutMillis: 30000, // 30 seconds + max: 20 // Maximum number of clients in the pool }); // Handle pool errors @@ -67,83 +49,91 @@ Object.keys(process.env) }); }); - /** - * Executes a database query with retry logic - * @async - * @param {string} query - SQL query to execute - * @param {Array} [variables] - Parameters for the SQL query - * @param {number} [timeout] - Statement timeout in milliseconds - * @returns {Promise} Query results or error object - * @throws {Error} Database connection or query errors - */ - dbs[key.split('_')[1]] = async (query, variables, timeout) => { - let retryCount = 0; - let lastError; - - while (retryCount < RETRY_LIMIT) { - /** @type {import('pg').PoolClient} */ - let client; - - try { - client = await pool.connect(); - - // Set statement timeout if specified - if (timeout || process.env.STATEMENT_TIMEOUT) { - await client.query(`SET statement_timeout = ${parseInt(timeout) || parseInt(process.env.STATEMENT_TIMEOUT) - }`); - } - - const { rows } = await client.query(query, variables); - return rows; - - } catch (err) { - lastError = err; - - // Log the error with retry information - logger({ - err, - query, - variables, - retry: retryCount + 1, - pool: key.split('_')[1] - }); - - /** - * Determine if error is retryable - * @type {boolean} - * @private - */ - const isRetryable = (err) => ( - RETRYABLE_ERROR_CODES.has(err.code) || - err.message.includes('Connection terminated unexpectedly') - ); - - if (!isRetryable) { - return err; - } - - retryCount++; - - if (retryCount < RETRY_LIMIT) { - // Exponential backoff - const delay = INITIAL_RETRY_DELAY * Math.pow(2, retryCount - 1); - await sleep(delay); - } - - } finally { - if (client) { - client.release(true); // Force release in case of errors - } - } + // Assigning clientQuery method to dbs property. + dbs[key.split('_')[1]] = async (query, variables, timeout) => + await clientQuery(pool, query, variables, timeout) + }); + +// Export dbs constant +module.exports = dbs; + +/** +@function clientQuery +@async + +@description +The clientQuery method creates a client connection from the provided Pool and executes a query on this pool. + +@param {Pool} pool The node-postgres connection Pool for a Client connection. +@param {string} query SQL query to execute +@param {Array} [variables] Parameters for the SQL query +@param {number} [timeout] Statement timeout in milliseconds +@returns {Promise} Query results or error object +@throws {Error} Database connection or query errors +*/ +async function clientQuery(pool, query, variables, timeout) { + + let retryCount = 0; + let lastError; + let client; + + while (retryCount < RETRY_LIMIT) { + + try { + client = await pool.connect(); + + timeout ??= process.env.STATEMENT_TIMEOUT + + // Set statement timeout if specified + if (timeout) { + + await client.query(`SET statement_timeout = ${parseInt(timeout)}`); } - // If we've exhausted all retries, return the last error - return lastError; - }; - }); + const { rows } = await client.query(query, variables); + + return rows; + + } catch (err) { + + // Log the error with retry information + logger({ + err, + query, + variables, + retry: retryCount + 1, + pool: pool.options.dbs + }); + + retryCount++; + + if (retryCount < RETRY_LIMIT) { + // Exponential backoff + const delay = INITIAL_RETRY_DELAY * Math.pow(2, retryCount - 1); + await sleep(delay); + } + + lastError = err + + } finally { + if (client) { + client.release(true); // Force release in case of errors + } + } + } + + // If we've exhausted all retries, return the last error + return lastError; +}; /** - * Database interface object containing query functions for each configured database - * @type {Object.>} - */ -module.exports = dbs; \ No newline at end of file +@function sleep +@description +Helper function to pause execution + +@param {number} ms Time to sleep in milliseconds +@returns {Promise} +*/ +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} From eda01aea0678a23e217255f145e727797f1be8f8 Mon Sep 17 00:00:00 2001 From: dbauszus-glx Date: Fri, 15 Nov 2024 16:25:51 +0000 Subject: [PATCH 09/12] assign dbs id from key array. --- mod/utils/dbs.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 53994ef695..25e8cd20f6 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -28,11 +28,13 @@ Object.keys(process.env) .filter(key => key.startsWith('DBS_')) .forEach(key => { + const id = key.split('_')[1] + /** @type {Pool} @private */ const pool = new Pool({ - dbs: key.split('_')[1], + dbs: id, connectionString: process.env[key], keepAlive: true, connectionTimeoutMillis: 5000, // 5 seconds @@ -45,12 +47,12 @@ Object.keys(process.env) logger({ err, message: 'Unexpected error on idle client', - pool: key.split('_')[1] + pool: id }); }); // Assigning clientQuery method to dbs property. - dbs[key.split('_')[1]] = async (query, variables, timeout) => + dbs[id] = async (query, variables, timeout) => await clientQuery(pool, query, variables, timeout) }); @@ -91,7 +93,7 @@ async function clientQuery(pool, query, variables, timeout) { } const { rows } = await client.query(query, variables); - + return rows; } catch (err) { From f48aae411a3aae0b37625e2c14eb619c435692f5 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Mon, 18 Nov 2024 09:50:16 +0200 Subject: [PATCH 10/12] Remove unused docs --- mod/utils/dbs.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 25e8cd20f6..06126d2e73 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -14,13 +14,10 @@ const { Pool } = require('pg'); const logger = require('./logger'); -/** @constant {number} RETRY_LIMIT Maximum number of retry attempts for failed queries */ const RETRY_LIMIT = 3; -/** @constant {number} INITIAL_RETRY_DELAY Base delay in milliseconds between retry attempts */ const INITIAL_RETRY_DELAY = 1000; -/** @constant {Object.} dbs containing database query functions */ const dbs = {}; // Initialize database pools and create query functions @@ -52,7 +49,7 @@ Object.keys(process.env) }); // Assigning clientQuery method to dbs property. - dbs[id] = async (query, variables, timeout) => + dbs[id] = async (query, variables, timeout) => await clientQuery(pool, query, variables, timeout) }); From 86b26c66177be3986d1cdced0c7cb097f70f3c07 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Tue, 19 Nov 2024 10:08:31 +0200 Subject: [PATCH 11/12] Adding in additional argument on connection string The connection string now takes an additional argument seperated by a pipe '|' which will override the default RETRY_LIMIT --- mod/utils/dbs.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 06126d2e73..853dab7110 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -14,7 +14,7 @@ const { Pool } = require('pg'); const logger = require('./logger'); -const RETRY_LIMIT = 3; +let RETRY_LIMIT = 3; const INITIAL_RETRY_DELAY = 1000; @@ -27,12 +27,20 @@ Object.keys(process.env) const id = key.split('_')[1] + //Splitting the dbs string + const dbs_string = process.env[key].split('|'); + + //The first argument in the dbs_string is the retry limit. + if (dbs_string[1]) { + RETRY_LIMIT = parseInt(dbs_string[1]); + } + /** @type {Pool} @private */ const pool = new Pool({ dbs: id, - connectionString: process.env[key], + connectionString: dbs_string[0],//This is the connection string without other arguments. keepAlive: true, connectionTimeoutMillis: 5000, // 5 seconds idleTimeoutMillis: 30000, // 30 seconds From d723efbd672d934470b26e48bcf8cc717eedc6d1 Mon Sep 17 00:00:00 2001 From: Robert Hurst Date: Tue, 19 Nov 2024 14:35:26 +0200 Subject: [PATCH 12/12] Update docs and remove dbs_string split --- api/api.js | 2 ++ mod/utils/dbs.js | 12 ++---------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/api/api.js b/api/api.js index 460efdfbf9..2b3191217d 100644 --- a/api/api.js +++ b/api/api.js @@ -46,6 +46,7 @@ The res object represents the HTTP response that an [Express] app sends when it @typedef {Object} env The process.ENV object holds configuration provided to the node process from the launch environment. The environment configuration allows the provision of keys and secrets which must not be accessible from the client. All env properties are limited to string type. @property {String} [DIR=''] The XYZ API path which concatenated with the domain for all requests. +@property {String} [DBS_=''] DBS_* values are the connections used to establish connections to pg servers with the [dbs]{@link module:/utils/dbs} module. @property {String} [PORT='3000'] The port on which the express app listens to for requests. @property {String} [COOKIE_TTL='36000'] The Time To Live for all cookies issued by the XYZ API. @property {String} [TITLE='GEOLYTIX | XYZ'] The TITLE value is used to identify cookies and is provided to as a param to Application View templates. @@ -59,6 +60,7 @@ The process.ENV object holds configuration provided to the node process from the @property {String} [FAILED_ATTEMPTS='3'] The [user/fromACL module]{@link module:/user/fromACL} will expire user validation if failed login attempts exceed the FAILED_ATTEMPTS value. @property {String} [PASSWORD_REGEXP='(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])^.{10,}$'] The [user/register module]{@link module:/user/register} will apply PASSWORD_REGEXP value to check the complexity of provided user passwords. @property {String} [STATEMENT_TIMEOUT] The [utils/dbs module]{@link module:/utils/dbs} will apply the STATEMENT_TIMEOUT to the query.client. +@property {String} [RETRY_LIMIT='3'] The [utils/dbs module]{@link module:/utils/dbs} will apply the RETRY_LIMIT to the query.client. @property {String} [WORKSPACE_AGE] The [workspace/cache module]{@link module:/mod/workspace/cache} flashes the workspace cache after the WORKSPACE_AGE is reached. @property {String} [CUSTOM_TEMPLATES] The [workspace/cache module]{@link module:/mod/workspace/cache} caches templates defined as a src in the CUSTOM_TEMPLATES env. @property {String} [TRANSPORT] The [utils/mailer module]{@link module:/utils/mailer} requires a TRANSPORT env. diff --git a/mod/utils/dbs.js b/mod/utils/dbs.js index 853dab7110..f77b0ccb90 100644 --- a/mod/utils/dbs.js +++ b/mod/utils/dbs.js @@ -14,7 +14,7 @@ const { Pool } = require('pg'); const logger = require('./logger'); -let RETRY_LIMIT = 3; +const RETRY_LIMIT = process.env.RETRY_LIMIT ?? 3; const INITIAL_RETRY_DELAY = 1000; @@ -27,20 +27,12 @@ Object.keys(process.env) const id = key.split('_')[1] - //Splitting the dbs string - const dbs_string = process.env[key].split('|'); - - //The first argument in the dbs_string is the retry limit. - if (dbs_string[1]) { - RETRY_LIMIT = parseInt(dbs_string[1]); - } - /** @type {Pool} @private */ const pool = new Pool({ dbs: id, - connectionString: dbs_string[0],//This is the connection string without other arguments. + connectionString: process.env[key], keepAlive: true, connectionTimeoutMillis: 5000, // 5 seconds idleTimeoutMillis: 30000, // 30 seconds