diff --git a/client/src/modules/DeckStateManager.js b/client/src/modules/DeckStateManager.js index 12235cd..773a0b9 100644 --- a/client/src/modules/DeckStateManager.js +++ b/client/src/modules/DeckStateManager.js @@ -1,6 +1,6 @@ import { globals } from '../config/globals.js'; import { toast } from './Toast.js'; -import { ModalManager } from './ModalManager'; +import { ModalManager } from './ModalManager.js'; export class DeckStateManager { constructor () { diff --git a/client/src/modules/GameCreationStepManager.js b/client/src/modules/GameCreationStepManager.js index eb6884f..2dda6bc 100644 --- a/client/src/modules/GameCreationStepManager.js +++ b/client/src/modules/GameCreationStepManager.js @@ -3,9 +3,9 @@ import { cancelCurrentToast, toast } from './Toast.js'; import { ModalManager } from './ModalManager.js'; import { XHRUtility } from './XHRUtility.js'; import { globals } from '../config/globals.js'; -import { templates } from './Templates.js'; -import { defaultCards } from '../config/defaultCards'; -import { UserUtility } from './UserUtility'; +import { HTMLFragments } from './HTMLFragments.js'; +import { defaultCards } from '../config/defaultCards.js'; +import { UserUtility } from './UserUtility.js'; export class GameCreationStepManager { constructor (deckManager) { @@ -192,7 +192,7 @@ function renderNameStep (containerId, step, game, steps) { const stepContainer = document.createElement('div'); setAttributes(stepContainer, { id: 'step-' + step, class: 'flex-row-container step' }); - stepContainer.innerHTML = templates.ENTER_NAME_STEP; + stepContainer.innerHTML = HTMLFragments.ENTER_NAME_STEP; document.getElementById(containerId).appendChild(stepContainer); const nameInput = document.querySelector('#moderator-name'); nameInput.value = game.moderatorName; @@ -246,9 +246,9 @@ function renderRoleSelectionStep (game, containerId, step, deckManager) { const stepContainer = document.createElement('div'); setAttributes(stepContainer, { id: 'step-' + step, class: 'flex-row-container-left-align step' }); - stepContainer.innerHTML = templates.CREATE_GAME_CUSTOM_ROLES; - stepContainer.innerHTML += templates.CREATE_GAME_DECK_STATUS; - stepContainer.innerHTML += templates.CREATE_GAME_DECK; + stepContainer.innerHTML = HTMLFragments.CREATE_GAME_CUSTOM_ROLES; + stepContainer.innerHTML += HTMLFragments.CREATE_GAME_DECK_STATUS; + stepContainer.innerHTML += HTMLFragments.CREATE_GAME_DECK; const exportHandler = (e) => { if (e.type === 'click' || e.code === 'Enter') { @@ -633,7 +633,7 @@ function addOptionsToList (deckManager, selectEl) { }); for (let i = 0; i < options.length; i++) { const optionEl = document.createElement('div'); - optionEl.innerHTML = templates.DECK_SELECT_ROLE; + optionEl.innerHTML = HTMLFragments.DECK_SELECT_ROLE; optionEl.classList.add('deck-select-role'); const alignmentClass = options[i].team === globals.ALIGNMENT.GOOD ? globals.ALIGNMENT.GOOD : globals.ALIGNMENT.EVIL; optionEl.classList.add(alignmentClass); diff --git a/client/src/modules/GameStateRenderer.js b/client/src/modules/GameStateRenderer.js index b27c1b5..fdc6c7a 100644 --- a/client/src/modules/GameStateRenderer.js +++ b/client/src/modules/GameStateRenderer.js @@ -1,6 +1,6 @@ import { globals } from '../config/globals.js'; import { toast } from './Toast.js'; -import { templates } from './Templates.js'; +import { HTMLFragments } from './HTMLFragments.js'; import { ModalManager } from './ModalManager.js'; export class GameStateRenderer { @@ -343,9 +343,9 @@ function renderGroupOfPlayers ( container.classList.add('game-player'); if (moderatorType) { container.dataset.pointer = player.id; - container.innerHTML = templates.MODERATOR_PLAYER; + container.innerHTML = HTMLFragments.MODERATOR_PLAYER; } else { - container.innerHTML = templates.GAME_PLAYER; + container.innerHTML = HTMLFragments.GAME_PLAYER; } container.querySelector('.game-player-name').innerText = player.name; const roleElement = container.querySelector('.game-player-role'); @@ -492,7 +492,7 @@ function removeExistingPlayerElements (killPlayerHandlers, revealRoleHandlers) { function createEndGamePromptComponent (socket, stateBucket) { if (document.querySelector('#end-game-prompt') === null) { const div = document.createElement('div'); - div.innerHTML = templates.END_GAME_PROMPT; + div.innerHTML = HTMLFragments.END_GAME_PROMPT; div.querySelector('#end-game-button').addEventListener('click', (e) => { e.preventDefault(); if (confirm('End the game?')) { diff --git a/client/src/modules/Templates.js b/client/src/modules/HTMLFragments.js similarity index 99% rename from client/src/modules/Templates.js rename to client/src/modules/HTMLFragments.js index 40dce19..3c4a8ab 100644 --- a/client/src/modules/Templates.js +++ b/client/src/modules/HTMLFragments.js @@ -1,4 +1,4 @@ -export const templates = { +export const HTMLFragments = { LOBBY: `
diff --git a/client/src/scripts/create.js b/client/src/scripts/create.js index 241bb49..d17355f 100644 --- a/client/src/scripts/create.js +++ b/client/src/scripts/create.js @@ -1,9 +1,11 @@ import { DeckStateManager } from '../modules/DeckStateManager.js'; import { GameCreationStepManager } from '../modules/GameCreationStepManager.js'; import { injectNavbar } from '../modules/Navbar.js'; +import createTemplate from "../view_templates/CreateTemplate.js"; const create = () => { injectNavbar(); + document.getElementById("game-creation-container").innerHTML = createTemplate; const deckManager = new DeckStateManager(); const gameCreationStepManager = new GameCreationStepManager(deckManager); gameCreationStepManager.renderStep('creation-step-container', 1); diff --git a/client/src/scripts/game.js b/client/src/scripts/game.js index 73d6a33..ad842e2 100644 --- a/client/src/scripts/game.js +++ b/client/src/scripts/game.js @@ -1,6 +1,6 @@ import { UserUtility } from '../modules/UserUtility.js'; import { globals } from '../config/globals.js'; -import { templates } from '../modules/Templates.js'; +import { HTMLFragments } from '../modules/HTMLFragments.js'; import { GameStateRenderer } from '../modules/GameStateRenderer.js'; import { toast } from '../modules/Toast.js'; import { GameTimerManager } from '../modules/GameTimerManager.js'; @@ -54,7 +54,7 @@ function syncWithGame (stateBucket, gameTimerManager, gameStateRenderer, timerWo stateBucket.currentGameState = gameState; document.querySelector('.spinner-container')?.remove(); document.querySelector('.spinner-background')?.remove(); - document.getElementById('game-content').innerHTML = templates.INITIAL_GAME_DOM; + document.getElementById('game-content').innerHTML = HTMLFragments.INITIAL_GAME_DOM; toast('You are connected.', 'success', true, true, 2); processGameState(stateBucket.currentGameState, cookie, socket, gameStateRenderer, gameTimerManager, timerWorker); } @@ -72,7 +72,7 @@ function processGameState (currentGameState, userId, socket, gameStateRenderer, } switch (currentGameState.status) { case globals.STATUS.LOBBY: - document.getElementById('game-state-container').innerHTML = templates.LOBBY; + document.getElementById('game-state-container').innerHTML = HTMLFragments.LOBBY; gameStateRenderer.renderLobbyHeader(); gameStateRenderer.renderLobbyPlayers(); if ( @@ -90,24 +90,24 @@ function processGameState (currentGameState, userId, socket, gameStateRenderer, gameStateRenderer.renderGameHeader(); switch (currentGameState.client.userType) { case globals.USER_TYPES.PLAYER: - document.getElementById('game-state-container').innerHTML = templates.PLAYER_GAME_VIEW; + document.getElementById('game-state-container').innerHTML = HTMLFragments.PLAYER_GAME_VIEW; gameStateRenderer.renderPlayerView(); break; case globals.USER_TYPES.KILLED_PLAYER: - document.getElementById('game-state-container').innerHTML = templates.PLAYER_GAME_VIEW; + document.getElementById('game-state-container').innerHTML = HTMLFragments.PLAYER_GAME_VIEW; gameStateRenderer.renderPlayerView(true); break; case globals.USER_TYPES.MODERATOR: - document.getElementById('game-state-container').innerHTML = templates.MODERATOR_GAME_VIEW; + document.getElementById('game-state-container').innerHTML = HTMLFragments.MODERATOR_GAME_VIEW; gameStateRenderer.renderModeratorView(); break; case globals.USER_TYPES.TEMPORARY_MODERATOR: - document.getElementById('game-state-container').innerHTML = templates.TEMP_MOD_GAME_VIEW; + document.getElementById('game-state-container').innerHTML = HTMLFragments.TEMP_MOD_GAME_VIEW; gameStateRenderer.renderTempModView(); break; case globals.USER_TYPES.SPECTATOR: - document.getElementById('game-state-container').innerHTML = templates.SPECTATOR_GAME_VIEW; + document.getElementById('game-state-container').innerHTML = HTMLFragments.SPECTATOR_GAME_VIEW; gameStateRenderer.renderSpectatorView(); break; default: @@ -122,7 +122,7 @@ function processGameState (currentGameState, userId, socket, gameStateRenderer, break; case globals.STATUS.ENDED: { const container = document.getElementById('game-state-container'); - container.innerHTML = templates.END_OF_GAME_VIEW; + container.innerHTML = HTMLFragments.END_OF_GAME_VIEW; container.classList.add('vertical-flex'); gameStateRenderer.renderEndOfGame(); break; @@ -297,7 +297,7 @@ function setClientSocketHandlers (stateBucket, gameStateRenderer, socket, timerW function displayStartGamePromptForModerators (gameState, gameStateRenderer) { const div = document.createElement('div'); - div.innerHTML = templates.START_GAME_PROMPT; + div.innerHTML = HTMLFragments.START_GAME_PROMPT; div.querySelector('#start-game-button').addEventListener('click', gameStateRenderer.startGameHandler); document.body.appendChild(div); } @@ -354,7 +354,7 @@ function activateRoleInfoButton (deck) { }); document.getElementById('role-info-button').addEventListener('click', (e) => { e.preventDefault(); - document.getElementById('prompt').innerHTML = templates.ROLE_INFO_MODAL; + document.getElementById('prompt').innerHTML = HTMLFragments.ROLE_INFO_MODAL; const modalContent = document.getElementById('game-role-info-container'); for (const card of deck) { const roleDiv = document.createElement('div'); diff --git a/client/src/view_templates/CreateTemplate.js b/client/src/view_templates/CreateTemplate.js new file mode 100644 index 0000000..f7ff594 --- /dev/null +++ b/client/src/view_templates/CreateTemplate.js @@ -0,0 +1,64 @@ +const template = + ` + + + +

Create A Game

+
+
+
+
+
+
+
+
+
+
+

Select your method of moderation:

+
+
+
+
+
+
+
` + +export default template; diff --git a/client/src/views/create.html b/client/src/views/create.html index bf3f9a7..986c9bc 100644 --- a/client/src/views/create.html +++ b/client/src/views/create.html @@ -21,69 +21,7 @@
-
- - - - -

Create A Game

-
-
-
-
-
-
-
-
-
-
-

Select your method of moderation:

-
-
-
-
-
-
-
-
+
diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..53f3802 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,24 @@ +module.exports = function(config) { + config.set({ + basePath: './', + frameworks: ['jasmine'], + files: [ + { pattern: 'spec/e2e/*.js', type: 'module' }, + { pattern: 'client/src/modules/*.js', type: 'module', included: true, served: true }, + { pattern: 'client/src/config/*.js', type: 'module', included: true, served: true }, + { pattern: 'client/src/model/*.js', type: 'module', included: true, served: true }, + { pattern: 'client/src/view_templates/*.js', type: 'module', included: true, served: true } + ], + reporters: ['progress'], + port: 9876 + colors: true, + logLevel: config.LOG_INFO, + browsers: ['ChromeHeadless'], + autoWatch: false, + concurrency: Infinity, + plugins: [ + 'karma-jasmine', + 'karma-chrome-launcher' + ] + }) +} diff --git a/package-lock.json b/package-lock.json index 7087139..d4702a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1740,6 +1740,16 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1775,6 +1785,12 @@ "es-abstract": "^1.19.0" } }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -1866,6 +1882,12 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "body-parser": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", @@ -1892,6 +1914,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browserslist": { "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", @@ -1944,11 +1975,49 @@ "supports-color": "^5.3.0" } }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -1977,6 +2046,12 @@ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -1997,6 +2072,18 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + } + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2052,6 +2139,12 @@ } } }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -2071,6 +2164,18 @@ "which": "^2.0.1" } }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2103,6 +2208,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2112,16 +2223,43 @@ "esutils": "^2.0.2" } }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } + }, "electron-to-chromium": { "version": "1.4.27", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.27.tgz", "integrity": "sha512-uZ95szi3zUbzRDx1zx/xnsCG+2xgZyy57pDOeaeO4r8zx5Dqe8Jv1ti8cunvBwJHVI5LzPuw8umKwZb3WKYxSQ==" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -2221,6 +2359,12 @@ "ansi-colors": "^4.1.1" } }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, "envinfo": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", @@ -2749,6 +2893,12 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -2824,6 +2974,12 @@ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.0.1.tgz", "integrity": "sha512-4J8og2zuaafv9egUfQ3G5+hRZfTtckimd4leYPkEXNn2XOQ/IBJIwDmHrwbd2ZbI6UEX3AlyAKLG2EWiXvgCig==" }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2854,6 +3010,24 @@ "flat-cache": "^3.0.4" } }, + "filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -2903,6 +3077,12 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", "dev": true }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "dev": true + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2913,11 +3093,29 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2935,6 +3133,12 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "get-intrinsic": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", @@ -3054,6 +3258,17 @@ } } }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3073,6 +3288,12 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3150,6 +3371,15 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -3194,6 +3424,12 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3209,6 +3445,12 @@ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-number-object": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", @@ -3282,6 +3524,18 @@ "is-docker": "^2.0.0" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3292,6 +3546,18 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, "jasmine": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.10.0.tgz", @@ -3299,12 +3565,32 @@ "requires": { "glob": "^7.1.6", "jasmine-core": "~3.10.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.10.1.tgz", + "integrity": "sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==" + } + } + }, + "jasmine-browser-runner": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jasmine-browser-runner/-/jasmine-browser-runner-1.0.0.tgz", + "integrity": "sha512-z28wHGQCrLenCOnOAvjs8fcgD5GcYFJg2SRwVK0WTPO6hpmc2N2rY40duePFfin7eEHOjqYPAa5Fuj7I62jqhQ==", + "dev": true, + "requires": { + "ejs": "^3.1.6", + "express": "^4.16.4", + "glob": "^7.1.7", + "selenium-webdriver": "^4.1.0" } }, "jasmine-core": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.10.1.tgz", - "integrity": "sha512-ooZWSDVAdh79Rrj4/nnfklL3NQVra0BcuhcuWoAwwi+znLDoUeH87AFfeX8s+YeYi6xlv5nveRyaA1v7CintfA==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.0.1.tgz", + "integrity": "sha512-w+JDABxQCkxbGGxg+a2hUVZyqUS2JKngvIyLGu/xiw2ZwgsoSB0iiecLQsQORSeaKQ6iGrCyWG86RfNDuoA7Lg==", + "dev": true }, "jest-worker": { "version": "27.4.5", @@ -3375,6 +3661,109 @@ "minimist": "^1.2.5" } }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jszip": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "requires": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "dev": true, + "requires": { + "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-jasmine": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-4.0.1.tgz", + "integrity": "sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw==", + "requires": { + "jasmine-core": "^3.6.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==" + } + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3390,6 +3779,15 @@ "type-check": "~0.4.0" } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, "loader-runner": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", @@ -3423,6 +3821,12 @@ "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -3434,6 +3838,36 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3507,6 +3941,15 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3533,6 +3976,12 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -3647,6 +4096,12 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3701,6 +4156,12 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -3715,6 +4176,12 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -3735,6 +4202,12 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, "qs": { "version": "6.9.6", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", @@ -3764,6 +4237,30 @@ "unpipe": "1.0.0" } }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -3837,6 +4334,18 @@ } } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -3859,6 +4368,12 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -3888,6 +4403,17 @@ "ajv-keywords": "^3.5.2" } }, + "selenium-webdriver": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.1.1.tgz", + "integrity": "sha512-Fr9e9LC6zvD6/j7NO8M1M/NVxFX67abHcxDJoP5w2KN/Xb1SyYLjMVPGgD14U2TOiKe4XKHf42OmFw9g2JgCBQ==", + "dev": true, + "requires": { + "jszip": "^3.6.0", + "tmp": "^0.2.1", + "ws": ">=7.4.6" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -3939,6 +4465,12 @@ "send": "0.17.2" } }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -4102,6 +4634,45 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", @@ -4122,6 +4693,15 @@ "define-properties": "^1.1.3" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4213,11 +4793,29 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -4270,6 +4868,12 @@ "mime-types": "~2.1.24" } }, + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -4306,6 +4910,12 @@ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4319,6 +4929,12 @@ "punycode": "^2.1.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -4335,6 +4951,12 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -4469,6 +5091,43 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4484,12 +5143,39 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, "yeast": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", diff --git a/package.json b/package.json index 3a84453..8f86757 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "start:dev:windows:no-hot-reload": "SET NODE_ENV=development && node server/main.js", "start": "NODE_ENV=production node server/main.js -- loglevel=trace port=8080", "start:windows": "SET NODE_ENV=production && node server/main.js -- loglevel=warn port=8080", - "test": "jasmine" + "test:unit": "jasmine", + "test:e2e": "karma start --single-run --browsers ChromeHeadless karma.conf.js" }, "engines": { "node": ">=14.0.0" @@ -34,6 +35,7 @@ "express-force-https": "^1.0.0", "express-rate-limit": "^6.0.1", "jasmine": "^3.5.0", + "karma-jasmine": "^4.0.1", "open": "^7.0.3", "socket.io": "^4.4.0", "socket.io-client": "^4.4.0", @@ -47,7 +49,11 @@ "eslint": "^8.6.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.0.0" + "eslint-plugin-promise": "^6.0.0", + "jasmine-browser-runner": "^1.0.0", + "jasmine-core": "^4.0.1", + "karma": "^6.3.16", + "karma-chrome-launcher": "^3.1.0" }, "nodemonConfig": { "ignore": [ diff --git a/spec/e2e/create_spec.js b/spec/e2e/create_spec.js new file mode 100644 index 0000000..b077d09 --- /dev/null +++ b/spec/e2e/create_spec.js @@ -0,0 +1,97 @@ +// TODO: clean up these deep relative paths? jsconfig.json is not working... + +import { GameCreationStepManager } from '../../client/src/modules/GameCreationStepManager.js'; +import { DeckStateManager } from '../../client/src/modules/DeckStateManager.js'; +import createTemplate from '../../client/src/view_templates/CreateTemplate.js'; + +describe('Create page', function () { + let gameCreationStepManager; + + beforeAll(function () { + spyOn(window, 'confirm').and.returnValue(true); + const container = document.createElement('div'); + container.setAttribute('id', 'game-creation-container'); + document.body.appendChild(container); + document.getElementById('game-creation-container').innerHTML = createTemplate; + const deckManager = new DeckStateManager(); + gameCreationStepManager = new GameCreationStepManager(deckManager); + gameCreationStepManager.renderStep('creation-step-container', 1); + }); + + beforeEach(function () {}); + + describe('deck builder page', function () { + beforeAll(function () { + document.getElementById('moderation-dedicated').click(); + document.getElementById('step-forward-button').click(); + }); + + beforeEach(function () { + document.querySelectorAll('.deck-select-role').forEach((roleEl) => { + roleEl + .querySelector('.deck-select-role-options') + .querySelector('.deck-select-remove') + .click(); + }); + }); + + it('should increment a widget when the plus button is clicked and have it show up in the included cards', () => { + const card = gameCreationStepManager.deckManager.getCurrentDeck()[0]; + const widget = document.getElementById('card-' + card.role.replaceAll(' ', '-')); + const plusElement = widget.querySelector('.compact-card-right'); + plusElement.click(); + + expect(card.quantity).toEqual(1); + expect(document.getElementsByClassName('deck-role').length).toEqual(1); + }); + + it('should decrement a widget when the minus button is clicked and remove the role from the included cards', () => { + const card = gameCreationStepManager.deckManager.getCurrentDeck()[0]; + card.quantity = 1; + const widget = document.getElementById('card-' + card.role.replaceAll(' ', '-')); + const plusElement = widget.querySelector('.compact-card-left'); + plusElement.click(); + + expect(card.quantity).toEqual(0); + expect(document.getElementsByClassName('deck-role').length).toEqual(0); + }); + + it('should create a role and display it in the custom role box', () => { + document.getElementById('custom-role-btn').click(); + document.getElementById('role-name').value = 'Test name'; + document.getElementById('role-description').value = 'Test description'; + document.getElementById('create-role-button').click(); + + expect(document.getElementsByClassName('deck-select-role').length).toEqual(1); + expect( + document.getElementsByClassName('deck-select-role')[0] + .querySelector('.deck-select-role-name').innerText + ) + .toEqual('Test name'); + }); + + it('should successfully update role information', () => { + document.getElementById('custom-role-btn').click(); + document.getElementById('role-name').value = 'Test name'; + document.getElementById('role-description').value = 'Test description'; + document.getElementById('create-role-button').click(); + document.getElementsByClassName('deck-select-role')[0] + .querySelector('.deck-select-role-options') + .querySelector('.deck-select-edit') + .click(); + document.getElementById('role-name').value = 'Test name edited'; + document.getElementById('create-role-button').click(); + + expect(document.getElementsByClassName('deck-select-role').length).toEqual(1); + expect( + document.getElementsByClassName('deck-select-role')[0] + .querySelector('.deck-select-role-name').innerText + ) + .toEqual('Test name edited'); + expect(gameCreationStepManager.deckManager.getCustomRoleOption( + document.getElementsByClassName('deck-select-role')[0] + .querySelector('.deck-select-role-name').innerText + ).role).toEqual('Test name edited'); + }); + }); +}); diff --git a/spec/support/jasmine-browser.json b/spec/support/jasmine-browser.json new file mode 100644 index 0000000..6491767 --- /dev/null +++ b/spec/support/jasmine-browser.json @@ -0,0 +1,21 @@ +{ + "srcDir": "src", + "srcFiles": [ + "**/*.js" + ], + "specDir": "spec/e2e", + "specFiles": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "env": { + "stopSpecOnExpectationFailure": false, + "stopOnSpecFailure": false, + "random": true + }, + "browser": { + "name": "headlessChrome" + } +}