spanish-quizzer

An app to quiz you on Spanish vocabulary and verb conjugations
git clone https://git.ashermorgan.net/spanish-quizzer/
Log | Files | Refs | README

commit 6e9b17b31dbeb8ba7e4503608f4156e34116e5f0
parent 3dc3c57588308f3946d67235202636e8bc2dbe25
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Sun, 18 Oct 2020 19:48:32 -0700

Merge pull request #22 from AsherMorgan/settings-component

Implement settings component.
Diffstat:
Mcss/settings.css | 43++++++++++++++++++-------------------------
Mindex.html | 135++-----------------------------------------------------------------------------
Mjs/home.js | 260++++++++++++++-----------------------------------------------------------------
Mjs/settings.js | 528+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mtests/test.app.js | 389++++++++-----------------------------------------------------------------------
Mtests/test.settings.js | 433+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
6 files changed, 904 insertions(+), 884 deletions(-)

diff --git a/css/settings.css b/css/settings.css @@ -1,22 +1,22 @@ /* Settings */ -#settings { +.settings { display: flex; flex-direction: column; align-items: center; } -#settings[hidden] { +.settings[hidden] { display: none; } -#settings h1 { +.settings h1 { font-size: 16px; font-weight: normal; margin-bottom: 10px; } -#settings h2 { +.settings h2 { font-size: 20px; margin-bottom: 5px; } -#vocabSettings, #verbSettings, #quizzerSettings, #studyMethodDiv { +.vocabSettings, .verbSettings, .quizzerSettings { margin-left: 5px; margin-right: 5px; margin-top: 10px; @@ -25,7 +25,7 @@ /* Filters */ -#vocabSettings h2 button, #verbSettings h2 button { +.vocabSettings h2 button, .verbSettings h2 button { padding: 3px; } .filter { @@ -49,21 +49,21 @@ /* Quizzer Settings div */ -#quizzerSettings div { +.quizzerSettings div { text-align: left; } -#quizzerSettings input[type=number] { +.quizzerSettings input[type=number] { width: 50px; } /* Start/Resume Buttons */ -#settingButtons { +.settingButtons { margin-top: 20px; margin-bottom: 10px; } -#settingButtons button { +.settingButtons button { width: 100px; height: 40px; font-size: 18px; @@ -71,10 +71,10 @@ } @media only screen and (max-width: 510px) { /* Expand Start/Resume buttons */ - #settingButtons { + .settingButtons { width: calc(100% - 10px); } - #settingButtons button { + .settingButtons button { width: calc(50% - 15px); height: 50px; } @@ -82,23 +82,16 @@ -/* Error Message */ -#settingsError { - margin: 0px 10px; -} - - - /* Conjugation settings on mobile devices */ @media only screen and (max-width: 510px) { - #verbSettings { + .verbSettings { width: calc(100% - 20px); } - #verbSettings .filter { + .verbSettings .filter { width: 100%; margin: 10px auto; } - #verbSettings .filter select, #verbSettings .filter button { + .verbSettings .filter select, .verbSettings .filter button { width: 100%; height: 30px; margin: 3px 0px; @@ -109,14 +102,14 @@ /* Vocab settings on mobile devices */ @media only screen and (max-width: 350px) { - #vocabSettings { + .vocabSettings { width: calc(100% - 20px); } - #vocabSettings .filter { + .vocabSettings .filter { width: 100%; margin: 10px auto; } - #vocabSettings .filter select, #vocabSettings s.filter button { + .vocabSettings .filter select, .vocabSettings s.filter button { width: 100%; height: 30px; margin: 3px 0px; diff --git a/index.html b/index.html @@ -46,138 +46,9 @@ </div> - <div id="settings" v-show="state === 'verbSettings' || state === 'vocabSettings'" hidden> - <div id="verbSettings" v-show="state === 'verbSettings'"> - <h1>Choose your settings and then click start.</h1> - - <h2> - Verb Filters - <button @click="AddVerbFilter();">Add Filter</button> - </h2> - - <div v-for="(filter, index) in verbFilters" class="filter"> - <select v-model="filter.tense"> - <option>All Tenses</option> - <option>Present Participles</option> - <option>Present Tense</option> - <option>Preterite Tense</option> - <option>Imperfect Tense</option> - </select> - <select v-model="filter.type"> - <option v-for="(available, type) in getTenseTypes(index)" :disabled="!available">{{ type }}</option> - </select> - <select v-model="filter.subject"> - <option v-for="(available, subject) in getTenseSubjects(index)" :disabled="!available">{{ subject }}</option> - </select> - <select v-model="filter.direction"> - <option>Eng. → Conj.</option> - <option>Esp. → Conj.</option> - <option>Conj. → Eng.</option> - <option>Conj. → Esp.</option> - </select> - <button class="itemRemove" @click="RemoveVerbFilter(index);">╳</button> - </div> - </div> - - - <div id="vocabSettings" v-show="state === 'vocabSettings'"> - <h1>Choose your settings and then click start.</h1> - - <h2> - Vocabulary Sets - <button @click="AddVocabFilter();">Add set</button> - </h2> - - <div v-for="(filter, index) in vocabFilters" class="filter"> - <select class="vocabSetName" v-model="filter.set"> - <optgroup label="Common Words"> - <option>Verbs</option> - <option>Adjectives</option> - <option>Adverbs</option> - <option>Prepositions</option> - <option>Transitions</option> - </optgroup> - <optgroup label="Spanish 1"> - <option>Colors</option> - <option>Days</option> - <option>Months</option> - <option>Questions</option> - <option>Weather</option> - <option>Family</option> - <option>Clothes</option> - </optgroup> - <optgroup label="Spanish 2"> - <option>Nature</option> - <option>House</option> - <option>Vacation</option> - <option>Childhood</option> - <option>Professions</option> - <option>Health</option> - </optgroup> - </select> - <select v-model="filter.type"> - <option v-for="(available, type) in getSetFilters(index)" :disabled="!available">{{ type }}</option> - </select> - <select v-model="filter.direction"> - <option>Eng. ↔ Esp.</option> - <option>Eng. → Esp.</option> - <option>Esp. → Eng.</option> - </select> - <button class="itemRemove" @click="RemoveVocabFilter(index);">╳</button> - </div> - </div> - - - <div id="quizzerSettings"> - <h2>Quizzer Settings</h2> - - <div> - <input type="checkbox" id="settingsDarkTheme" v-model="darkTheme"> - <label for="settingsDarkTheme">Dark Mode</label> - </div> - <div> - <label for="settingsPromptType">Prompt type</label> - <select id="settingsPromptType" v-model="promptType"> - <option>Text</option> - <option>Audio</option> - <option>Both</option> - </select> - </div> - <div> - <label for="settingsInputType">Input type</label> - <select id="settingsInputType" v-model="inputType"> - <option>Text</option> - <option>Voice</option> - <option>Either</option> - </select> - </div> - <div> - <label for="settingsRepeatPrompts">When I miss a prompt</label> - <select id="settingsRepeatPrompts" v-model="onMissedPrompt"> - <option>Correct me</option> - <option>Tell me</option> - <option>Ignore it</option> - </select> - </div> - <div> - <label for="settingsRepeatPrompts">Repeat missed prompts</label> - <select id="settingsRepeatPrompts" v-model="repeatPrompts"> - <option>Never</option> - <option>Immediately</option> - <option>5 prompts later</option> - <option>At the end</option> - </select> - </div> - </div> - - <div id="settingButtons"> - <button id="settingsStart" onclick="CreateSession();">Start</button> - <button id="settingsResume" onclick="ResumeSession();">Resume</button> - </div> - - <div id="settingsError" v-show="errorMsg" class="centered bad">{{ errorMsg }}</div> - </div> - + <settings id="settings" v-show="state === 'verbSettings' || state === 'vocabSettings'" hidden + :category="state === 'verbSettings' ? 'verbs' : 'vocab'" @start-session="StartSession"> + </settings> <quizzer id="quizzer" v-show="state === 'verbQuizzer' || state === 'vocabQuizzer'" :active="state === 'verbQuizzer' || state === 'vocabQuizzer'" hidden :starting-index="promptIndex" :starting-prompts="prompts" @new-prompt="updateProgress" diff --git a/js/home.js b/js/home.js @@ -13,14 +13,10 @@ function loadVue() { data: { state: "home", - darkTheme: document.body.classList.contains("dark"), - verbFilters: [], - vocabFilters: [], - errorMsg: "", - promptType: localStorage.getItem("promptType") || "Text", - inputType: localStorage.getItem("inputType") || "Text", - onMissedPrompt: localStorage.getItem("onMissedPrompt") || "Correct me", - repeatPrompts: localStorage.getItem("repeatPrompts") || "Never", + promptType: "Text", + inputType: "Text", + onMissedPrompt: "Correct me", + repeatPrompts: "Never", prompts: [], promptIndex: 0, @@ -48,172 +44,6 @@ function loadVue() { }, /** - * Add a verb filter on the settings page. - */ - AddVerbFilter: function() { - this.verbFilters.push({tense:"All Tenses", type:"All Types", subject:"All Subjects", direction:"Eng. → Conj."}); - }, - - /** - * Remove a verb filter from the settings page. - * @param {Number} index - The index of the verb filter. - */ - RemoveVerbFilter: function(index) { - // Remove filter - this.verbFilters.splice(index, 1); - }, - - /** - * Add a vocab filter on the settings page. - */ - AddVocabFilter: function() { - this.vocabFilters.push({set:"Verbs", type:"All Types", direction:"Eng. ↔ Esp."}); - }, - - /** - * Remove a vocab filter from the settings page. - * @param {Number} index - The index of the vocab filter. - */ - RemoveVocabFilter: function(index) { - // Remove filter - this.vocabFilters.splice(index, 1); - }, - - /** - * Get the regularity filters available for a verb filter. - * @param {Number} index - The index of the verb filter. - * @returns {object} - An object with boolean properties for each regularity filter. - */ - getTenseTypes: function(index) { - // Get filter options - let filters = {"All Types":true, "Reflexive":true, "Regular":true, "Nonregular":true, "Stem Changing":true, "Orthographic":true, "Irregular":true} - switch(this.verbFilters[index].tense) - { - case "All Tenses": - break; - case "Present Participles": - filters["Reflexive"] = false; // Reflexive - filters["Orthographic"] = false; // Orthographic - break; - case "Present Tense": - filters["Orthographic"] = false; // Orthographic - break; - case "Preterite Tense": - break; - case "Imperfect Tense": - filters["Stem Changing"] = false; // Stem Changing - filters["Orthographic"] = false; // Orthographic - break; - } - - // Reset type if needed - if (!filters[this.verbFilters[index].type]) { - this.verbFilters[index].type = "All Types"; - } - - // Return filters - return filters; - }, - - /** - * Get the subject filters available for a verb filter. - * @param {Number} index - The index of the verb filter. - * @returns {object} - An object with boolean properties for each subject filter. - */ - getTenseSubjects: function(index) { - // Set default filters - let filters = {"All Subjects":true, "Yo":true, "Tú":true, "Él":true, "Nosotros":true, "Ellos":true} - - if (this.verbFilters[index].tense === "Present Participles") { - // Override filters - filters["Yo"] = false; - filters["Tú"] = false; - filters["Él"] = false; - filters["Nosotros"] = false; - filters["Ellos"] = false; - - // Reset subject - this.verbFilters[index].subject = "All Subjects"; - } - - // Return filters - return filters; - }, - - /** - * Get the filters available for a vocab Set. - * @param {Number} index - The index of the vocab filter. - * @returns {Array} - An array containing available filters. - */ - getSetFilters: function(index) { - // Get filter options - let filters = {"All Types":true, "Adjectives":true, "Nouns":true, "Verbs":true} - switch(this.vocabFilters[index].set) - { - case "Verbs": - filters["Adjectives"] = false; - filters["Nouns"] = false; - filters["Verbs"] = false; - break; - - case "Adjectives": - filters["Nouns"] = false; - filters["Verbs"] = false; - break; - - case "Adverbs": - filters["Adjectives"] = false; - filters["Nouns"] = false; - filters["Verbs"] = false; - break; - - case "Prepositions": - case "Transitions": - case "Questions": - filters["Adjectives"] = false; - filters["Nouns"] = false; - filters["Verbs"] = false; - break; - - case "Colors": - filters["Nouns"] = false; - filters["Verbs"] = false; - break; - - case "Days": - case "Months": - filters["Adjectives"] = false; - filters["Verbs"] = false; - break; - - case "Weather": - case "Professions": - filters["Adjectives"] = false; - break; - - case "Family": - case "Clothes": - filters["Verbs"] = false; - break; - - case "Nature": - case "House": - case "Vacation": - case "Childhood": - case "Health": - break; - } - - // Reset type if needed - if (!filters[this.vocabFilters[index].type]) { - this.vocabFilters[index].type = "All Types"; - } - - // Return filters - return filters; - }, - - /** * Update the user's progress in localStorage. * @param {Array} prompts - The list of prompts. * @param {Number} index - The index of the current prompt. @@ -234,55 +64,55 @@ function loadVue() { // Save progress to local storage localStorage.setItem(prefix + "prompts", JSON.stringify(prompts)); localStorage.setItem(prefix + "prompt", JSON.stringify(index)); - } - }, - - watch: { - /** - * Update the app theme. - */ - darkTheme: function(value) { - SetTheme(value); }, /** - * Update the promptType setting in localStorage. - * @param {String} value - The prompt type. + * Perform validation checks and then start the quizzer. + * @param {Array} prompts - The list of prompts. + * @param {Number} promptIndex - The index of the current prompt. + * @param {String} promptType - The prompt type. + * @param {String} inputType - The input type. + * @param {String} onMissedPrompt - The onMissedPrompt setting value. + * @param {String} repeatPrompts - The repeat prompts setting value. */ - promptType: function(value) { - localStorage.setItem("promptType", value); - }, + StartSession: function(prompts, promptIndex, promptType, inputType, onMissedPrompt, repeatPrompts) { + // Validate browser for voice input + if (this.inputType !== "Text") { + if (typeof InstallTrigger !== "undefined") { + // Browser is Firefox + alert("You must enable speech recognition in about:config."); + } + else if (!window.chrome || (!window.chrome.webstore && !window.chrome.runtime)) { + // Browser is not Googole Chrome or Microsoft (Chromium) Edge + alert("Your browser does not support voice input."); + return; + } + } - /** - * Update the inputType setting in localStorage. - * @param {String} value - The input type. - */ - inputType: function(value) { - localStorage.setItem("inputType", value); - }, + // Give iOS devices ringer warning for prompt audio + if (this.promptType !== "Text") { + if (!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) { + alert("Please make sure your ringer is on in order to hear audio prompts."); + } + } - /** - * Update the onMissedPrompt setting in localStorage. - * @param {String} value - The onMissedPrompt setting value. - */ - onMissedPrompt: function(value) { - localStorage.setItem("onMissedPrompt", value); - }, + // Copy over prompts and promptIndex + this.prompts = prompts; + this.promptIndex = promptIndex; - /** - * Update the repeatPrompts setting in localStorage. - * @param {String} value - The repeat prompts setting value. - */ - repeatPrompts: function(value) { - localStorage.setItem("repeatPrompts", value); - }, + // Copy over settings + this.promptType = promptType + this.inputType = inputType + this.onMissedPrompt = onMissedPrompt + this.repeatPrompts = repeatPrompts - /** - * Clear the error message when the state changes. - */ - state: function() { - // Reset error message - app.errorMsg = ""; + // Show and hide elements (also enables the quizzer) + if (this.state === "verbSettings") { + this.state = "verbQuizzer"; + } + else if (this.state === "vocabSettings") { + this.state = "vocabQuizzer"; + } } }, }); diff --git a/js/settings.js b/js/settings.js @@ -1,132 +1,428 @@ -/** - * Start a new quizzer session - */ -function CreateSession() { - // Get prompts - if (app.state === "vocabSettings") { - // Filter and load Sets into prompts - app.prompts = []; - for (let filter of app.vocabFilters) - { - // Add filtered set - app.prompts.push(...ApplyVocabFilter(Sets[filter.set], filter.type, filter.direction)); - } +let settings = Vue.component("settings", { + props: { + category: { + type: Boolean, + default: "verbs", + }, + }, - // Shuffle prompts - app.prompts = Shuffle(app.prompts); - } - else if (app.state === "verbSettings") { - // Get prompts - app.prompts = Shuffle(ApplyVerbFilter(Sets["Verbs"], app.verbFilters)); - } + data: function() { + return { + darkTheme: document.body.classList.contains("dark"), + verbFilters: [], + vocabFilters: [], + promptType: localStorage.getItem("promptType") || "Text", + inputType: localStorage.getItem("inputType") || "Text", + onMissedPrompt: localStorage.getItem("onMissedPrompt") || "Correct me", + repeatPrompts: localStorage.getItem("repeatPrompts") || "Never", + }; + }, - // Set progress - app.promptIndex = 0; - - // Start quizzer - try { - StartSession(); - } - catch (e) { - switch (e) { - case "Terms is empty.": - app.errorMsg = "Your custom vocabulary set must contain at least one term."; - document.getElementById("settingsError").scrollIntoView(false); - break; - default: - app.errorMsg = "An error occured."; - document.getElementById("settingsError").scrollIntoView(false); - throw e; - } - } -} + methods: { + /** + * Add a filter to the settings page. + */ + AddFilter: function() { + if (this.category === "verbs") { + this.verbFilters.push({tense:"All Tenses", type:"All Types", subject:"All Subjects", direction:"Eng. → Conj."}); + } + else if (this.category === "vocab") { + this.vocabFilters.push({set:"Verbs", type:"All Types", direction:"Eng. ↔ Esp."}); + } + }, + /** + * Remove a filter from the settings page. + * @param {Number} index - The index of the verb filter. + */ + RemoveFilter: function(index) { + if (this.category === "verbs") { + this.verbFilters.splice(index, 1); + } + else if (this.category === "vocab") { + this.vocabFilters.splice(index, 1); + } + }, + /** + * Get the regularity filters available for a verb filter. + * @param {Number} index - The index of the verb filter. + * @returns {object} - An object with boolean properties for each regularity filter. + */ + getTenseTypes: function(index) { + // Get filter options + let filters = {"All Types":true, "Reflexive":true, "Regular":true, "Nonregular":true, "Stem Changing":true, "Orthographic":true, "Irregular":true} + switch(this.verbFilters[index].tense) + { + case "All Tenses": + break; + case "Present Participles": + filters["Reflexive"] = false; // Reflexive + filters["Orthographic"] = false; // Orthographic + break; + case "Present Tense": + filters["Orthographic"] = false; // Orthographic + break; + case "Preterite Tense": + break; + case "Imperfect Tense": + filters["Stem Changing"] = false; // Stem Changing + filters["Orthographic"] = false; // Orthographic + break; + } -/** - * Resume the previous quizzer session. - */ -function ResumeSession() { - // Get localStorage prefix - let prefix; - if (app.state === "vocabSettings") { - prefix = "vocab-" - } - else if (app.state === "verbSettings") { - prefix = "verb-" - } + // Reset type if needed + if (!filters[this.verbFilters[index].type]) { + this.verbFilters[index].type = "All Types"; + } - // Load prompts and progress - app.prompts = JSON.parse(localStorage.getItem(prefix + "prompts")); - app.promptIndex = parseInt(localStorage.getItem(prefix + "prompt")); + // Return filters + return filters; + }, - // Start quizzer - try { - StartSession(); - } - catch (e) { - switch (e) { - case "Bad arguments.": - app.errorMsg = "An error occured while resuming the previous session."; - document.getElementById("settingsError").scrollIntoView(false); - break; - case "Terms is empty.": - app.errorMsg = "Your custom vocabulary set must contain at least one term."; - document.getElementById("settingsError").scrollIntoView(false); - break; - default: - app.errorMsg = "An error occured."; - document.getElementById("settingsError").scrollIntoView(false); - throw e; - } - } -} + /** + * Get the subject filters available for a verb filter. + * @param {Number} index - The index of the verb filter. + * @returns {object} - An object with boolean properties for each subject filter. + */ + getTenseSubjects: function(index) { + // Set default filters + let filters = {"All Subjects":true, "Yo":true, "Tú":true, "Él":true, "Nosotros":true, "Ellos":true} + + if (this.verbFilters[index].tense === "Present Participles") { + // Override filters + filters["Yo"] = false; + filters["Tú"] = false; + filters["Él"] = false; + filters["Nosotros"] = false; + filters["Ellos"] = false; + + // Reset subject + this.verbFilters[index].subject = "All Subjects"; + } + // Return filters + return filters; + }, + /** + * Get the filters available for a vocab Set. + * @param {Number} index - The index of the vocab filter. + * @returns {Array} - An array containing available filters. + */ + getSetFilters: function(index) { + // Get filter options + let filters = {"All Types":true, "Adjectives":true, "Nouns":true, "Verbs":true} + switch(this.vocabFilters[index].set) + { + case "Verbs": + filters["Adjectives"] = false; + filters["Nouns"] = false; + filters["Verbs"] = false; + break; + + case "Adjectives": + filters["Nouns"] = false; + filters["Verbs"] = false; + break; -/** - * Perform validation checks and then start the quizzer. - */ -function StartSession() { - // Validate prompts and promptIndex - if (!app.prompts) { - throw "Bad arguments."; - } - else if (app.prompts.length === 0) { - throw "Terms is empty."; - } - else if (isNaN(app.promptIndex) || app.promptIndex < 0 || app.promptIndex >= app.prompts.length) { - throw "Bad arguments."; - } + case "Adverbs": + filters["Adjectives"] = false; + filters["Nouns"] = false; + filters["Verbs"] = false; + break; - // Validate browser for voice input - if (app.inputType !== "Text") { - if (typeof InstallTrigger !== "undefined") { - // Browser is Firefox - alert("You must enable speech recognition in about:config."); - } - else if (!window.chrome || (!window.chrome.webstore && !window.chrome.runtime)) { - // Browser is not Googole Chrome or Microsoft (Chromium) Edge - alert("Your browser does not support voice input."); - return; - } - } + case "Prepositions": + case "Transitions": + case "Questions": + filters["Adjectives"] = false; + filters["Nouns"] = false; + filters["Verbs"] = false; + break; + + case "Colors": + filters["Nouns"] = false; + filters["Verbs"] = false; + break; + + case "Days": + case "Months": + filters["Adjectives"] = false; + filters["Verbs"] = false; + break; + + case "Weather": + case "Professions": + filters["Adjectives"] = false; + break; - // Give iOS devices ringer warning for prompt audio - if (app.promptType !== "Text") { - if (!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) { - alert("Please make sure your ringer is on in order to hear audio prompts."); - } - } + case "Family": + case "Clothes": + filters["Verbs"] = false; + break; + + case "Nature": + case "House": + case "Vacation": + case "Childhood": + case "Health": + break; + } - // Show and hide elements (also enables the quizzer) - if (app.state === "verbSettings") { - app.state = "verbQuizzer"; - } - else if (app.state === "vocabSettings") { - app.state = "vocabQuizzer"; - } -} + // Reset type if needed + if (!filters[this.vocabFilters[index].type]) { + this.vocabFilters[index].type = "All Types"; + } + + // Return filters + return filters; + }, + + /** + * Start a new quizzer session + */ + CreateSession: function() { + // Get prompts + let prompts; + if (this.category === "vocab") { + // Filter and load Sets into prompts + prompts = []; + for (let filter of this.vocabFilters) + { + // Add filtered set + prompts.push(...ApplyVocabFilter(Sets[filter.set], filter.type, filter.direction)); + } + + // Shuffle prompts + prompts = Shuffle(prompts); + } + else if (this.category === "verbs") { + // Get prompts + prompts = Shuffle(ApplyVerbFilter(Sets["Verbs"], this.verbFilters)); + } + + // Set progress + let promptIndex = 0; + + // Validate prompts + if (prompts.length === 0) { + alert("Your custom vocabulary set must contain at least one term."); + return; + } + + // Start quizzer + this.$emit("start-session", prompts, promptIndex, this.promptType, this.inputType, this.onMissedPrompt, this.repeatPrompts); + }, + + /** + * Resume the previous quizzer session. + */ + ResumeSession: function() { + // Get localStorage prefix + let prefix; + if (this.category === "vocab") { + prefix = "vocab-" + } + else if (this.category === "verbs") { + prefix = "verb-" + } + + // Load prompts and progress + let prompts = JSON.parse(localStorage.getItem(prefix + "prompts")); + let promptIndex = parseInt(localStorage.getItem(prefix + "prompt")); + + // Validate prompts and promptIndex + if (!prompts) { + alert("An error occured while resuming the previous session."); + return; + } + else if (prompts.length === 0) { + alert("Your custom vocabulary set must contain at least one term."); + return; + } + else if (isNaN(promptIndex) || promptIndex < 0 || promptIndex >= prompts.length) { + alert("An error occured while resuming the previous session."); + return; + } + + // Start quizzer + this.$emit("start-session", prompts, promptIndex, this.promptType, this.inputType, this.onMissedPrompt, this.repeatPrompts); + }, + }, + + watch: { + /** + * Update the app theme. + */ + darkTheme: function(value) { + SetTheme(value); + }, + + /** + * Update the promptType setting in localStorage. + * @param {String} value - The prompt type. + */ + promptType: function(value) { + localStorage.setItem("promptType", value); + }, + + /** + * Update the inputType setting in localStorage. + * @param {String} value - The input type. + */ + inputType: function(value) { + localStorage.setItem("inputType", value); + }, + + /** + * Update the onMissedPrompt setting in localStorage. + * @param {String} value - The onMissedPrompt setting value. + */ + onMissedPrompt: function(value) { + localStorage.setItem("onMissedPrompt", value); + }, + + /** + * Update the repeatPrompts setting in localStorage. + * @param {String} value - The repeat prompts setting value. + */ + repeatPrompts: function(value) { + localStorage.setItem("repeatPrompts", value); + }, + }, + + template: ` + <div class="settings"> + <div class="verbSettings" v-show="category === 'verbs'"> + <h1>Choose your settings and then click start.</h1> + + <h2> + Verb Filters + <button @click="AddFilter();">Add Filter</button> + </h2> + + <div v-for="(filter, index) in verbFilters" class="filter"> + <select v-model="filter.tense"> + <option>All Tenses</option> + <option>Present Participles</option> + <option>Present Tense</option> + <option>Preterite Tense</option> + <option>Imperfect Tense</option> + </select> + <select v-model="filter.type"> + <option v-for="(available, type) in getTenseTypes(index)" :disabled="!available">{{ type }}</option> + </select> + <select v-model="filter.subject"> + <option v-for="(available, subject) in getTenseSubjects(index)" :disabled="!available">{{ subject }}</option> + </select> + <select v-model="filter.direction"> + <option>Eng. → Conj.</option> + <option>Esp. → Conj.</option> + <option>Conj. → Eng.</option> + <option>Conj. → Esp.</option> + </select> + <button class="itemRemove" @click="RemoveFilter(index);">╳</button> + </div> + </div> + + + <div class="vocabSettings" v-show="category === 'vocab'"> + <h1>Choose your settings and then click start.</h1> + + <h2> + Vocabulary Sets + <button @click="AddFilter();">Add set</button> + </h2> + + <div v-for="(filter, index) in vocabFilters" class="filter"> + <select class="vocabSetName" v-model="filter.set"> + <optgroup label="Common Words"> + <option>Verbs</option> + <option>Adjectives</option> + <option>Adverbs</option> + <option>Prepositions</option> + <option>Transitions</option> + </optgroup> + <optgroup label="Spanish 1"> + <option>Colors</option> + <option>Days</option> + <option>Months</option> + <option>Questions</option> + <option>Weather</option> + <option>Family</option> + <option>Clothes</option> + </optgroup> + <optgroup label="Spanish 2"> + <option>Nature</option> + <option>House</option> + <option>Vacation</option> + <option>Childhood</option> + <option>Professions</option> + <option>Health</option> + </optgroup> + </select> + <select v-model="filter.type"> + <option v-for="(available, type) in getSetFilters(index)" :disabled="!available">{{ type }}</option> + </select> + <select v-model="filter.direction"> + <option>Eng. ↔ Esp.</option> + <option>Eng. → Esp.</option> + <option>Esp. → Eng.</option> + </select> + <button class="itemRemove" @click="RemoveFilter(index);">╳</button> + </div> + </div> + + + <div class="quizzerSettings"> + <h2>Quizzer Settings</h2> + + <div> + <input type="checkbox" id="settingsDarkTheme" v-model="darkTheme"> + <label for="settingsDarkTheme">Dark Mode</label> + </div> + <div> + <label for="settingsPromptType">Prompt type</label> + <select id="settingsPromptType" v-model="promptType"> + <option>Text</option> + <option>Audio</option> + <option>Both</option> + </select> + </div> + <div> + <label for="settingsInputType">Input type</label> + <select id="settingsInputType" v-model="inputType"> + <option>Text</option> + <option>Voice</option> + <option>Either</option> + </select> + </div> + <div> + <label for="settingsRepeatPrompts">When I miss a prompt</label> + <select id="settingsRepeatPrompts" v-model="onMissedPrompt"> + <option>Correct me</option> + <option>Tell me</option> + <option>Ignore it</option> + </select> + </div> + <div> + <label for="settingsRepeatPrompts">Repeat missed prompts</label> + <select id="settingsRepeatPrompts" v-model="repeatPrompts"> + <option>Never</option> + <option>Immediately</option> + <option>5 prompts later</option> + <option>At the end</option> + </select> + </div> + </div> + + <div class="settingButtons"> + <button class="settingsStart" @click="CreateSession();">Start</button> + <button class="settingsResume" @click="ResumeSession();">Resume</button> + </div> + </div> + `, +}); diff --git a/tests/test.app.js b/tests/test.app.js @@ -9,20 +9,24 @@ describe("App", function() { expect(app.state).to.equal("home"); }); - it("VerFilters should be empty", function() { - expect(app.verbFilters.length).to.equal(0); + it("PromptType should be 'Text'", function() { + expect(app.promptType).to.equal("Text"); }); - it("VocabFilters should be empty", function() { - expect(app.vocabFilters.length).to.equal(0); + it("InputType should be 'Text'", function() { + expect(app.inputType).to.equal("Text"); }); - it("ErrorMsg should be empty", function() { - expect(app.errorMsg).to.equal(""); + it("OnMissedPrompt should be 'Correct me'", function() { + expect(app.onMissedPrompt).to.equal("Correct me"); + }); + + it("RepeatPrompts should be 'Never'", function() { + expect(app.repeatPrompts).to.equal("Never"); }); it("Prompts should be empty", function() { - expect(app.vocabFilters.length).to.equal(0); + expect(app.prompts.length).to.equal(0); }); it("PromptIndex should be 0", function() { @@ -75,361 +79,40 @@ describe("App", function() { }); }); - describe("AddVerbFilter method", function() { - it("Should add a verb filter", function() { - // Assert filters is empty - expect(app.verbFilters.length).to.equal(0); - - // Add filter - app.AddVerbFilter(); - - // Assert filter added - expect(app.verbFilters.length).to.equal(1); - expect(app.verbFilters[0]["tense"]).to.equal("All Tenses"); - expect(app.verbFilters[0]["type"]).to.equal("All Types"); - expect(app.verbFilters[0]["subject"]).to.equal("All Subjects"); - expect(app.verbFilters[0]["direction"]).to.equal("Eng. → Conj."); - }); - }); - - describe("RemoveVerbFilter method", function() { - it("Should remove the specified filter", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Present Tense", "type":"All Types"}, - {"tense":"Preterite Tense", "type":"All Types"}, - {"tense":"Imperfect Tense", "type":"All Types"} - ] - - // Remove filter - app.RemoveVerbFilter(1); - - // Assert filter removed - expect(app.verbFilters.length).to.equal(2); - expect(app.verbFilters[0]["tense"]).to.equal("Present Tense"); - expect(app.verbFilters[0]["type"]).to.equal("All Types"); - expect(app.verbFilters[1]["tense"]).to.equal("Imperfect Tense"); - expect(app.verbFilters[1]["type"]).to.equal("All Types"); - }); - }); - - describe("AddVocabFilter method", function() { - it("Should add a vocab filter", function() { - // Assert filters is empty - expect(app.vocabFilters.length).to.equal(0); - - // Add filter - app.AddVocabFilter(); - - // Assert filter added - expect(app.vocabFilters.length).to.equal(1); - expect(app.vocabFilters[0]["set"]).to.equal("Verbs"); - expect(app.vocabFilters[0]["type"]).to.equal("All Types"); - expect(app.vocabFilters[0]["direction"]).to.equal("Eng. ↔ Esp."); - }); - }); - - describe("RemoveVocabFilter method", function() { - it("Should remove the specified filter", function() { - // Initialize filters - app.vocabFilters = [ - {"set":"Verbs", "type":"All Definitions"}, - {"set":"Adjectives", "type":"All Definitions"}, - {"set":"Adverbs", "type":"All Definitions"}, - ] - - // Remove filter - app.RemoveVocabFilter(1); - - // Assert filter removed - expect(app.vocabFilters.length).to.equal(2); - expect(app.vocabFilters[0]["set"]).to.equal("Verbs"); - expect(app.vocabFilters[0]["type"]).to.equal("All Definitions"); - expect(app.vocabFilters[1]["set"]).to.equal("Adverbs"); - expect(app.vocabFilters[1]["type"]).to.equal("All Definitions"); - }); - }); - - describe("GetTenseTypes method", function() { - it("Should be correct for All Tenses", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"All Types", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseTypes(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Reflexive"]).to.equal(true); - expect(filters["Regular"]).to.equal(true); - expect(filters["Nonregular"]).to.equal(true); - expect(filters["Stem Changing"]).to.equal(true); - expect(filters["Orthographic"]).to.equal(true); - expect(filters["Irregular"]).to.equal(true); - }); - - it("Should be correct for Present Tense", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Present Tense", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseTypes(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Reflexive"]).to.equal(true); - expect(filters["Regular"]).to.equal(true); - expect(filters["Nonregular"]).to.equal(true); - expect(filters["Stem Changing"]).to.equal(true); - expect(filters["Orthographic"]).to.equal(false); - expect(filters["Irregular"]).to.equal(true); - }); - - it("Should change selection if not available", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Present Tense", "type":"Orthographic"} - ] - - // Get filters - let filters = app.getTenseTypes(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Reflexive"]).to.equal(true); - expect(filters["Regular"]).to.equal(true); - expect(filters["Nonregular"]).to.equal(true); - expect(filters["Stem Changing"]).to.equal(true); - expect(filters["Orthographic"]).to.equal(false); - expect(filters["Irregular"]).to.equal(true); - - // Assert selection changed - expect(app.verbFilters[0]["type"]).to.equal("All Types"); - }); - - it("Should not change selection if available", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Preterite Tense", "type":"Orthographic"} - ] - - // Get filters - let filters = app.getTenseTypes(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Reflexive"]).to.equal(true); - expect(filters["Regular"]).to.equal(true); - expect(filters["Nonregular"]).to.equal(true); - expect(filters["Stem Changing"]).to.equal(true); - expect(filters["Orthographic"]).to.equal(true); - expect(filters["Irregular"]).to.equal(true); - - // Assert selection not changed - expect(app.verbFilters[0]["type"]).to.equal("Orthographic"); - }); - }); - - describe("GetTenseSubjects method", function() { - it("Should be correct for All Tenses", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"All Types", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseSubjects(0); - - // Assert filters are correct - expect(filters["All Subjects"]).to.equal(true); - expect(filters["Yo"]).to.equal(true); - expect(filters["Tú"]).to.equal(true); - expect(filters["Él"]).to.equal(true); - expect(filters["Nosotros"]).to.equal(true); - expect(filters["Ellos"]).to.equal(true); - }); - - it("Should be correct for Present Participles", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Present Participles", "subject":"All Subjects", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseSubjects(0); - - // Assert filters are correct - expect(filters["All Subjects"]).to.equal(true); - expect(filters["Yo"]).to.equal(false); - expect(filters["Tú"]).to.equal(false); - expect(filters["Él"]).to.equal(false); - expect(filters["Nosotros"]).to.equal(false); - expect(filters["Ellos"]).to.equal(false); - }); - - it("Should change selection if not available", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Present Participles", "subject":"Yo", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseSubjects(0); - - // Assert filters are correct - expect(filters["All Subjects"]).to.equal(true); - expect(filters["Yo"]).to.equal(false); - expect(filters["Tú"]).to.equal(false); - expect(filters["Él"]).to.equal(false); - expect(filters["Nosotros"]).to.equal(false); - expect(filters["Ellos"]).to.equal(false); - - // Assert selection changed - expect(app.verbFilters[0]["subject"]).to.equal("All Subjects"); - }); - - it("Should not change selection if available", function() { - // Initialize filters - app.verbFilters = [ - {"tense":"Preterite Tense", "subject":"Yo", "type":"All Types"} - ] - - // Get filters - let filters = app.getTenseSubjects(0); - - // Assert filters are correct - expect(filters["All Subjects"]).to.equal(true); - expect(filters["Yo"]).to.equal(true); - expect(filters["Tú"]).to.equal(true); - expect(filters["Él"]).to.equal(true); - expect(filters["Nosotros"]).to.equal(true); - expect(filters["Ellos"]).to.equal(true); - - // Assert selection not changed - expect(app.verbFilters[0]["subject"]).to.equal("Yo"); - }); - }); - - describe("GetSetFilters method", function() { - it("Should be correct for Verbs", function() { - // Initialize filters - app.vocabFilters = [ - {"set":"Verbs", "type":"All Definitions"} - ] - - // Get filters - let filters = app.getSetFilters(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Adjectives"]).to.equal(false); - expect(filters["Nouns"]).to.equal(false); - expect(filters["Verbs"]).to.equal(false); - }); - - it("Should be correct for sets with 1 type", function() { - // Initialize filters - app.vocabFilters = [ - {"set":"Colors", "type":"All Definitions"} - ] - - // Get filters - let filters = app.getSetFilters(0); - - // Assert filters are correct - expect(filters["All Types"]).to.equal(true); - expect(filters["Adjectives"]).to.equal(true); - expect(filters["Nouns"]).to.equal(false); - expect(filters["Verbs"]).to.equal(false); - }); - - it("Should change selection if not available", function() { - // Initialize filters - app.vocabFilters = [ - {"set":"Colors", "type":"Verbs"} - ] - - // Get filters - let filters = app.getSetFilters(0); - - // Assert selection changed - expect(filters["All Types"]).to.equal(true); - expect(filters["Adjectives"]).to.equal(true); - expect(filters["Nouns"]).to.equal(false); - expect(filters["Verbs"]).to.equal(false); - expect(app.vocabFilters[0]["type"]).to.equal("All Types"); - }); - - it("Should not change selection if available", function() { - // Initialize filters - app.vocabFilters = [ - {"set":"Professions", "type":"Verbs"} - ] - - // Get filters - let filters = app.getSetFilters(0); - - // Assert selection not changed - expect(filters["All Types"]).to.equal(true); - expect(filters["Adjectives"]).to.equal(false); - expect(filters["Nouns"]).to.equal(true); - expect(filters["Verbs"]).to.equal(true); - expect(app.vocabFilters[0]["type"]).to.equal("Verbs"); - }); - }); - - describe("PromptType watch", function() { - it("Should update setting in localStorage", async function() { - // Save original setting from localStorage - let originalValue = localStorage.getItem("promptType"); - - // Set promptType - app.promptType = "test"; - await app.$nextTick(); + describe("StartSession method", function() { + it("Should import parameter values", function() { + // Call StartSession + app.StartSession([1, 2, 3], 4, "a", "b", "c", "d"); - // Assert localStorage setting updated - expect(localStorage.getItem("promptType")).to.equal("test"); - - // Restore original setting to localStorage - localStorage.setItem("promptType", originalValue); + // Assert parameters imported + expect(app.prompts).to.have.members([1, 2, 3]); + expect(app.promptIndex).to.equal(4); + expect(app.promptType).to.equal("a"); + expect(app.inputType).to.equal("b"); + expect(app.onMissedPrompt).to.equal("c"); + expect(app.repeatPrompts).to.equal("d"); }); - }); - describe("InputType watch", function() { - it("Should update setting in localStorage", async function() { - // Save original setting from localStorage - let originalValue = localStorage.getItem("inputType"); - - // Set inputType - app.inputType = "test"; - await app.$nextTick(); + it("Should set state to 'verbQuizzer' if state is 'verbSettings'", function() { + // Initialize settings + app.state = "verbSettings"; - // Assert localStorage setting updated - expect(localStorage.getItem("inputType")).to.equal("test"); + // Call StartSession + app.StartSession([1, 2, 3], 4, "a", "b", "c", "d"); - // Restore original setting to localStorage - localStorage.setItem("inputType", originalValue); + // Assert parameters imported + expect(app.state).to.equal("verbQuizzer"); }); - }); - describe("RepeatPrompts watch", function() { - it("Should update setting in localStorage", async function() { - // Save original setting from localStorage - let originalValue = localStorage.getItem("repeatPrompts"); - - // Set repeatPrompts - app.repeatPrompts = "test"; - await app.$nextTick(); + it("Should set state to 'vocabQuizzer' if state is 'vocabSettings'", function() { + // Initialize settings + app.state = "vocabSettings"; - // Assert localStorage setting updated - expect(localStorage.getItem("repeatPrompts")).to.equal("test"); + // Call StartSession + app.StartSession([1, 2, 3], 4, "a", "b", "c", "d"); - // Restore original setting to localStorage - localStorage.setItem("repeatPrompts", originalValue); + // Assert parameters imported + expect(app.state).to.equal("vocabQuizzer"); }); }); }); diff --git a/tests/test.settings.js b/tests/test.settings.js @@ -1,4 +1,394 @@ describe("Settings", function() { + let Settings; + beforeEach(function() { + // Create settings component + Settings = new settings(); + }); + + describe("Created lifecycle hook", function() { + it("Category should be 'verbs'", function() { + expect(Settings.category).to.equal("verbs"); + }); + + it("VerFilters should be empty", function() { + expect(Settings.verbFilters.length).to.equal(0); + }); + + it("VocabFilters should be empty", function() { + expect(Settings.vocabFilters.length).to.equal(0); + }); + }); + + describe("AddFilter method", function() { + it("Should add a verb filter if category is 'verbs'", function() { + // Initialize variables + Settings.category = "verbs"; + expect(Settings.verbFilters.length).to.equal(0); + expect(Settings.vocabFilters.length).to.equal(0); + + // Add filter + Settings.AddFilter(); + + // Assert filter added + expect(Settings.verbFilters.length).to.equal(1); + expect(Settings.verbFilters[0]["tense"]).to.equal("All Tenses"); + expect(Settings.verbFilters[0]["type"]).to.equal("All Types"); + expect(Settings.verbFilters[0]["subject"]).to.equal("All Subjects"); + expect(Settings.verbFilters[0]["direction"]).to.equal("Eng. → Conj."); + expect(Settings.vocabFilters.length).to.equal(0); + }); + + it("Should add a vocab filter if category is 'vocab'", function() { + // Initialize variables + Settings.category = "vocab"; + expect(Settings.verbFilters.length).to.equal(0); + expect(Settings.vocabFilters.length).to.equal(0); + + // Add filter + Settings.AddFilter(); + + // Assert filter added + expect(Settings.vocabFilters.length).to.equal(1); + expect(Settings.vocabFilters[0]["set"]).to.equal("Verbs"); + expect(Settings.vocabFilters[0]["type"]).to.equal("All Types"); + expect(Settings.vocabFilters[0]["direction"]).to.equal("Eng. ↔ Esp."); + expect(Settings.verbFilters.length).to.equal(0); + }); + }); + + describe("RemoveFilter method", function() { + it("Should remove the specified verb filter", function() { + // Initialize filters + Settings.category = "verbs"; + Settings.verbFilters = [ + "verb1", + "verb2", + "verb3", + ]; + Settings.vocabFilters = [ + "vocab1", + "vocab2", + "vocab3", + ]; + + // Remove filter + Settings.RemoveFilter(1); + + // Assert filter removed + expect(Settings.verbFilters.length).to.equal(2); + expect(Settings.verbFilters[0]).to.equal("verb1"); + expect(Settings.verbFilters[1]).to.equal("verb3"); + expect(Settings.vocabFilters.length).to.equal(3); + }); + + it("Should remove the specified vocab filter", function() { + // Initialize filters + Settings.category = "vocab"; + Settings.verbFilters = [ + "verb1", + "verb2", + "verb3", + ]; + Settings.vocabFilters = [ + "vocab1", + "vocab2", + "vocab3", + ]; + + // Remove filter + Settings.RemoveFilter(1); + + // Assert filter removed + expect(Settings.verbFilters.length).to.equal(3); + expect(Settings.vocabFilters.length).to.equal(2); + expect(Settings.vocabFilters[0]).to.equal("vocab1"); + expect(Settings.vocabFilters[1]).to.equal("vocab3"); + }); + }); + + describe("GetTenseTypes method", function() { + it("Should be correct for All Tenses", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"All Types", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseTypes(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Reflexive"]).to.equal(true); + expect(filters["Regular"]).to.equal(true); + expect(filters["Nonregular"]).to.equal(true); + expect(filters["Stem Changing"]).to.equal(true); + expect(filters["Orthographic"]).to.equal(true); + expect(filters["Irregular"]).to.equal(true); + }); + + it("Should be correct for Present Tense", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Present Tense", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseTypes(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Reflexive"]).to.equal(true); + expect(filters["Regular"]).to.equal(true); + expect(filters["Nonregular"]).to.equal(true); + expect(filters["Stem Changing"]).to.equal(true); + expect(filters["Orthographic"]).to.equal(false); + expect(filters["Irregular"]).to.equal(true); + }); + + it("Should change selection if not available", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Present Tense", "type":"Orthographic"} + ] + + // Get filters + let filters = Settings.getTenseTypes(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Reflexive"]).to.equal(true); + expect(filters["Regular"]).to.equal(true); + expect(filters["Nonregular"]).to.equal(true); + expect(filters["Stem Changing"]).to.equal(true); + expect(filters["Orthographic"]).to.equal(false); + expect(filters["Irregular"]).to.equal(true); + + // Assert selection changed + expect(Settings.verbFilters[0]["type"]).to.equal("All Types"); + }); + + it("Should not change selection if available", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Preterite Tense", "type":"Orthographic"} + ] + + // Get filters + let filters = Settings.getTenseTypes(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Reflexive"]).to.equal(true); + expect(filters["Regular"]).to.equal(true); + expect(filters["Nonregular"]).to.equal(true); + expect(filters["Stem Changing"]).to.equal(true); + expect(filters["Orthographic"]).to.equal(true); + expect(filters["Irregular"]).to.equal(true); + + // Assert selection not changed + expect(Settings.verbFilters[0]["type"]).to.equal("Orthographic"); + }); + }); + + describe("GetTenseSubjects method", function() { + it("Should be correct for All Tenses", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"All Types", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseSubjects(0); + + // Assert filters are correct + expect(filters["All Subjects"]).to.equal(true); + expect(filters["Yo"]).to.equal(true); + expect(filters["Tú"]).to.equal(true); + expect(filters["Él"]).to.equal(true); + expect(filters["Nosotros"]).to.equal(true); + expect(filters["Ellos"]).to.equal(true); + }); + + it("Should be correct for Present Participles", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Present Participles", "subject":"All Subjects", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseSubjects(0); + + // Assert filters are correct + expect(filters["All Subjects"]).to.equal(true); + expect(filters["Yo"]).to.equal(false); + expect(filters["Tú"]).to.equal(false); + expect(filters["Él"]).to.equal(false); + expect(filters["Nosotros"]).to.equal(false); + expect(filters["Ellos"]).to.equal(false); + }); + + it("Should change selection if not available", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Present Participles", "subject":"Yo", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseSubjects(0); + + // Assert filters are correct + expect(filters["All Subjects"]).to.equal(true); + expect(filters["Yo"]).to.equal(false); + expect(filters["Tú"]).to.equal(false); + expect(filters["Él"]).to.equal(false); + expect(filters["Nosotros"]).to.equal(false); + expect(filters["Ellos"]).to.equal(false); + + // Assert selection changed + expect(Settings.verbFilters[0]["subject"]).to.equal("All Subjects"); + }); + + it("Should not change selection if available", function() { + // Initialize filters + Settings.verbFilters = [ + {"tense":"Preterite Tense", "subject":"Yo", "type":"All Types"} + ] + + // Get filters + let filters = Settings.getTenseSubjects(0); + + // Assert filters are correct + expect(filters["All Subjects"]).to.equal(true); + expect(filters["Yo"]).to.equal(true); + expect(filters["Tú"]).to.equal(true); + expect(filters["Él"]).to.equal(true); + expect(filters["Nosotros"]).to.equal(true); + expect(filters["Ellos"]).to.equal(true); + + // Assert selection not changed + expect(Settings.verbFilters[0]["subject"]).to.equal("Yo"); + }); + }); + + describe("GetSetFilters method", function() { + it("Should be correct for Verbs", function() { + // Initialize filters + Settings.vocabFilters = [ + {"set":"Verbs", "type":"All Definitions"} + ] + + // Get filters + let filters = Settings.getSetFilters(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Adjectives"]).to.equal(false); + expect(filters["Nouns"]).to.equal(false); + expect(filters["Verbs"]).to.equal(false); + }); + + it("Should be correct for sets with 1 type", function() { + // Initialize filters + Settings.vocabFilters = [ + {"set":"Colors", "type":"All Definitions"} + ] + + // Get filters + let filters = Settings.getSetFilters(0); + + // Assert filters are correct + expect(filters["All Types"]).to.equal(true); + expect(filters["Adjectives"]).to.equal(true); + expect(filters["Nouns"]).to.equal(false); + expect(filters["Verbs"]).to.equal(false); + }); + + it("Should change selection if not available", function() { + // Initialize filters + Settings.vocabFilters = [ + {"set":"Colors", "type":"Verbs"} + ] + + // Get filters + let filters = Settings.getSetFilters(0); + + // Assert selection changed + expect(filters["All Types"]).to.equal(true); + expect(filters["Adjectives"]).to.equal(true); + expect(filters["Nouns"]).to.equal(false); + expect(filters["Verbs"]).to.equal(false); + expect(Settings.vocabFilters[0]["type"]).to.equal("All Types"); + }); + + it("Should not change selection if available", function() { + // Initialize filters + Settings.vocabFilters = [ + {"set":"Professions", "type":"Verbs"} + ] + + // Get filters + let filters = Settings.getSetFilters(0); + + // Assert selection not changed + expect(filters["All Types"]).to.equal(true); + expect(filters["Adjectives"]).to.equal(false); + expect(filters["Nouns"]).to.equal(true); + expect(filters["Verbs"]).to.equal(true); + expect(Settings.vocabFilters[0]["type"]).to.equal("Verbs"); + }); + }); + + describe("PromptType watch", function() { + it("Should update setting in localStorage", async function() { + // Save original setting from localStorage + let originalValue = localStorage.getItem("promptType"); + + // Set promptType + Settings.promptType = "test"; + await Settings.$nextTick(); + + // Assert localStorage setting updated + expect(localStorage.getItem("promptType")).to.equal("test"); + + // Restore original setting to localStorage + localStorage.setItem("promptType", originalValue); + }); + }); + + describe("InputType watch", function() { + it("Should update setting in localStorage", async function() { + // Save original setting from localStorage + let originalValue = localStorage.getItem("inputType"); + + // Set inputType + Settings.inputType = "test"; + await Settings.$nextTick(); + + // Assert localStorage setting updated + expect(localStorage.getItem("inputType")).to.equal("test"); + + // Restore original setting to localStorage + localStorage.setItem("inputType", originalValue); + }); + }); + + describe("RepeatPrompts watch", function() { + it("Should update setting in localStorage", async function() { + // Save original setting from localStorage + let originalValue = localStorage.getItem("repeatPrompts"); + + // Set repeatPrompts + Settings.repeatPrompts = "test"; + await Settings.$nextTick(); + + // Assert localStorage setting updated + expect(localStorage.getItem("repeatPrompts")).to.equal("test"); + + // Restore original setting to localStorage + localStorage.setItem("repeatPrompts", originalValue); + }); + }); + describe("ApplyVocabFilter method", function() { // Initialize vocab let vocab = [ @@ -500,49 +890,6 @@ describe("Settings", function() { }); }); - describe("StartSession method", function() { - beforeEach(function() { - // Initialize Vue - loadVue(); - }); - - it("Should throw \"Bad Arguments\" when prompts is null", function() { - // Initialize prompts and promptIndex - app.prompts = null; - app.promptIndex = 0; - - // Assert raises error - expect(StartSession).to.throw("Bad arguments."); - }); - - it("Should throw \"Bad Arguments\" when promptIndex is negative", function() { - // Initialize prompts and promptIndex - app.prompts = ["a", "b", "c"]; - app.promptIndex = -1; - - // Assert raises error - expect(StartSession).to.throw("Bad arguments."); - }); - - it("Should throw \"Bad Arguments\" when promptIndex is invalid", function() { - // Initialize prompts and promptIndex - app.prompts = ["a", "b", "c"]; - app.promptIndex = 3; - - // Assert raises error - expect(StartSession).to.throw("Bad arguments."); - }); - - it("Should throw \"Terms is empty\" when prompts is empty", function() { - // Initialize prompts and promptIndex - app.prompts = []; - app.promptIndex = 0; - - // Assert raises error - expect(StartSession).to.throw("Terms is empty."); - }); - }); - describe("Shuffle method", function() { it("Should not alter list", function() { // Initialize list