├── .github ├── stale.yml └── workflows │ └── test.yml ├── .gitignore ├── README.md ├── SpecRunner.html ├── img ├── aquaman.jpg ├── background.jpg ├── batman.jpg ├── captain-america.jpg ├── fantastic-four.jpg ├── flash.jpg ├── green-arrow.jpg ├── green-lantern.jpg ├── ironman.jpg ├── spiderman.jpg ├── superman.jpg ├── the-avengers.jpg └── thor.jpg ├── index.html ├── jasmine └── jasmine-2.8.0 │ ├── boot.js │ ├── console.js │ ├── ironhack-logo.png │ ├── jasmine-html.js │ ├── jasmine.css │ ├── jasmine.js │ └── jasmine_favicon.png ├── src ├── index.js └── memory.js ├── styles └── style.css └── tests └── memory.spec.js /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 21 5 | 6 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 7 | exemptLabels: 8 | - bug 9 | - enhancement 10 | 11 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 12 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 13 | daysUntilClose: 7 14 | 15 | # Label to use when marking as stale 16 | staleLabel: stale 17 | 18 | # Comment to post when marking as stale. Set to `false` to disable 19 | markComment: > 20 | This pull request has been automatically marked as stale because it didn't have any recent activity. It will be closed if no further activity occurs. Thank you 21 | for your contributions. 22 | closeComment: > 23 | This pull request is closed. Thank you. 24 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Automated Testing 2 | on: push 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Load code 8 | uses: actions/checkout@v2 9 | - name: Prepare environment 10 | uses: actions/setup-node@v2 11 | with: 12 | node-version: '14' 13 | check-latest: true 14 | - name: Install dependencies 15 | run: npm i 16 | - name: Run tests 17 | run: npm run test -- --ci --reporters=default --reporters=jest-junit 18 | - name: Reports the results of tests 19 | uses: IgnusG/jest-report-action@v2.3.3 20 | if: always() 21 | with: 22 | access-token: ${{ secrets.GITHUB_TOKEN }} 23 | run-name: test 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .vscode 4 | package-lock.json 5 | yarn.lock 6 | *.log 7 | lab-solution.html 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo_ironhack_blue 7](https://user-images.githubusercontent.com/23629340/40541063-a07a0a8a-601a-11e8-91b5-2f13e4e6b441.png) 2 | 3 | # LAB | DOM Memory Game 4 | 5 |
6 | 7 | 8 | ![Memory Game Board](https://i.imgur.com/H6GLZGQ.jpg) 9 | 10 |
11 | 12 |

Learning Goals

13 |
14 | Upon completion of this exercise, you will be able to: 15 | 16 | - Select HTML elements using JavaScript DOM methods and properties. 17 | - Access and modify content of HTML elements using JavaScript DOM properties. 18 | - Add and remove HTML elements to/from the DOM using JavaScript DOM methods and properties. 19 | - Add and remove event listeners to respond to user actions, such as button clicks. 20 | - Iterate over lists of HTML elements and perform actions on each element, (e.g., accessing values, adding or removing events). 21 | - Manipulate HTML element properties, values and attributes using JavaScript DOM methods and properties: `element.setAttribute()`, `element.getAttribute()`, `element.classList.add()`, `element.classList.remove()`, `element.classList.toggle()`, `classList`, `style`, `value`, and `type`. 22 | - Use classes and OOP to organize data, functionality, and game elements. 23 | - Create a simple 2d game using HTML, CSS, JavaScript, and DOM. 24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 | ## Introduction 34 | 35 | We just learned how to use JavaScript to manipulate DOM elements. Great! Let's practice a bit more and have fun while developing a game. 36 | 37 |
38 | 39 | ## Requirements 40 | 41 | - Fork this repo. 42 | 43 | - Clone this repo. 44 | 45 | 46 | 47 | ## Submission 48 | 49 | - Upon completion, run the following commands: 50 | 51 | ```bash 52 | git add . 53 | git commit -m "Solved lab" 54 | git push origin master 55 | ``` 56 | 57 | - Create a Pull Request so that your TAs can check your work. 58 | 59 | 60 | 61 |
62 | 63 | ## Test Your Code 64 | 65 | This LAB is equipped with unit tests to provide automated feedback on your lab progress. In case you want to check the tests, they are in the `tests/memory.spec.js` file. 66 | 67 | 68 | 69 | To run the tests and your JavaScript code, open the `SpecRunner.html` file using the [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) VSCode extension. 70 | 71 | 72 | 73 | To see the outputs of the `console.log` in your JavaScript code, open the [Console in the Developer Tools](https://developer.chrome.com/docs/devtools/open/#console). 74 | 75 |
76 | 77 | ## Instructions 78 | 79 | 80 | 81 | ### Iteration 0: The game rules 82 | 83 | Do you remember that game called Memory that you used to play with the actual paper cards? To win, you needed to memorize the position of the paired card. Well, the logic of the game we will be building is the same. 84 | 85 | - The game consists of an even number of cards (precisely, **24**) with a specific image on one side and a generic blue background on the other side. 86 | - Each image appears on two cards. 87 | 88 | **The game rules:** 89 | 90 | - When the game starts, all cards are turned face down. 91 | - The player then flips over two cards, selecting them by clicking on them. 92 | - If the selected two cards have the same image, they remain face up. Otherwise, the cards flip back over after a short time. 93 | 94 | The goal of the game is to get all the cards flipped face-up in the least number of tries. That means that a lower number of attempts scores better. 95 | 96 | 97 | 98 | 99 | 100 |
101 | 102 | ### Iteration 1: Initial set up 103 | 104 | First, you will do some routine work: we need to make sure that all files we need are connected to the file that is rendering cards in the browser. 105 | 106 | The file that is rendering the cards is actually `index.html`, so we have to **make sure that the _styles_ and _JS files_ are loading** when we open the game in the browser: 107 | 108 | - **styles**: link the provided CSS file `styles/style.css` in the `` of the `index.html` page, 109 | - **the logic**: take a look at the `src/index.js` and `src/memory.js` files. You already have one file for the logic and one file for the HTML/CSS interactions (DOM manipulation). Link these two file at the bottom of the `index.html` page. 110 | 111 | After you linking the files in `index.html` page, you should be able to see the board, the cards, and the score. 112 | 113 |
114 | 115 | 116 | 117 | ### Iteration 2: Plan your game 118 | 119 | In this iteration, you will work on the game logic. You can see this part, like defining the methods that will take care of the game logic. No visible result will be shown just yet, and we will make sure everything works properly just by printing everything in the console. 120 | 121 | 122 | 123 | You will be working in the `src/memory.js` file. 124 | 125 | 126 | 127 | The game logic for this game is pretty simple: 128 | 129 | 1. we need a `MemoryGame` class, 130 | 2. we need a _method_ to _shuffle_ cards, 131 | 3. we need a _method_ to _compare cards_, and 132 | 4. we need a _method_ to check if the game is finished. 133 | 134 | _Side note:_ We will make a single-player version of the game, which will simplify some of the logic. 135 | 136 | Let's do this step by step. 137 | 138 |
139 | 140 | #### Iteration 2.1: The `MemoryGame` class 141 | 142 | If you open `src/memory.js` file, you will see that it is preset for you: 143 | 144 | ```js 145 | class MemoryGame { 146 | constructor(cards) { 147 | this.cards = cards; 148 | // add the rest of the class properties here 149 | } 150 | shuffleCards() { 151 | // ... 152 | } 153 | checkIfPair(card1, card2) { 154 | // ... 155 | } 156 | checkIfFinished() { 157 | // ... 158 | } 159 | } 160 | ``` 161 | 162 | 1. The `MemoryGame` class: we created a `MemoryGame` class and, as we can see in its constructor, it will receive an array of cards as a parameter and set this array to a `this.cards` property. 163 | 2. We also need a `this.pickedCards` array, where we will be storing the cards the user has clicked so we can compare them. 164 | 3. Finally, a `this.pairsClicked` and `this.pairsGuessed` properties where will be adding every time a user choose and guess a pair. Go ahead and add these to the constructor. 165 | 166 |
167 | 168 | #### Iteration 2.2: The class methods 169 | 170 | 1. Create logic for the method `shuffleCards()` to shuffle the cards - every time you create a new game, the order of the cards should change. 171 | 172 | **Hint:** It would be a good idea to implement something like a [Fisher-Yates Shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). If you struggle with this method, you can skip it for the moment and go back to it later. 173 | 174 | 2. When a user picks 2 cards, we will need to check if they are the same. Let's create logic for the method `checkIfPair()`, which will receive two parameters, the names of both cards selected by the user (example: `'ironman'` and `'batman'`). The method will add 1 to our `pairsClicked` property, and if the cards are the same also add 1 to `pairsGuessed`. It should return `true` or `false` depending on the result of comparing both cards. 175 | 176 | So, to summarize, we will have to update _pairsClicked_ on every two open cards by a user - it doesn't matter if the cards are the same. If two cards that we are comparing are the same, then _pairsGuessed_ gets updated with +1. 177 | 178 | 3. Finally, we need to make sure our game ends, and for that, we can add some logic to the `checkIfFinished()` method. Here we need to check if our property `pairsGuessed` has reached _the numbers of pairs the game has_. 179 | 180 |
181 | 182 | 183 | ### Iteration 3: DOM & Interactions 184 | 185 | Once you have completed the implementation of the memory game logic or functionality, you will move forward to `src/index.js` and work on the DOM interactions. 186 | 187 | What do we consider as interaction is what happens when the user clicks on the card: 188 | 189 | - how do we get the movement/flipping sides effect, 190 | 191 | - how we keep the cards showing images if they are found to be the same and 192 | -how do we make cards flip back to the blue background if the cards are not the same? All the time, keep in mind, we need to work only with two cards at the same time. 193 | 194 |
195 | 196 | Think about the interactions your user and the game will have: basically, the user will click on elements of the page (cards) and receive some result - whether they guessed the pair or not. 197 | 198 | - The first thing that is done for us - each card's information is dynamically filled in the tiles, and the board is pre-filled with cards for us. As we want this behavior to be triggered as soon as the page loads, we need to wrap it under a `load` event. This is also already done for us. 199 | 200 | ```javascript 201 | // src/index.js 202 | 203 | window.addEventListener('load', (event) => { 204 | // some code goes here 205 | }); 206 | ``` 207 | 208 | - The other important interaction is the click event listener. On click on every single card, we can get some information about that specific card. This code snippet, which is also already provided for us, serves for that. 209 | 210 | ```javascript 211 | // src/index.js 212 | 213 | // Bind the click event of each element to a function 214 | document.querySelectorAll('.card').forEach((card) => { 215 | card.addEventListener('click', () => { 216 | // TODO: write some code here 217 | console.log('Card clicked: ', card); 218 | }); 219 | }); 220 | ``` 221 | 222 | To flip a card, you can have multiple approaches. We will give you two possible ways (but you can find even more than that): 223 | 224 | - Option 1: on click, add the class `turned` next to the class `card` to the `div` that represents each card - like in the following example: 225 | 226 | ```html 227 | 228 |
229 |
230 |
231 |
232 | 233 | 234 |
235 |
236 |
237 |
238 | ``` 239 | 240 | - Option 2: another alternative is to toggle the classes _back_ and _front_ when the user clicks on a card. For this functionality, the method `element.classList.toggle()` can be very helpful. This method receives a string as the first argument (the class to toggle). [It can also receive a second _optional_ argument with a boolean expression](https://stackoverflow.com/questions/23663151/whats-the-point-of-the-second-argument-in-element-classlist-toggle/23663302#23663302) (in that case, the class is added when the expression is true, and removed when the expression is false): 241 | 242 | ```javascript 243 | /* one argument */ 244 | el.classList.toggle('foobar'); 245 | // if it doesn't have the class 'foobar' --> add the class 'foobar' 246 | // if it already has the class 'foobar' --> remove the class 'foobar' 247 | 248 | /* two arguments */ 249 | el.classList.toggle('abc', someBool); 250 | // if someBool evaluates to true -> add the class 'abc' 251 | // if someBool evaluates to false -> remove the class 'abc' 252 | ``` 253 | 254 | Now when you have cards flipping from back to front and vice versa, you have to make sure you call `.checkIfPair(card1, card2)` method. If the two cards are the same, they should get class _blocked_, which is going to keep them flipped so we can see images. 255 | 256 | _Hint 1_: The array of picked cards can't ever hold more than two cards. 257 | _Hint 2_: Make sure you call `checkIfFinished` method to check if the condition for the end of the game is true, and if so, you can just alert the end, or be more creative and add some text on the canvas - displaying _You won!!!_ 258 | 259 |
260 | 261 | ## Extra Resources 262 | 263 | - [Fisher-Yates Shuffle](https://bost.ocks.org/mike/shuffle/) 264 | 265 |
266 | 267 | **Happy coding!** 💙 268 | -------------------------------------------------------------------------------- /SpecRunner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Jasmine Spec Runner v2.8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /img/aquaman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/aquaman.jpg -------------------------------------------------------------------------------- /img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/background.jpg -------------------------------------------------------------------------------- /img/batman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/batman.jpg -------------------------------------------------------------------------------- /img/captain-america.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/captain-america.jpg -------------------------------------------------------------------------------- /img/fantastic-four.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/fantastic-four.jpg -------------------------------------------------------------------------------- /img/flash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/flash.jpg -------------------------------------------------------------------------------- /img/green-arrow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/green-arrow.jpg -------------------------------------------------------------------------------- /img/green-lantern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/green-lantern.jpg -------------------------------------------------------------------------------- /img/ironman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/ironman.jpg -------------------------------------------------------------------------------- /img/spiderman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/spiderman.jpg -------------------------------------------------------------------------------- /img/superman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/superman.jpg -------------------------------------------------------------------------------- /img/the-avengers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/the-avengers.jpg -------------------------------------------------------------------------------- /img/thor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/img/thor.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Superhero Memory Game 8 | 9 | 10 | 11 |
12 |

Superhero Memory Game

13 |
14 |
15 |

Score

16 |

Pairs clicked: 0

17 |

Pairs guessed: 0

18 |
19 |
20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/boot.js: -------------------------------------------------------------------------------- 1 | /** 2 | Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. 3 | 4 | If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. 5 | 6 | The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. 7 | 8 | [jasmine-gem]: http://github.com/pivotal/jasmine-gem 9 | */ 10 | 11 | (function() { 12 | 13 | /** 14 | * ## Require & Instantiate 15 | * 16 | * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. 17 | */ 18 | window.jasmine = jasmineRequire.core(jasmineRequire); 19 | 20 | /** 21 | * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. 22 | */ 23 | jasmineRequire.html(jasmine); 24 | 25 | /** 26 | * Create the Jasmine environment. This is used to run all specs in a project. 27 | */ 28 | var env = jasmine.getEnv(); 29 | 30 | /** 31 | * ## The Global Interface 32 | * 33 | * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. 34 | */ 35 | var jasmineInterface = jasmineRequire.interface(jasmine, env); 36 | 37 | /** 38 | * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. 39 | */ 40 | extend(window, jasmineInterface); 41 | 42 | /** 43 | * ## Runner Parameters 44 | * 45 | * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. 46 | */ 47 | 48 | var queryString = new jasmine.QueryString({ 49 | getWindowLocation: function() { return window.location; } 50 | }); 51 | 52 | var filterSpecs = !!queryString.getParam("spec"); 53 | 54 | var catchingExceptions = queryString.getParam("catch"); 55 | env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); 56 | 57 | var throwingExpectationFailures = queryString.getParam("throwFailures"); 58 | env.throwOnExpectationFailure(throwingExpectationFailures); 59 | 60 | var random = queryString.getParam("random"); 61 | env.randomizeTests(random); 62 | 63 | var seed = queryString.getParam("seed"); 64 | if (seed) { 65 | env.seed(seed); 66 | } 67 | 68 | /** 69 | * ## Reporters 70 | * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). 71 | */ 72 | var htmlReporter = new jasmine.HtmlReporter({ 73 | env: env, 74 | onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, 75 | onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, 76 | onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); }, 77 | addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, 78 | getContainer: function() { return document.body; }, 79 | createElement: function() { return document.createElement.apply(document, arguments); }, 80 | createTextNode: function() { return document.createTextNode.apply(document, arguments); }, 81 | timer: new jasmine.Timer(), 82 | filterSpecs: filterSpecs 83 | }); 84 | 85 | /** 86 | * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. 87 | */ 88 | env.addReporter(jasmineInterface.jsApiReporter); 89 | env.addReporter(htmlReporter); 90 | 91 | /** 92 | * Filter which specs will be run by matching the start of the full name against the `spec` query param. 93 | */ 94 | var specFilter = new jasmine.HtmlSpecFilter({ 95 | filterString: function() { return queryString.getParam("spec"); } 96 | }); 97 | 98 | env.specFilter = function(spec) { 99 | return specFilter.matches(spec.getFullName()); 100 | }; 101 | 102 | /** 103 | * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. 104 | */ 105 | window.setTimeout = window.setTimeout; 106 | window.setInterval = window.setInterval; 107 | window.clearTimeout = window.clearTimeout; 108 | window.clearInterval = window.clearInterval; 109 | 110 | /** 111 | * ## Execution 112 | * 113 | * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. 114 | */ 115 | var currentWindowOnload = window.onload; 116 | 117 | window.onload = function() { 118 | if (currentWindowOnload) { 119 | currentWindowOnload(); 120 | } 121 | htmlReporter.initialize(); 122 | env.execute(); 123 | }; 124 | 125 | /** 126 | * Helper function for readability above. 127 | */ 128 | function extend(destination, source) { 129 | for (var property in source) destination[property] = source[property]; 130 | return destination; 131 | } 132 | 133 | }()); 134 | -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/console.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2017 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | function getJasmineRequireObj() { 24 | if (typeof module !== 'undefined' && module.exports) { 25 | return exports; 26 | } else { 27 | window.jasmineRequire = window.jasmineRequire || {}; 28 | return window.jasmineRequire; 29 | } 30 | } 31 | 32 | getJasmineRequireObj().console = function(jRequire, j$) { 33 | j$.ConsoleReporter = jRequire.ConsoleReporter(); 34 | }; 35 | 36 | getJasmineRequireObj().ConsoleReporter = function() { 37 | 38 | var noopTimer = { 39 | start: function(){}, 40 | elapsed: function(){ return 0; } 41 | }; 42 | 43 | function ConsoleReporter(options) { 44 | var print = options.print, 45 | showColors = options.showColors || false, 46 | onComplete = options.onComplete || function() {}, 47 | timer = options.timer || noopTimer, 48 | specCount, 49 | failureCount, 50 | failedSpecs = [], 51 | pendingCount, 52 | ansi = { 53 | green: '\x1B[32m', 54 | red: '\x1B[31m', 55 | yellow: '\x1B[33m', 56 | none: '\x1B[0m' 57 | }, 58 | failedSuites = []; 59 | 60 | print('ConsoleReporter is deprecated and will be removed in a future version.'); 61 | 62 | this.jasmineStarted = function() { 63 | specCount = 0; 64 | failureCount = 0; 65 | pendingCount = 0; 66 | print('Started'); 67 | printNewline(); 68 | timer.start(); 69 | }; 70 | 71 | this.jasmineDone = function() { 72 | printNewline(); 73 | for (var i = 0; i < failedSpecs.length; i++) { 74 | specFailureDetails(failedSpecs[i]); 75 | } 76 | 77 | if(specCount > 0) { 78 | printNewline(); 79 | 80 | var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' + 81 | failureCount + ' ' + plural('failure', failureCount); 82 | 83 | if (pendingCount) { 84 | specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount); 85 | } 86 | 87 | print(specCounts); 88 | } else { 89 | print('No specs found'); 90 | } 91 | 92 | printNewline(); 93 | var seconds = timer.elapsed() / 1000; 94 | print('Finished in ' + seconds + ' ' + plural('second', seconds)); 95 | printNewline(); 96 | 97 | for(i = 0; i < failedSuites.length; i++) { 98 | suiteFailureDetails(failedSuites[i]); 99 | } 100 | 101 | onComplete(failureCount === 0); 102 | }; 103 | 104 | this.specDone = function(result) { 105 | specCount++; 106 | 107 | if (result.status == 'pending') { 108 | pendingCount++; 109 | print(colored('yellow', '*')); 110 | return; 111 | } 112 | 113 | if (result.status == 'passed') { 114 | print(colored('green', '.')); 115 | return; 116 | } 117 | 118 | if (result.status == 'failed') { 119 | failureCount++; 120 | failedSpecs.push(result); 121 | print(colored('red', 'F')); 122 | } 123 | }; 124 | 125 | this.suiteDone = function(result) { 126 | if (result.failedExpectations && result.failedExpectations.length > 0) { 127 | failureCount++; 128 | failedSuites.push(result); 129 | } 130 | }; 131 | 132 | return this; 133 | 134 | function printNewline() { 135 | print('\n'); 136 | } 137 | 138 | function colored(color, str) { 139 | return showColors ? (ansi[color] + str + ansi.none) : str; 140 | } 141 | 142 | function plural(str, count) { 143 | return count == 1 ? str : str + 's'; 144 | } 145 | 146 | function repeat(thing, times) { 147 | var arr = []; 148 | for (var i = 0; i < times; i++) { 149 | arr.push(thing); 150 | } 151 | return arr; 152 | } 153 | 154 | function indent(str, spaces) { 155 | var lines = (str || '').split('\n'); 156 | var newArr = []; 157 | for (var i = 0; i < lines.length; i++) { 158 | newArr.push(repeat(' ', spaces).join('') + lines[i]); 159 | } 160 | return newArr.join('\n'); 161 | } 162 | 163 | function specFailureDetails(result) { 164 | printNewline(); 165 | print(result.fullName); 166 | 167 | for (var i = 0; i < result.failedExpectations.length; i++) { 168 | var failedExpectation = result.failedExpectations[i]; 169 | printNewline(); 170 | print(indent(failedExpectation.message, 2)); 171 | print(indent(failedExpectation.stack, 2)); 172 | } 173 | 174 | printNewline(); 175 | } 176 | 177 | function suiteFailureDetails(result) { 178 | for (var i = 0; i < result.failedExpectations.length; i++) { 179 | printNewline(); 180 | print(colored('red', 'An error was thrown in an afterAll')); 181 | printNewline(); 182 | print(colored('red', 'AfterAll ' + result.failedExpectations[i].message)); 183 | 184 | } 185 | printNewline(); 186 | } 187 | } 188 | 189 | return ConsoleReporter; 190 | }; 191 | -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/ironhack-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/jasmine/jasmine-2.8.0/ironhack-logo.png -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/jasmine-html.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2017 Pivotal Labs 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | jasmineRequire.html = function(j$) { 24 | j$.ResultsNode = jasmineRequire.ResultsNode(); 25 | j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); 26 | j$.QueryString = jasmineRequire.QueryString(); 27 | j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); 28 | }; 29 | 30 | jasmineRequire.HtmlReporter = function(j$) { 31 | 32 | var noopTimer = { 33 | start: function() {}, 34 | elapsed: function() { return 0; } 35 | }; 36 | 37 | function HtmlReporter(options) { 38 | var env = options.env || {}, 39 | getContainer = options.getContainer, 40 | createElement = options.createElement, 41 | createTextNode = options.createTextNode, 42 | onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, 43 | onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, 44 | onRandomClick = options.onRandomClick || function() {}, 45 | addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, 46 | filterSpecs = options.filterSpecs, 47 | timer = options.timer || noopTimer, 48 | results = [], 49 | specsExecuted = 0, 50 | failureCount = 0, 51 | pendingSpecCount = 0, 52 | htmlReporterMain, 53 | symbols, 54 | failedSuites = []; 55 | 56 | this.initialize = function() { 57 | clearPrior(); 58 | htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, 59 | createDom('div', {className: 'jasmine-banner'}, 60 | createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}), 61 | createDom('span', {className: 'jasmine-version'}, j$.version) 62 | ), 63 | createDom('ul', {className: 'jasmine-symbol-summary'}), 64 | createDom('div', {className: 'jasmine-labname'}), 65 | createDom('div', {className: 'jasmine-alert'}), 66 | createDom('div', {className: 'jasmine-results'}, 67 | createDom('div', {className: 'jasmine-failures'}) 68 | ) 69 | ); 70 | getContainer().appendChild(htmlReporterMain); 71 | }; 72 | 73 | var totalSpecsDefined; 74 | this.jasmineStarted = function(options) { 75 | totalSpecsDefined = options.totalSpecsDefined || 0; 76 | timer.start(); 77 | }; 78 | 79 | var summary = createDom('div', {className: 'jasmine-summary'}); 80 | 81 | var topResults = new j$.ResultsNode({}, '', null), 82 | currentParent = topResults; 83 | 84 | this.suiteStarted = function(result) { 85 | currentParent.addChild(result, 'suite'); 86 | currentParent = currentParent.last(); 87 | }; 88 | 89 | this.suiteDone = function(result) { 90 | if (result.status == 'failed') { 91 | failedSuites.push(result); 92 | } 93 | 94 | if (currentParent == topResults) { 95 | return; 96 | } 97 | 98 | currentParent = currentParent.parent; 99 | }; 100 | 101 | this.specStarted = function(result) { 102 | currentParent.addChild(result, 'spec'); 103 | }; 104 | 105 | var failures = []; 106 | this.specDone = function(result) { 107 | if (noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { 108 | console.error('Spec \'' + result.fullName + '\' has no expectations.'); 109 | } 110 | 111 | if (result.status != 'disabled') { 112 | specsExecuted++; 113 | } 114 | 115 | if (!symbols){ 116 | symbols = find('.jasmine-symbol-summary'); 117 | } 118 | 119 | symbols.appendChild(createDom('li', { 120 | className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status, 121 | id: 'spec_' + result.id, 122 | title: result.fullName 123 | } 124 | )); 125 | 126 | if (result.status == 'failed') { 127 | failureCount++; 128 | 129 | var failure = 130 | createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, 131 | createDom('div', {className: 'jasmine-description'}, 132 | createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) 133 | ), 134 | createDom('div', {className: 'jasmine-messages'}) 135 | ); 136 | var messages = failure.childNodes[1]; 137 | 138 | for (var i = 0; i < result.failedExpectations.length; i++) { 139 | var expectation = result.failedExpectations[i]; 140 | var stringStart = expectation.stack.indexOf("at UserContext."); 141 | var shortStackTrace = expectation.stack.slice(stringStart); 142 | messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message)); 143 | messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, shortStackTrace)); 144 | } 145 | 146 | 147 | failures.push(failure); 148 | } 149 | 150 | if (result.status == 'pending') { 151 | pendingSpecCount++; 152 | } 153 | }; 154 | 155 | this.jasmineDone = function(doneResult) { 156 | var banner = find('.jasmine-banner'); 157 | var labName = find('.jasmine-labname'); 158 | var alert = find('.jasmine-alert'); 159 | var order = doneResult && doneResult.order; 160 | labName.appendChild(createDom('img', {src: 'jasmine/jasmine-2.8.0/ironhack-logo.png'}, '')); 161 | labName.appendChild(createDom('span', {}, 'Lab - Name of the LAB')); 162 | alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); 163 | 164 | banner.appendChild( 165 | createDom('div', { className: 'jasmine-run-options' }, 166 | createDom('span', { className: 'jasmine-trigger' }, 'Options'), 167 | createDom('div', { className: 'jasmine-payload' }, 168 | createDom('div', { className: 'jasmine-exceptions' }, 169 | createDom('input', { 170 | className: 'jasmine-raise', 171 | id: 'jasmine-raise-exceptions', 172 | type: 'checkbox' 173 | }), 174 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')), 175 | createDom('div', { className: 'jasmine-throw-failures' }, 176 | createDom('input', { 177 | className: 'jasmine-throw', 178 | id: 'jasmine-throw-failures', 179 | type: 'checkbox' 180 | }), 181 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')), 182 | createDom('div', { className: 'jasmine-random-order' }, 183 | createDom('input', { 184 | className: 'jasmine-random', 185 | id: 'jasmine-random-order', 186 | type: 'checkbox' 187 | }), 188 | createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order')) 189 | ) 190 | )); 191 | 192 | var raiseCheckbox = find('#jasmine-raise-exceptions'); 193 | 194 | raiseCheckbox.checked = !env.catchingExceptions(); 195 | raiseCheckbox.onclick = onRaiseExceptionsClick; 196 | 197 | var throwCheckbox = find('#jasmine-throw-failures'); 198 | throwCheckbox.checked = env.throwingExpectationFailures(); 199 | throwCheckbox.onclick = onThrowExpectationsClick; 200 | 201 | var randomCheckbox = find('#jasmine-random-order'); 202 | randomCheckbox.checked = env.randomTests(); 203 | randomCheckbox.onclick = onRandomClick; 204 | 205 | var optionsMenu = find('.jasmine-run-options'), 206 | optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'), 207 | optionsPayload = optionsMenu.querySelector('.jasmine-payload'), 208 | isOpen = /\bjasmine-open\b/; 209 | 210 | optionsTrigger.onclick = function() { 211 | if (isOpen.test(optionsPayload.className)) { 212 | optionsPayload.className = optionsPayload.className.replace(isOpen, ''); 213 | } else { 214 | optionsPayload.className += ' jasmine-open'; 215 | } 216 | }; 217 | 218 | if (specsExecuted < totalSpecsDefined) { 219 | var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; 220 | var skippedLink = addToExistingQueryString('spec', ''); 221 | alert.appendChild( 222 | createDom('span', {className: 'jasmine-bar jasmine-skipped'}, 223 | createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage) 224 | ) 225 | ); 226 | } 227 | var statusBarMessage = ''; 228 | var statusBarClassName = 'jasmine-bar '; 229 | 230 | if (totalSpecsDefined > 0) { 231 | statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); 232 | if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } 233 | statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed'; 234 | } else { 235 | statusBarClassName += 'jasmine-skipped'; 236 | statusBarMessage += 'No specs found'; 237 | } 238 | 239 | var seedBar; 240 | if (order && order.random) { 241 | seedBar = createDom('span', {className: 'jasmine-seed-bar'}, 242 | ', randomized with seed ', 243 | createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed) 244 | ); 245 | } 246 | 247 | alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar)); 248 | 249 | var errorBarClassName = 'jasmine-bar jasmine-errored'; 250 | var errorBarMessagePrefix = 'AfterAll '; 251 | 252 | for(var i = 0; i < failedSuites.length; i++) { 253 | var failedSuite = failedSuites[i]; 254 | for(var j = 0; j < failedSuite.failedExpectations.length; j++) { 255 | alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message)); 256 | } 257 | } 258 | 259 | var globalFailures = (doneResult && doneResult.failedExpectations) || []; 260 | for(i = 0; i < globalFailures.length; i++) { 261 | var failure = globalFailures[i]; 262 | alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message)); 263 | } 264 | 265 | var results = find('.jasmine-results'); 266 | results.appendChild(summary); 267 | 268 | summaryList(topResults, summary); 269 | 270 | function summaryList(resultsTree, domParent) { 271 | var specListNode; 272 | for (var i = 0; i < resultsTree.children.length; i++) { 273 | var resultNode = resultsTree.children[i]; 274 | if (filterSpecs && !hasActiveSpec(resultNode)) { 275 | continue; 276 | } 277 | if (resultNode.type == 'suite') { 278 | var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id}, 279 | createDom('li', {className: 'jasmine-suite-detail'}, 280 | createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) 281 | ) 282 | ); 283 | 284 | summaryList(resultNode, suiteListNode); 285 | domParent.appendChild(suiteListNode); 286 | } 287 | if (resultNode.type == 'spec') { 288 | if (domParent.getAttribute('class') != 'jasmine-specs') { 289 | specListNode = createDom('ul', {className: 'jasmine-specs'}); 290 | domParent.appendChild(specListNode); 291 | } 292 | var specDescription = resultNode.result.description; 293 | if(noExpectations(resultNode.result)) { 294 | specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; 295 | } 296 | if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { 297 | specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; 298 | } 299 | specListNode.appendChild( 300 | createDom('li', { 301 | className: 'jasmine-' + resultNode.result.status, 302 | id: 'spec-' + resultNode.result.id 303 | }, 304 | createDom('a', {href: specHref(resultNode.result)}, specDescription) 305 | ) 306 | ); 307 | } 308 | } 309 | } 310 | 311 | if (failures.length) { 312 | alert.appendChild( 313 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'}, 314 | createDom('span', {}, 'Spec List | '), 315 | createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures'))); 316 | alert.appendChild( 317 | createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'}, 318 | createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'), 319 | createDom('span', {}, ' | Failures '))); 320 | 321 | find('.jasmine-failures-menu').onclick = function() { 322 | setMenuModeTo('jasmine-failure-list'); 323 | }; 324 | find('.jasmine-spec-list-menu').onclick = function() { 325 | setMenuModeTo('jasmine-spec-list'); 326 | }; 327 | 328 | // Set the default list to be shown - test descriptions or failures 329 | // setMenuModeTo('jasmine-failure-list'); 330 | setMenuModeTo('jasmine-spec-list'); 331 | 332 | 333 | var failureNode = find('.jasmine-failures'); 334 | for (i = 0; i < failures.length; i++) { 335 | failureNode.appendChild(failures[i]); 336 | } 337 | } 338 | }; 339 | 340 | return this; 341 | 342 | function find(selector) { 343 | return getContainer().querySelector('.jasmine_html-reporter ' + selector); 344 | } 345 | 346 | function clearPrior() { 347 | // return the reporter 348 | var oldReporter = find(''); 349 | 350 | if(oldReporter) { 351 | getContainer().removeChild(oldReporter); 352 | } 353 | } 354 | 355 | function createDom(type, attrs, childrenVarArgs) { 356 | var el = createElement(type); 357 | 358 | for (var i = 2; i < arguments.length; i++) { 359 | var child = arguments[i]; 360 | 361 | if (typeof child === 'string') { 362 | el.appendChild(createTextNode(child)); 363 | } else { 364 | if (child) { 365 | el.appendChild(child); 366 | } 367 | } 368 | } 369 | 370 | for (var attr in attrs) { 371 | if (attr == 'className') { 372 | el[attr] = attrs[attr]; 373 | } else { 374 | el.setAttribute(attr, attrs[attr]); 375 | } 376 | } 377 | 378 | return el; 379 | } 380 | 381 | function pluralize(singular, count) { 382 | var word = (count == 1 ? singular : singular + 's'); 383 | 384 | return '' + count + ' ' + word; 385 | } 386 | 387 | function specHref(result) { 388 | return addToExistingQueryString('spec', result.fullName); 389 | } 390 | 391 | function seedHref(seed) { 392 | return addToExistingQueryString('seed', seed); 393 | } 394 | 395 | function defaultQueryString(key, value) { 396 | return '?' + key + '=' + value; 397 | } 398 | 399 | function setMenuModeTo(mode) { 400 | htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); 401 | } 402 | 403 | function noExpectations(result) { 404 | return (result.failedExpectations.length + result.passedExpectations.length) === 0 && 405 | result.status === 'passed'; 406 | } 407 | 408 | function hasActiveSpec(resultNode) { 409 | if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') { 410 | return true; 411 | } 412 | 413 | if (resultNode.type == 'suite') { 414 | for (var i = 0, j = resultNode.children.length; i < j; i++) { 415 | if (hasActiveSpec(resultNode.children[i])) { 416 | return true; 417 | } 418 | } 419 | } 420 | } 421 | } 422 | 423 | return HtmlReporter; 424 | }; 425 | 426 | jasmineRequire.HtmlSpecFilter = function() { 427 | function HtmlSpecFilter(options) { 428 | var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); 429 | var filterPattern = new RegExp(filterString); 430 | 431 | this.matches = function(specName) { 432 | return filterPattern.test(specName); 433 | }; 434 | } 435 | 436 | return HtmlSpecFilter; 437 | }; 438 | 439 | jasmineRequire.ResultsNode = function() { 440 | function ResultsNode(result, type, parent) { 441 | this.result = result; 442 | this.type = type; 443 | this.parent = parent; 444 | 445 | this.children = []; 446 | 447 | this.addChild = function(result, type) { 448 | this.children.push(new ResultsNode(result, type, this)); 449 | }; 450 | 451 | this.last = function() { 452 | return this.children[this.children.length - 1]; 453 | }; 454 | } 455 | 456 | return ResultsNode; 457 | }; 458 | 459 | jasmineRequire.QueryString = function() { 460 | function QueryString(options) { 461 | 462 | this.navigateWithNewParam = function(key, value) { 463 | options.getWindowLocation().search = this.fullStringWithNewParam(key, value); 464 | }; 465 | 466 | this.fullStringWithNewParam = function(key, value) { 467 | var paramMap = queryStringToParamMap(); 468 | paramMap[key] = value; 469 | return toQueryString(paramMap); 470 | }; 471 | 472 | this.getParam = function(key) { 473 | return queryStringToParamMap()[key]; 474 | }; 475 | 476 | return this; 477 | 478 | function toQueryString(paramMap) { 479 | var qStrPairs = []; 480 | for (var prop in paramMap) { 481 | qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); 482 | } 483 | return '?' + qStrPairs.join('&'); 484 | } 485 | 486 | function queryStringToParamMap() { 487 | var paramStr = options.getWindowLocation().search.substring(1), 488 | params = [], 489 | paramMap = {}; 490 | 491 | if (paramStr.length > 0) { 492 | params = paramStr.split('&'); 493 | for (var i = 0; i < params.length; i++) { 494 | var p = params[i].split('='); 495 | var value = decodeURIComponent(p[1]); 496 | if (value === 'true' || value === 'false') { 497 | value = JSON.parse(value); 498 | } 499 | paramMap[decodeURIComponent(p[0])] = value; 500 | } 501 | } 502 | 503 | return paramMap; 504 | } 505 | 506 | } 507 | 508 | return QueryString; 509 | }; 510 | -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/jasmine.css: -------------------------------------------------------------------------------- 1 | body { overflow-y: scroll; } 2 | 3 | .jasmine-labname { 4 | display: flex; 5 | align-items: center; 6 | justify-content: left; 7 | background-color: #2e354c; /* #32c3ff */ 8 | padding: 8px; 9 | } 10 | 11 | .jasmine-labname span { 12 | color: white; 13 | font-size: 19px; 14 | margin-left: 10px; 15 | } 16 | 17 | .jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } 18 | .jasmine_html-reporter a { text-decoration: none; } 19 | .jasmine_html-reporter a:hover { text-decoration: underline; } 20 | .jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } 21 | .jasmine_html-reporter .jasmine-banner, .jasmine_html-reporter .jasmine-symbol-summary, .jasmine_html-reporter .jasmine-summary, .jasmine_html-reporter .jasmine-result-message, .jasmine_html-reporter .jasmine-spec .jasmine-description, .jasmine_html-reporter .jasmine-spec-detail .jasmine-description, .jasmine_html-reporter .jasmine-alert .jasmine-bar, .jasmine_html-reporter .jasmine-stack-trace { padding-left: 9px; padding-right: 9px; } 22 | .jasmine_html-reporter .jasmine-banner { position: relative; } 23 | .jasmine_html-reporter .jasmine-banner .jasmine-title { background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAZCAMAAACGusnyAAACdlBMVEX/////AP+AgICqVaqAQICZM5mAVYCSSZKAQICOOY6ATYCLRouAQICJO4mSSYCIRIiPQICHPIeOR4CGQ4aMQICGPYaLRoCFQ4WKQICPPYWJRYCOQoSJQICNPoSIRICMQoSHQICHRICKQoOHQICKPoOJO4OJQYOMQICMQ4CIQYKLQICIPoKLQ4CKQICNPoKJQISMQ4KJQoSLQYKJQISLQ4KIQoSKQYKIQICIQISMQoSKQYKLQIOLQoOJQYGLQIOKQIOMQoGKQYOLQYGKQIOLQoGJQYOJQIOKQYGJQIOKQoGKQIGLQIKLQ4KKQoGLQYKJQIGKQYKJQIGKQIKJQoGKQYKLQIGKQYKLQIOJQoKKQoOJQYKKQIOJQoKKQoOKQIOLQoKKQYOLQYKJQIOKQoKKQYKKQoKJQYOKQYKLQIOKQoKLQYOKQYKLQIOJQoGKQYKJQYGJQoGKQYKLQoGLQYGKQoGJQYKKQYGJQIKKQoGJQYKLQIKKQYGLQYKKQYGKQYGKQYKJQYOKQoKJQYOKQYKLQYOLQYOKQYKLQYOKQoKKQYKKQYOKQYOJQYKKQYKLQYKKQIKKQoKKQYKKQYKKQoKJQIKKQYKLQYKKQYKKQIKKQYKKQYKKQYKKQIKKQYKJQYGLQYGKQYKKQYKKQYGKQIKKQYGKQYOJQoKKQYOLQYKKQYOKQoKKQYKKQoKKQYKKQYKJQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKJQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKLQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKKQYKmIDpEAAAA0XRSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAiIyQlJycoKissLS4wMTQ1Njc4OTo7PDw+P0BCQ0RISUpLTE1OUFNUVVdYWFlaW15fYGFiY2ZnaGlqa2xtb3BxcnN0dnh5ent8fX5/gIGChIWIioyNjo+QkZOUlZaYmZqbnJ2eoKGio6WmqKmsra6vsLGztre4ubq7vL2+wMHDxMjJysvNzs/Q0dLU1tfY2dvc3t/g4eLj5ebn6Onq6+zt7u/w8vP09fb3+Pn6+/z9/vkVQXAAAAMaSURBVHhe5dXxV1N1GMfxz2ABbDgIAm5VDJOyVDIJLUMaVpBWUZUaGbmqoGpZRSiGiRWp6KoZ5AB0ZY50RImZQIlahKkMYXv/R90dBvET/rJfOr3Ouc8v99zPec59zvf56j+vYKlViSf7250X4Mr3O29Tgq08BdGB4DhcekEJ5YkQKFsgWZdtj9JpV+I8xPjLFqkrsEIqO8PHSpis36jWazcqjEsfJjkvRssVU37SdIOu4XCf5vEJPsnwJpnRNU9JmxhMk8l1gehIrq7hTFjzOD+Vf88629qKMJVNltInFeRexRQyJlNeqd1iGDlSzrIUIyXbyFfm3RYprcQRe7lqtWyGYbfc6dT0R2vmdOOkX3u55C1rP37ftiH+tDby4r/RBT0w8TyEkr+epB9XgPDmSYYWbrhCuFYaIyw3fDQAXTnSkh+ANofiHmWf9l+FY1I90FdQTetstO00o23novzVsJ7uB3/C5TkbjRwZ5JerwV4iRWq9HFbFMaK/d0TYqayRiQPuIxxS3Bu8JWU90/60tKi7vkhaznez0a/TbVOKj5CaOZh6fWG6/Lyv9B/ZLR1gw/S/fpbeVD3MCW1li6SvWDOn65tr99/uvWtBS0XDm4s1t+sOHpG0kpBKx/l77wOSnxLpcx6TXmXLTPQOKYOf9Q1dfr8/SJ2mFdCvl1Yl93DiHUZvXeLJbGSzYu5gVJ2slbSakOR8dxCq5adQ2oFLqsE9Ex3L4qQO0eOPeU5x56bypXp4onSEb5OkICX6lDat55TeoztNKQcJaakrz9KCb95oD69IKq+yKW4XPjknaS52V0TZqE2cTtXjcHSCRmUO88e+85hj3EP74i9p8pylw7lxgMDyyl6OV7ZejnjNMfatu87LxRbH0IS35gt2a4ZjmGpVBdKK3Wr6INk8jWWSGqbA55CKgjBRC6E9w78ydTg3ABS3AFV1QN0Y4Aa2pgEjWnQURj9L0ayK6R2ysEqxHUKzYnLvvyU+i9KM2JHJzE4vyZOyDcOwOsySajeLPc8sNvPJkFlyJd20wpqAzZeAfZ3oWybxd+P/3j+SG3uSBdf2VQAAAABJRU5ErkJggg==') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } 24 | .jasmine_html-reporter .jasmine-banner .jasmine-version { margin-left: 14px; position: relative; top: 6px; } 25 | .jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } 26 | .jasmine_html-reporter .jasmine-version { color: #aaa; } 27 | .jasmine_html-reporter .jasmine-banner { margin-top: 14px; } 28 | .jasmine_html-reporter .jasmine-duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } 29 | .jasmine_html-reporter .jasmine-symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } 30 | .jasmine_html-reporter .jasmine-symbol-summary li { display: inline-block; height: 10px; width: 14px; font-size: 16px; } 31 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed { font-size: 14px; } 32 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-passed:before { color: #007069; content: "\02022"; } 33 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed { line-height: 9px; } 34 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } 35 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled { font-size: 14px; } 36 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-disabled:before { color: #bababa; content: "\02022"; } 37 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending { line-height: 17px; } 38 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-pending:before { color: #ba9d37; content: "*"; } 39 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty { font-size: 14px; } 40 | .jasmine_html-reporter .jasmine-symbol-summary li.jasmine-empty:before { color: #ba9d37; content: "\02022"; } 41 | .jasmine_html-reporter .jasmine-run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } 42 | .jasmine_html-reporter .jasmine-run-options .jasmine-trigger { cursor: pointer; padding: 8px 16px; } 43 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } 44 | .jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } 45 | .jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 46 | .jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } 47 | .jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } 48 | .jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } 49 | .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } 50 | .jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } 51 | .jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } 52 | .jasmine_html-reporter .jasmine-bar a { color: white; } 53 | .jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list, .jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures { display: none; } 54 | .jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list, .jasmine_html-reporter.jasmine-failure-list .jasmine-summary { display: none; } 55 | .jasmine_html-reporter .jasmine-results { margin-top: 14px; } 56 | .jasmine_html-reporter .jasmine-summary { margin-top: 14px; } 57 | .jasmine_html-reporter .jasmine-summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } 58 | .jasmine_html-reporter .jasmine-summary ul.jasmine-suite { margin-top: 7px; margin-bottom: 7px; } 59 | .jasmine_html-reporter .jasmine-summary li.jasmine-passed a { color: #007069; } 60 | .jasmine_html-reporter .jasmine-summary li.jasmine-failed a { color: #ca3a11; } 61 | .jasmine_html-reporter .jasmine-summary li.jasmine-empty a { color: #ba9d37; } 62 | .jasmine_html-reporter .jasmine-summary li.jasmine-pending a { color: #ba9d37; } 63 | .jasmine_html-reporter .jasmine-summary li.jasmine-disabled a { color: #bababa; } 64 | .jasmine_html-reporter .jasmine-description + .jasmine-suite { margin-top: 0; } 65 | .jasmine_html-reporter .jasmine-suite { margin-top: 14px; } 66 | .jasmine_html-reporter .jasmine-suite a { color: #333; } 67 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } 68 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } 69 | .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } 70 | .jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } 71 | .jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } 72 | .jasmine_html-reporter .jasmine-stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } 73 | -------------------------------------------------------------------------------- /jasmine/jasmine-2.8.0/jasmine_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ironhack-labs/lab-javascript-memory-game/e744529e695cc661dd69811bfc3a9dbfa472fefb/jasmine/jasmine-2.8.0/jasmine_favicon.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const cards = [ 2 | { name: 'aquaman', img: 'aquaman.jpg' }, 3 | { name: 'batman', img: 'batman.jpg' }, 4 | { name: 'captain america', img: 'captain-america.jpg' }, 5 | { name: 'fantastic four', img: 'fantastic-four.jpg' }, 6 | { name: 'flash', img: 'flash.jpg' }, 7 | { name: 'green arrow', img: 'green-arrow.jpg' }, 8 | { name: 'green lantern', img: 'green-lantern.jpg' }, 9 | { name: 'ironman', img: 'ironman.jpg' }, 10 | { name: 'spiderman', img: 'spiderman.jpg' }, 11 | { name: 'superman', img: 'superman.jpg' }, 12 | { name: 'the avengers', img: 'the-avengers.jpg' }, 13 | { name: 'thor', img: 'thor.jpg' }, 14 | { name: 'aquaman', img: 'aquaman.jpg' }, 15 | { name: 'batman', img: 'batman.jpg' }, 16 | { name: 'captain america', img: 'captain-america.jpg' }, 17 | { name: 'fantastic four', img: 'fantastic-four.jpg' }, 18 | { name: 'flash', img: 'flash.jpg' }, 19 | { name: 'green arrow', img: 'green-arrow.jpg' }, 20 | { name: 'green lantern', img: 'green-lantern.jpg' }, 21 | { name: 'ironman', img: 'ironman.jpg' }, 22 | { name: 'spiderman', img: 'spiderman.jpg' }, 23 | { name: 'superman', img: 'superman.jpg' }, 24 | { name: 'the avengers', img: 'the-avengers.jpg' }, 25 | { name: 'thor', img: 'thor.jpg' } 26 | ]; 27 | 28 | const memoryGame = new MemoryGame(cards); 29 | 30 | window.addEventListener('load', (event) => { 31 | let html = ''; 32 | memoryGame.cards.forEach((pic) => { 33 | html += ` 34 |
35 |
36 |
37 |
38 | `; 39 | }); 40 | 41 | // Add all the divs to the HTML 42 | document.querySelector('#memory-board').innerHTML = html; 43 | 44 | // Bind the click event of each element to a function 45 | document.querySelectorAll('.card').forEach((card) => { 46 | card.addEventListener('click', () => { 47 | // TODO: write some code here 48 | console.log(`Card clicked: ${card}`); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /src/memory.js: -------------------------------------------------------------------------------- 1 | class MemoryGame { 2 | constructor(cards) { 3 | this.cards = cards; 4 | // add the rest of the class properties here 5 | } 6 | 7 | shuffleCards() { 8 | // ... write your code here 9 | } 10 | 11 | checkIfPair(card1, card2) { 12 | // ... write your code here 13 | } 14 | 15 | checkIfFinished() { 16 | // ... write your code here 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /styles/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | 4 | background: url('../img/background.jpg') no-repeat; 5 | background-size: cover; 6 | font-family: 'Helvetica Neue', Arial, sans-serif; 7 | } 8 | 9 | #memory-board { 10 | background: #dddddd; 11 | width: 820px; 12 | height: 540px; 13 | padding: 70px; 14 | margin: 0px auto; 15 | border-radius: 84px; 16 | box-shadow: inset 0px 0px 20px -6px #615961; 17 | } 18 | 19 | .card { 20 | display: inline-block; 21 | perspective: 300px; 22 | transform-style: preserve-3d; 23 | position: relative; 24 | } 25 | 26 | .card.turned { 27 | pointer-events: none; 28 | } 29 | 30 | .card.turned .front { 31 | transform: rotateY(0deg); 32 | } 33 | .card.turned .back { 34 | transform: rotateY(180deg); 35 | } 36 | 37 | .card .back, 38 | .card .front { 39 | width: 71px; 40 | height: 71px; 41 | margin: 10px; 42 | padding: 20px; 43 | font-size: 64px; 44 | transition: transform 0.6s ease; 45 | } 46 | 47 | .card .back { 48 | background-color: #456783; 49 | } 50 | 51 | .card .front { 52 | position: absolute; 53 | left: 0; 54 | top: 0; 55 | transform: rotateY(-180deg) translateZ(1px); 56 | backface-visibility: hidden; 57 | } 58 | 59 | #score { 60 | background-color: rgba(215, 44, 44, 0.8); 61 | border-radius: 8px; 62 | font-size: 30px; 63 | font-family: Arial; 64 | width: 200px; 65 | padding: 20px; 66 | margin-left: 75%; 67 | } 68 | 69 | h1 { 70 | color: rgba(215, 40, 40, 0.9); 71 | font-weight: bolder; 72 | font-size: 67px; 73 | text-align: center; 74 | text-shadow: 0px 0px 20px #969696; 75 | } 76 | 77 | h2 { 78 | margin-top: 0; 79 | color: #456783; 80 | font-weight: bolder; 81 | font-size: 35px; 82 | text-align: center; 83 | text-shadow: 1px red; 84 | } 85 | 86 | p { 87 | font-weight: bolder; 88 | font-size: 20px; 89 | text-align: center; 90 | } 91 | -------------------------------------------------------------------------------- /tests/memory.spec.js: -------------------------------------------------------------------------------- 1 | const cardsArray = [ 2 | { name: 'aquaman', img: 'aquaman.jpg' }, 3 | { name: 'batman', img: 'batman.jpg' }, 4 | { name: 'captain america', img: 'captain-america.jpg' }, 5 | { name: 'fantastic four', img: 'fantastic-four.jpg' }, 6 | { name: 'flash', img: 'flash.jpg' }, 7 | { name: 'green arrow', img: 'green-arrow.jpg' }, 8 | { name: 'green lantern', img: 'green-lantern.jpg' }, 9 | { name: 'ironman', img: 'ironman.jpg' }, 10 | { name: 'aquaman', img: 'aquaman.jpg' }, 11 | { name: 'batman', img: 'batman.jpg' }, 12 | { name: 'captain america', img: 'captain-america.jpg' }, 13 | { name: 'fantastic four', img: 'fantastic-four.jpg' }, 14 | { name: 'flash', img: 'flash.jpg' }, 15 | { name: 'green arrow', img: 'green-arrow.jpg' }, 16 | { name: 'green lantern', img: 'green-lantern.jpg' }, 17 | { name: 'ironman', img: 'ironman.jpg' } 18 | ]; 19 | 20 | let memoryGame; 21 | 22 | describe('MemoryGame', () => { 23 | beforeEach(() => { 24 | memoryGame = new MemoryGame(cardsArray); 25 | }); 26 | 27 | it('should be declared', () => { 28 | expect(typeof MemoryGame).toBe('function'); 29 | }); 30 | 31 | describe('constructor method', () => { 32 | it('should receive `cards` as a parameter and store the cards in its own `cards` property', () => { 33 | expect(MemoryGame.constructor.length).toBe(1); 34 | expect(memoryGame.cards instanceof Array).toBe(true); 35 | }); 36 | 37 | it('should have a pickedCards property starting off as an empty array', () => { 38 | expect(memoryGame.pickedCards).toBeDefined(); 39 | expect(memoryGame.pickedCards instanceof Array).toBe(true); 40 | expect(memoryGame.pickedCards.length).toBe(0); 41 | }); 42 | 43 | it('should have a pairsClicked property starting off as 0', () => { 44 | expect(memoryGame.pairsClicked).toBe(0); 45 | }); 46 | 47 | it('should have a pairsGuessed property starting off as 0', () => { 48 | expect(memoryGame.pairsGuessed).toBeDefined(); 49 | }); 50 | }); 51 | 52 | describe('shuffleCards method', () => { 53 | beforeEach(() => { 54 | memoryGame = new MemoryGame(cardsArray); 55 | }); 56 | 57 | it('should be declared', () => { 58 | expect(typeof memoryGame.shuffleCards).toBe('function'); 59 | }); 60 | 61 | it('should return undefined if argument (cards array) is not passed', () => { 62 | expect(typeof new MemoryGame().shuffleCards()).toBe('undefined'); 63 | }); 64 | 65 | it('should return the shuffled (mixed) array of cards', () => { 66 | const formerCards = memoryGame.cards.map((card) => card.name).toString(); 67 | memoryGame.shuffleCards(); 68 | const newCards = memoryGame.cards.map((card) => card.name).toString(); 69 | expect(formerCards === newCards).toBe(false); 70 | }); 71 | }); 72 | 73 | describe('checkIfPair method', () => { 74 | it('should be declared', () => { 75 | expect(typeof memoryGame.checkIfPair).toBe('function'); 76 | }); 77 | 78 | it('should add 1 to `pairsClicked` when we call it', () => { 79 | memoryGame.checkIfPair('batman', 'ironman'); 80 | expect(memoryGame.pairsClicked).toBe(1); 81 | }); 82 | 83 | it('should return true when comparing cards that are the same', () => { 84 | expect(memoryGame.checkIfPair('ironman', 'ironman')).toBe(true); 85 | }); 86 | 87 | it('should return false when the comparing cards are not the same', () => { 88 | expect(memoryGame.checkIfPair('ironman', 'flash')).toBe(false); 89 | }); 90 | 91 | it('should add 1 to pairsGuessed if they are the same card', () => { 92 | memoryGame.pairsGuessed = 0; 93 | memoryGame.checkIfPair('ironman', 'ironman'); 94 | expect(memoryGame.pairsGuessed).toBe(1); 95 | }); 96 | 97 | it('should not add to pairsGuessed if the cards are not the same', () => { 98 | memoryGame.pairsGuessed = 0; 99 | memoryGame.checkIfPair('ironman', 'green lantern'); 100 | expect(memoryGame.pairsGuessed).toBe(0); 101 | }); 102 | }); 103 | 104 | describe('checkIfFinished method', () => { 105 | it('should be declared', () => { 106 | expect(typeof memoryGame.checkIfFinished).toBe('function'); 107 | }); 108 | 109 | it('should return false at the beginning of the game', () => { 110 | expect(memoryGame.checkIfFinished()).toBe(false); 111 | }); 112 | 113 | it("should return false if there's still some pairs to be guessed", () => { 114 | memoryGame.pairsGuessed = 4; 115 | expect(memoryGame.checkIfFinished()).toBe(false); 116 | }); 117 | 118 | it('should return true if all pairs are guessed', () => { 119 | memoryGame.pairsGuessed = 8; 120 | expect(memoryGame.checkIfFinished()).toBe(true); 121 | }); 122 | }); 123 | }); 124 | --------------------------------------------------------------------------------