├── .gitignore ├── .nvmrc ├── LICENSE ├── README.md ├── package.json ├── src ├── assets │ ├── main.css │ └── main.js └── index.html └── test └── main.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 6 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Eric J Fisher 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Use JavaScript to Create a "Code Breaker" Game 2 | 3 | You'll build a Code Breaker game using JavaScript. Based off the board game Mastermind, the game will randomly generate a hidden code and the player gets 10 attempts to guess that code based on provided feedback. 4 | 5 | ![alt tag](https://cloud.githubusercontent.com/assets/5638847/22342332/074b39a4-e3c2-11e6-8147-d33c5937079a.gif) 6 | 7 | # Getting Started 8 | 9 | To get started with this project, head over to the [Link to Repository](https://www.codeschool.com/projects/CodeBreaker) project on Code School and begin! It'll walk you through all of the steps below. They're included here in the readme in case you work better locally or want to try working on this project offline. 10 | 11 | To get set up locally, run the following commands: 12 | 13 | ``` 14 | npm install 15 | npm start 16 | ``` 17 | 18 | # Live Demo 19 | 20 | [Check out this link] (https://codeschool-projects.github.io/CodeBreakerProject/) to see a working version of this project. Feel free to alter and expand on this project to make your own twist on the Code Breaker game once you've completed the steps. 21 | 22 | You'll build a Code Breaker game that you can play and show off to others as an example of your abilities in JavaScript. 23 | 24 | # Setup Instructions 25 | 26 | Once you have cloned the forked repository, go into the directory containing the project and look for the `/src` directory. This is the directory where you will be making changes when you start the following step-by-step instructions. You can simply open those files in any text editor to get started. 27 | 28 | In this project, all of your changes will happen in the `/src/assets/main.js` file. 29 | 30 | # Tasks 31 | 32 | Complete the following tasks to finish this project. 33 | 34 | ## Create `setHiddenFields` function 35 | 36 | Create a function named `setHiddenFields` that sets the `answer` variable equal to a randomly generated whole number between 0 and 9999. 37 | 38 | **Hint:** `Math.random()` can be used to randomly generate a number between 0 and 1 (up to 18 decimal points) and `Math.floor(input)` can be used to round down to the nearest whole number. 39 | 40 | ## Make sure the hidden input `answer`'s value is exactly 4 characters long 41 | 42 | In our `setHiddenFields` function we need to make sure the hidden input `answer` is exactly 4 characters long. (If our random number generates "42", we want to set the `value` of `answer` to "0042".) 43 | 44 | **Hint:** In order to add a zero to the front of an answer, it must be a string, not a number. You can convert numbers to strings with `.toString()`. We can create a `while` loop that runs while `answer.length` is less than 4 that puts a `0` before answer's current value. 45 | 46 | ## Set the hidden input `attempt`'s value to zero 47 | 48 | In our `setHiddenFields` function, we should also set the hidden input `attempt` to `0`. 49 | 50 | ## Only set the `answer` and `attempt` hidden inputs when they aren't already set 51 | 52 | Call the `setHiddenFields` function in the body of the `guess` function, but also write some logic so that it's only called when answer and attempt haven't already been set. 53 | 54 | **Hint:** we can use an `if` condition to only run our code when `answer` or `attempt` is empty (`''`). 55 | 56 | ## Create `setMessage` function 57 | 58 | Create a `setMessage` function with one parameter. This function should set the `message` label to whatever is provided to the parameter. 59 | 60 | **Hint:** With a label, you'll want to set its `.innerHTML`, not its `.value`. 61 | 62 | ## Create `validateInput` function 63 | 64 | Create a function `validateInput` with one parameter. If the parameter has a `length` of 4, return `true` — otherwise, use the `setMessage` function to set the `message` label to `"Guesses must be exactly 4 characters long."`, then return `false`. 65 | 66 | ## Call the `validateInput` function from the `guess` function 67 | 68 | Create an `if` condition block that uses `validateInput` with a parameter of `input.value` as the conditional. If `validateInput` returns `false`, then use `return false` to stop execution of the `guess` function, otherwise we should increment the `attempt` hidden input by 1. 69 | 70 | **Hint:** You can negate a value on the `if` statement by using the exclamation point, like this: `if(!someValue)`. 71 | 72 | ## Create `getResults` function 73 | 74 | Create a `getResults` function that has one parameter. In this function, we need to add the results of the user's guess to our `results` div's `innerHTML`. Each result should begin with `
' + input + '
` where `input` is the value the user guessed. Then for each character, you should add `` if the character is in the correct position in the `answer`, a `` if the character is in the `answer` but isn't in the right position, and `` if the number isn't in the `answer` at all. Don't forget to close your divs! 75 | 76 | **Hint:*** You can create a variable to hold the initial div, then add each character's results to that variable in a `for` loop, then add the closing `div` tags after the loop. After which you can just set the `results` element's `innerHTML` to that variable. 77 | 78 | ## Check for correct guess 79 | 80 | In our `getResults` function, create a variable that counts how many characters were guessed correctly. If all characters were guessed correctly, the function should return `true`, otherwise `false`. 81 | 82 | ## Set up win condition 83 | 84 | Add a call to the `getResults` function at the end of our `guess` function. If `getResults` returns true, use the `setMessage` function to set the `message` label to `"You Win! :)"`. 85 | 86 | ## Set up lose condition 87 | 88 | If `getResults` returns `false` and the hidden input `attempt` value is greater than or equal to 10, use the `setMessage` function to set the `message` label to `"You Lose! :("`. 89 | 90 | ## Continue play condition 91 | 92 | If neither a win or lose condition is met, use the `setMessage` function to set the `message` label to `"Incorrect, try again."`. 93 | 94 | ## Create a `showAnswer` function 95 | 96 | Create a function `showAnswer` that has one parameter. This function should set the `innerHTML` of the `code` label to the `value` of the `answer` hidden input. In addition to this, it should take the parameter as a `true` or `false` (indicating if the player won or lost) if the parameter is `true` add ` success` to `code`'s `className` — otherwise, it should add ` failure`. (Note the space before ` success` and ` failure`.) 97 | 98 | ## Create a `showReplay` function 99 | 100 | Create a function `showReplay` with no parameters. This function will change the `style.display` of `guessing-div` div to `none` and the `style.display` of the `replay-div` div to `block`, making it so the user can start over after they win or lose the game. 101 | 102 | ## Add `showAnswer` and `showReplay` to win / lose conditions 103 | 104 | When a player wins in addition to `setMessage` call, they should also call `showAnswer` passing `true` for its parameter, and finally make a call to `showReplay`. When the player loses, they should call `showAnswer` with `false` for the parameter and then `showReplay`. 105 | 106 | # Next Steps 107 | 108 | Now that you've completed this project, you should make it available online so you can share your progress with others! One way to do this is by using GitHub Pages. 109 | 110 | To deploy your `/src` directory to GitHub Pages, be sure to commit all of your changes and make a new branch called `gh-pages`. Once you are checked in to the `gh-pages` branch, run the following command: 111 | 112 | ```git subtree push --prefix src origin gh-pages``` 113 | 114 | This will push the `src` folder up to GitHub on the `gh-pages` branch. After that, you should be able to open up `http://username.github.io/CodeBreakerProject`, where `username` is your GitHub username. 115 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-breaker-project", 3 | "version": "1.0.0", 4 | "description": "Code Breaker Project", 5 | "private": true, 6 | "scripts": { 7 | "start": "browser-sync start --server ./src --files ./src", 8 | "test": "mocha -t 20000 test/*.spec.js", 9 | "test-watch": "npm test -- --bail --watch", 10 | "deploy:github-pages": "git subtree push --prefix src origin gh-pages" 11 | }, 12 | "author": "Eric J Fisher ", 13 | "license": "MIT", 14 | "devDependencies": { 15 | "browser-sync": "^2.14.0", 16 | "chai": "^3.5.0", 17 | "javascript-sandbox": "git+https://github.com/codeschool/javascript-sandbox.git", 18 | "jsdom": "^9.4.1", 19 | "mocha": "^3.0.1", 20 | "sinon": "^1.17.5" 21 | }, 22 | "engines": { 23 | "node": ">=6" 24 | } 25 | } -------------------------------------------------------------------------------- /src/assets/main.css: -------------------------------------------------------------------------------- 1 | .code { 2 | font-size: 50px; 3 | padding-left: 70px; 4 | } 5 | 6 | .failure { 7 | color: #d9534f; 8 | } 9 | 10 | .success { 11 | color: #5cb85c; 12 | } 13 | 14 | .form-inline { 15 | margin-bottom: 10px; 16 | } 17 | 18 | .message { 19 | font-weight: bold; 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/main.js: -------------------------------------------------------------------------------- 1 | let answer = document.getElementById('answer'); 2 | let attempt = document.getElementById('attempt'); 3 | 4 | function guess() { 5 | let input = document.getElementById('user-guess'); 6 | //add functionality to guess function here 7 | } 8 | 9 | //implement new functions here -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Code Breaker 10 | 11 | 12 |
13 |
14 |

Code Breaker

15 |
16 |

17 | ???? 18 |

19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 |
27 | 28 | 31 | 32 |
33 |

34 |
35 | 36 |
37 |
38 | Guess 39 | Result 40 |
41 |
42 |
43 | 44 |
45 |

Objective:

46 |

Guess the randomly generated 4 digit code.

47 | 48 |

Rules:

49 |
    50 |
  • Each guess must consist of 4 numeric characters.
  • 51 |
  • Numbers may be used more than once!
  • 52 |
  • You win only if your guess is an exact match.
  • 53 |
  • You lose if you fail to guess the code under 10 guesses.
  • 54 |
  • 55 | 56 | Indicates a number is in the correct place. 57 |
  • 58 | 59 | Indicates a number is part of the code, but not in the right position. 60 |
  • 61 |
  • 62 | 63 | Doesn't consider how many times a number exists in the code. 64 |
  • 65 |
  • 66 | 67 | Indicates a number is not part of the code. 68 |
  • 69 |
70 |
71 |
72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /test/main.spec.js: -------------------------------------------------------------------------------- 1 | // Libraries 2 | const fs = require('fs'); 3 | const jsdom = require('jsdom'); 4 | const { assert } = require('chai'); 5 | const sinon = require('sinon'); 6 | const srcScript = fs.readFileSync('./src/assets/main.js', 'utf8'); 7 | 8 | const scriptRegex = /<\s*script[\s\S]*?>[\s\S]*?<\s*\/\s*script\s*>/ig; 9 | 10 | // HTML Page 11 | let srcHtml = fs.readFileSync('./src/index.html', 'utf8'); 12 | srcHtml = srcHtml.replace( 13 | scriptRegex, 14 | (tag) => !/src\s*=['"][^'"]*assets\//i.test(tag) ? tag : '' 15 | ); 16 | 17 | // JSDOM Setup 18 | const virtualConsole = jsdom.createVirtualConsole(); 19 | virtualConsole.sendTo(console); 20 | 21 | // Tests 22 | describe('CodeBreaker :', () => { 23 | 24 | let document; 25 | let window; 26 | 27 | // Setup 28 | before((done) => { 29 | 30 | document = jsdom.jsdom(srcHtml, { 31 | virtualConsole: virtualConsole, 32 | }); 33 | 34 | window = document.defaultView; 35 | 36 | window.addEventListener('load', () => { 37 | // Adds script tag 38 | const scriptEl = window.document.createElement('script'); 39 | scriptEl.appendChild(window.document.createTextNode(srcScript)); 40 | window.document.body.appendChild(scriptEl); 41 | setTimeout(()=> { 42 | done(); 43 | }, 2000) 44 | }); 45 | }); 46 | 47 | // Tests 48 | describe('setHiddenFields()', function() { 49 | it('should set the `value` of element `answer` to a random whole number between 0 and 9999. @randomNumber',function() { 50 | assert(typeof window.setHiddenFields === "function",'a function named `setHiddenFields` was not found.'); 51 | 52 | var array = []; 53 | if (typeof window.setHiddenFields === 'function') { 54 | for(var i = 0; i < 10; i++) 55 | { 56 | window.setHiddenFields(); 57 | array.push(document.getElementById('answer').value); 58 | } 59 | array.sort(); 60 | } 61 | 62 | assert(array.length > 0, '`setHiddenFields` didn\'t change the `value` of the `answer` hidden field. `setHiddenFields` should change the `answer.value` variable.'); 63 | var current = null; 64 | var duplicates = 0; 65 | for(var i = 0; i < array.length; i++) { 66 | assert(array[i] >= 0 && array[i] <= 9999, '`answer.value` was ' + array[i] + ' which is not between 0 and 9999.'); 67 | assert(array[i].indexOf('.') == -1, '`answer.value` was ' + array[i] + ' which is not a whole number.'); 68 | if(array[i] != current) { 69 | current = array[i]; 70 | } else { 71 | duplicates++; 72 | } 73 | } 74 | assert(duplicates < 3,'`setHiddenFields` was run 10 times and `answer.value` was the same more than 3 times. `answer.value` does not appear to be random.'); 75 | }); 76 | 77 | it('should set the `value` of element `answer` to a number exactly 4 characters long. @answerLength', function() { 78 | assert(typeof window.setHiddenFields === "function",'a function named `setHiddenFields` was not found.'); 79 | 80 | var array = []; 81 | if (typeof window.setHiddenFields === 'function') { 82 | for(var i = 0; i < 10; i++) 83 | { 84 | window.setHiddenFields(); 85 | array.push(document.getElementById('answer').value.toString()); 86 | } 87 | array.sort(); 88 | } 89 | 90 | assert(array.length > 0, '`setHiddenFields` didn\'t change the `value` of the `answer` hidden field. `setHiddenFields` should change the `answer.value` variable.'); 91 | for(var i = 0; i < array.length; i++) { 92 | assert(array[i].length == 4, 'The `value` of the element `answer` was ' + array[i] + ' which is not exactly 4 characters long.'); 93 | } 94 | }); 95 | 96 | it('should set the `value` of element `attempt` to 0. @setAttempt', function() { 97 | assert(typeof window.setHiddenFields === "function",'a function named `setHiddenFields` was not found.'); 98 | window.setHiddenFields(); 99 | assert(document.getElementById('attempt').value == 0, 'The `value` of element `attempt` was "' + document.getElementById('attempt').value + '" which is not 0.'); 100 | }); 101 | 102 | it('should only run if the `value` of elements `attempt` or `answer` are empty. @preventClearing', function() { 103 | assert(typeof window.setHiddenFields === "function",'a function named `setHiddenFields` was not found.'); 104 | //make sure fields are populated before testing 105 | window.setHiddenFields(); 106 | var expectedAnswer = document.getElementById('answer').value; 107 | window.guess(); 108 | assert(expectedAnswer != '','`setHiddenFields` didn\'t change the `value` of the `answer` hidden field. `setHiddenFields` should change the `answer.value` variable.'); 109 | assert(expectedAnswer == document.getElementById('answer').value,'the `value` of element `answer` was changed even though `answer` had already been provided a `value`. Only update the `value` of `answer` when answer is empty; `(\'\')`'); 110 | }); 111 | }); 112 | 113 | describe('setMessage()', function(){ 114 | it('should accept one parameter and set the `innerHTML` of element `message` to that parameter. @setMessage', function(){ 115 | assert(typeof window.setMessage === "function",'a function named `setMessage` was not found.'); 116 | window.setMessage('test `setMessage` function.'); 117 | assert(document.getElementById('message').innerHTML == 'test `setMessage` function.', '`message`s `innerHTML` did not match the provided value.'); 118 | }); 119 | }); 120 | 121 | describe('validateInput()', function(){ 122 | it('should accept one parameter and return `true` only when that parameter\'s `length` is 4. @validateInput', function() { 123 | assert(typeof window.validateInput === "function",'a function named `validateInput` was not found.'); 124 | assert(window.validateInput('1234') == true,'`validateInput` did not return `true` when the `length` of `input` was 4. `validateInput` should return `true` when `input`\'s `length` is 4.'); 125 | assert(window.validateInput('123') == false, 'When the input\'s `length` was not 4 `validateInput` did not return `false`. `validateInput` should return `false` anytime `input` has a length that isn\'t 4.'); 126 | }); 127 | 128 | it('should run when `guess` runs @runValidation', function(){ 129 | assert(typeof window.validateInput === "function",'a function named `validateInput` was not found.'); 130 | document.getElementById('user-guess').value = "12345"; 131 | document.getElementById('attempt').value = "0"; 132 | var spy = sinon.spy(window, "validateInput"); 133 | window.guess(); 134 | assert(window.validateInput.calledOnce,'`validateInput` was not run when `guess` ran.'); 135 | assert(document.getElementById('message').innerHTML == "Guesses must be exactly 4 characters long.",'When `validateInput` returns `false` the `innerHTML` of `message` should be set to "Guesses must be exactly 4 characters long."'); 136 | assert(document.getElementById('attempt').value == 0, 'The `value` of `attempt` increased when `validateInput` returned `false`, this should only iterate when `validateInput` returns `true`.'); 137 | document.getElementById('user-guess').value = "1234"; 138 | document.getElementById('attempt').value = "0"; 139 | document.getElementById('message').innerHTML = ""; 140 | window.guess(); 141 | assert(document.getElementById('message').innerHTML != "Guesses must be exactly 4 characters long.",'The `innerHTML` of `message` should only be set to "Guesses must be exactly 4 characters long." when `validateInput` returns `false`, however; this message was set when `validateInput` returned `true`.'); 142 | assert(document.getElementById('attempt').value == 1, 'The `value` of `attempt` should increase by 1 when `validateInput` returns `true`.'); 143 | }); 144 | }); 145 | 146 | describe('getResults() @getResults', function(){ 147 | it('should accept one parameter and add to the `results` element\'s `innerHTML` based on how close the parameter is to the value of element `answer`. Each result should begin with `
\' + input + \'
` where `input` is the function\'s parameter. Foreach character in `input`: add `` if the character is in the element `answer`\s `value` and in the correct position, add `` if the character is in element `answer`\`s `value`, but is not in the correct position, and add `` if the character is not in `answer`\'s `value` at all. @getResults',function(){ 148 | assert(typeof window.getResults === "function",'a function named `getResults` was not found.'); 149 | //Setup 150 | document.getElementById('results').innerHTML = ''; 151 | document.getElementById('answer').value = '1234'; 152 | //first character correct, second wrong place, third and fouth wrong 153 | window.getResults('1300'); 154 | //add tests for starting and stopping divs? 155 | //add tests for each result? 156 | 157 | var oks = (document.getElementById('results').innerHTML.match(/glyphicon-ok/g) || []).length; 158 | var transfers = (document.getElementById('results').innerHTML.match(/glyphicon-transfer/g) || []).length; 159 | var removes = (document.getElementById('results').innerHTML.match(/glyphicon-remove/g) || []).length; 160 | 161 | assert(oks > 0, 'correct characters are not being marked as correct.'); 162 | assert(oks < 2, 'some characters are being incorrectly marked as correct.'); 163 | assert(transfers > 0, 'characters that were present in the answer, but not in the right position are not getting marked correctly.'); 164 | assert(transfers < 2, 'some characters are being incorrectly marked as in the answer, but not in the right position.'); 165 | assert(removes > 1, 'characters not present in the answer are not being marked as wrong.'); 166 | assert(removes < 3, 'some characters are being incorrectly marked as not in the anwser.'); 167 | }); 168 | 169 | it('should return `true` if element `answer`\'s `value` and parameter match, otherwise return `false` @correctGuess', function(){ 170 | assert(typeof window.getResults === "function",'a function named `getResults` was not found.'); 171 | document.getElementById('answer').value = '1234'; 172 | assert(window.getResults('1234'), 'did not return `true` when parameter matched element `answer`\'s `value`.'); 173 | assert(!window.getResults('0000'), 'did not return `false` whene parameter did not match element `answer`\'s `value`.'); 174 | }); 175 | }); 176 | 177 | describe('guess()', function(){ 178 | it('should call `setMessage` with value "You Win! :)" when `getResults` returns `true`. @winCondition', function(){ 179 | assert(typeof window.getResults === "function",'a function named `getResults` was not found.'); 180 | document.getElementById('answer').value = '1234'; 181 | document.getElementById('attempt').value = '1'; 182 | document.getElementById('user-guess').value = '1234'; 183 | window.guess(); 184 | assert(document.getElementById('message').innerHTML == 'You Win! :)', 'didn\'t set the message to "You Win! :)" when user input matched element `answer`\'s `value`'); 185 | }); 186 | 187 | it('should call `setMessage` with the value "You Lose! :(" when element `attempt`\'s `value` is 10 or more and `getResurts` returns false. @loseCondition', function(){ 188 | assert(typeof window.getResults === "function",'a function named `getResults` was not found.'); 189 | document.getElementById('answer').value = '1234'; 190 | document.getElementById('attempt').value = '10'; 191 | document.getElementById('user-guess').value = '4321'; 192 | window.guess(); 193 | assert(document.getElementById('message').innerHTML == 'You Lose! :(', 'didn\'t set the message to "You Lose! :(" when user input did not match element `answer`\'s `value` and `attempt`\'s `value` was 10 or more.'); 194 | }); 195 | 196 | it('should call `setMessage` with the value "Incorrect, try again." when element `answer`\'s `value` does not match user input, but `attempt`\'s `value` is less than 10. @tryAgain', function(){ 197 | assert(typeof window.getResults === "function",'a function named `getResults` was not found.'); 198 | document.getElementById('answer').value = '1234'; 199 | document.getElementById('attempt').value = '1'; 200 | document.getElementById('user-guess').value = '4321'; 201 | window.guess(); 202 | assert(document.getElementById('message').innerHTML == 'Incorrect, try again.', 'didn\'t set the message to "Incorrect, try again." when user input did not match element `answer`\'s `value` and `attempt`\'s `value` was less than 10.'); 203 | }); 204 | }); 205 | 206 | describe('showAnswer()', function(){ 207 | it('should accept one parameter and set the `innerHTML` of element `code` to match element `answer`\'s value. If parameter is `true` element `code` should have ` success` added to it\'s `className` otherwise ` failure` should be added to it\`s `className`. (Note: the spaces before ` success` and ` failure` are required) @showAnswer', function(){ 208 | assert(typeof window.showAnswer === "function",'a function named `showAnswer` was not found.'); 209 | var code = document.getElementById('code'); 210 | //test true 211 | window.setHiddenFields(); 212 | window.showAnswer(true); 213 | assert(document.getElementById('answer').value == code.innerHTML, '`code`\'s `innerHTML` did not match the `answer`\'s value when parameter was `true`.'); 214 | assert(code.className.indexOf(' success') != -1,'`code`\'s `className` did not have ` success` in it when parameter was `true`.'); 215 | //test false 216 | code.value = ''; 217 | code.className = 'code'; 218 | window.showAnswer(false); 219 | assert(document.getElementById('answer').value == code.innerHTML, '`code`\'s `innerHTML` did not match the `answer`\'s value when parameter was `false`.'); 220 | assert(code.className.indexOf(' failure') != -1,'`code`\'s `className` did not have ` failure` in it when parameter was `false`.'); 221 | }); 222 | }); 223 | 224 | describe('showReplay()', function(){ 225 | it('should set element `guessing-div`\'s `style` to "display:none" element `replay-div`\'s `style` to "display:block". @showReplay', function(){ 226 | assert(typeof window.showReplay === "function",'a function named `showReplay` was not found.'); 227 | window.showReplay(); 228 | assert(document.getElementById('guessing-div').style.display == "none", '`guessing-div`\'s `style` was not set to "display:none".'); 229 | assert(document.getElementById('replay-div').style.display == "block", '`replay-div`\'s `style` was not set to "display:block".'); 230 | }); 231 | }); 232 | 233 | describe('guess()', function(){ 234 | it('should call `showAnswer` and `showReplay` when either the player guesses correctly, or runs out of attempts. If player wins provide `true` to the `showAnswer` call, otherwise `false`. @winLoseConditions', function(){ 235 | assert(typeof window.showAnswer === "function",'a function named `showAnswer` was not found.'); 236 | assert(typeof window.showReplay === "function",'a function named `showReplay` was not found.'); 237 | //win outcome 238 | document.getElementById('answer').value = '1234'; 239 | document.getElementById('attempt').value = '1'; 240 | document.getElementById('user-guess').value = '1234'; 241 | window.guess(); 242 | assert(document.getElementById('guessing-div').style.display == "none", '`showReplay` was not run when game win condition was met.'); 243 | assert(document.getElementById('message').innerHTML == 'You Win! :)','`showAnswer` was not run when game win condition was met.'); 244 | //lose outcame 245 | document.getElementById('answer').value = '1234'; 246 | document.getElementById('attempt').value = '10'; 247 | document.getElementById('user-guess').value = '4321'; 248 | window.guess(); 249 | assert(document.getElementById('guessing-div').style.display == "none", '`showReplay` was not run when game lose condition was met.'); 250 | assert(document.getElementById('message').innerHTML == 'You Lose! :(','`showAnswer` was not run when game lose condition was met.'); 251 | }); 252 | }); 253 | }); 254 | --------------------------------------------------------------------------------