├── License.md ├── README.md ├── css ├── icomoon.css ├── normalize.css └── style.css ├── fonts ├── icomoon.eot ├── icomoon.svg ├── icomoon.ttf └── icomoon.woff ├── index.html ├── jasmine └── spec │ └── feedreader.js └── js └── app.js /License.md: -------------------------------------------------------------------------------- 1 | 2 | Copyright © 2012 - 2020, Udacity, Inc. 3 | 4 | Udacity hereby grants you a license in and to the Educational Content, including but not limited to homework assignments, programming assignments, code samples, and other educational materials and tools (as further described in the Udacity Terms of Use), subject to, as modified herein, the terms and conditions of the Creative Commons Attribution-NonCommercial- NoDerivs 3.0 License located at http://creativecommons.org/licenses/by-nc-nd/4.0 and successor locations for such license (the "CC License") provided that, in each case, the Educational Content is specifically marked as being subject to the CC License. 5 | 6 | Udacity expressly defines the following as falling outside the definition of "non-commercial": 7 | (a) the sale or rental of (i) any part of the Educational Content, (ii) any derivative works based at least in part on the Educational Content, or (iii) any collective work that includes any part of the Educational Content; 8 | (b) the sale of access or a link to any part of the Educational Content without first obtaining informed consent from the buyer (that the buyer is aware that the Educational Content, or such part thereof, is available at the Website free of charge); 9 | (c) providing training, support, or editorial services that use or reference the Educational Content in exchange for a fee; 10 | (d) the sale of advertisements, sponsorships, or promotions placed on the Educational Content, or any part thereof, or the sale of advertisements, sponsorships, or promotions on any website or blog containing any part of the Educational Material, including without limitation any "pop-up advertisements"; 11 | (e) the use of Educational Content by a college, university, school, or other educational institution for instruction where tuition is charged; and 12 | (f) the use of Educational Content by a for-profit corporation or non-profit entity for internal professional development or training. 13 | 14 | 15 | 16 | THE SERVICES AND ONLINE COURSES (INCLUDING ANY CONTENT) ARE PROVIDED "AS IS" AND "AS AVAILABLE" WITH NO REPRESENTATIONS OR WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. YOU ASSUME TOTAL RESPONSIBILITY AND THE ENTIRE RISK FOR YOUR USE OF THE SERVICES, ONLINE COURSES, AND CONTENT. WITHOUT LIMITING THE FOREGOING, WE DO NOT WARRANT THAT (A) THE SERVICES, WEBSITES, CONTENT, OR THE ONLINE COURSES WILL MEET YOUR REQUIREMENTS OR EXPECTATIONS OR ACHIEVE THE INTENDED PURPOSES, (B) THE WEBSITES OR THE ONLINE COURSES WILL NOT EXPERIENCE OUTAGES OR OTHERWISE BE UNINTERRUPTED, TIMELY, SECURE OR ERROR-FREE, (C) THE INFORMATION OR CONTENT OBTAINED THROUGH THE SERVICES, SUCH AS CHAT ROOM SERVICES, WILL BE ACCURATE, COMPLETE, CURRENT, ERROR- FREE, COMPLETELY SECURE OR RELIABLE, OR (D) THAT DEFECTS IN OR ON THE SERVICES OR CONTENT WILL BE CORRECTED. YOU ASSUME ALL RISK OF PERSONAL INJURY, INCLUDING DEATH AND DAMAGE TO PERSONAL PROPERTY, SUSTAINED FROM USE OF SERVICES. 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Overview 2 | 3 | In this project you are given a web-based application that reads RSS feeds. The original developer of this application clearly saw the value in testing, they've already included [Jasmine](http://jasmine.github.io/) and even started writing their first test suite! Unfortunately, they decided to move on to start their own company and we're now left with an application with an incomplete test suite. That's where you come in. 4 | 5 | 6 | ## Why this Project? 7 | 8 | Testing is an important part of the development process and many organizations practice a standard of development known as "test-driven development." This is when developers write tests first, before they ever start developing their application. All the tests initially fail and then they start writing application code to make these tests pass. 9 | 10 | Whether you work in an organization that uses test-driven development or in an organization that uses tests to make sure future feature development doesn't break existing features, it's an important skill to have! 11 | 12 | 13 | ## What will I learn? 14 | 15 | You will learn how to use Jasmine to write a number of tests against a pre-existing application. These will test the underlying business logic of the application as well as the event handling and DOM manipulation. 16 | 17 | 18 | ## How will this help my career? 19 | 20 | Writing effective tests requires analyzing multiple aspects of an application including the HTML, CSS and JavaScript - an extremely important skill when changing teams or joining a new company. 21 | 22 | Good tests give you the ability to quickly analyze whether new code breaks an existing feature within your codebase, without having to manually test all of the functionality. 23 | 24 | 25 | # Development Strategy 26 | 27 | For a refresher (or reference) before you begin writing code, we recommend reviewing the content from [JavaScript Testing](https://www.udacity.com/course/javascript-testing--ud549). Your project will be evaluated by a Udacity code reviewer according to the [Feed Reader Testing project rubric](https://review.udacity.com/#!/rubrics/18/view). Please review for detailed project requirements. 28 | 29 | 1. Familiarize yourself with the starter code 30 | * Open up `index.html` and review the functionality of the application within your browser 31 | * What is all the code in `app.js` doing? Be sure to read all code comments 32 | * Check out `style.css`. How is styling applied to the application? 33 | 2. Explore the Jasmine spec file in `feedreader.js` 34 | * This is the file in which you'll be writing your tests 35 | * Make sure to read all code comments here as well 36 | * Review the [Jasmine documentation](http://jasmine.github.io) if needed 37 | 3. Edit the `allFeeds` variable in `app.js` to make the provided test fail 38 | * See how Jasmine visualizes this failure in your application 39 | * Return the `allFeeds` variable to a passing state after reviewing the failed test 40 | 4. Write a test that loops through each feed in the `allFeeds` object and ensures it has a URL defined _and_ that the URL is not empty 41 | * For example, how would you use a `for...of` loop in this test? 42 | 5. Write a test that loops through each feed in the `allFeeds` object and ensures it has a name defined and that the name is not empty 43 | * Think about how you wrote the previous test. What are you testing for this time? 44 | 6. Write a new test suite named `"The menu"` 45 | * What are you `describe`-ing in this test suite? 46 | 7. Write a test that ensures the menu element is hidden by default 47 | * You'll have to analyze the HTML and the CSS to determine how the hiding/showing of the menu element is implemented 48 | * What code in `app.js` is directly involved with toggling the menu on and off? 49 | 8. Write a test that ensures the menu changes visibility when the menu icon is clicked. This test should have two expectations: does the menu display itself when clicked, and does it hide when clicked again? 50 | * Think about how you wrote the previous test. What is different this time around? 51 | * Which clickable element are you checking for? 52 | * How do you "simulate" a mouse click that element without actually clicking it? 53 | 9. Write a test suite named `"Initial Entries"` 54 | * What are you `describe`-ing in this test suite? 55 | 10. Write a test that ensures when the `loadFeed` function is called and completes its work, there is at least a single `.entry` element within the `.feed` container 56 | * How does Jasmine's `beforeEach()`function work? 57 | * How does the `loadFeed()` function in `app.js` work? Is it synchronous or asynchronous? 58 | 11. Write a test suite named `"New Feed Selection"` 59 | * What are you `describe`-ing in this test suite? 60 | 12. Write a test that ensures when a new feed is loaded by the `loadFeed` function that the content actually changes 61 | * How is this test different from the previous test? 62 | 63 | Additionally, note that: 64 | 65 | * No test should be dependent on the results of another 66 | * Callbacks should be used to ensure that feeds are loaded before they are tested 67 | * Error handling should be implemented for undefined variables and out-of-bound array access 68 | * When complete, all of your tests should pass 69 | 70 | When you're all finished, write a `README` file detailing all steps required to successfully run the application. If you have added additional tests, provide documentation for what these future features are and what the tests are checking for. 71 | 72 | # Contributing 73 | 74 | This repository is the starter code for _all_ Udacity students. Therefore, we most likely will not accept pull requests. 75 | 76 | # Archival Note 77 | This repository is deprecated; therefore, we are going to archive it. However, learners will be able to fork it to their personal Github account but cannot submit PRs to this repository. If you have any issues or suggestions to make, feel free to: 78 | - Utilize the https://knowledge.udacity.com/ forum to seek help on content-specific issues. 79 | - Submit a support ticket along with the link to your forked repository if (learners are) blocked for other reasons. Here are the links for the [retail consumers](https://udacity.zendesk.com/hc/en-us/requests/new) and [enterprise learners](https://udacityenterprise.zendesk.com/hc/en-us/requests/new?ticket_form_id=360000279131). -------------------------------------------------------------------------------- /css/icomoon.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icomoon'; 3 | src:url('../fonts/icomoon.eot?efsk18'); 4 | src:url('../fonts/icomoon.eot?#iefixefsk18') format('embedded-opentype'), 5 | url('../fonts/icomoon.woff?efsk18') format('woff'), 6 | url('../fonts/icomoon.ttf?efsk18') format('truetype'), 7 | url('../fonts/icomoon.svg?efsk18#icomoon') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | [class^="icon-"], [class*=" icon-"] { 13 | font-family: 'icomoon'; 14 | speak: none; 15 | font-style: normal; 16 | font-weight: normal; 17 | font-variant: normal; 18 | text-transform: none; 19 | line-height: 1; 20 | 21 | /* Better Font Rendering =========== */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | .icon-list:before { 27 | content: "\e600"; 28 | } 29 | -------------------------------------------------------------------------------- /css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | *, 2 | *:after, 3 | *:before: { 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | box-sizing: border-box; 9 | } 10 | 11 | body { 12 | color: #111; 13 | font-family: 'Roboto', sans-serif; 14 | font-weight: 300; 15 | margin: 0; 16 | } 17 | 18 | a { 19 | text-decoration: none; 20 | color: #111; 21 | } 22 | 23 | a:hover h2 { 24 | text-decoration: underline; 25 | } 26 | 27 | h1 { 28 | display: inline-block; 29 | font-weight: 100; 30 | margin: 0 0 0 0.5em; 31 | } 32 | 33 | h2 { 34 | font-weight: 400; 35 | margin: 0; 36 | } 37 | 38 | .header { 39 | background: #4caf50; 40 | color: #fff; 41 | position: fixed; 42 | top: 0; 43 | width: 100%; 44 | padding: 0.5em 1em; 45 | } 46 | 47 | .icon-list { 48 | font-size: 1.5em; 49 | color: #FFF; 50 | } 51 | 52 | .slide-menu { 53 | position: absolute; 54 | top: 3.5em; 55 | padding: 1em; 56 | background: #4caf50; 57 | height: 100%; 58 | width: 10em; 59 | transform: translate3d(0, 0, 0); 60 | transition: transform 0.2s; 61 | } 62 | 63 | .slide-menu ul { 64 | list-style: none; 65 | margin: 0; 66 | padding: 0; 67 | } 68 | 69 | .slide-menu li { 70 | padding: 0; 71 | } 72 | 73 | .slide-menu li a { 74 | color: #fff; 75 | display: block; 76 | padding: 0.5em 0; 77 | } 78 | 79 | .menu-hidden .slide-menu { 80 | transform: translate3d(-12em, 0, 0); 81 | transition: transform 0.2s; 82 | } 83 | 84 | .feed { 85 | margin: 4em 0 0; 86 | } 87 | 88 | .entry { 89 | border-bottom: 1px solid #ddd; 90 | padding: 1em; 91 | margin: 0.5em 0; 92 | } 93 | -------------------------------------------------------------------------------- /fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-feedreader/49dd8624987bd8cf0e0a9a2e3a5dac9d430ef1f9/fonts/icomoon.eot -------------------------------------------------------------------------------- /fonts/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-feedreader/49dd8624987bd8cf0e0a9a2e3a5dac9d430ef1f9/fonts/icomoon.ttf -------------------------------------------------------------------------------- /fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/udacity/frontend-nanodegree-feedreader/49dd8624987bd8cf0e0a9a2e3a5dac9d430ef1f9/fonts/icomoon.woff -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |