Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

todo solution #153

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
31d5aca
Adds bower.json with angular and bootstrap as dependencies and moves …
angusjfw Jan 31, 2016
0ff98a1
Adds and configures jasmine and karma for unit testing and protractor…
angusjfw Jan 31, 2016
ac12edb
Adds user stories and protractor test for page.
angusjfw Jan 31, 2016
8f737b4
Renames feature test file.
angusjfw Jan 31, 2016
e6b42d9
Creates app dir and node express sever.
angusjfw Jan 31, 2016
898af0b
Creates angular app in app.js and creates index.html with titles and…
angusjfw Jan 31, 2016
8fbacb7
Adds feature test for adding and displaying tasks.
angusjfw Jan 31, 2016
7e8a7bd
Adds unit test for todoListController model defaults.
angusjfw Jan 31, 2016
db59604
Moves project out of app/ dir, renames js/ to src/ and switches karma…
angusjfw Jan 31, 2016
216d605
Corrects naming capitalisation to match angular convention.
angusjfw Jan 31, 2016
4d1a01e
Creates controller with tasks array.
angusjfw Jan 31, 2016
9090b44
Adds controller, newTask input and addTask button to html and modifie…
angusjfw Jan 31, 2016
44f7910
Adds addTask function, passing feature test to add + display tasks.
angusjfw Jan 31, 2016
b732fc9
Adds unit test for addTask function.
angusjfw Jan 31, 2016
4451f7d
Adds feature and unit level tests for clearing newTask box.
angusjfw Jan 31, 2016
b5da99f
Improve test to get newTask input value using helper module.
angusjfw Jan 31, 2016
d8e16f6
Clears input field after use.
angusjfw Jan 31, 2016
ca377b8
Adds feature test for task completion and creates test helper module.
angusjfw Feb 1, 2016
971a100
Implements checking off tasks by adding checkbox to each task and bin…
angusjfw Feb 1, 2016
a4f3bd8
Adds unit test for task.done default and implements default in contro…
angusjfw Feb 1, 2016
59020a8
Adds feature test for filtering tasks.
angusjfw Feb 1, 2016
0d75d8a
Splits feature tests to multiple files and fixes filtering tests.
angusjfw Feb 1, 2016
3c2172c
Adds radio button group to interface with bootstrap styling and angul…
angusjfw Feb 1, 2016
6b07a9d
Adds unit tests for filtering tasks.
angusjfw Feb 1, 2016
a5bc695
Implements task filtering with function in controller linked to radio…
angusjfw Feb 1, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bower_components
node_modules
npm-debug.log
2 changes: 1 addition & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,5 @@
"yui" : false, // Yahoo User Interface

// Custom Globals
"globals" : { "toDoList": true, "angular": true } // additional predefined global variables
"globals" : { "todoList": true, "angular": true } // additional predefined global variables
}
55 changes: 10 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,38 @@
# Todo Challenge

* Deadline: submit completed pull request by 9am on Monday
* You may use whatever level of JavaScript you feel comfortable with - pure JS, jQuery, Angular, or whatever weird and wonderful framework you want to try. Extra points for DogeScript

Steps
-------

1. Fill out your learning plan self review for the week: https://github.com/makersacademy/learning_plan
2. Fork this repo, and clone to your local machine
3. Complete the following challenge:

## Challenge

![Todo mockup](https://makersacademy.mybalsamiq.com/mockups/2914603.png?key=afabb09aef2901a2732515ae4349c1ec0458294b)

Build a Todo list as a mini front-end application. You don't have to use a database, the front-end is more important - you can use an appropriate data structure stored somewhere in your JavaScript (this time only!)

Here are the core user stories:
#To-Do

### User Stories / Features
```
As a forgetful person
I want to store my tasks
So that I don't forget them
```

```
As a person with limited time
I want to instantly be able to update my todo list (adding and changing entries)
So that I have more time to think about other things
```

```
As a person who actually gets stuff done
I want to mark my tasks as done
So that I don't do them twice
```

Here are some other user stories you may choose to implement:

```
As a person with a lot of tasks
I want to be able to filter my tasks by "All", "Active", "Complete"
So that I only see the relevant tasks
```

```
As a person who doesn't like counting by hand
I want to see a total number of tasks
So that I don't have to count
```

```
As someone who has done lots of stuff
I want to be able to clear my completed tasks
So I never see them again
```

As you may imagine, implementing a To-do list is very much a solved problem. However, we are mainly interested in seeing how you approach testing and design. We are looking for:

* well written, well structured acceptance and unit tests
* clear and expressive JavaScript
* good HTML5 markup

Don't worry about deployment, and make sure you read the CONTRIBUTING.md when submitting a pull request.

## Extensions

* Deploy the app
* Create a persistance layer (e.g. MongoDB), or use LocalStorage or the filesystem through Node
* Make it look purdy (CSS) - try a framework like Bootstrap or Foundation

## CI

Read the `.travis.yml` if any of the steps below don't make sense!

* Make sure you have set up `npm test` in your `package.json` so that it runs your Karma tests
* Make sure you have your Protractor config file at `e2e/conf.js`
* Make sure `npm start` spins up whatever serves up your app - `http-server`, Sinatra or Node

Good luck!
27 changes: 27 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "todo_challenge",
"homepage": "https://github.com/angusjfw/todo_challenge",
"authors": [
"hibreez <[email protected]>"
],
"description": "todo app in angularjs",
"main": "",
"moduleType": [],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "^2.2.0",
"bootstrap": "^3.3.6",
"angular": "^1.4.9"
},
"devDependencies": {
"angular-mocks": "^1.4.9",
"angular-route": "^1.4.9"
}
}
73 changes: 73 additions & 0 deletions docs/CHALLENGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Todo Challenge

* Deadline: submit completed pull request by 9am on Monday
* You may use whatever level of JavaScript you feel comfortable with - pure JS, jQuery, Angular, or whatever weird and wonderful framework you want to try. Extra points for DogeScript

Steps
-------

1. Fill out your learning plan self review for the week: https://github.com/makersacademy/learning_plan
2. Fork this repo, and clone to your local machine
3. Complete the following challenge:

## Challenge

![Todo mockup](https://makersacademy.mybalsamiq.com/mockups/2914603.png?key=afabb09aef2901a2732515ae4349c1ec0458294b)

Build a Todo list as a mini front-end application. You don't have to use a database, the front-end is more important - you can use an appropriate data structure stored somewhere in your JavaScript (this time only!)

Here are the core user stories:

```
As a forgetful person
I want to store my tasks
So that I don't forget them

As a person with limited time
I want to instantly be able to update my todo list (adding and changing entries)
So that I have more time to think about other things

As a person who actually gets stuff done
I want to mark my tasks as done
So that I don't do them twice
```

Here are some other user stories you may choose to implement:

```
As a person with a lot of tasks
I want to be able to filter my tasks by "All", "Active", "Complete"
So that I only see the relevant tasks

As a person who doesn't like counting by hand
I want to see a total number of tasks
So that I don't have to count

As someone who has done lots of stuff
I want to be able to clear my completed tasks
So I never see them again
```

As you may imagine, implementing a To-do list is very much a solved problem. However, we are mainly interested in seeing how you approach testing and design. We are looking for:

* well written, well structured acceptance and unit tests
* clear and expressive JavaScript
* good HTML5 markup

Don't worry about deployment, and make sure you read the CONTRIBUTING.md when submitting a pull request.

## Extensions

* Deploy the app
* Create a persistance layer (e.g. MongoDB), or use LocalStorage or the filesystem through Node
* Make it look purdy (CSS) - try a framework like Bootstrap or Foundation

## CI

Read the `.travis.yml` if any of the steps below don't make sense!

* Make sure you have set up `npm test` in your `package.json` so that it runs your Karma tests
* Make sure you have your Protractor config file at `e2e/conf.js`
* Make sure `npm start` spins up whatever serves up your app - `http-server`, Sinatra or Node

Good luck!
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!doctype html>

<html lang="en" ng-app="TodoList">
<head>
<meta charset="utf-8">
<title>To-Do List</title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" href="todoList.css">
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>

<script src="src/app.js"></script>
<script src="src/todoListController.js"></script>
</head>

<body ng-controller="TodoListController as todoCtrl">
<div class="container">

<div class="page-header row">
<h1>to do:</h1>
</div>

<form class="form-horizontal">
<input type="text" name="new-task" ng-model="todoCtrl.newTask" />
<button class="btn-success" ng-click="todoCtrl.addTask()">Add Task</button>
</form>

<ul class="list-group">
<li ng-repeat="task in todoCtrl.tasks">
<input type="checkbox" ng-model="task.done" />
<span class="done-{{task.done}}">{{task.name}}</span>
</li>
</ul>

<div class="btn-group" data-toggle="buttons">
<label class="btn btn-primary active">
<input type="radio" id="filter-all" ng-model="todoCtrl.filter"
ng-value="all" ng-change="updateFilter" checked /> All
</label>
<label class="btn btn-primary">
<input type="radio" id="filter-active" ng-model="todoCtrl.filter"
ng-value="active" ng-change="updateFilter" /> Active
</label>
<label class="btn btn-primary">
<input type="radio" id="filter-completed" ng-model="todoCtrl.filter"
ng-value="completed" ng-change="updateFilter" /> Completed
</label>
</div>

</div>
</body>
</html>
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "todo_challenge",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/angusjfw/todo_challenge.git"
},
"author": "",
"license": "ISC",
"engines": {
"node": "5.4.0"
},
"devDependencies": {
"jasmine-core": "^2.4.1",
"karma": "^0.13.19",
"karma-chrome-launcher": "^0.2.2",
"karma-jasmine": "^0.3.6",
"karma-phantomjs-launcher": "^1.0.0",
"phantomjs": "^2.1.3",
"phantomjs-prebuilt": "^2.1.3",
"protractor": "^3.0.0"
},
"dependencies": {
"bower": "^1.7.7",
"express": "^4.13.4"
}
}
14 changes: 14 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
var express = require('express');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'require' is not defined.

var app = express();

app.set('port', (process.env.PORT || 5000));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'process' is not defined.

app.use(express.static(__dirname));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'__dirname' is not defined.


app.get('/', function(request, response) {
response.render('index');
});

app.listen(app.get('port'), function() {
console.log('Node app is running on port' + app.get('port'));
});

1 change: 1 addition & 0 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var todoList = angular.module('TodoList', []);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'angular' is not defined.

13 changes: 13 additions & 0 deletions src/todoListController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
todoList.controller('TodoListController', [function() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'todoList' is not defined.

var self = this;

self.tasks = [];

self.addTask = function() {
self.tasks.push({
name: self.newTask,
done: false
})
self.newTask = '';
}
}]);
28 changes: 28 additions & 0 deletions test/e2e/addingTasksSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var helper = require('./todoListHelper.js');

describe('TodoList', function() {
var title, pageHeader, newTaskEntry, addTaskButton, tasks;

beforeAll(function() {
browser.get('http://localhost:5000');
title = browser.getTitle();
pageHeader = element(by.className('page-header')).getText();
newTaskEntry = element(by.model('todoCtrl.newTask'));
addTaskButton = element(by.buttonText('Add Task'));
tasks = element.all(by.repeater('task in todoCtrl.tasks'));
});

it('has a title tag and page header text', function() {
expect(title).toEqual('To-Do List');
expect(pageHeader).toEqual('to do:');
});

describe('adding tasks', function() {
it('stores and displays new tasks entered by the user', function() {
newTaskEntry.sendKeys('collect dry cleaning');
addTaskButton.click();
expect(tasks.first().getText()).toEqual('collect dry cleaning');
expect(helper.getInputValue(newTaskEntry)).toEqual('');
});
});
});
7 changes: 7 additions & 0 deletions test/e2e/conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['addingTasksSpec.js', 'markingTasksSpec.js', 'filteringTasksSpec.js'],
capabilities: {
browserName: 'chrome'
}
}
41 changes: 41 additions & 0 deletions test/e2e/filteringTasksSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
var helper = require('./todoListHelper.js');

describe('TodoList', function() {
var newTaskEntry, tasks;
var allTasksButton, activeTasksButton, completedTasksButton;

beforeAll(function() {
browser.get('http://localhost:5000');
newTaskEntry = element(by.model('todoCtrl.newTask'));
tasks = element.all(by.repeater('task in todoCtrl.tasks'));
allTasksButton = element(by.id('filter-all')).element(by.xpath('..'));
activeTasksButton = element(by.id('filter-active')).element(by.xpath('..'));
completedTasksButton = element(by.id('filter-completed')).element(by.xpath('..'));
});

describe('filtering tasks', function() {
beforeAll(function() {
newTaskEntry.sendKeys('learn angular\n');
newTaskEntry.sendKeys('go shopping\n');
newTaskEntry.sendKeys('collect dry cleaning\n');
helper.completeTask(1);
});

it('can show all tasks', function() {
allTasksButton.click();
expect(helper.getTaskCount()).toEqual(3);
});

it('can filter for active tasks', function() {
activeTasksButton.click();
expect(helper.getTaskCount()).toEqual(2);
expect(tasks.first().getText()).toEqual('go shopping');
});

it('can filter for completed tasks', function() {
completedTasksButton.click();
expect(helper.getTaskCount()).toEqual(1);
expect(tasks.first().getText()).toEqual('learn angular');
});
});
});
Loading