acammies
2018-04-17 15c296b5993b494810ea4b43df01671e7e9fd22b
commit | author | age
15c296 1 # Revenge Of The Automated Testing
5a16fd 2
142de4 3 > The purpose of this lab is to develop and validate a new feature using TDD; and to promote the assured feature through the pipeline.
01245c 4
9e07af 5 ![comic-header](../images/exercise3/comic-header.png)
RH 6
7 [Image Source](https://cdn-images-1.medium.com/max/1600/1*wF_fSCH-gLYfMbkwb3gR2w.png)
8
01245c 9 ---
5a16fd 10
D 11 ## Learning Outcomes
01245c 12
5a16fd 13 As a learner you will be able to
01245c 14
142de4 15 * Understand the why behind TDD
D 16 * Implement a feature using TDD for frontend and backend
17 * Write end to end tests for the feature and run them in CI
5a16fd 18
D 19 ## Tools and Frameworks
01245c 20
5a16fd 21 > Name of tool - short description and link to docs or website
D 22
142de4 23 1.  [Jest](https://facebook.github.io/jest/) - Zero configuration testing platform
D 24 Jest is used by Facebook to test all JavaScript code including React applications. One of Jest's philosophies is to provide an integrated "zero-configuration" experience. We observed that when engineers are provided with ready-to-use tools, they end up writing more tests, which in turn results in more stable and healthy code bases.
25 1.  [Vue Test Utils](https://vue-test-utils.vuejs.org/en/) - Vue Test Utils is the official unit testing utility library for Vue.js.
26 1.  [Nightwatch.js](http://nightwatchjs.org/) - Nightwatch.js is an easy to use Node.js based End-to-End (E2E) testing solution for browser based apps and websites. It uses the powerful W3C WebDriver API to perform commands and assertions on DOM elements.
27 1.  [Mocha](https://mochajs.org/) - Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.
28 1.  [Sinon](http://sinonjs.org/) - Standalone test spies, stubs and mocks for JavaScript. 
29 Works with any unit testing framework.
5a16fd 30
D 31 ## Big Picture
01245c 32
5a16fd 33 This exercise begins cluster containing blah blah
D 34
01245c 35 ---
5a16fd 36
D 37 ## 10,000 Ft View
38
142de4 39 > The goal of this exercise is to add a new component to the application using TDD to create and validate it's behaviour. The User story we have been given is as follows:
5a16fd 40
142de4 41 *As a doer I want to mark todos as important so that I can keep track of and complete high prirority todos first*
01245c 42
142de4 43 _Acceptance Criteria_
D 44 - [ ] should be doable with a single click
45 - [ ] should add a red flag against the todo when marked important
46 - [ ] should remove the red colour flag on the flag when important removed
47 - [ ] should not affect existing todos
48
49 _On page load:_
50 - [ ] should display existing todos that are not marked important
51 - [ ] should display existing todos that are marked important with an red flag
5a16fd 52
D 53 ## Step by Step Instructions
3050f4 54 > This is a fairly structured guide with references to exact filenames and sections of text to be added.
5a16fd 55
2889a2 56 ### Part 0 - Introduction to TDD.
A 57 > _We'll show you what TDD is, and introduce our existing tests within our code._
58
59 #### Part 0a - What is TDD?
60 > _Here is a brief introduction of TDD and why we use it._
61
58caef 62 **Test Driven Development (TDD)** is a software development process that relies on the repetition of a very short development cycle. Requirements are turned into test cases, where the software is developed to pass the tests. In other words, it creates a safety net that serves to keep the developer's problems/bugs at bay while enabling the developer to refactor efficiently. This is opposed to software development that allows software to be added that is not proven to meet requirements.
2889a2 63
58caef 64 The TDD can be illustrated with the following diagram;
RH 65 ![TDD-diagram](../images/exercise3/TDD-lifecycle.jpg)
2889a2 66
A 67 #### Part 0b - Introduction to our tests.
68 > _In this part we will get familiar with the layout of our tests_
69
0976ea 70 2. We'll go into detail on how to write tests further on. To run your test suites run the following in the root of your `todolist-fe` or `todolist-api` repositories.
A 71 ```bash
72 $ npm run test
73 ```
74
75 2. This command will run all `*spec.js` files. Our test files are stored in the following places:
2889a2 76
91b04f 77   - There are 2 Api test files: `todolist-api/server/api/todo/todo.spec.js` & `todolist-api/server/mocks/mock-routes.spec.js`
A 78
79   - There are 12 Frontend test files stored in these directories: `todolist-fe/tests/unit/vue-components/*` & `todolist-fe/tests/unit/javascript/*`
0976ea 80
287627 81 2. Explanation of Mocha and js test syntax through Bananalogy:
0976ea 82 ![todoitem-fail-test](../images/exercise3/bdd-bananas.png)
A 83
15c296 84   * TODO - expand upon this.
A 85   * `describe` is used to group tests together. The string `"a bunch of ripe bananas"` is for human reading and allows you to identify tests.
86   * `it` is a statement that contains a test. It should contain an assertion such as `expect` or `should`. It follows the syntax of `describe` where the string passed in identifies the statement.
287627 87
A 88 2. Visit [mochajs.org](https://mochajs.org/) for more in-depth documentation.
89
01245c 90 ### Part 1 - Tests in our Pipeline
d1565e 91 > _In this exercise we will improve the pipeline created already by adding some unit tests for the frontend & backend along with some end to end tests (e2e) to validate the full solution_
5a16fd 92
d1565e 93 #### Part 1a - Unit tests
655873 94 > In this exercise we will execute our test for the frontend and backend locally. Once verified we will add them to Jenkins.
d1565e 95
655873 96 2. Before linking our automated testing to the pipeline we'll first ensure the tests run locally. Change to the `todolist-fe` directory and run `test`.
3050f4 97 ```bash
A 98 $ cd todolist-fe
99 $ npm run test
100 ```
101 <p class="tip" > 
8fc8df 102 `test` is an alias used that runs `vue-cli-service test` from the scripts object in `package.json`
3050f4 103 </p>
A 104 ![new-gitlab-proj](../images/exercise3/screenshot-scripts.png)
d1565e 105
3050f4 106 2. You should see an output similar to the following. The above command has run a test suite for every `*.spec.js` file. The table generated in the terminal shows the code coverage. We're going to be focusing on the unit tests for now.
A 107 ![new-gitlab-proj](../images/exercise3/test-run-locally.png)
108
109 2. Repeat the same process for `todolist-api` and verify that all the tests run.
110 ```bash
111 $ cd todolist-api
112 $ npm run test
113 ```
b81187 114
3050f4 115 2. Navigate to your instance of jenkins at `https://jenkins-<YOUR_NAME>-ci-cd.apps.s8.core.rht-labs.com/`. 
A 116 Click on `dev-todolist-fe-build` and then click the `configure` button on the left-hand side.
117 ![new-gitlab-proj](../images/exercise3/jenkins-configure-job.png)
118
119 2. Scroll to the `Build` part of the configuration page and add `scl enable rh-nodejs8 'npm run test'` below `scl enable rh-nodejs8 'npm install'`. Click `save` or `apply` at the bottom to save the changes.
120 ![new-gitlab-proj](../images/exercise3/jenkins-build-step.png)
121
8fc8df 122 2. Scroll to the `Post-build Actions` section and click `Add post-build action`. Select `Publish xUnit test result report`.
A 123 ![new-gitlab-proj](../images/exercise3/xunit-action.png)
b81187 124
A 125 2. Click the `Add` button under `Publish xUnit test result report` and select `JUnit`. In the pattern field enter `test-report.xml`. In the `Failed Tests Thresholds`  input box enter 0 under `Red Ball Total`. It should look a little something like this:
126 ![new-gitlab-proj](../images/exercise3/post-build-actions.png)
127
0976ea 128 2. Click `save` or `apply` at the bottom to save the changes. Run the `dev-todolist-fe-build` job and verify that this passes and the `build` and `bake` jobs are both triggered.
b81187 129
A 130 2. We're now going to deliberately fail a test to ensure that `bake` and `deploy` jobs aren't triggered if any tests fail. Go to `ListOfTodos.spec.js` in `/tests/unit/vue-components` and head to `line 38`. Add `not.` before `toHaveBeenCalled()`.
131 ![new-gitlab-proj](../images/exercise3/change-test-to-fail.png)
132
0976ea 133 2. Push this to Gitlab and run the build job.
b81187 134 ```bash
A 135 $ git add .
136 $ git commit -m "Deliberately failed test to test the pipeline stops me deploying broken code"
137 $ git push
138 ```
139
140 2. Rerun the `dev-todolist-fe-build` job. It should have failed and not run any other builds. 
141 ![new-gitlab-proj](../images/exercise3/jenkins-with-failing-build.png)
142
ff561b 143 2. Undo the changes you made to the `ListOfTodos.spec.js` file, commit your code and rerun the build. This should trigger a full `build --> bake --> deploy` of `todolist-fe`.
A 144
145 2. We're now going to do the same for the api. Head to the `configure` panel of the `dev-todolist-api-build` job. 
146
147 2. Add `scl enable rh-nodejs8 'npm run test:ci'` above `npm run build:ci`.
148 ![new-gitlab-proj](../images/exercise3/api-build-step.png)
149
227301 150 2. Scroll to the `Post-build Actions` section and click `Add post-build action`. Select `Publish xUnit test result report`.
ff561b 151
A 152 2. Click the `Add` button under `Publish xUnit test result report` and select `JUnit`. In the pattern field enter `reports/server/mocha/test-results.xml`. In the `Failed Tests Thresholds`  input box enter 0 under `Red Ball Total`. It should look a little something like this:
153 ![new-gitlab-proj](../images/exercise3/api-post-build.png)
154
155 2. We're now going to deliberately fail a test again to ensure that `bake` and `deploy` jobs aren't triggered if any tests fail. Go to `todo.spec.js` in `/server/api/todo` and head to `line 35`. Replace `false` with `true`. 
156 ![new-gitlab-proj](../images/exercise3/api-fail-build.png)
157
0976ea 158 2. Push this to Gitlab and run the build job.
ff561b 159 ```bash
A 160 $ git add .
161 $ git commit -m "Deliberately failed test to test the pipeline stops me deploying broken code"
162 $ git push
163 ```
164
0976ea 165 2. If successful this will fail the build and not run the `bake` or `deploy` jobs. 
A 166
167 <p class="tip">
168   NOTE - Don't forget to undo the changes that you made to your tests!
169 </p>
ff561b 170
d1565e 171 #### Part 1b - End to End tests (e2e)
227301 172 > TODO - this section is not complete
d1565e 173
01245c 174 2.  Add new part to the dev pipeline (`dev-todolist-fe-e2e`)
d1565e 175
227301 176 2. Add e2e tests and reporting to Jenkins
d1565e 177
142de4 178 ### Part 2 - TodoList new feature
d1565e 179 > _In this exercise we will introduce a new feature to create an important flag on the todos. In order to be able to build and test our feature we will use TDD_
D 180
142de4 181 *As a doer I want to mark todos as important so that I can keep track of and complete high prirority todos first*
d1565e 182
142de4 183 _Acceptance Criteria_
D 184 - [ ] should be doable with a single click
185 - [ ] should add a red flag against the todo when marked important
186 - [ ] should remove the red colour flag on the flag when important removed
187 - [ ] should not affect existing todos
d1565e 188
142de4 189 _On page load:_
D 190 - [ ] should display existing todos that are not marked important
191 - [ ] should display existing todos that are marked important with an red flag
d1565e 192
01245c 193 #### Part 1a - Create todolist-api tests
142de4 194 > Using [Mocha](https://mochajs.org/) as our test runner; we will now write some tests for backend functionality to persist our important-flag. The changes required to the backend are minimal but we will use TDD to create our test first, then implement the functionality.
01245c 195
D 196 3.  Create a new branch in your `todolist-api` app for our feature and push it to the remote
d1565e 197 ```bash
D 198 $ git checkout -b feature/important-flag
199 $ git push -u origin feature/important-flag
5a16fd 200 ```
D 201
01245c 202 3.  Navigate to the `server/api/todo/todo.spec.js` file. This contains all of the existing todo list api tests. These are broken down into simple `describe("api definition", function(){})` blocks which is BDD speak for how the component being tested should behave. Inside of each `it("should do something ", function(){})` statements we use some snappy language to illustrate the expected behaviour of the test. For example a `GET` request of the api is described and tested for the return to be of type Array as follows.
D 203 ```javascript
204 describe("GET /api/todos", function() {
205     it("should respond with JSON array", function(done) {
206         request(app)
207         .get("/api/todos")
208         .expect(200)
209         .expect("Content-Type", /json/)
210         .end(function(err, res) {
211             if (err) return done(err);
212             // Test goes here
213             res.body.should.be.instanceof(Array);
214             done();
215         });
142de4 216       });
01245c 217 });
D 218 ```
219 where:
142de4 220 _ `describe` is used to group tests together into a collection asserting some feature; for example the get all todos api.
D 221 _ `it` is an individual test statement and should contain an `expect` or a `should` statement asserting behaviour of the API under test.
222 _ `request` is a library for making http calls to the api.
223 _ `.expect(200)` asserts the HTTP Return Code
224 _ `res.body.should.be.instanceof(Array);` is the actual test call
225 _ `done();` tells the test runner that `mocha` has finished execution. This is needed as the http calls are asynchronous.
5a16fd 226
142de4 227 3.  With this knowledge; let's implement our test for the `important` flag. We expect the fronted to introduce a new property on each `todo` that gets passed to the backend called `important`. The API will need to handle this new property and pass it into the mongodb. Let's begin implementing this functionality by writing our test case. Navigate to the `PUT /api/todos` section of the test which should be at the bottom ![todo-api-tests](../images/exercise3/todo-api-tests.png).
01245c 228
142de4 229 3.  Before writing our test; let's first make sure all the existing tests are passing.
D 230 ```bash
01245c 231 $ npm run test
D 232 ```
233
142de4 234 3.  With all the tests passing; let's add our new one. For ease of completing this exercise a template of a new test has been written at the very end of the file. A PUT request responds in our API with the data that it just updated, so provided that MongoDB accepted the change, it will respond with an object that has the `important` property on it. To write our test; edit the `it("should ....", function(done) {` by completing the following:
01245c 235     * Edit the `it("should ...")` to describe the imporant flag we're testing
D 236     * Edit the `.send()` to include `important: true` property
237     * Add a new test assertion to check that `res.body.important` is `true` below the `// YOUR TEST GO HERE` line.
238 ```javascript
142de4 239 it("should mark todo as important and persist it", function(done) {
01245c 240     request(app)
D 241       .put("/api/todos/" + todoId)
142de4 242       .send({
D 243         title: "LOVE endpoint/server side testing!",
244         completed: true,
245         important: true
246       })
01245c 247       .expect(200)
D 248       .expect("Content-Type", /json/)
249       .end(function(err, res) {
142de4 250           if (err) return done(err);
D 251           res.body.should.have.property("_id");
252           res.body.title.should.equal("LOVE endpoint/server side testing!");
253           // YOUR TEST GO HERE
254           res.body.important.should.equal(true);
255           done();
01245c 256       });
142de4 257 });
01245c 258 ```
D 259
142de4 260 3.  Run your test. It should fail.
D 261 ```bash
01245c 262 $ npm run test
D 263 ```
264 ![fail-mocha](../images/exercise3/fail-mocha.png)
265
142de4 266 3.  With our test now failing; let's implement the feature. This is quite a simple change; all we need to do it update the `server/api/todo/todo.model.js` to allow an additional property on the schema called `important` of type Boolean.
01245c 267 ```javascript
D 268 const TodoSchema = new Schema({
142de4 269   title: String,
D 270   completed: Boolean,
271   important: Boolean
01245c 272 });
D 273 ```
274
142de4 275 3.  With your changes to the Database schema updated; re-run your tests.
D 276 ```bash
01245c 277 $ npm run test
D 278 ```
279
142de4 280 3.  Commit your code to the `feature/important-flag` branch and then merge onto the `develop` branch as follows
01245c 281 <p class="tip">
D 282 NOTE - At this point in a residency we would peer review the code before pushing it to develop or master branch!
283 </p>
142de4 284 ```bash
01245c 285 $ git add .
D 286 $ git commit -m "ADD backend schema updates"
287 $ git checkout develop
288 $ git merge feature/important-flag
289 $ git push --all
290 ```
291
292 #### Part 1b - Create todolist-fe tests
142de4 293 > Using [Jest](https://facebook.github.io/jest/) as our test runner and the `vue-test-utils` library for managing our vue components; we will now write some tests for fronted functionality to persist our important-flag. The changes required to the front end are quite large but we will use TDD to create our test first, then implement the functionality. 
01245c 294
142de4 295 Our TodoList App uses `vuex` to manage the state of the apps' todos and `axios` HTTP library to connect to the backend. `Vuex` is an opinionated framework for managing application state and has some key design features you will need to know to continue with the exercise. 
01245c 296
142de4 297 In `vuex` the application state is managed by a `store`. The `store` houses all the todos we have retrieved from the backend as well as the `getter` methods for our array of `todos`. In order to make changes to the store, we could call the store directly and update each todo item but as earlier said; vuex is an opinionated module with it's own way of updating the store. It is bad practice to call the store directly. 
D 298
299 There are two parts of the lifecycle to updating the store, the `actions` & `mutations`. When the user clicks a todo to mark it as complete; the `actions` are called. An action could involve a call to the backend or some pre-processing of the data. Once this is done, the change is committed to the store by calling the `mutation` function. A store should only ever be manipulated through a mutation function. Calling the mutation will then update the todo object in the apps local store for rendering in the view.
300
301 For example; when marking a todo as done in the UI, the following flow occurs
302     * The `TodoItem.vue` calls the `markTodoDone()` function which dispatches an event to the store.
303     * This calls the `updateTodo()` function in the `actions.js` file
304     * The action will update the backend db (calling our `todolist-api`) with our updated todo object.
305     * The action will commit the change to the store by calling the mutation method `MARK_TODO_COMPLETED`
306     * The `MARK_TODO_COMPLETED` will directly access the store object and update it with the new state value
307     * The `ListOfTodos.vue` component is watching the store for changes and when something gets updated it re-renders the `TodoItem.vue`.
308
309 3. Let's implement our feature by first creating a branch. Our new feature, important flag will behave in the same way as the `MARK_TODO_COMPLETED`. Create a new branch in your `todolist-fe` app for our feature and push it to the remote
01245c 310 ```bash
D 311 $ git checkout -b feature/important-flag
312 $ git push -u origin feature/important-flag
313 ```
d1565e 314
142de4 315 3. Let's get our tests running by executing a `--watch` on our tests. This will keep re-running our tests everytime there is a file change. All the tests should be passing when we begin
D 316 ```bash
317 $ npm run test -- --watch
318 ```
319
7d4ccd 320 3. There are three places we will add new tests to validate our function behaves as expected against the acceptance criteria from Feature Story supplied to us. We will need to write tests for our `TodoItem.vue` to handle having a red flag and that it is clickable. Our app is going to need to persist the changes in the backend so we'll want to make changes to our `actions.js` and `mutations.js` to keep the api and local copy of the store in sync. Let's start with our `TodoItem.vue` component. Open the `tests/unit/vue-components/TodoItem.spec.js` file. This has been templated with some example test to correspond with our A/Cs for speed of doing the lab. Find the describe block for our important flag tests. It is setup already with a `beforeEach()` hook for test setup.
142de4 321 ![important-flag-before](../images/exercise3/important-flag-before.png)
D 322
323 3. Each of our test cases has it's skeleton in place already for example the `TodoItem.vue` component takes a property of `todos` when rendering. This setup is already done for each of our tests so all we have to do is fill in our assertions.
324 ![todoitem-skeleton-tests](../images/exercise3/todoitem-skeleton-tests.png)
325
326 3. Let's implement the first test `it("should render a button with important flag"`. This test will assert if the button is present on the page and it contains the `.important-flag` CSS class. To implement this; add the expect statement as follows.  
327 ```javascript
328   it("should render a button with important flag", () => {
329     const wrapper = mount(TodoItem, {
330       propsData: { todoItem: importantTodo }
331     });
332     // TODO - test goes here!
333     expect(wrapper.find(".important-flag").exists()).toBe(true);
334   });
335 ```
336
337 3. Save the file and we should see in our test watch the test case has started failing because we have not yet implemented the feature!
338 ![todoitem-fail-test](../images/exercise3/todoitem-fail-test.png)
339
340 3. With a basic assertion in place, let's continue on to the next few tests. We want the important flag to be red when an item in the todolist is marked accordingly. Conversely we want it to be not red when false. Let's create a check for `.red-flag` CSS property to be present when imporant is true and not when false.
341 ```javascript
342   it("should set the colour to red when true", () => {
343     const wrapper = mount(TodoItem, {
344       propsData: { todoItem: importantTodo }
345     });
346     // TODO - test goes here!
347     expect(wrapper.find(".red-flag").exists()).toBe(true);
348   });
349   it("should set the colour to not red when false", () => {
350     importantTodo.important = false;
351     const wrapper = mount(TodoItem, {
352       propsData: { todoItem: importantTodo }
353     });
354     // TODO - test goes here!
355     expect(wrapper.find(".red-flag").exists()).toBe(false);
356   });
357 ```
358
7d4ccd 359 3. Finally, we want to make the flag clickable and for it to call a function to update the state. The final test in the `TodoItem.spec.js` we want to create should simulate this behaviour. Implement the `it("call makImportant when clicked", () ` test by first simulating the click of our important-flag and asserting the function `markImportant()` to write is executed.
142de4 360 ```javascript
D 361   it("call makImportant when clicked", () => {
362     const wrapper = mount(TodoItem, {
363       methods,
364       propsData: { todoItem: importantTodo }
365     });
366     // TODO - test goes here!
367     const input = wrapper.find(".important-flag");
368     input.trigger("click");
369     expect(methods.markImportant).toHaveBeenCalled();
370   });
371 ```
372
373 3. With our tests written for the feature's UI component, let's implement our code to pass the tests. Open up the `src/components/TodoItem.vue`. Each vue file is broken down into 3 sections
374     * The `<template></template>` contains the HTML of our component. This could include references to other Components also
375     * The `<script></script>` contains the JavaScript of our component and is essentially the logic for our component. It defines things like `properties`, `methods` and other `components`
376     * The `<style></style>` contains the encapsulated CSS of our component
377 Underneath the `</md-list-item>` tag, let's add a new md-button. Add a `.important-flag` class on the `md-button` and put the svg of the flag provided inside it.
378 ```html
379     </md-list-item>
380     <!-- TODO - SVG for use in Lab3 -->
381     <md-button class="important-flag">
382         <svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" ><path d="M0 0h24v24H0z" fill="none"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></svg>
383     </md-button>
384 ```
385
386 3. We should now see the first of our failing tests has started to pass. Running the app locally (using `npm run serve`) should show the flag appear in the UI. It is clickable but won't fire any events and the colour is not red as per our requirement. Let's continue to implement the colour change for the flag. On our `<svg/>` tag, add some logic to bind the css to the property of a `todo.important` by adding ` :class="{'red-flag': todoItem.important}"  `. This logic will apply the CSS class when `todo.important`  is true.
387 ```html
388 <md-button class="important-flag">
389     <svg :class="{'red-flag': todoItem.important}"  height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" ><path d="M0 0h24v24H0z" fill="none"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></svg>
390 </md-button>
391 ```
392
393 3. More tests should now be passing. Let's wire the click of the flag to an event in Javascript. In the methods section of the `<script></script>` tags in the Vue file, implement the `markImportant()`. We want to wire this to the action to updateTodo, just like we have in the `markCompleted()` call above it. We also need to pass and additional property to this method call `imporant`
394 ```javascript
395     markImportant() {
396       // TODO - FILL THIS OUT IN THE LAB EXERCISE
397       this.$store.dispatch("updateTodo", {id: this.todoItem._id, important: true});
398       console.info("INFO - Mark todo as important ", this.todoItem.important);
399     },
400 ```
401
402 3. Finally - let's connect the click button in the DOM to the Javascript function we've just created. In the template, add a click handler to the md-button to call the function `markImportant()` by adding ` @click="markImportant()"` to the `<md-button> tag 
403 ```html
404     <!-- TODO - SVG for use in Lab3 -->
405     <md-button class="important-flag" @click="markImportant()">
406         <svg :class="{'red-flag': todoItem.important}"  height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" ><path d="M0 0h24v24H0z" fill="none"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></svg>
407     </md-button>
408 ```
409
410 3. The previously failing tests should have started to pass now. With this work done, let's commit our code. On the terminal, run 
411 ```bash
412 $ git add .
413 $ git commit -m "Implementing the todoitem flag"
414 $ git push
415 ```
416
7d4ccd 417 3. If we try to use our important flag, we should see it's still not behaving as expected; this is because we're not updating the state of the app in response to the click event. We need to implement the `actions` and `mutations` for our feature. Let's start with the tests. Open the `tests/unit/javascript/actions.spec.js` and navigate to the bottom of the file. Our action should should commit the `MARK_TODO_IMPORTANT` to the mutations. Scroll to the end of the test file and implement the skeleton test by adding `expect(commit.firstCall.args[0]).toBe("MARK_TODO_IMPORTANT");` as the assertion.
142de4 418 ```javascript
D 419   it("should call MARK_TODO_IMPORTANT", done => {
420     const commit = sinon.spy();
421     state.todos = todos;
422     actions.updateTodo({ commit, state }, { id: 1, important: true }).then(() => {
423         // TODO - test goes here!
424         expect(commit.firstCall.args[0]).toBe("MARK_TODO_IMPORTANT");
425         done();
426     });
427   });
428 ```
429
7d4ccd 430 3. We should now have more failing tests, let's fix this by adding the call from our action to the mutation method. Open the `src/store/actions.js` file and scroll to the bottom to the `updateTodo()` method. Complete the if block by adding `commit("MARK_TODO_IMPORTANT", i);` as shown below.
142de4 431 ```javascript
D 432 updateTodo({ commit, state }, { id, important }) {
433     let i = state.todos.findIndex(todo => todo._id === id);
434     if (important) {
435         // TODO - add commit imporant here!
436         commit("MARK_TODO_IMPORTANT", i);
437     } else {
438         commit("MARK_TODO_COMPLETED", i);
439     }
440 ```
441
442 3. Finally, let's implement the `mutation` for our feature. Again, starting with the tests..... Open the `tests/unit/javascript/mutations.spec.js`. Our mutation method is responsible to toggling the todo's `important` property between true and 
443 false. Let's implement the tests for this functionality by setting imporant to be true and calling the method expecting the inverse and setting it to false and calling the method expecting the inverse. 
444 ```javascript
445   it("it should MARK_TODO_IMPORTANT as false", () => {
446     state.todos = importantTodos;
447     // TODO - test goes here!
448     mutations.MARK_TODO_IMPORTANT(state, 0);
449     expect(state.todos[0].important).toBe(false);
450   });
451
452   it("it should MARK_TODO_IMPORTANT as true", () => {
453     state.todos = importantTodos;
454     // TODO - test goes here!
455     state.todos[0].important = false;
456     mutations.MARK_TODO_IMPORTANT(state, 0);
457     expect(state.todos[0].important).toBe(true);
458   });
459 ```
460
461 3. With our tests running and failing, let's implement the feature to their spec. Open the `src/store/mutations.js` and add another function called `MARK_TODO_IMPORTANT` below the `MARK_TODO_COMPLETED` to toggle `todo.important` between true and false.
462 ```javascript
463   MARK_TODO_IMPORTANT(state, index) {
464     console.log("INFO - MARK_TODO_IMPORTANT");
465     state.todos[index].important = !state.todos[index].important;
466   }
467 ```
468
469 3. All our tests should now be passing. On the watch tab where they are running, hit `u` to re-run all tests and update any snapshots.
470
471 3. With all our tests now passing, let's commit our code. On the terminal, run
472 ```bash
473 $ git add .
474 $ git commit -m "Implementing the store and actions"
475 $ git push
476 ```
477
478 3. Before running a build in Jenkins, let's add our tests and code to the develop branch
479 <p class="tip">
480 NOTE - At this point in a residency we would peer review the code before pushing it to develop or master branch!
481 </p>
482 ```bash
483 $ git checkout develop
484 $ git merge feature/important-flag
485 $ git push --all
486 ```
487
488 3. Run a build in Jenkins. We should see the test trend increase as we've added more tests. Validate the flag is working as expected.
d1565e 489
D 490 #### Part 1c - Create todolist e2e tests
491
142de4 492 3.  TODO !!
5a16fd 493
01245c 494 ---
5a16fd 495
D 496 ## Extension Tasks
01245c 497
5a16fd 498 > _Ideas for go-getters. Advanced topic for doers to get on with if they finish early. These will usually not have a solution and are provided for additional scope._
D 499
01245c 500 * Add Auth to your application
D 501 * Do some other stuff
5a16fd 502
D 503 ## Additional Reading
01245c 504
5a16fd 505 > List of links or other reading that might be of use / reference for the exercise
D 506
507 ## Slide links
01245c 508
D 509 > link back to the deck for the supporting material