Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "",
"main": "src/server.js",
"scripts": {
"start:fe:dev": "webpack-dev-server --hot --inline --content-base static",
"test": "tape -r babel-register 'src/**/*spec.js'"
},
"babel": {
Expand All @@ -19,7 +20,10 @@
"babel-preset-stage-0": "^6.5.0"
},
"devDependencies": {
"babel-loader": "^6.2.10",
"babel-register": "^6.14.0",
"tape": "^4.6.0"
"tape": "^4.6.0",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
}
}
Empty file added src/Todo.js
Empty file.
59 changes: 59 additions & 0 deletions src/Todo.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import test from 'tape';
import Todo from './Todo';

test( 'Todo', t => {
let actual, expected, todo;
let testTodo = {
id: 'test',
title: 'Test',
complete: true,
};

todo = Todo( testTodo ); // use new if using a constructor

actual = todo.getId();
expected = testTodo.id;
t.equal( actual, expected, 'with object, should store the id' );

actual = todo.getTitle();
expected = testTodo.title;
t.equal( actual, expected, 'with object, should store the title' );

actual = todo.isComplete();
expected = testTodo.complete;
t.equal( actual, expected, 'with object, should store the completion' );

todo = Todo( 'Test' ); // use new if using a constructor

actual = typeof todo.getId();
expected = 'string';
t.equal( actual, expected, 'with title, should generate an id' );

actual = todo.getTitle();
expected = 'Test';
t.equal( actual, expected, 'with title, should store the title' );

actual = todo.isComplete();
expected = false;
t.equal( actual, expected, 'with title, should default to not complete' );

todo = Todo( 'Test' ); // use new if using a constructor
todo.toggleComplete();
actual = todo.isComplete();
expected = true;
t.equal( actual, expected, 'toggleComplete should complete uncompleted todos' );

todo.toggleComplete();
actual = todo.isComplete();
expected = false;
t.equal( actual, expected, 'toggleComplete should uncomplete completed todos' );

todo = Todo( 'Test' ); // use new if using a constructor
todo.setTitle( 'New' );
actual = todo.getTitle();
expected = 'New';
t.equal( actual, expected, 'setTitle should change the title' );

t.end();
});

Empty file added src/TodoApp.js
Empty file.
70 changes: 70 additions & 0 deletions src/TodoApp.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import test from 'tape';
import TodoApp from './TodoApp';
import Todo from './Todo';

test( 'TodoApp', t => {
let actual, expected, app;

// app = TodoApp(); // use new if using a constructor

actual = app.isFiltered();
expected = false;
t.deepEqual( actual, expected, 'should begin without a filter' );

actual = app.getTodos();
expected = [];
t.deepEqual( actual, expected, 'should begin an empty set of todos' );

app.addTodo( 'Test' );

actual = app.getTodos().length;
expected = 1;
t.equal( actual, expected, 'addTodo should add a todo' );

let [ todo ] = app.getTodos();
actual = typeof todo.getTitle;
actual = 'function';
t.ok( actual, 'addTodo should add todos as Todo instances' );

actual = todo.getTitle();
expected = 'Test';
t.equal( actual, expected, 'addTodo should set the title of the todo to that passed' );

app.toggleFilter();
todo.toggleComplete();
actual = app.getTodos().length;
expected = 0;
t.equal( actual, expected, 'should use filter to hide todos' );

app.toggleFilter();
actual = app.getTodos().length;
expected = 1;
t.equal( actual, expected, 'should show all todos when filter removed' );

app.rmTodo( todo.getId() );
actual = app.getTodos().length;
expected = 0;
t.equal( actual, expected, 'rmTodo should remove a todo by its id' );

app.setTodos([ Todo( '1' ), Todo( '2' ) ]); // use new if using a constructor
actual = app.getTodos().length;
expected = 2;
t.equal( actual, expected, 'setTodos should replace all todos witht those provided' );

app = TodoApp(); // use new if using a constructor
app.addTodo({ id: '1', complete: false, title: 'One' });
app.addTodo({ id: '2', complete: false, title: 'Two' });

app.toggleComplete( '1' );
let [ todo1, todo2 ] = app.getTodos();
t.equal( todo1.isComplete(), true, 'toggleComplete should toggle the status of the todo' );
t.equal( todo2.isComplete(), false, 'toggleComplete should not toggle other todos' );

app.setTitle( '2', 'New' );
[ todo1, todo2 ] = app.getTodos();
t.equal( todo1.getTitle(), 'One', 'setTitle should not change other todos' );
t.equal( todo2.getTitle(), 'New', 'setTitle should change the title of the todo' );

t.end();
});

100 changes: 59 additions & 41 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,59 @@
export function double ( x ) {
return x * 2;
}

