donal
2018-04-18 7f49cd77405e5349914c0c4caf20a593a4787903
commit | author | age
43f2f2 1 # Exercise Title
D 2
5285f8 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.
f6d2bd 4
D 5 ---
43f2f2 6
D 7 ## Learning Outcomes
f6d2bd 8
43f2f2 9 As a learner you will be able to
f6d2bd 10
5285f8 11 * Understand the why behind TDD
D 12 * Implement a feature using TDD for frontend and backend
13 * Write end to end tests for the feature and run them in CI
43f2f2 14
D 15 ## Tools and Frameworks
f6d2bd 16
43f2f2 17 > Name of tool - short description and link to docs or website
D 18
5285f8 19 1.  [Jest](https://facebook.github.io/jest/) - Zero configuration testing platform
D 20 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.
21 1.  [Vue Test Utils](https://vue-test-utils.vuejs.org/en/) - Vue Test Utils is the official unit testing utility library for Vue.js.
22 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.
23 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.
24 1.  [Sinon](http://sinonjs.org/) - Standalone test spies, stubs and mocks for JavaScript. 
25 Works with any unit testing framework.
43f2f2 26
D 27 ## Big Picture
f6d2bd 28
43f2f2 29 This exercise begins cluster containing blah blah
D 30
f6d2bd 31 ---
43f2f2 32
D 33 ## 10,000 Ft View
34
5285f8 35 > 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:
43f2f2 36
5285f8 37 *As a doer I want to mark todos as important so that I can keep track of and complete high prirority todos first*
f6d2bd 38
5285f8 39 _Acceptance Criteria_
D 40 - [ ] should be doable with a single click
41 - [ ] should add a red flag against the todo when marked important
42 - [ ] should remove the red colour flag on the flag when important removed
43 - [ ] should not affect existing todos
44
45 _On page load:_
46 - [ ] should display existing todos that are not marked important
47 - [ ] should display existing todos that are marked important with an red flag
43f2f2 48
D 49 ## Step by Step Instructions
91cc51 50 > This is a fairly structured guide with references to exact filenames and sections of text to be added.
43f2f2 51
D 52
f6d2bd 53 ### Part 1 - Tests in our Pipeline
D 54
bc2216 55 > _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_
43f2f2 56
bc2216 57 #### Part 1a - Unit tests
bc975e 58 > In this exercise we will execute our test for the frontend and backend locally. Once verified we will add them to Jenkins.
bc2216 59
bc975e 60 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`.
91cc51 61 ```bash
A 62 $ cd todolist-fe
63 $ npm run test
64 ```
65 <p class="tip" > 
60bca4 66 `test` is an alias used that runs `vue-cli-service test` from the scripts object in `package.json`
91cc51 67 </p>
A 68 ![new-gitlab-proj](../images/exercise3/screenshot-scripts.png)
bc2216 69
91cc51 70 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 71 ![new-gitlab-proj](../images/exercise3/test-run-locally.png)
72
73 2. Repeat the same process for `todolist-api` and verify that all the tests run.
74 ```bash
75 $ cd todolist-api
76 $ npm run test
77 ```
6e5072 78
91cc51 79 2. Navigate to your instance of jenkins at `https://jenkins-<YOUR_NAME>-ci-cd.apps.s8.core.rht-labs.com/`. 
A 80 Click on `dev-todolist-fe-build` and then click the `configure` button on the left-hand side.
81 ![new-gitlab-proj](../images/exercise3/jenkins-configure-job.png)
82
83 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.
84 ![new-gitlab-proj](../images/exercise3/jenkins-build-step.png)
85
60bca4 86 2. Scroll to the `Post-build Actions` section and click `Add post-build action`. Select `Publish xUnit test result report`.
A 87 ![new-gitlab-proj](../images/exercise3/xunit-action.png)
6e5072 88
A 89 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:
90 ![new-gitlab-proj](../images/exercise3/post-build-actions.png)
91
92 2. Click `save` or `apply` at the bottom to save the changes. Rerun the `dev-todolist-fe-build` job and verify that this passes and the `build` and `bake` jobs are both triggered.
93
94 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()`.
95 ![new-gitlab-proj](../images/exercise3/change-test-to-fail.png)
96
97 2. Push this to Gitlab and rerun the build job.
98 ```bash
99 $ git add .
100 $ git commit -m "Deliberately failed test to test the pipeline stops me deploying broken code"
101 $ git push
102 ```
103
104 2. Rerun the `dev-todolist-fe-build` job. It should have failed and not run any other builds. 
105 ![new-gitlab-proj](../images/exercise3/jenkins-with-failing-build.png)
106
2717b2 107 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 108
109 2. We're now going to do the same for the api. Head to the `configure` panel of the `dev-todolist-api-build` job. 
110
111 2. Add `scl enable rh-nodejs8 'npm run test:ci'` above `npm run build:ci`.
112 ![new-gitlab-proj](../images/exercise3/api-build-step.png)
113
4f979b 114 2. Scroll to the `Post-build Actions` section and click `Add post-build action`. Select `Publish xUnit test result report`.
2717b2 115
A 116 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:
117 ![new-gitlab-proj](../images/exercise3/api-post-build.png)
118
119 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`. 
120 ![new-gitlab-proj](../images/exercise3/api-fail-build.png)
121
122 2. Push this to Gitlab and rerun the build job.
123 ```bash
124 $ git add .
125 $ git commit -m "Deliberately failed test to test the pipeline stops me deploying broken code"
126 $ git push
127 ```
128
129 2. If successful this will fail the build and not run the `bake` or `deploy` jobs. Don't forget to remove the changes that you made to your tests!
130
bc2216 131 #### Part 1b - End to End tests (e2e)
8529b9 132 > _Unit tests are a great way to get immediate feedback as part of testing an application. End to end tests that drive user behaviour are another amazing way to assess an application is behaving as expected._
bc2216 133
8529b9 134 In this exercise we will add a new stage to our pipeline called `dev-todolist-fe-e2e` that will run after the deploy has been completed. End to end tests will use Nightwatchjs to orchestrate a selenium webdriver instance that controls the web browser; in this case Chrome!
D 135
136 2. Let's start by checking our tests execute locally. On the terminal move to the `todolist-fe` folder. Our end to end tests are stored in `tests/e2e/specs/`. The vuejs cli uses nightwatch and comes pre-configured to run tests against Chrome. We have created some additional configuration in the root of the project `nightwatch.config.js` to run headless in CI mode on Jenkins.
137 ```bash
138 $ cd todolist-fe
139 ```
140
141 2. Run the tests locally by executing the following. This should start the dev server and run the test. You may see the browser pop up and close while tests execute.
142 ```bash
143 $ npm run e2e
144 ```
e0761f 145 ![local-e2e](../images/exercise3/local-e2e.png)
8529b9 146
e0761f 147 2. With tests executing locally; let's add them to our Jenkins pipeline. To do this; we'll create a new job and connect it up to our `todolist-fe` jobs. Open Jenkins and create a `New Item` called `dev-todolist-fe-e2e`. Make this Job `Freestyle`.
8529b9 148
e0761f 149 2. On the configuration page; Set the Label for the job to run on as `jenkins-slave-npm` and a build parameter of `BUILD_TAG`
D 150 ![e2e-general](../images/exercise3/e2e-general.png)
bc2216 151
e0761f 152 2. On the Source Code Management tab; set the source code to git and add the url to your `todolist-fe` app. Set the branch to `refs/tags/${BUILD_TAG}`
D 153 ![e2e-git](../images/exercise3/e2e-git.png)
154
155 2. Set `Color ANSI Console Output` on the `Build Environment` section 
156
157 2. On the Build section; add a build step to execute shell and fill in the followin substituting the domain name and `YOUR_NAME` accordingly:
158 ```bash
159 export E2E_TEST_ROUTE="http://todolist-fe-<YOUR_NAME>-dev.apps.somedomain.com/"
160 scl enable rh-nodejs8 'npm install'
161 scl enable rh-nodejs8 'npm run e2e:ci'
162 ```
163 ![e2e-steps](../images/exercise3/e2e-steps.png)
164
165 2. Add a Post Build action to publish Junit test scores and add `reports/e2e/specs/*.xml` to the report location.
166 ![e2e-post-build](../images/exercise3/e2e-post-build.png)
167
7f49cd 168 2. Finally; connect the e2e job to our deploy by editing the post build actions on `dev-todolist-fe-deploy`. Set trigger parameterised build on other jobs to be `dev-todolist-fe-e2e` and set the params to the current ones.
D 169 ![e2e-trigger](../images/exercise3/e2e-trigger.png)
170
e0761f 171 2. Run the pipeline from the beginning to see the tests executed.
bc2216 172
5285f8 173 ### Part 2 - TodoList new feature
bc2216 174 > _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 175
5285f8 176 *As a doer I want to mark todos as important so that I can keep track of and complete high prirority todos first*
bc2216 177
5285f8 178 _Acceptance Criteria_
D 179 - [ ] should be doable with a single click
180 - [ ] should add a red flag against the todo when marked important
181 - [ ] should remove the red colour flag on the flag when important removed
182 - [ ] should not affect existing todos
bc2216 183
5285f8 184 _On page load:_
D 185 - [ ] should display existing todos that are not marked important
186 - [ ] should display existing todos that are marked important with an red flag
bc2216 187
f6d2bd 188 #### Part 1a - Create todolist-api tests
5285f8 189 > 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.
f6d2bd 190
D 191 3.  Create a new branch in your `todolist-api` app for our feature and push it to the remote
bc2216 192 ```bash
D 193 $ git checkout -b feature/important-flag
194 $ git push -u origin feature/important-flag
43f2f2 195 ```
D 196
f6d2bd 197 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 198 ```javascript
199 describe("GET /api/todos", function() {
200     it("should respond with JSON array", function(done) {
201         request(app)
202         .get("/api/todos")
203         .expect(200)
204         .expect("Content-Type", /json/)
205         .end(function(err, res) {
206             if (err) return done(err);
207             // Test goes here
208             res.body.should.be.instanceof(Array);
209             done();
210         });
5285f8 211       });
f6d2bd 212 });
D 213 ```
214 where:
5285f8 215 _ `describe` is used to group tests together into a collection asserting some feature; for example the get all todos api.
D 216 _ `it` is an individual test statement and should contain an `expect` or a `should` statement asserting behaviour of the API under test.
217 _ `request` is a library for making http calls to the api.
218 _ `.expect(200)` asserts the HTTP Return Code
219 _ `res.body.should.be.instanceof(Array);` is the actual test call
220 _ `done();` tells the test runner that `mocha` has finished execution. This is needed as the http calls are asynchronous.
43f2f2 221
5285f8 222 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).
f6d2bd 223
5285f8 224 3.  Before writing our test; let's first make sure all the existing tests are passing.
D 225 ```bash
f6d2bd 226 $ npm run test
D 227 ```
228
5285f8 229 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:
f6d2bd 230     * Edit the `it("should ...")` to describe the imporant flag we're testing
D 231     * Edit the `.send()` to include `important: true` property
232     * Add a new test assertion to check that `res.body.important` is `true` below the `// YOUR TEST GO HERE` line.
233 ```javascript
5285f8 234 it("should mark todo as important and persist it", function(done) {
f6d2bd 235     request(app)
D 236       .put("/api/todos/" + todoId)
5285f8 237       .send({
D 238         title: "LOVE endpoint/server side testing!",
239         completed: true,
240         important: true
241       })
f6d2bd 242       .expect(200)
D 243       .expect("Content-Type", /json/)
244       .end(function(err, res) {
5285f8 245           if (err) return done(err);
D 246           res.body.should.have.property("_id");
247           res.body.title.should.equal("LOVE endpoint/server side testing!");
248           // YOUR TEST GO HERE
249           res.body.important.should.equal(true);
250           done();
f6d2bd 251       });
5285f8 252 });
f6d2bd 253 ```
D 254
5285f8 255 3.  Run your test. It should fail.
D 256 ```bash
f6d2bd 257 $ npm run test
D 258 ```
259 ![fail-mocha](../images/exercise3/fail-mocha.png)
260
5285f8 261 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.
f6d2bd 262 ```javascript
D 263 const TodoSchema = new Schema({
5285f8 264   title: String,
D 265   completed: Boolean,
266   important: Boolean
f6d2bd 267 });
D 268 ```
269
5285f8 270 3.  With your changes to the Database schema updated; re-run your tests.
D 271 ```bash
f6d2bd 272 $ npm run test
D 273 ```
274
5285f8 275 3.  Commit your code to the `feature/important-flag` branch and then merge onto the `develop` branch as follows
f6d2bd 276 <p class="tip">
D 277 NOTE - At this point in a residency we would peer review the code before pushing it to develop or master branch!
278 </p>
5285f8 279 ```bash
f6d2bd 280 $ git add .
D 281 $ git commit -m "ADD backend schema updates"
282 $ git checkout develop
283 $ git merge feature/important-flag
284 $ git push --all
285 ```
286
287 #### Part 1b - Create todolist-fe tests
5285f8 288 > 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. 
f6d2bd 289
5285f8 290 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. 
f6d2bd 291
5285f8 292 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 293
294 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.
295
296 For example; when marking a todo as done in the UI, the following flow occurs
297     * The `TodoItem.vue` calls the `markTodoDone()` function which dispatches an event to the store.
298     * This calls the `updateTodo()` function in the `actions.js` file
299     * The action will update the backend db (calling our `todolist-api`) with our updated todo object.
300     * The action will commit the change to the store by calling the mutation method `MARK_TODO_COMPLETED`
301     * The `MARK_TODO_COMPLETED` will directly access the store object and update it with the new state value
302     * The `ListOfTodos.vue` component is watching the store for changes and when something gets updated it re-renders the `TodoItem.vue`.
303
304 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
f6d2bd 305 ```bash
D 306 $ git checkout -b feature/important-flag
307 $ git push -u origin feature/important-flag
308 ```
bc2216 309
5285f8 310 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 311 ```bash
312 $ npm run test -- --watch
313 ```
314
bc581a 315 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.
5285f8 316 ![important-flag-before](../images/exercise3/important-flag-before.png)
D 317
318 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.
319 ![todoitem-skeleton-tests](../images/exercise3/todoitem-skeleton-tests.png)
320
321 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.  
322 ```javascript
323   it("should render a button with important flag", () => {
324     const wrapper = mount(TodoItem, {
325       propsData: { todoItem: importantTodo }
326     });
327     // TODO - test goes here!
328     expect(wrapper.find(".important-flag").exists()).toBe(true);
329   });
330 ```
331
332 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!
333 ![todoitem-fail-test](../images/exercise3/todoitem-fail-test.png)
334
335 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.
336 ```javascript
337   it("should set the colour to red when true", () => {
338     const wrapper = mount(TodoItem, {
339       propsData: { todoItem: importantTodo }
340     });
341     // TODO - test goes here!
342     expect(wrapper.find(".red-flag").exists()).toBe(true);
343   });
344   it("should set the colour to not red when false", () => {
345     importantTodo.important = false;
346     const wrapper = mount(TodoItem, {
347       propsData: { todoItem: importantTodo }
348     });
349     // TODO - test goes here!
350     expect(wrapper.find(".red-flag").exists()).toBe(false);
351   });
352 ```
353
bc581a 354 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.
5285f8 355 ```javascript
D 356   it("call makImportant when clicked", () => {
357     const wrapper = mount(TodoItem, {
358       methods,
359       propsData: { todoItem: importantTodo }
360     });
361     // TODO - test goes here!
362     const input = wrapper.find(".important-flag");
363     input.trigger("click");
364     expect(methods.markImportant).toHaveBeenCalled();
365   });
366 ```
367
368 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
369     * The `<template></template>` contains the HTML of our component. This could include references to other Components also
370     * 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`
371     * The `<style></style>` contains the encapsulated CSS of our component
372 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.
373 ```html
374     </md-list-item>
375     <!-- TODO - SVG for use in Lab3 -->
376     <md-button class="important-flag">
377         <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>
378     </md-button>
379 ```
380
381 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.
382 ```html
383 <md-button class="important-flag">
384     <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>
385 </md-button>
386 ```
387
388 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`
389 ```javascript
390     markImportant() {
391       // TODO - FILL THIS OUT IN THE LAB EXERCISE
392       this.$store.dispatch("updateTodo", {id: this.todoItem._id, important: true});
393       console.info("INFO - Mark todo as important ", this.todoItem.important);
394     },
395 ```
396
397 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 
398 ```html
399     <!-- TODO - SVG for use in Lab3 -->
400     <md-button class="important-flag" @click="markImportant()">
401         <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>
402     </md-button>
403 ```
404
405 3. The previously failing tests should have started to pass now. With this work done, let's commit our code. On the terminal, run 
406 ```bash
407 $ git add .
408 $ git commit -m "Implementing the todoitem flag"
409 $ git push
410 ```
411
bc581a 412 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.
5285f8 413 ```javascript
D 414   it("should call MARK_TODO_IMPORTANT", done => {
415     const commit = sinon.spy();
416     state.todos = todos;
417     actions.updateTodo({ commit, state }, { id: 1, important: true }).then(() => {
418         // TODO - test goes here!
419         expect(commit.firstCall.args[0]).toBe("MARK_TODO_IMPORTANT");
420         done();
421     });
422   });
423 ```
424
bc581a 425 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.
5285f8 426 ```javascript
D 427 updateTodo({ commit, state }, { id, important }) {
428     let i = state.todos.findIndex(todo => todo._id === id);
429     if (important) {
430         // TODO - add commit imporant here!
431         commit("MARK_TODO_IMPORTANT", i);
432     } else {
433         commit("MARK_TODO_COMPLETED", i);
434     }
435 ```
436
437 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 
438 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. 
439 ```javascript
440   it("it should MARK_TODO_IMPORTANT as false", () => {
441     state.todos = importantTodos;
442     // TODO - test goes here!
443     mutations.MARK_TODO_IMPORTANT(state, 0);
444     expect(state.todos[0].important).toBe(false);
445   });
446
447   it("it should MARK_TODO_IMPORTANT as true", () => {
448     state.todos = importantTodos;
449     // TODO - test goes here!
450     state.todos[0].important = false;
451     mutations.MARK_TODO_IMPORTANT(state, 0);
452     expect(state.todos[0].important).toBe(true);
453   });
454 ```
455
456 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.
457 ```javascript
458   MARK_TODO_IMPORTANT(state, index) {
459     console.log("INFO - MARK_TODO_IMPORTANT");
460     state.todos[index].important = !state.todos[index].important;
461   }
462 ```
463
464 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.
465
466 3. With all our tests now passing, let's commit our code. On the terminal, run
467 ```bash
468 $ git add .
469 $ git commit -m "Implementing the store and actions"
470 $ git push
471 ```
472
473 3. Before running a build in Jenkins, let's add our tests and code to the develop branch
474 <p class="tip">
475 NOTE - At this point in a residency we would peer review the code before pushing it to develop or master branch!
476 </p>
477 ```bash
478 $ git checkout develop
479 $ git merge feature/important-flag
480 $ git push --all
481 ```
482
483 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.
bc2216 484
D 485 #### Part 1c - Create todolist e2e tests
486
e0761f 487 3. TODO !!
43f2f2 488
f6d2bd 489 ---
43f2f2 490
D 491 ## Extension Tasks
f6d2bd 492
43f2f2 493 > _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 494
e0761f 495 * Edit the `dev-todolist-fe-e2e` job so it takes a parameter of the `BUILD_TAG` and only checks out this tag when running the e2e
f6d2bd 496 * Do some other stuff
43f2f2 497
D 498 ## Additional Reading
f6d2bd 499
43f2f2 500 > List of links or other reading that might be of use / reference for the exercise
D 501
502 ## Slide links
f6d2bd 503
D 504 > link back to the deck for the supporting material