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 index bd8e0da..9062bdd 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,7 +1,14 @@ module.exports = function(config) { config.set({ + basePath: './', frameworks: ['jasmine'], - files: ['spec/**/*.js'], + 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, // karma web server port colors: true, diff --git a/spec/e2e/create_spec.js b/spec/e2e/create_spec.js new file mode 100644 index 0000000..790b601 --- /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); + let 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', () => { + let card = gameCreationStepManager.deckManager.getCurrentDeck()[0]; + let widget = document.getElementById('card-' + card.role.replaceAll(' ', '-')) + let 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', () => { + let card = gameCreationStepManager.deckManager.getCurrentDeck()[0]; + card.quantity = 1; + let widget = document.getElementById('card-' + card.role.replaceAll(' ', '-')) + let 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/e2e/e2eRunner.js b/spec/e2e/e2eRunner.js deleted file mode 100644 index 5878f09..0000000 --- a/spec/e2e/e2eRunner.js +++ /dev/null @@ -1,15 +0,0 @@ -const jasmineBrowser = require('jasmine-browser-runner'); - - -const config = require('../support/jasmine-browser.json'); -jasmineBrowser.startServer(config, { port: 4321 }); - -const puppeteer = require('puppeteer'); - -(async () => { - const browser = await puppeteer.launch({ headless: true }); // default is true - const page = await browser.newPage(); - await page.goto('http://localhost:4321'); -})(); - -