export function doubleXTimes ( x, num ) {
let result = x;

// i++ === i = i + 1
// what is the difference between using let and var?
for ( let i = 0; i < num; i++ ) {
// result = result * 2;
result = double( result ); // internal implementation detail
}

return result;
}

export const doubleEach = arr => arr.map( x => double( x ) );

// export function doubleEach ( arr ) {
// // let result = [];

// return arr.map( x => double( x ) );
// // return arr.map( function ( x ) {
// // return double ( x );
// // });

// // arr.forEach( x => result.push( double( x ) ) );
// // arr.forEach( function ( x, i ) {
// // // result.push( double( x ) );
// // result.push( double( arr[ i ] ) );
// // });

// // for ( let i = 0; i < arr.length; i++ ) {
// // // result.push( arr[i] * 2 );
// // result.push( double( arr[i] ) );
// // }

// // return result;
// }

function onReady () {
const addTodoForm = document.getElementById( 'addTodoForm' );
const todoList = document.getElementById( 'todoList' );
const newTodoText = document.getElementById( 'newTodoText' );

// create todo object array
var todos = [
{
title: "item1",
complete: false
}, {
title: "item2",
complete: false
}, {
title: "item3",
complete: true
}
];

function renderTheUi ( todos ) {
for (i=0; i < todos.length; i++) {
var newLi = document.createElement("li");
if (todos[i].complete) {
newLi.classList.add( "todo--complete" );
}
newLi.textContent = todos[i].title;
todoList.appendChild(newLi).addEventListener( 'click', function() {
this.classList.toggle( 'todo--complete' );
});
}
}

function createNewTodo ( title ) {
todos.push({ title: title, complete: false });
// re-render
renderTheUi( todos );
} // end createNewTodo function

// handle form submission and adding new todo items
addTodoForm.addEventListener( 'submit', function(event) {
event.preventDefault();
var title = newTodoText.value;

// add it to the todos array
createNewTodo(title);

// reset the input form value
newTodoText.value = '';
});

renderTheUi( todos );
} // end onReady()

if ( document.readyState !== 'loading' ) {
onReady();
} else {
document.addEventListener( 'DOMContentLoaded', onReady );
}

35 changes: 0 additions & 35 deletions src/spec.js
Original file line number Diff line number Diff line change
@@ -1,35 +0,0 @@
import test from 'tape';
import { double, doubleXTimes, doubleEach } from './index';

test( 'double fn', function ( test ) {
// GWT: Given-When-Then
const actual = double( 2 );
let expected = 4;

test.equal( actual, expected, 'should double the number' );

test.end();
});

test( 'doubleXTimes', function ( test ) {
const actual = doubleXTimes( 2, 4 );
const expected = 32;

test.equal( actual, expected, 'should double the number four times' );

test.end();
});

test( 'doubleEach', function ( test ) {
const actual = doubleEach([ 0, 1, 2, 3, 4 ]);
const expected = [ 0, 2, 4, 6, 8 ];

// { one: 1 } !== { one: 1 }
// { one: { two: 2 } } !== { one: { two: 2 } }
// but they are deeply equal

test.deepEqual( actual, expected, 'should double the number four times' );

test.end();
});

46 changes: 46 additions & 0 deletions src/spy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export const spyOn = ( target, method ) => {
let spy = {
calls: [],

reset () {
this.calls = [];
},
};

const oldMethod = target[ method ];
target[ method ] = ( ...args ) => {
spy.calls.push({
args: args,
});

return oldMethod.apply( target, args );
};

return spy;
};

export const createSpy = oldMethod => {
let spy;

spy = function ( ...args ) {
spy.calls.push({
args: args,
});

spy.called = true;

if ( oldMethod ) {
return oldMethod( ...args );
}
};

spy.reset = () => {
spy.calls = [];
spy.called = false;
};

spy.reset();

return spy;
};

6 changes: 6 additions & 0 deletions static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!DOCTYPE html><html>  <head>    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Todo App</title>    <style>      /**       * Block-Element-Modifer (BEM)       */      .todo--complete {        text-decoration: line-through;  color:red;      }    </style>  </head>  <body>    <h1>The Todo App!</h1>
    <form id="addTodoForm">      <label for="newTodoText">New Todo:</label>      <input type="text" id="newTodoText" />      <button type="submit">Add Todo!</button>    </form>
    <button id="toggleBtn">Toggle Filter</button>
    <ul id="todoList">    </ul>
    <script src="../src/index.js"></script>  </body></html>
31 changes: 31 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
var path = require( 'path' );
var webpack = require( 'webpack' );

module.exports = {
devtool: 'source-map',

entry: './src',

output: {
path: path.join( __dirname, 'dist' ),
filename: 'bundle.js',
publicPath: '/static/',
},

plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ sourceMap: true }),
],

module: {
loaders: [
{
test: /\.js$/,
loaders: [ 'babel-loader' ],
include: path.join( __dirname, 'src' ),
},
],
}
};