<file_sep>import superagent from 'superagent'
import {logError} from '../lib/utils'

// ACTION CREATORS
export const albumSet = albums => ({
  type: 'ALBUM_SET',
  payload: albums
})

export const albumCreate = album => ({
  type: 'ALBUM_CREATE',
  payload: album
})

export const albumUpdate = album => ({
  type: 'ALBUM_UPDATE',
  payload: album
})

export const albumDelete = album => ({
  type: 'ALBUM_DELETE',
  payload: album
})

// ASYNC ACTIONS
export const albumFetchRequest = () => dispatch => {
  return superagent.get(`${__API_URL__}/api/v1/album`)
  .then(res => dispatch(albumSet(res.body)))
  .catch(logError)
}

export const albumCreateRequest = album => (dispatch, getState) => {
  return superagent.post(`${__API_URL__}/api/v1/album`)
  .send(album)
  .then(res => dispatch(albumCreate(res.body)))
  .catch(logError)
}

export const albumUpdateRequest = album => dispatch => {
  return superagent.put(`${__API_URL__}/api/v1/album/${album._id}`)
  .send(album)
  .then(() => dispatch(albumUpdate(album)))
  .catch(logError)
}

export const albumDeleteRequest = album => dispatch => {
  return superagent.delete(`${__API_URL__}/api/v1/album/${album._id}`)
  .then(() => dispatch(albumDelete(album)))
  .catch(logError)
}
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 41: OAuth
===

## Learning Objectives
* Students will learn to set up a Google Cloud application
* Students will learn to implement OAuth2 on the server side

## Readings
* Skim [OAuth wiki](https://en.wikipedia.org/wiki/OAuth)
* Read [OAuth2 simplified](https://aaronparecki.com/oauth-2-simplified/)
* Read [Google OAuth2 Docs](https://developers.google.com/identity/protocols/OAuth2)
* Read [Google OAuth Server Side](https://developers.google.com/identity/protocols/OAuth2WebServer)
* Read [Google OpenId Docs](https://developers.google.com/identity/protocols/OpenIDConnect)

## OAUTH2.0
OAuth is an open standard for access delegation. It servers as a way to give users the ability to grant apps access to services, without giving the apps their password.

#### Access Code
* First the client needs to grant the application permission.
* To do this you need to give an anchor tag that will take them to the services authorization page
* The anchor tag should pass the following information through a query string to the authorization server
  * `response_type=code` indicates that your server wants to receive an authorization code
  * `client_id=<your client id>` tells the authorization server which app the user is granting access to
  * `redirect_uri=<your redirect uri>` tells the auth server which server endpoint to redirect to
  * `scope=<list of scopes>` tells the auth server what you want the user to give access to
  * `state=<anything you want>` a place where you can store info to pass to your server if you want

#### Access Token
* If the users grants access to the app the auth server will redirect to your redirect uri callback with a code
* Once you have a code you can exchange it for and access token by making a post request to the authorization server and providing the following information
  * `grant_type=authorization_code`
  * `code=<the code your received`
  * `redirect_uri=REDIRECT_URI` must be same as the redirect uri your client provided
  * `client_id=<your client id>` tells the auth server which app is making the requests
  * `client_secret=<your client secret>` authenticates that the app making the request is the app registered with the `client_id`
* once you get an Access Token you can use it to make API calls to the service on be have of that user
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 32: Combining Reducers
===

## Daily Plan
- Notes
    - Anything top of mind?

- Code Review
- Combining Reducers using Redux
    - Adds a second resource to our kanban board
- Testing our React/Redux App with Jest and Enzyme
- Lab preview

## Learning Objectives
* Students will learn to combine reducers to simplify the management of complex application state

## Readings
* Read [combine reducers](http://redux.js.org/docs/api/combineReducers.html)

## combineReducers
Reducers are great tools for defining state  and state changes to your applications. However as your application state gets more complex, your reducers become hard to manage. `combineReducers` is a redux method that enables you to create a single reducer from many reducers that define sub states and their interactions. a state returned from a combined reducer is an object where each _sub state reducer_ defines a property on that object.
<file_sep>'use strict'

// function inclusiveRandom(min, max) {
//   return Math.random() * (max - min) + 1
// }

module.exports = function randomNum(min, max) {
  return Math.random() * (max - min) + 1
}<file_sep>'use strict'

const server = require('../../lib/server')
const superagent = require('superagent')
const mocks = require('../lib/mocks')
const faker = require('faker')
require('jest')

describe('DELETE /api/v1/track', function () {
  beforeAll(() => this.base = `:${process.env.PORT}/api/v1/track`)
  beforeAll(server.start)
  afterAll(server.stop)

  describe('Valid requests', () => {
    beforeAll(() => {
      return mocks.album.createOne()
        .then(album => this.mockAlbum = album)
        .then(() => {
          this.fakeTrack = {
            title: faker.hacker.ingverb(),
            artist: faker.hacker.noun(),
            album: this.mockAlbum._id,
          }

          return superagent.post(`${this.base}`)
          .send(this.fakeTrack)
          .then(res => this.response = res)
        })
    })

    it('should return a status 204 on successful deletion', () => {
      return superagent.delete(`${this.base}/${this.response.body._id}`)
      .then(res => expect(res.status).toEqual(204))
    })
  })

  describe('inValid requests', () => {
    it('should return a 404 given an invalid ID', () => {
      return superagent.delete(`${this.base}/1234`)
      .catch(err => expect(err.status).toEqual(404))
    })
  })
})
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 29:  Component Composition
===

## Daily Plan
- Notes:
    - Anything top of mind?

- Hash Tables
- Code Review: _Are we really solid on state and props?_
- Composition vs Inheritance: _Just compose..._
- Building Reusable Components through `props.children`
- Lab Preview
    - _reminder for scott... no CSS challenge this week. next week._

## Learning Objectives
* Students will learn to about composition vs inheritance
* Students will learn to compose react components using props

## Readings
* Read [Conditional Rendering](https://facebook.github.io/react/docs/conditional-rendering.html)
* Read [Lists and Keys](https://facebook.github.io/react/docs/lists-and-keys.html)
* Read [Composition vs Inheritance](https://facebook.github.io/react/docs/composition-vs-inheritance.html)
* Read [Thinking in React](https://facebook.github.io/react/docs/thinking-in-react.html)


## Component Composition
#### Composition
Some components don't know their children a head of time. React components can use the special `children` prop to pass children directly into their output. For example a `SpeechBubble` component could be passed a `SuccessMessage` or `ErrorMessage` component to be used as a child component.

#### Specialization
Composition can be used to create special cases of another component. For example a `Modal` component could be composed to create a `SignupModal` or a `LoginModal`.
<file_sep>'use strict'

const debug = require('debug')('http:storage')

const storage = module.exports = {}
const memory = {}

// memory = {
//   'Notes': {
//     '1234.5678.9012': {
//       '_id': '1234.5678.9012',
//       'title': '',
//       'content': '',
//     },
//   },
//   'Categories': {
//     ...
//   },
// }

storage.create = function(schema, item) {
  debug('Created a new thing')

  return new Promise((resolve, reject) => {
    if(!schema || !item) return reject(new Error('Cannot create a new item; Schema and Item required'))

    if(!memory[schema]) memory[schema] = {}

    memory[schema][item._id] = item
    return resolve(memory[schema][item._id])
  })
}

storage.fetchOne = function() {

}

storage.fetchAll = function() {

}

storage.update = function() {

}

storage.delete = function() {

}
<file_sep>'use strict'

const EE = require('events').EventEmitter
const ee = module.exports = new EE()

ee.on('someEvent', function (data) {
  console.log('ran the thing!', data)
})<file_sep>import reducer from '../reducer/category'
require('jest')

describe('category reducer', () => {
  it('should return the initial state on first call', () => {
    expect(reducer(undefined, {})).toEqual([])
  })

  it('should handle CATEGORY_CREATE', () => {
    let categoryOne = { _id: '1234', title: 'wat', timestamp: new Date() }
    let categoryTwo = { _id: '4567', title: 'who', timestamp: new Date() }

    let state = reducer([categoryOne], {
      type: 'CATEGORY_CREATE',
      payload: categoryTwo,
    })

    expect(state).toContain(categoryOne)
    expect(state).toContain(categoryTwo)
  })
})
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 27: Forms and Props
===

## Daily Plan
- Notes:
    - anything top of mind?

- Code Review
- SCSS Syntax Introduction
- Forms and Props!!
- Lifecycle Hooks
- Lab Preview

## Learning Objectives
* Students will learn to test react components using jest and enzyme
* Students will learn to manage controlled inputs
* Students will learn to pass data from parent to child through props

## Readings
* Read [Components and Props](https://facebook.github.io/react/docs/components-and-props.html)
* Read [State and Lifecycle](https://facebook.github.io/react/docs/state-and-lifecycle.html)
* Read [Handling Events](https://facebook.github.io/react/docs/handling-events.html)
* Read [Forms](https://facebook.github.io/react/docs/forms.html)

## Forms and Inputs
React form elements maintain internal state. Think of React inputs as stateful child components. This means that we must manage the state of inputs through our own stateful  component and one way data binding. We create a parent component I'll refer to as a _form-container_ that manages the state for all child components of the form, passing any necessary state down into inputs through props. Each input has an `onChange` event that we can handle and use to update our _form-container's_ state each time the user interacts with an input.

## Props
Components accept arbitrary inputs called "props". In jsx props are passed into a component with a syntax that looks like html attributes. `props` is the name of the object passed into a component constructor, any prop added to a component in the jsx will be accessible as a property on `props`. After `props` is passed into the constructor's `super` they are available on the context by using `this.props`. **`props` are READ ONLY**

``` javascript
// props is the argument passed to the constructor
// props can be accessed on `this` after being passed into super
class Foo extends React.Component {
  constructor(props){
    super(props)
    console.log('title', props.title)
    console.log('content', props.content)
  }
  render(){
    return (
      <div>
        <h1> {this.props.title} </h1>
        <p> {this.props.content} </p>
      </div>
    )
  }
}

// adding props to a component
<Foo title='some literal value value' content={this.state.article.content}>
```

## One Way Data flow
State can only be passed from parent to child through props. This enforces the idea of one way data flow. One way data flow is the way to describe that state can only be passed down the component tree (not up). If a child wants to pass some data to its parent, the parent can pass a function to the child through props and the child may invoke that function and pass it data for the parent to manage.
<file_sep># Lab 10 - Express

## API endpoints

* POST: "/api/v1/note"
    Requires: Title and Content as JSON;

    This endpoint takes a JSON string containing a title and content, it then feeds that into the note constructor before finally passing it to the storage module. The storage module then writes the JSON to a file under the correct directory.

* PUT: "/api/v1/note/:_id"
    Requires: ID as a parameter; Title Content and ID as JSON;

    This endpoint takes the parameter provided and verifies it against the JSON provided it then builds a new note object using the provided data including the ID provided. It then passes the note and ID to the storage module which writes it to the appropriate file.

* GET: "/api/v1/note" or "/api/v1/note/:_id"
    Required: No requirements for getting a list of available files; ID as a parameter for one file;

    This endpoint first verifies whether an ID was passed as a parameter. If ID is not present it will get a list of the file names from the storage module and pass them back as a response. If ID is present it will pass that ID to the storage module and get a single file with that name.

* DELETE: "/api/v1/note/:_id"
    Required: ID as a parameter;

    This endpoint using the ID provided locates and deletes the file that shares the same ID.<file_sep>'use strict'

const Note = require('../model/note')
const storage = require('../lib/storage')
const bodyParser = require('body-parser').json()
const errorHandler = require('../lib/error-handler')

module.exports = function(router) {
  router.post('/', bodyParser, (req, res) => {
    let newNote

    new Note(req.body.title, req.body.content)
    .then(note => newNote = note)
    .then(note => JSON.stringify(note))
    .then(json => storage.create('note', newNote._id, json))
    .then(() => res.status(201).json(newNote))
    .catch(err => errorHandler(err, res))
  })
  router.get('/:_id', (req, res) => {
    storage.fetchOne('note', req.params._id)
    .then(buffer => buffer.toString())
    .then(json => JSON.parse(json))
    .then(note => res.status(200).json(note))
    .catch(err => errorHandler(err, res))
  })
  router.get('/', (req, res) => {
    storage.fetchAll('note')
    .then(paths => {
      console.log('paths', paths)
      return paths.map(p => p.split('.')[0])
    })
    .then(ids => {
      console.log('ids', ids)
      res.status(200).json(ids)
    })
    .catch(err => errorHandler(err, res))
  })
  router.delete('/:_id', (req, res) => {
    storage.destroy('note', req.params._id)
    // .then(() => res.status(200).send('some message'))
    .then(() => res.sendStatus(204))
    .catch(err => errorHandler(err, res))
  })
  router.put('/:_id', bodyParser, (req, res) => {
    storage.fetchOne('note', req.params._id)
    .then(buffer => buffer.toString())
    .then(json => JSON.parse(json))
    .then(note => ({
      _id: req.params._id,
      title: req.body.title || note.title,
      content: req.body.content || note.content
    }))
    .then(note => JSON.stringify(note))
    .then(json => storage.update('note', req.params._id, json))
    .then(() => res.sendStatus(204))
    .catch(err => errorHandler(err, res))
  })
}<file_sep>'use strict'

const server = require('../../lib/server')
const superagent = require('superagent')
const mocks = require('../lib/mocks')
const faker = require('faker')
require('jest')

describe('GET /api/v1/track', function () {
  beforeAll(() => this.base = `:${process.env.PORT}/api/v1/track`)
  beforeAll(server.start)
  afterAll(server.stop)
  afterEach(mocks.album.removeAll)
  afterEach(mocks.track.removeAll)

  describe('Valid requests', () => {
    beforeAll(() => {
      return mocks.track.createMany(25)
      .then(results => this.trackData = results)
    })

    it('should return an array of IDs given no ID parameter in the route', () => {
      return superagent.get(`${this.base}`)
      .then(res => {
        expect(res.body).toBeInstanceOf(Array)
        expect(res.body.includes(this.trackData.tracks[0]._id.toString())).toBeTruthy()
        expect(res.body.includes(this.trackData.tracks[10]._id.toString())).toBeTruthy()
        expect(res.body.includes(this.trackData.tracks[18]._id.toString())).toBeTruthy()
      })
      it('should return a status 200', () => {
        return superagent.get(`${this.base}`)
        .then(res => expect(res.status).toEqual(200))
      })

      it('should return a status 200 given a valid ID', () => {
        return superagent.get(`${this.base}/${this.trackData.tracks[0]._id}`)
        .then(res => expect(res.status).toEqual(200))
      })
      it('should return the correct data from a given objects ID', () => {
        return superagent.get(`${this.base}/${this.trackData.tracks[0]._id}`)
        .then(res => {
          expect(res.body._id).toEqual(this.trackData.tracks[0]._id)
          expect(res.body.title).toEqual(this.trackData.tracks[0].title)
          expect(res.body.artist).toEqual(this.trackData.tracks[0].artist)
        })
      })
    })
  })

  describe('inValid requests', () => {

  })
})
<file_sep>'use strict';

const server = require('../../lib/server.js');
const superagent = require('superagent');
const mock = require('../lib/mock.js');
const faker = require('faker');

require('jest');

describe('POST', function() {
  beforeAll(server.start);
  afterAll(server.stop);
  afterAll(mock.rider.removeAll);
  afterAll(mock.bike.removeAll);

  describe('Valid req/res', () => {
    beforeAll(() => {
      this.rider = {name: faker.name.firstName()};
      return superagent.post(':4000/api/v1/rider')
        .send(this.rider)
        .then(res => this.res = res);
    });
    it('should post a new rider object with a name and bike property', () => {
      expect(this.res.body.name).toBe(this.rider.name);
      expect(this.res.body).toHaveProperty('bikes');
    });
    it('should respond with a status of 201', () => {
      expect(this.res.status).toBe(201);
    });
  });

  describe('Invalid req/res', () => {
    it('should return a status 404 on bad path', () => {
      return superagent.post(':4000/api/v1/doesnotexist')
        .send(this.rider)
        .catch(err => {
          expect(err.status).toBe(404);
          expect(err.response.text).toMatch(/path error/i);
        });
    });
    it('should return a status 400 on a bad request body', () => {
      return superagent.post(':4000/api/v1/bike')
        .send({})
        .catch(err => expect(err.status).toBe(400));
    });
  });
});<file_sep>'use strict'

const fs = require('fs')
const Bmp = require('./lib/bitmap')

// console.log(process.argv[2])

fs.readFile('./assets/bitmap.bmp', (err, data) => {
  let bmp = new Bmp(data)
  console.log(bmp)

  // console.log(bmp.pixelArray.length)
  // console.log(bmp.colorTable[0], bmp.colorTable[1], bmp.colorTable[2], bmp.colorTable[3])
  for(let i = 0; i < bmp.pixelArray.length; i+4) {
    let gray = (bmp.pixelArray[i] + bmp.pixelArray[i + 1] + bmp.pixelArray[i + 2]) / 3

    bmp.pixelArray[i] = gray
    bmp.pixelArray[i+1] = gray
    bmp.pixelArray[i+2] = gray
  }

  fs.writeFile(`${__dirname}/assets/new.bmp`, bmp.allData, (err, data) => {
    if(err) throw new Error(err)
    console.log('made it')
  })
})<file_sep>'use strict';

const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'), {suffix: 'Prom'});

const storage = module.exports = {};


storage.create = (schema, item) => {

  let json = JSON.stringify(item);
  return fs.writeFileProm(`${__dirname}/../data/${schema}/${item._id}.json`, json)   // O(1) Normal Operation (Best Case)
    .then(() => item);

};


storage.fetchOne = (schema, id) => {
  return fs.readFileProm(`${__dirname}/../data/${schema}/${id}.json`);   // O(1) Normal Operation (Best Case)
};


storage.fetch = (schema) => {
  return fs.readdirProm(`${__dirname}/../data/${schema}`)   // O(n) Normal Operation (Best Case)
    .then(dir => dir.map(file => file.split('.')[0]));
};


storage.update = (schema, id, item) => {
  if (item._id !== id) return Promise.reject(new Error('Validation Error: Cannot update file with unmatched ID'));
  let json = JSON.stringify(item);
  return fs.writeFileProm(`${__dirname}/../data/${schema}/${id}.json`, json)   // O(1) Normal Operation (Best Case)
    .then(() => item);


};


storage.destroy = (schema, id) => {
  return fs.unlinkProm(`${__dirname}/../data/${schema}/${id}.json`);   // O(1) Normal Operation (Best Case)
};
<file_sep>'use strict'

const server = require('../../lib/server')
const superagent = require('superagent')
const mocks = require('../lib/mocks')
const faker = require('faker')
require('jest')

describe('POST /api/v1/track', function() {
  beforeAll(() => this.base = `:${process.env.PORT}/api/v1/track`)
  beforeAll(server.start)
  afterAll(server.stop)
  afterEach(mocks.album.removeAll)
  afterEach(mocks.track.removeAll)

  describe('Valid requests', () => {
    beforeAll(() => {
      return mocks.album.createOne()
      .then(album => this.mockAlbum = album)
      .then(() => {
        this.fakeTrack = {
          title: faker.hacker.ingverb(),
          artist: faker.hacker.noun(),
          album: this.mockAlbum._id,
        }

        return superagent.post(`${this.base}`)
        .send(this.fakeTrack)
        .then(res => this.response = res)
      })
    })

    it('should return a status of 201', () => {
      expect(this.response.status).toEqual(201)
    })
    it('should return a new track instance', () => {
      expect(this.response.body).toHaveProperty('_id')
    })
  })

  describe('inValid requests', () => {
    it('should return a status 400 given no request body', () => {
      return superagent.post(`${this.base}`)
      .send()
      .catch(err => expect(err.status).toEqual(400))
    })
    it('should return a status 400 given an improperly formatted body', () => {
      return superagent.post(`${this.base}`)
      .send({gnarf: 200})
      .catch(err => expect(err.status).toEqual(400))
    })
  })
})
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 34: UI Styling
===
----

## Daily Plan
- Notes:
    - Anything top of mind?

- Code Review
- Review of SCSS: _What questions are there?_
- Review of SMACSS-ish structure for component-based architecture
- Custom forms: _Build a slider checkbox_
- Lab Preview

## Learning Objectives
* students will be able to use SCSS to create component based and modular CSS styles
* students will be able to *generally* conform to the SMACCS principles for creating base, layout, and theme containers for their application styles
* students will be able to create and use global SCSS variables for reusable styles
* students will have a level of competency is styling custom form elements within an application

## Resources
* [sass getting started guide](http://sass-lang.com/guide)

## Overview
* SCSS is a variation of SASS, which stands for "syntactically awesome stylesheets"
  * SCSS gives us the ability to do the following things with our CSS styles
    * creation of modular css "partials"
    * nesting of CSS rules
    * ability to import partials into/from other partial files
    * ability to create functional CSS components and mixins
    * ability to use math operators in CSS
* SCSS partials are often modularized to fit the following structure:
  - **style**
    - **lib**
      - **base**
        - `_base.scss`
        - `_reset.scss`
      - **theme**
        - `_vars.scss`
      - **layout**
        - `_header.scss`
        - `_footer.scss`
        - `_content.scss`
  - **component**
    - **my-component-dir**
      - `_my-component-dir.scss`
    - **another-component-dir**
      - `_another-component-dir.scss`
<file_sep>import './_slider.scss'
import React from 'react'

class SliderCheckbox extends React.Component {
  render() {
    return (
      <div className={this.props.config.className + ' slider-checkbox'}>
        <input
          type='checkbox'
          name={this.props.config.name}
          id={this.props.config.id}
          defaultChecked={false}
          onChange={this.props.onChange}/>

        <label htmlFor={this.props.config.id}><div></div></label>
      </div>
    )
  }
}

export default SliderCheckbox
<file_sep>'use strict'

const reader = require('../lib/reader')
require('jest')

describe('Reader Module', function() {
  describe('#read', () => {
    let paths = [`${__dirname}/data/one.txt`, `${__dirname}/data/two.txt`, `${__dirname}/data/three.txt`]

    describe('Valid inputs', () => {
      it('should return the file data in the same order passed; one, two, three', (done) => {
        let expected = 'Short.Long.Medium.'
        reader.read(paths, (err, results) => {
          let arr = [results[0].split(' ')[0], results[1].split(' ')[0], results[2].split(' ')[0]].join('')

          expect(expected).toEqual()
          done()
        })
      })


      it('should accept an array of file paths and return a null argument for err', (done) => {
        reader.read(paths, (err, results) => {
          // console.log('err', err)
          expect(err).toBeNull()
          done()
        })
      })

      it('should accept an array of file paths and return an array of results', (done) => {
        reader.read(paths, (err, results) => {
          expect(results).toBeInstanceOf(Array)
          done()
        })
      })
      it('should accept an array of file paths and return something', (done) => {
        reader.read(paths, (err, results) => {
          expect(results).not.toBeNull()
          done()
        })
      })
      it('should return an array with the length of 3', (done) =>{
        reader.read(paths, (err, results) => {
          expect(results.length).toBe(3)
          done()
        })
      })
    })

    // describe('Invalid inputs', () => {
    //   it('should return an error given invalid file paths', () => {

    //   })
    // })

  })
  // describe('#writer', () => {
  //   it('should ...', () => {})
  //   it('should ...', () => {})
  //   it('should ...', () => {})
  // })
})
<file_sep>'use strict';

// Testing Dependencies
const server = require('../../lib/server');
const superagent = require('superagent');
require('jest');

// Test Variables
let port = process.env.PORT;
let api = `:${port}/api/v1/note`;

describe('Route Testing', () => {
  this.mockNote = {title: 'test', content: 'run'};
  beforeAll(() => server.start(port, () => console.log(`listening on ${port}`)));
  afterAll(() => server.stop());

  describe('POST /api/v1/note', () => {
    beforeAll(() => {
      return superagent.post(api)
        .send(this.mockNote)
        .then(res => this.response = res);
    });
    describe('Valid Routes/Data', () => {
      it('Should respond with a status of 201', () => {
        expect(this.response.status).toBe(201);
      });
      it('Should post a single note and return it', () => {
        expect(this.response.body).toHaveProperty('title');
        expect(this.response.body).toHaveProperty('content');
        expect(this.response.body).toHaveProperty('_id');
      });
      it('Should respond with a correct title and content', () => {
        expect(this.response.body.title).toBe('test');
        expect(this.response.body.content).toBe('run');
      });
    });

    describe('Invalid Routes/Data', () => {
      it('Should return a 404 for an invalid path', () => {
        return superagent.post(':4000/api/v1/node')
          .catch(err => {
            expect(err.status).toBe(404);
            expect(err.response.text).toMatch(/Path/);
          });
      });
      it('Should respond with a bad request if bad data is sent', () => {
        return superagent.post(api)
          .catch(err => {
            expect(err.status).toBe(400);
          });
      });
    });
  });
});
<file_sep>'use strict';

const Bike = require('../../model/bike.js');
const mocks = require('../lib/mock')
require('jest');

describe('Bike Module', function() {
  describe('Bike schema', () => {
    this.mockRider = mocks.rider.createOne()
    let newBike = new Bike({
      make: 'Huffy',
      category: 'BMX',
      rider: this.mockRider._id
    });

    it('should create a object', () => {
      expect(newBike).toBeInstanceOf(Object);
    });

    it('should have a rider ID property that matches the mockRider', () => {
      expect(newBike.rider).toEqual(this.mockRider._id)
    })
  });
});<file_sep>import cardReducer from './card'
import {combineReducers} from 'redux'
import categoryReducer from './category'

export default combineReducers({
  cards: cardReducer,
  categories: categoryReducer,
})
<file_sep>'use strict';

const reader = require('../lib/reader.js');
const imagePath = `${__dirname}/asset/bitmap.bmp`;
const newPath = `${__dirname}/asset/test-bitmap.bmp`;
const badPath = `${__dirname}/assets/test-bitmap.bmp`;
const bitmap = require('../lib/bitmap.js');
const transform = require('../lib/transform.js');
const fs = require('fs');
require('jest');

describe('Reader Module', function() {
  describe('#Read', () => {
    it('should read file', (done) => {
      reader.read(imagePath, (err, fd) => {
        if(err) console.error(err);
        expect(fd).not.toBeNull();
        done();
      });
    });

    it('should not read a file if it does not exist', (done) => {
      reader.read(badPath, (err, fd) => {
        if(err) console.error(err);
        expect(err).not.toBeNull();
        done();
      });
    });

    it('should error if file path is missing.', (done) => {
      reader.read('', (err, fd) => {
        if(err) console.error(err);
        expect(err).not.toBeNull();
        done();
      });
    });
  });

  describe('#Write', () => {
    it('should create a new file', (done) => {
      reader.read(imagePath, (err, fd) => {
        if(err) console.error(err);
        expect(fd).not.toBeNull();
        bitmap.parse(fd, (err, bmp) => {
          if(err) console.error(err);
          reader.write(bmp, newPath, err => {
            if(err) return console.error(err);
            expect(fs.existsSync(newPath)).toBe(true);
            done();
          });
        });
      });
    });

    it('should write data to a new file', (done) => {
      reader.read(imagePath, (err, fd) => {
        let original_data = fd;
        if(err) console.error(err);
        expect(fd).not.toBeNull();
        bitmap.parse(fd, (err, bmp) => {
          if(err) console.error(err);
          reader.write(bmp, newPath, err => {
            if(err) return console.error(err);
            reader.read(imagePath, (err, fd) => {
              let new_data = fd;
              expect(Buffer.compare(original_data, new_data)).toBe(0);
              done();
            });
          });
        });
      });
    });


    it('should not write a new file if the directory does not exist', (done) => {
      reader.read(imagePath, (err, fd) => {
        if(err) console.error(err);
        expect(fd).not.toBeNull();
        bitmap.parse(fd, (err, bmp) => {
          if(err) console.error(err);
          reader.write(bmp, badPath, err => {
            if(err) console.error(err);
            expect(err).not.toBeNull();
            done();
          });
        });
      });
    });

  });
  describe('#Bitmap', () => {
    it('should read file and create new bmp object', (done) => {
      reader.read(imagePath, (err, fd) => {
        if(err) console.error(err);
        expect(fd).not.toBeNull();
        bitmap.parse(fd, (err, bmp) => {
          if(err) console.error(err);
          expect(bmp).not.toBeNull();
          done();
        });
      });
    });
  });
  describe('#Transform', () => {
    it('should write a changed file', (done) => {
      reader.read(imagePath, (err, fd) => {
        if(err) console.error(err);
        bitmap.parse(fd, (err, bmp) => {
          if(err) console.error(err);
          let original = bmp.allData;
          transform.reverse(bmp, (err, bmpNew) => {
            if(err) console.error(err);
            let altered = bmpNew.allData;
            reader.write(bmpNew, newPath, err => {
              if(err) return console.error(err);
              expect(Buffer.compare(original, altered)).toBe(0);
              done();
            });
          });
        });
      });
    });
  });
});
<file_sep>import React from 'react'
import {Provider} from 'react-redux'
import createStore from '../lib/store'
import Adapter from 'enzyme-adapter-react-16'
import { configure, shallow, mount } from 'enzyme'
import Dashboard from '../component/dashboard/dashboard'

require('jest')

configure({ adapter: new Adapter() })

describe('<Dashboard />', function () {
  beforeAll(() => {
    let wrapper = mount(<Provider store={createStore()}><Dashboard/></Provider>)
    wrapper.setProps({ categories: [
      { _id: '1234', title: 'wat', timestamp: new Date() },
      { _id: '4567', title: 'who', timestamp: new Date() }]})

    this.wrapper = wrapper
  })
  afterAll(() => this.wrapper.unmount())

  it('should render two category items in the DOM', () => {
    // console.log(this.wrapper.html())
    // expect(this.wrapper.find('.dashboard').length).toBe(1)
  })
})
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 14: Relationship Modeling
===

## Daily Plan
- Notes:
    - Anything top of mind?
    - [Sign up for 1:1s](https://calendar.google.com/calendar/selfsched?sstoken=UU1Zb1dLQnF<KEY>&pli=1)

- Code Review _Review Mongoose Connection Updates_
- Mongodb Relationships / Populations
- Lifecycle Hooks _Middleware_
- Testing _DB Mocks_
- Lab Preview

## Learning Objectives
* Students will learn about relationship modeling
* Students will be able to create "one to one", "one to many", and "many to many" model relationships using a MongoDB ODM

## Resources
* Read [mongoose populate docs](http://mongoosejs.com/docs/populate.html)
* Skim [mongoose api docs](http://mongoosejs.com/docs/api.html)

## Model Relationships
When the modeling real world as data you will quickly discover that data has relationships to other data. In fact in the real world it is rare, if not impossible, for something to exist that has no relationships to other things. On the other hand in theoretical world we can describe a thing with out describing its relationships to other things. Software engineers have discovered useful ways to describe the relationships (or lack of) between data that can easily be mapped to a database.

#### One
A Model that stands on its own. A web app example includes a simple Note that has no relationship with any other model, It contains all the data it needs.

```
Note
  id: 1
  content 'get milk and cookies.'
```

#### One to One
When a Model Foo that is related to a single Model Bar. Some web app examples include every user having a single profile, every profile having a single profile photo, every client is limited to a single contact email.

```
User
  id: 888
  username: slugbyte
  profileID: 123

Profile
  id: 123
  bio: 'i love javascript'
  url: 'www.codefellows.com'
  userID: 888
```

#### One to Many
A Model Foo that is related to many Bar Models. Some web app examples include every user having may posts but posts have a singe user, every photo having many comments but each comment is to a single photo, every post having many likes but each like is to a single post.

```
Photo
  id: 5678
  url: 'www.example.com/image/sunset.jpg'
  comments: [ 44 65 78 ]

Comment
  id: 44
  content: 'SO MUCH BEAUTY! <3'

Comment
  id: 65
  content: 'awesome photo'

Comment
  id: 78
  content: 'LUL, look at the clouds'
```


#### Many to Many
Many Foo models that can each have relationships to many Bar Models. A web app examples includes every user having a relation ship with many friends and each of those users have relationships with a many different friends.

Some databases (including MongoDB) do not natively support models having many to many relationships, but many to many can still be created through the use of a second model.

###### Using One Model
```
User
  id: 1234
  username: 'teapot'
  friends: [ 1001 3333 4321 ]

User
  id: 1001
  username: 'peach'
  friends: [ 1234 5000 ]
```

###### Using A Second Model
```
User
  id: 1234
  username: 'teapot'
  friendsID: 33

User
  id: 1001
  username: 'peach'
  freindsID: 77

Friends
  id: 33
  users: [ 1001 3333 4321]

Friends
  id: 77
  users: [ 1234 5000 ]
```
<file_sep>'use strict'

const Note = require('../model/note')
const storage = require('../lib/storage')
const debug = require('debug')('http:route-note')


module.exports = function(router) {
  router.post('/api/v1/note', (req, res) => {
    debug('POST /api/v1/note')

    try {
      debugger;
      let newNote = new Note(req.body.title, req.body.content)

      storage.create('Note', newNote)
      .then(storedNote => {
        res.writeHead(201, {'Content-Type': 'application/json'})
        res.write(JSON.stringify(storedNote))
        res.end()
      })
    } catch(err) {
      debug(`There was a bad request: ${err}`)

      res.writeHead(400, {'Content-Type': 'text/plain'})
      res.write('Bad Request')
      res.end()
    }
  })

  router.get('/api/v1/note', (req, res) => {

  })

  router.put('/api/v1/note', (req, res) => {

  })

  router.delete('/api/v1/note', (req, res) => {

  })
}
<file_sep>import React from 'react'

class ExpenseCreateForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: '',
      price: 0,
    }

    this.handleChange = this.handleChange.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleChange(e) {
    this.setState({[e.target.name]: e.target.value})
  }

  handleSubmit(e) {
    e.preventDefault()
    let expense = {...this.state}
    expense._id = Math.random().toString()

    this.props.dashboard.setState({expenses: [...this.props.dashboard.state.expenses, expense]})
    // this.props.dashboard.setState(prevState => ({
    //   expenses: [...prevState.expenses, expense]
    // }))
  }

  render() {
    return (
      <form className="expense-create-form" onSubmit={this.handleSubmit}>
        <input
          type="text"
          name="name"
          value={this.state.name}
          onChange={this.handleChange}
          placeholder="Bought Dan a new (Matchbox) car"/>

        <input
          type="number"
          name="price"
          value={this.state.price}
          onChange={this.handleChange}
          placeholder='3.50'/>

        <button type="submit">Spend</button>

        {/* <SomeComponent dashboard={this.props.dashboard}/> */}
      </form>
    )
  }
}

export default ExpenseCreateForm
<file_sep>'use strict'

const myMath = require('./lib/math')


myMath.absolute(-10000)<file_sep>const reader = require('../lib/reader.js');
const imagePath = `${__dirname}/asset/bitmap.bmp`;
const not_imagePath = `${__dirname}/asset/not_image.txt`;
const wrongBMP_imagePath = `${__dirname}/asset/MARBLES.BMP`;
const bitmap = require('../lib/bitmap.js');



describe('#bitmap test Module', function() {
  it('should return error if buffer is null', (done) => {
    bitmap.parse(null, (err, bmp) => {
      if(err) console.error(err);
      expect(err).not.toBeNull();
      done();
    });
  });
  it('should return object when passed a buffer', (done) => {
    reader.read(imagePath, (err, data) => {
      bitmap.parse(data, (err, bmp) => {
        if(err) console.error(err);
        expect(bmp).toBeInstanceOf(Object);
        done();
      });
    });
  });
  it('should return an error when passed a buffer that is not from a bitmap', (done) => {
    reader.read(not_imagePath, (err, data) => {
      bitmap.parse(data, (err, bmp) => {
        if(err) console.error(err);
        expect(err).not.toBeNull();
        done();
      });
    });
  });
  // it('should return an error when passed a buffer that is not from a windows bitmap of the proper format', (done) => {
  //   reader.read(wrongBMP_imagePath, (err, data) => {
  //     bitmap.parse(data, (err, bmp) => {
  //       if(err) console.error(err);
  //       expect(err).not.toBeNull();
  //       done();
  //     });
  //   });
  // });
});<file_sep>'use strict'

const mongoose = require('mongoose')

const Track = mongoose.Schema({
  'speechiness': Number,
  'key' : { type: Number },
  'time_signature': { type: Number },
  'liveness' : { type: Number },
  'loudness': { type: Number },
  'duration_ms' : { type: Number },
  'danceability': { type: Number },
  'duration' : { type: Number },
  'valence': { type: Number },
  'acousticness' : { type: Number },
  'spotify_id': { type: String },
  'volume_number' : { type: Number },
  'energy': { type: Number },
  'tempo' : { type: Number },
  'instrumentalness': { type: Number },
  'mode' : { type: Number },
  'number': { type: Number },
  'artist' : { type: String, require: true },
  'title': { type: String, require: true },
}, {timestamps: true})

module.exports = mongoose.model('tracks', Track)<file_sep>import * as actions from '../action/category-actions'
require('jest')

describe('category actions', () => {
  it('should create an action to add a category', () => {
    let category = {title: 'hello world'}
    let action = actions.categoryCreate(category)

    expect(action.type).toEqual('CATEGORY_CREATE')
    expect(action.payload).toHaveProperty('_id')
    expect(action.payload).toHaveProperty('timestamp')
  })
})
<file_sep>import React from 'react'

class ExpenseUpdateForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = this.props.expense
      ? this.props.expense
      : {
        _id: '',
        name: '',
        price: 0,
      }

    this.handleChange = this.handleChange.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleSubmit(e) {
    e.preventDefault()
    this.props.dashboard.setState(prevState => {
      expenses: prevState.expenses.map(expense => {
        if(expense._id === this.state._id) {
          console.log('made it')
          return this.state
        }
        return expense
      })
    })
    // this.props.dashboard.setState(prevState => {
    //   expenses: prevState.expenses.map(expense =>
    //     expense._id === this.state._id ? this.state : expense)
    // })
  }

  handleChange(e) {
    this.setState({[e.target.name]: e.target.value})
  }

  render() {
    return (
      <form
        className="expense-update-form"
        onSubmit={this.handleSubmit}>

        <input
          type="text"
          name="name"
          value={this.state.name}
          onChange={this.handleChange}/>

        <input
          type="number"
          name="price"
          value={this.state.price}
          onChange={this.handleChange}/>

        <button type="submit">update</button>
        <button type="button" onClick={this.props.toggleEdit}>cancel</button>
      </form>
    )
  }
}

export default ExpenseUpdateForm
<file_sep>import React from 'react';
import {connect} from 'react-redux';
import {categoryCreate, categoryDelete, categoryUpdate} from '../../action/category-actions';
import CategoryForm from '../category-form/index';
import CategoryItem from '../category-list/index';

class Dashboard extends React.Component {
  render() {
    return(
      <section>
        <h1>Expenses Categories</h1>

        <CategoryForm
          buttonText='create'
          onComplete={this.props.dashboardCategoryCreate}/>

        {this.props.categories ?
          this.props.categories.map(cat =>
            <CategoryItem key={cat._id}
              category={cat}
              handleDelete={this.props.dashboardCategoryDelete}
              handleUpdate={this.props.dashboardCategoryUpdate}
            />)
          :
          undefined
        }
      </section>
    );
  }
}

const mapStateToProps = state => ({
  categories: state,
});

const mapDispatchToProps = (dispatch, getState) => ({
  dashboardCategoryCreate: category => dispatch(categoryCreate(category)),
  dashboardCategoryDelete: category => dispatch(categoryDelete(category)),
  dashboardCategoryUpdate: category => dispatch(categoryUpdate(category)),
});

export default connect(mapStateToProps, mapDispatchToProps) (Dashboard);
<file_sep>'use strict';

const mongoose = require('mongoose');

const Rider = module.exports = mongoose.Schema({
  name: {type: String, max: 32},
  bikes: [{type: mongoose.Schema.Types.ObjectId, ref: 'bikes'}],
});

Rider.pre('save', function(next) {
  this.validate((err) => {
    if(err) next(() => console.error(err))
    next()
  })
})

module.exports = mongoose.model('riders', Rider);<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 03: Asynchronous Callbacks
=====================================

## Daily Plan
- Notes:
    - Anything top of mind?
    - Career Coaching Assignments _heads up that they're coming!!_

- Node Callback Pattern
- The Event Loop
- Recursion
    - Quick code challenge _sum all numbers from 0 to n_
    - Lets solve it with a call stack exercise
- Async (concurrency)
- FS Module _working with the file system_
    - Buffers _Introduction_
- Testing Async Code
  - Tell it when it can be `done` OR just `return` the async code...

- Lab Preview
    - Lab Setups _Code challenges and general labs_
    - Whiteboard Process Discussion


# Learning Objectives
* Students will understand the how synchronous and asynchronous code runs in the Javascript runtime
* Students will be able to manage asynchronous data flow using error first callbacks
* Students will be able to utilize the asynchronous methods on the built-in Node modules
* Students will be able to work with raw data using Node's Buffers
* Students will be able to test asynchronous code using a BDD testing framework

# Resources
* Watch [What the Heck is the Event Loop Anyway](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
* Read [Understanding Error First Callbacks](http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/)
* Skim [Node's File System Module Docs](https://Nodejs.org/dist/latest-v9.x/docs/api/fs.html)
* Skim [Node's buffer documentation](https://Nodejs.org/api/buffer.html#buffer_buffer)

# Javascript Runtime
* There are many Javascript runtimes.
* V8 is the name of the runtime used in Chrome browsers and NodeJS.
* V8 will be used in the following descriptions of how JavaScript a runtime works, but other browsers and JavaScript environments have the same behaviors.

# Concurrency
* In programing, concurrency means that a program can run more than one thing at a time.
* The ability to do multiple things at a time can greatly increase the amount of things your program can do in a given moment in time. However, traditional means of handling concurrency are extremely complex, and often lead to bugs!
* Javascript is a single threaded language.
  * Which means that it can only do a single thing at a time.
  * However, the JavaScript runtime is setup in such a way that your programs can still have some concurrent behavior, as long as the concurrent behavior is not implemented in JavaScript.

## Node's Concurrency
* The Node C++ apis are written in such a way that they deal with all the complexities of concurrency for us!
  * We are programming at a higher abstraction - removing the need to deal with lower level threading
  * The NodeJS event loop operates under a single thread
    * NodeJS uses many threads "underneath the hood" (libuv)
* NodeJs concurrency through the use of events and callbacks
  * When a JavaScript function makes a call to Node APIs, it passes the Node API a callback.
    * The Node api does it thing
    * Passes its results into the callback
    * Enqueues the callback onto the callback queue
### Call Stack
* The stack keeps track of each function that is currently running in JavaScript
* At any given point in time JavaScript is only running the function on top of the call stack
* Each time a function gets invoked it gets pushed onto the call stack
* Each time a function returns it gets popped from the call stack
### Event Loop
* when NodeJS starts up, it processes the input script then begins processing the event loop
* The event loop constantly checks if the call stack is empty
* When the stack is empty it dequeues any functions on the callback queue and pushes them onto the stack
### Callback Queue
  * The callback queue holds completion handling functions from passed Node APIs
  * Functions stored on the Callback Queue are not executing, they are only waiting to be put on to the Call Stack.

## Node asynchronous callback pattern
* Node functions that have asynchronous input or output take a callback as the last argument
  * Node functions that do not pass back data always have callback functions take the form `(err) => { }`
  * Node functions that do pass back data always have callback functions take the form `(err, data) => { }`


# Working With Binary Data (Part 1)
## Bits and bytes
* A bit is the smallest unit of data in a computer
  * A bit contains a single binary value, 0 or 1
* A byte is comprised of 8 bits
  * We often refer to a nibble as 4 bits (half of a byte)
## Endianness
* Refers to the order of bytes
* Little endian
  * Bytes are written from left to right
* Big endian
  * Bytes are written from right to left
## Buffers
* Buffers are an array of bytes
* Example:
  ```Javascript
    var buff = Buffer.from('Welcome to Bufferville');
    console.log(buff);
    <Buffer 77 65 6c 63 6f 6d 65 20 74 6f 20 62 75 66 66 65 72 76 69 6c 6c 65>
  ```
* Common encoding types:
  * UTF-8 (default)
    * `buff.toString('utf-8')`
  * Base64
    * `buff.toString('base64')`
  * Hex
    * `buff.toString('hex')`

## File System (a.k.a FS) Module
* The FS module is the Node interface to the file system
* The FS module has synchronous and asynchronous methods
* If the method does not have sync in its name you can assume its synchronous
* In this class we will **NEVER** use the synchronous methods
* Useful globals
  * `__dirname` - the absolute path to the directory the current file is in
  * `__filename` - the absolute path to the current file
* Create File
  * `fs.writeFile(filepath, data [, options], callback);`
  * The callback should take the form `(error) => {}`
* Read File
  * `fs.readFile(filepath [, options], callback);`
  * The callback should take the form `(error, data) => {}`
* Delete File
  * `fs.unlink(filepath, callback);`
  * The callback should take the form `(error) => {}`
* Other useful methods
  * `readdir` - reads the contents of a directory
  * `mkdir` - create a directory
  * `stat` - get information about a file/dir/link
  * `watch` - watch a file for changes

#### Asynchronous Testing
 * **Calling `done`**
   * Jest gives us a short timeframe to call `done` before a timeout error occurs
     * be sure to call `done` in the appropriate location (usually, this in your internal logic)
     * calling `done` in the wrong block will likely cause a false positive test result

 * **demo:** testing file system I/O<file_sep>let initialState = {
  // 'uncategorized': [] // maybe we want to force any cards to this key when we delete a category?
}

// {
//   'id1234': [],
//   'id456': [],
// }

export default (state=initialState, action) => {
  let {type, payload} = action

  switch(type) {
    case 'CATEGORY_CREATE': return {...state, [payload._id]: []}
    case 'CATEGORY_DELETE':
      let changedState = {...state}
      delete changedState[payload._id]
      return changedState
    case 'CARD_CREATE': return // you do the thing
    case 'CARD_UPDATE': return // you do the thing
    case 'CARD_DELETE': return // you do the thing
    case 'CARD_RESET': return initialState
    default: return state
  }
}
<file_sep>'use strict'

const Album = require('../model/album')
const bodyParser = require('body-parser').json()
const errorHandler = require('../lib/error-handler')

module.exports = function(router) {
  router.route('/album/:_id?')
  .get((req, res) => {
    if(req.params._id) {
      return Album.findById(req.params._id)
      .then(album => res.status(200).json(album))
      .catch(err => errorHandler(err, res))
    }
    Album.find()
    // .then(albums => albums.map(a => a._id))
    .then(ids => res.status(200).json(ids))
    .catch(err => errorHandler(err, res))
  })
  .post(bodyParser, (req, res) => {
    new Album(req.body).save()
    .then(album => res.status(201).json(album))
    .catch(err => errorHandler(err, res))
  })
  .put(bodyParser, (req, res) => {
    Album.findByIdAndUpdate(req.params._id, req.body, {upsert: true, runValidators: true})
    .then(() => res.sendStatus(204))
    .catch(err => errorHandler(err, res))
  })
  .delete((req, res) => {
    Album.findByIdAndRemove(req.params._id)
    .then(() => res.sendStatus(204))
    .catch(err => errorHandler(err, res))
  })
}
<file_sep>


- Merge Sort
- Quick Sort
- Selection Sort
- Radix Sort
<file_sep>'use strict'

const faker = require('faker')
const Album = require('../../model/album')
const Track = require('../../model/track')

const mock = module.exports = {}

// Album Mocks - One, Many, RemoveAll
mock.album = {}

mock.album.createOne = () => new Album({ name: faker.hacker.adjective() }).save()

mock.album.createMany = n =>
  Promise.all(new Array(n).fill(0).map(mock.album.createOne))

mock.album.removeAll = () => Promise.all([Album.remove()])


// Track Mocks - One, Many, RemoveAll
mock.track = {}

mock.track.createOne = () => {
  let result = {}

  return mock.album.createOne()
  .then(album => {
    result.album = album
    return new Track({
      artist: `${faker.name.firstName()} ${faker.name.lastName()}`,
      title: faker.hacker.ingverb(),
      album: album._id.toString(),
    }).save()
  })
  .then(track => result.track = track)
  .then(() => result)
}

mock.track.createMany = n => {
  let result = {}

  return mock.album.createOne()
  .then(album => {
    result.album = album
    let trackProms = new Array(n).fill(0).map(() => new Track({
      artist: `${faker.name.firstName()} ${faker.name.lastName()}`,
      title: faker.hacker.ingverb(),
      album: album._id.toString(),
    }).save())
    return Promise.all(trackProms)
  })
  .then(tracks => result.tracks = tracks)
  .then(() => result)
}

mock.track.removeAll = () => Promise.all([Track.remove()])
<file_sep>'use strict'

const math = require('../lib/math')
require('jest') // This is not required

// This is a basic Jest assertion
expect(math.floor(1.123)).not.toEqual(1.123)
expect(math.floor(1.123)).toEqual(1)


describe('Math Module', function() {
  describe('#Floor', function() {
    it('should take in a floating point number, and return the previous whole integer', function() {
      expect(math.floor(1.123)).toEqual(1)
      expect(math.floor(1.123)).not.toEqual(1.123)
    })

    it('should validate that the input for `num` is a numeric value', function() {
      // expect(...)
    })
  })
  describe('#Ceiling', function() {

  })
  describe('#Absolute', function() {

  })
})<file_sep>'use strict'

// Application dependencies
const net = require('net')
const Client = require('./model/client')
const cmd = require('./lib/cmd')

// Application setup
const server = module.exports = net.createServer()
const PORT = process.env.PORT || 3000
let clientPool = []

// Server instance setup
server.on('connection', function(socket) {
  let client = new Client(socket)
  clientPool.push(client)
  clientPool.map(c => c.socket.write(`\t${client.nick} has joined the game\n`))

  socket.on('data', function(data) {
    // This is where you will abstract away to your command parser module...

    // console.log('socket data', data)
    let message = data.toString()
    clientPool.filter(
      c => c.user !== client.user).map(
        c => c.socket.write(`${client.nick}: ${message}\n`))
  })

  socket.on('close', function() {
    clientPool = clientPool.filter(c => c.user !== client.user)
    clientPool.map(c => c.socket.write(`\t${client.nick} has left the channel\n`))
  })

  socket.on('error', function(err) {
    console.error(err)
  })
})

server.listen(PORT, () => console.log(`Listening on ${PORT}`))<file_sep>'use strict'

const uuid = require('uuid/v4')

module.exports = function Note(title, content) {
  return new Promise((resolve, reject) => {
    if(!title || !content) return reject(new Error('Validation Error. Cannot create Note. Title and Content required.'))
    this._id = uuid()
    this.title = title
    this.content = content

    return resolve(this)
  })
}<file_sep>'use strict'

const colors = require('./lib/colors')
// colors => {makeBlue: function() {}, ...}

colors.makeBlue(/* pass in some args */) // => turn something blue
colors.makeRed(/* pass in some args */) // => turn something red
<file_sep>'use strict';

const index = require('../index.js');
require('jest');

describe('Index Module', function() {
  describe('#Start', () => {
    it('should not run without arguments', () => {
      expect(index.processImage([])).toEqual(expect.stringContaining('Invalid arguments'));
    });
    it('should not run with less than three arguments', () => {
      expect(index.processImage(['./__test__/asset/bitmap.bmp', 'test'])).toEqual(expect.stringContaining('Invalid arguments'));
    });
    it('should not run with invalid transform method', () => {
      expect(index.processImage(['node', 'index.js', './__test__/asset/bitmap.bmp', 'test', 'foo'])).toEqual(expect.stringContaining('Invalid transform method'));
    });
  });
});
<file_sep>'use strict';

const server = require('../../lib/server.js');
const superagent = require('superagent');
const mock = require('../lib/mock.js');
const faker = require('faker');

require('jest');

describe('POST', function() {
  beforeAll(server.start);
  afterAll(server.stop);
  afterAll(mock.rider.removeAll);
  afterAll(mock.bike.removeAll);

  beforeAll(() => {
    return mock.rider.createOne()
      .then(rider => this.rider = rider)
      .then(() => {
        this.fakeBike = {
          make: faker.hacker.noun(),
          category: faker.hacker.verb(),
          rider: this.rider._id,
        };
      });
  }); 
  describe('Valid req/res', () => {
    beforeAll(() => {
      return superagent.post(':4000/api/v1/bike')
        .send(this.fakeBike)
        .then(res => this.response = res);
    });
    it('should post a new bike with make, and _id', () => {
      expect(this.response.body).toHaveProperty('make');
      // expect(this.resBike.body).toHaveProperty('year');
      expect(this.response.body).toHaveProperty('_id');
    });
    it('should respond with a status of 201', () => {
      expect(this.response.status).toBe(201);
    });
  });

  describe('Invalid req/res', () => {
    it('should return a status 404 on bad path', () => {
      return superagent.post(':4000/api/v1/doesnotexist')
        .send(this.mockNote)
        .catch(err => {
          expect(err.status).toBe(404);
          expect(err.response.text).toMatch(/path error/i);
        });
    });
    it('should return a status 400 on a bad request body', () => {
      return superagent.post(':4000/api/v1/bike')
        .send({})
        .catch(err => expect(err.status).toBe(400));
    });
  });
});<file_sep>// you all get to define your expense actions!
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 10: Doubly Linked Lists, Stacks, Queues & Binary Search
===

## Daily Plan
- Notes:
    - Anything top of mind?
    - Data Structures Repos _at some point..._

- Code Review _Implement FS Storage?_
- Stacks & Queues
- Lab Preview


## Learning Objectives
* Students will be able to implement a doubly linked list
* Students will be able to implement a stack
* Students will be able to identify use cases for a stack
* Students will be able to implement a queue
* Students will be able to identify use cases for a queue
* Students will understand the inner workings or Binary Search

## Resources
* Watch [stacks and queues](https://www.youtube.com/watch?v=wjI1WNcIntg)
* Skim [stack wiki](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))
* Skim [queue wiki](https://en.wikipedia.org/wiki/Queue_(abstract_data_type))

#### Stacks
Stacks are a data structure that serve as a collection of elements. These elements are stacked in a last in, first out sequence **(aka FILO - first in, last out)**. It may help to think about a stack as a collection of plates and the way that you add and remove them.

Common methods include:
  * `pop` removes the most recent element from the stack
  * `push` adds a new element to the stack

#### Queues
Queues are also a data structure that serve as a collection of elements. Elements in a queue are added in a first in, first out sequence **(aka FIFO - first in first out)**. It may help to think about a queue as a bunch of people standing in line at a concert - the first person in line is the first person in the venue.

Common methods include:
  * `enqueue` is used to add an element to the end of a queue
  * `dequeue` is used to retrieve and remove an element from the beginning of a queue<file_sep>'use strict';

const Note = require('../model/note');
const debug = require('debug')('http:route-note');
const bodyParser = require('body-parser').json();
const storage = require('../lib/storage');
const errorHandler = require('../lib/error-handler');

module.exports = function (router) {

  router.post('/note', bodyParser, (req, res) => {
    debug('Begin Post');
    new Note(req.body.title, req.body.content)   // O(1) Normal Operation (Best Case)
      .then(note => storage.create('Note', note))
      .then(item => res.status(201).json(item))
      .catch(err => errorHandler(err, res));

  });

  router.get('/note/:_id', (req, res) => {
    debug('Begin Get One');
    storage.fetchOne('Note', req.params._id)   // O(1) Normal Operation (Best Case)
      .then(buffer => buffer.toString())
      .then(json => JSON.parse(json))
      .then(note => res.status(200).json(note))
      .catch(err => errorHandler(err, res));

  });

  router.get('/note', (req, res) => {
    debug('Begin Get All');
    storage.fetch('Note')   // O(n) Normal Operation (Best Case)
      .then(files => res.status(200).json(files))
      .catch(err => errorHandler(err, res));
  });

  router.put('/note/:_id', bodyParser, (req, res) => {
    debug('Begin Put');
    storage.update('Note', req.params._id, req.body) // O(1) Normal Operation (Best Case)
      .then(() => res.status(204).send())
      .catch(err => errorHandler(err, res));
  });

  router.delete('/note/:_id', (req, res) => {
    debug('Begin Delete');
    storage.destroy('Note', req.params._id)   // O(1) Normal Operation (Best Case)
      .then(() => res.status(204).send())
      .catch(err => errorHandler(err, res));

  });

};<file_sep>import React from 'react'
import {renderIf} from '../../../lib/utils'
import ExpenseUpdateForm from '../expense-update-form/expense-update-form';

class ExpenseItem extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      item: this.props.item ? this.props.item : {},
      editing: false,
    }

    this.handleEditing = this.handleEditing.bind(this)
  }

  handleEditing() {
    this.setState({editing: !this.state.editing})
  }

  render() {
    return (
      <li
        className="expense-item"
        id={this.state.item._id}
        onDoubleClick={this.handleEditing}>

        <p>Name: {this.state.item.name}</p>
        <p>Price: ${this.state.item.price}</p>
        {renderIf(this.state.editing,
          <ExpenseUpdateForm
            expense={this.state.item}
            toggleEdit={this.handleEditing}
            dashboard={this.props.dashboard}/>
        )}
      </li>
    )
  }
}

export default ExpenseItem
<file_sep>'use strict'

const server = require('../server')
const net = require('net')
require('jest')

describe('Server module', function() {
  afterAll(() => server.close())

  describe('setting up a connection to the server', () => {
    it('should connect and notify me that I joined the channel', done => {
      let socket = net.connect({port: 3000})
      // console.log(socket)
      socket.on('data', data => {
        expect(data.toString()).toMatch(/has joined the chat/)
        // expect(data.toString()).not.toMatch(/BOOGIE NIGHTS/)
        socket.end()
        done()
      })
    })
  })


  // SCOTT WILL FIX THIS ONE
  // describe('testing facepalm command', () => {
  //   it('should facepalm', done => {
  //     let messages = []

  //     let socket = net.connect({port: 3000})


  //     socket.write('@facepalm', () => {
  //       socket.on('data', data => {
  //         console.log('data', data.toString())
  //         messages.push(data.toString())
  //         socket.end(null, () => {
  //           console.log(messages)
  //           expect(messages[0]).toMatch(/is disappointed/)
  //           done()
  //         })
  //       })
  //     })
  //   })
  })
})<file_sep>import './styles/reset.scss'
import './styles/main.scss'

import React from 'react'
import ReactDom from 'react-dom'
import Select from './components/form-elements/select/select'
import FormInput from './components/form-elements/input/input'
import Slider from './components/form-elements/slider-checkbox/slider'

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      title: '',
      dropDown: {},
      slider: false,
    }

    this.handleSubmit = this.handleSubmit.bind(this)
    this.handleChange = this.handleChange.bind(this)
    this.sliderToggle = this.sliderToggle.bind(this)
    this.handleDropdown = this.handleDropdown.bind(this)
  }

  handleSubmit(e) {
    e.preventDefault()
    console.log(this.state)
  }

  handleChange(e) {
    this.setState({[e.target.name]: e.target.value})
  }

  sliderToggle(e) {
    console.log('slider is:', e.target.checked)
    this.setState({slider: e.target.checked})
  }

  handleDropdown(item) {
    this.setState({dropDown: item})
  }

  render() {
    return (
      <div className="application">
        <h1>Hello world!</h1>
        <h3>Check out my custom form elements</h3>

        <div className="form-container">
          <form onSubmit={this.handleSubmit}>
            <FormInput
              config={({
                className: 'form-inputs',
                name: 'title',
                value: this.state.title,
                type: 'text',
                placeholder: 'React Documentation'
              })}
              onChange={this.handleChange}/>

              <Slider
                config={({
                  id: 'slider-one',
                  className: 'slider-checkbox',
                  value: this.state.sliderOne,
                  name: 'slider-one'
                })}
                onChange={this.sliderToggle}/>

              <Select
                config={{
                  classes: '',
                  items: [{_id: '1234', name: 'Hello'}, {_id: '4567', name: 'Goodbye'}, {_id: '8901', name: 'Wat'}]
                }}
                onComplete={this.handleDropdown}/>

            <button type="submit">submit</button>
          </form>
        </div>
      </div>
    )
  }
}

ReactDom.render(<App />, document.getElementById('root'))
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 33: Redux Middleware
===

## Daily Plan
- Notes
    - Anything top of mind?

- Code Review
- Redux Middleware
- Thunk
- Lab Preview

## Learning Objectives
* Students will be able to create middleware for redux
* Students will be able to add third party middleware to redux

## Readings
* Read [redux middleware](http://redux.js.org/docs/advanced/Middleware.html)

## Overview
Redux middleware provides a third-party extension point between dispatching and action and the moment it reaches the reducer. It can be used for logging actions, adding promise support, making api requests, caching, throttling, and much more.
<file_sep>'use strict'

// Application dependencies
const express = require('express')
const cors = require('cors')
const errorHandler = require('./error-handler')


// Application setup
const app = express()
const router_notes = express.Router()
// const router_users = express.Router()
// const router_images = express.Router()
app.use('/api/v1/note', router_notes)
// app.use('/api/v1/users', router_users)
// app.use('/api/v1/images', router_images)
// app.use(bodyParser) // Applies the package to every route in the app
app.use(cors())

// Route setup
require('../route/route-note')(router_notes)
// require('../route/route-category')(router)
app.use('/{0,}', (req, res) => errorHandler(new Error('Path Error. Route not found.'), res))

// Server controls
const server = module.exports = {}
server.isOn = false
server.http = null

server.start = function(port, callback) {
  if(server.isOn) return callback(new Error('Server running. Cannot start server again.'))
  server.isOn = true
  server.http = app.listen(port, callback)
}

server.stop = function(callback) {
  if(!server.isOn) return callback(new Error('Server not running. You\'re dumb. Don\'t do that.'))
  server.isOn = false
  server.http.close()
}<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 37: Cookies
===

## Daily Plan
- Notes:
    - Anything top of mind?
    - Project Teams & Planning
    - Final Exams - Next week: Scott will put out a schedule.

- Code Review
- Review of Cookies / Browser State
- Client-side Auth
- Lab Preview

## Learning Objectives
* Students will be able to manage Basic and Bearer authentication on the client side
* Students will be able to manage cookies on the client side

## Readings
* Read [cookies](https://www.quirksmode.org/js/cookies.html)
* Read [Http Cookie Wiki](https://en.wikipedia.org/wiki/HTTP_cookie)

## Cookies
Cookies are key value pairs that can store text. They are meant to be a reliable place to store stateful information on the browser. Cookies can be given an expiration date, and the browser will automatically remove them when that date occurs.
<file_sep>let validateAlbum = payload => {
  if(!payload._id) throw new Error('VALIDATION ERROR. Album must have an ID')
  if(!payload.name) throw new Error('VALIDATION ERROR. Album must have name')
}

export default (state=[], action) => {
  let {type, payload} = action
  // validateAlbum(payload) // Reminder that we can't do this in every case, so it's situational.

  switch(type) {
    case 'ALBUM_SET': return payload
    case 'ALBUM_CREATE':
      validateAlbum(payload)
      return [...state, payload]
    case 'ALBUM_UPDATE':
      validateAlbum(payload)
      return state.map(album => album._id === payload._id ? payload : album)
    case 'ALBUM_DELETE':
      validateAlbum(payload)
      return state.filter(album => album._id !== payload._id)
    default: return state
  }
}
<file_sep>import React from 'react';

class ExpenseForm extends React.Component{
  constructor(props){
    super(props);// Vinicio - we HAVE to call this super()
    this.state = {
      name : '',
      price : 0,
    };
    //----------------------------------------------------
    // Binding Handlers
    //----------------------------------------------------
    let memberFunctions = Object.getOwnPropertyNames(ExpenseForm.prototype);
    for(let functionName of memberFunctions){
      if(functionName.startsWith('handle')){
        this[functionName] = this[functionName].bind(this);
      }
    }
    //----------------------------------------------------
  }
  //------------------------------------------------------
  // Member Function
  //------------------------------------------------------
  handleSubmit(event){
    event.preventDefault();
    this.props.handleAddExpense(this.state);
    // vinicio - clearing the form
    this.setState({
      name : '',
      price : 0,
    });
  }

  handleChange(event){
    let {name,value} = event.target;
    // vinicio - name will be the name of the input we are working with

    this.setState({
      [name]: value,
    });
  }

  //------------------------------------------------------
  // Lifecycle hooks
  //------------------------------------------------------
  render(){
    return(
      <form className='expense-form' onSubmit={this.handleSubmit}>
        <input
          type='text'
          name='name'
          placeholder='name'
          value={this.state.name}
          onChange={this.handleChange}  
        />
        <input
          type='number'
          name='price'
          placeholder='price'
          value={this.state.price}
          onChange={this.handleChange}  
        />
        <button type='submit'> create expense </button>
      </form>
    );
  }
};

export default ExpenseForm;<file_sep>'use strict';

const Bike = require('../model/bike.js');
const bodyParser = require('body-parser').json();
const errorHandler = require('../lib/error-handler.js');

module.exports = function(router) {
  router.route('/bike/:_id?')
    .get((req, res) => {

      if(req.params._id) {
        return Bike.findById(req.params._id)
          .populate('rider')
          .then(bike => res.status(200).json(bike))
          .catch(err => errorHandler(err, res));
      }
      Bike.find()
        .then(bike => bike.map(bike => bike._id))
        .then(bike => res.status(200).json(bike))
        .catch(err => errorHandler(err, res));
    })
    .post(bodyParser, (req, res) => {
      new Bike(req.body).save()
        .then(bike => res.status(201).json(bike))
        .catch(err => errorHandler(err, res));
    })
    .put(bodyParser, (req, res) => {
      Bike.findOneAndUpdate(req.params._id, req.body, {upsert: true, runValidators: true})
        .then(() => res.sendStatus(204))
        .catch(err => errorHandler(err, res));

    })
    .delete((req, res) => {
      Bike.findById(req.params._id)
        .then(bike => bike.remove())
        .then(() => res.sendStatus(204))
        .catch(err => errorHandler(err, res));

    });
};<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 39: TBD
===

## Learning Objectives
<!-- * need more content here... svg and fonts isn't enough for a full day -->

* Students will be able to load fonts with webpack
* Students will be able to create icons using SVGs
* Students will learn the difference between icon fonts and inline svgs

## Readings
* Skim [url-loader docs](https://webpack.js.org/loaders/url-loader/)
* Read [icon-font vs inline-vg](https://css-tricks.com/icon-fonts-vs-svg/)

## URL Loader
The url loader can either copy an imported asset into the build path, or turn it into a DataURL. This DataURL can be used to preview the image in the browser, prior to gaining a response from S3, with the newly created AWS CDN url.

## SVGs
SVGs are natively supported in HTML. By using inline SVG's you open the potential for much more styling control.
<file_sep>import React from 'react'
import {connect} from 'react-redux'
import {
  albumFetchRequest,
  albumCreateRequest} from '../../actions/album-actions'

class Dashboard extends React.Component {
  componentWillMount() {
    this.props.fetchAlbums()
  }

  render() {
    return (
      <div className="dashboard-container">
        <h1>Hello world - music things</h1>

        {this.props.albums ?
          this.props.albums.map(album =>
            <div key={album._id}>
              {/* <span onClick={() => this.props.deleteAlbum(album)}>x</span> */}
              <p>{album.name}</p>
            </div>)
          :
          undefined
        }
      </div>
    )
  }
}

let mapStateToProps = state => ({
  albums: state.albums,
})

let mapDispatchToProps = dispatch => ({
  fetchAlbums: () => dispatch(albumFetchRequest()),
  createAlbum: album => dispatch(albumCreateRequest(album)),
  // deleteAlbum: album => dispatch(albumDeleteRequest(album)),
})

export default connect(mapStateToProps, mapDispatchToProps)(Dashboard)
<file_sep>import superagent from 'superagent'
import { logError } from '../lib/utils'

export const trackSet = tracks => ({
  type: 'TRACK_SET',
  payload: tracks
})

export const trackCreate = track => ({
  type: 'TRACK_CREATE',
  payload: track
})

export const trackUpdate = track => ({
  type: 'TRACK_UPDATE',
  payload: track
})

export const trackDelete = track => ({
  type: 'TRACK_DELETE',
  payload: track
})

export const trackFetchRequest = () => dispatch => {
  return superagent.get(`${__API_URL__}/api/v1/track`)
  .then(res => dispatch(trackSet(res.body)))
  .catch(logError)
}

export const trackCreateRequest = track => dispatch => {
  return superagent.post(`${__API_URL__}/api/v1/track`)
  .send(track)
  .then(res => dispatch(trackCreate(res.body)))
  .catch(logError)
}

export const trackUpdateRequest = track => dispatch => {
  return superagent.put(`${__API_URL__}/api/v1/track/${track._id}`)
  .send(track)
  .then(() => dispatch(trackUpdate(track)))
  .catch(logError)
}

export const trackDeleteRequest = track => dispatch => {
  return superagent.delete(`${__API_URL__}/api/v1/track/${track._id}`)
  .then(() => dispatch(trackDelete(track)))
  .catch(logError)
}
<file_sep>'use strict'

const server = require('../lib/server')
const superagent = require('superagent')


describe('Server module', function() {
  beforeAll(() => server.start(4444))
  afterAll(() => server.stop())

  describe('Valid Request to the API', () => {
    describe('GET /time', () => {
      it('should respond with a status 200', () => {
        return superagent.get(':4444/time')
        .then(res => {
          expect(res.status).toBe(200)
        })
        //.catch() // usually not needed in a case of successful request
      })
      it('should return a date/time object', () => {
        return superagent.get(':4444/time')
        .then(res => {
          expect(res.body).toHaveProperty('now')
          expect(res.body).toBeInstanceOf(Object)
        })
      })
    })
  })

  describe('Invalid Request to the API', () => {
    it('should return a 404 status code', () => {
      return superagent.get(':4444/doesNotExist')
      .catch(err => {
        expect(err.status).toBe(404)
      })
    })
  })
})<file_sep>'use strict'

const fs = require('fs')

fs.readFile(`${__dirname}/data/one.html`, (err, data) => {
  if(err) console.error(err)
  let buffer = data
  let fd = data.toString()
  let hex = data.toString('hex')
  let tim = hex * 3 // will return NaN

  // some manipulation or aggregation of the data, buffer or otherwise

  fs.writeFile(`${__dirname}/data/new.html`, tim, err => err ? console.error(err) : undefined)
})<file_sep>import React from 'react'
import {connect} from 'react-redux'
import CardForm from '../card-form/card-form'
import {cardUpdate, cardDelete} from '../../../action/card-actions'

class CardItem extends React.Component {
  render() {
    return (
      <section id={this.props.card._id}>
        <h3>{this.props.title}</h3>
        <span onClick={() => this.props.cardDelete(this.props.card)}>x</span>
        <CardForm
          buttonText="update"
          card={this.props.card}
          onComplete={this.props.cardUpdate}/>
      </section>
    )
  }
}

let mapStateToProps = () => ({})
let mapDispatchToProps = (dispatch, getState) => ({
  cardUpdate: card => dispatch(cardUpdate(card)),
  cardDelete: card => dispatch(cardDelete(card)),
})

export default connect(mapStateToProps, mapDispatchToProps)(CardItem)
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 01: Node Ecosystem
=====================================

## Daily Plan
- Notes:
    - Anything top of mind? _expect this question every day!_
    - Housekeeping Items _see whiteboard_

- Course Overview
    - 1st Half _Node, Express, MongoDB_
    - 2nd Half _React & Redux_
    - Daily Process Introduction _Normally_
        - 9a: Lecture
        - 12p: Lunch
        - 1p: Whiteboard challenge
        - 130p - 6p: Labs

- Git/Github & Other Tools
- Developer Environment _You should not be thinking much about it at this point_
- NodeJS _Reintroduction_
    - Strict Mode: Use. Always. It's helping your code run as optimal as possible for the JS Engine!
- CommonJS Modules _and a quick chat about import/export_
- Testing with Jest _Test Driven Development_
- Lab & Whiteboard Challenge Preview
    - Whiteboarding Process _Time permitting_



# Learning Objectives
* Students will be able to set up a node project
* Students will be able to create node modules that conform to the CommonJS module pattern
* Students will be able to construct and run unit tests
* Students will be able explain the TDD philosophy of red, green, refactor

-----

## Readings
### Node.js
* Read [About Node]
* Read/Skim [Node Modules](https://nodejs.org/docs/latest/api/modules.html#modules_modules)
* Skim [Node API](https://nodejs.org/docs/latest-v7.x/api/)
* Skim [About V8]
* Skim [What is NPM]

### Test-Driven Development
* Read [A Gentle Intro to TDD in JS]
  * Read only part 1
  * We'll be using a different framework than the one used in this article, but most of the concepts and principles are applicable to the framework we'll be using (Jest)
* Read [Getting Started with Jest](https://facebook.github.io/jest/docs/en/getting-started.html)
* Skim [Expect Docs](https://facebook.github.io/jest/docs/en/expect.html)

### ES6
* Read [Just Another Guide to ES6]
* Skim [Node's ES6 Docs]

-----

## Setting up a development workspace
Before people are developers, they often develop many habits they will need to unlearn:
* Use the command line whenever possible. In the long run it will save you a lot of time.
* It is highly important to keep our file system organized.
  * If your problem is finding your code, you are in deep trouble!.
  * Create a dir structure for keeping track of you class work.
* File naming tips
  * Never put space bars in your file names.
  * Use `-` or `_` instead. But choose one and stick with it... don't use both!.
  * Never use capital letters in your filenames, unless its convention (like README.md).
    * Some file systems (like osx) don't keep track of Case and will cause git issues.
``` text
 * $HOME/
  | - Desktop/
  | - Downloads/
  | - ...
  | - cf-401/
  |   | - labs/
  |   |   | - lab-01-node-ecosystem
  |   |   | - lab-02-tools-and-context
  |   |   | - ...
  |   | - lecture-notes/
  |   |   | - class-01-node-ecosystem
  |   |   | - class-02-tools-and-context
  |   |   | - ...
  ```
## Node.JS
* Node is an asynchronous, event-driven runtime used to build back-end (a.k.a Server Side) JavaScript applications.
* Node uses an "event loop" to work only when events are triggered.
    * When Node has no work to be done, Node sleeps.
* Node input and output (I/O) is non-blocking.
  * This save developers from having to worry about concurrent programming patterns.
* At a high level, Node is composed of two main components:
  * __Javascript API__ :
    * Internally, Node uses [libuv](https://github.com/libuv/libuv) for I/O.
  * __V8 Javascript engine__
* Node's documentation has a stability index.
  * 0 - deprecated - don't use the feature.
  * 1 - Experimental - don't use this feature in something you care about.
  * 2 - Stable - fine to use.
  * 3 - Locked - fine to use.
* *Make sure you read the docs for the version of node you're using.*

## NPM
* NPM is a package manager for installing javascript libraries.
* NPM is composed of the following.
  * A registry where all the packages are hosted.
  * A search engine where you can find packages.
  * A CLI where that helps you interface with the registry.
  * A for profit organization.

## CommonJS modules
* Modules are used to break down applications into smaller pieces.
* Why are modules useful?
  * The common `<script src=""></script>` pattern used to work with JavaScript loads variables and functions into global scope.
  * Relying in the global space is error-prone due to naming conflicts and unexpected side-effects.
  * Modules allow us to explicitly define what's loaded in the global scope.
    * This plays a huge role in allowing Javascript developers to build large scale applications.

### Using CommonJS modules
* In Node.js, every JavaScript file is a module.
* CommonJS modules work based on 2 main elements:
  * The `module.exports` object
    * Anything that is assigned to module.exports can be accessed by other modules via the `require` function.
    * Everything else will be hidden from other modules.
  * The `require` function
    * Searches and loads CommonJS modules.
    * The require function expects a relative or absolute path to the module being imported.
      * Like: `require('./relative/path/to/the/module.js')`.
* CommonJS modules cannot be co-dependent
  * If module "A" requires module "B" then "B" can not also require "A".
* *ES6 introduced a different module format that is not compatible with CommonJS modules.*
   * *At this time, both ES6 and CommonJS modules are common in JavaScript codebases, so we'll learn both in this course.*

## Testing and TDD
* TDD is a software development process where you write tests before you write code.
* It relies on a very short development cycle.
  * It encourages to build small things at a time.
### TDD Process
* This process is called __red, green, refactor__:
* __Red__
  * Bake a plan for the features needed to make a program work.
  * Choose a feature to implement.
  * Write code that tests that features behavior.
  * The tests now should fail, because the feature has not been implemented.
* __Green__
  * Write the feature itself.
  * The tests now should pass, because the feature has been implemented.
* __Refactor__
  * Refactor you code to optimize it.
  * The tests should still pass, because the behavior should not have changed.

## Jest
* Jest is a testing framework.
  * Its job is to facilitate writing and running tests.
* Expect is an assertion library.
  * Its job facilitate writing expectations and then throw errors when the expectations are not met.
* When testing with jest, we'll primarily work with 3 functions:
  * `descride`
  * `test`
  * `expect`

<!--links -->
[About Node]: https://nodejs.org/en/about/
[Node's ES6 Docs]: https://nodejs.org/en/docs/es6/
[libuv Docs]: https://github.com/libuv/libuv
[About V8]: https://developers.google.com/v8/
[What is NPM]: https://docs.npmjs.com/getting-started/what-is-npm
[A Gentle Intro to TDD in JS]: http://jrsinclair.com/articles/2016/gentle-introduction-to-javascript-tdd-intro/
[Just Another Guide to ES6]: https://medium.com/sons-of-javascript/javascript-an-introduction-to-es6-1819d0d89a0f#.wb7rj1gin<file_sep>import React from 'react'
import {connect} from 'react-redux'
import {renderIf} from '../../../lib/utils'
import CardForm from '../../card/card-form/card-form'
import CardItem from '../../card/card-item/card-item'
import {cardCreate} from '../../../action/card-actions'
import CategoryForm from '../category-form/category-form'
import {categoryUpdate, categoryDelete} from '../../../action/category-actions'

class CategoryItem extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      category: this.props.category ? this.props.category : {},
      editing: false,
    }
    this.handleEditing = this.handleEditing.bind(this)
  }

  handleEditing() {
    this.setState({editing: !this.state.editing})
  }

  render() {
    return (
      <div className="category-item" onDoubleClick={this.handleEditing}>
        <h3>{this.state.category.title}</h3>
        <p onClick={() => this.props.categoryDelete(this.state.category)}>x</p>
        <CategoryForm
          buttonText="update"
          onComplete={this.props.categoryUpdate}/>

        <CardForm
          buttonText="create"
          categoryId={this.props.category._id}
          onComplete={this.props.cardCreate}/>

        {renderIf(this.props.cards[this.props.category._id],
          this.props.cards[this.props.category._id].map(card => <CardItem key={card._id} card={card}/>)
        )}

      </div>
    )
  }
}

const mapStateToProps = state => ({
  cards: state.cards,
})

const mapDispatchToProps = (dispatch, getState) => ({
  categoryUpdate: category => dispatch(categoryUpdate(category)),
  categoryDelete: category => dispatch(categoryDelete(category)),
  cardCreate: card => dispatch(cardCreate(card)),
})

export default connect(mapStateToProps, mapDispatchToProps)(CategoryItem)
<file_sep>'use strict';

const net = require('net');
const Client = require('./model/client');
const cmd = require('./lib/cmd');
const ascii = require('./assets/ascii');

const server = module.exports = net.createServer();
const PORT = process.env.PORT || 3000;
let clientPool = [];

server.on('connection', function (socket) {
  let client = new Client(socket);
  clientPool.push(client);
  clientPool.map(c => c.socket.write(`\n\t${client.nick} has joined the chat\n`))

  socket.on('data', function (data) {
    let msg = cmd(data, clientPool);
    socket.emit(msg.command, msg);
  });

  socket.on('list', function () {
    client.socket.write('\n\tConnected Users:\n');
    clientPool.map (c =>  client.socket.write(`\n\t${c.nick}\n`));
  });

  socket.on('nickname', function(data) {
    clientPool.map(c => c.socket.write(`\n\t\t${client.nick} has changed their name to ${data.name}\n`));
    client.nick = data.name;
  });

  socket.on('message', function (data) {
    let message = data.said;
    clientPool.filter(c => c.user !== client.user)
      .map(c => c.socket.write(`\n${client.nick}: ${message}\n`));
    client.socket.write(`\nYou (${client.nick}) Said: ${message}\n`);
  });

  socket.on('dm', function (data) {
    let who = clientPool.filter(c => c.nick === data.name);
    who[0].socket.write(`\nDirectly From ${client.nick}: ${data.said}\n`);
    client.socket.write(`\nDirectly To ${data.name}: ${data.said}\n`);
  });

  socket.on('jeep', function () {
    let jeep = ascii.jeep.split('%');
    clientPool.map(c => c.socket.write(`\n${jeep[0]}${client.nick}'s A JEEP\n\n`));
  });

  socket.on('facepalm', function () {
    clientPool.map(c => c.socket.write(`\n${client.nick} is disappointed\n\n${ascii.facepalm}`));
  });

  socket.on('close', function () {
    clientPool = clientPool.filter(c => c.user !== client.user);
    clientPool.map(c => c.socket.write(`\n\t${client.nick} has left the chat\n`));
    socket.end();
  });

  socket.on('error', function (data) {
    client.socket.write(`\n\t\t!!!\tError\t!!!:\n \t\t${data.err}\n`);
  });
});

server.listen(PORT, () => console.log(`listening on ${PORT}`));<file_sep>#!/usr/bin/env node
'use strict';
const start = module.exports = {};

const reader = require('./lib/reader.js');
const bitmap = require('./lib/bitmap.js');
const transform = require('./lib/transform.js');

start.processImage = function(args) {
  if(args.length < 5) {
    let arg_err = 'Invalid arguments - Expecting: <file-Path> <new-file-name> <transform-method>';
    console.log(arg_err);
    // process.stdOut.write()
    return arg_err;
  }

  let [imagePath, newName, tm] = args.slice(2);
  let imgDir = imagePath.split('/').slice(0, -1).join('/');
  let newPath = `${imgDir}/${newName}.bmp`;

  if(!transform.hasOwnProperty(tm)) {
    let method_error = 'Invalid transform method - Expecting one of: <random> <invert> <reverse> <boostGreen> <boostRed> <boostBlue> <redChannel> <blackWhite> <invert2> <invert3> <invert4>';
    console.log(method_error);
    return method_error;
  }

  reader.read(imagePath, (err, fd) => {
    if(err) return err;
    bitmap.parse(fd, (err, bmp) => {
      if(err) err; // return err?
      transform[tm](bmp, (err, bmp) => {
        if(err) err; // return err?
        reader.write(bmp, newPath, err => {
          if(err) err; // return err?
        });
      });
    });
  });
};

start.processImage(process.argv);
<file_sep>export const PICTURES_ROUTE = '/photos';<file_sep>'use strict'

// Application dependencies
const http = require('http')
const Router = require('./router')

// Router setup
const router = new Router()
require('../route/route-note')(router)

// Application setup
const app = http.createServer(router.route())

// Server controls
const server = module.exports = {}
server.start = (port, cb) => app.listen(port, cb)
server.stop = (cb) => app.close(cb)<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 36: Asynchronous Actions
===

## Daily Plan
- Notes:
    - Anything top of mind?
    - What's happening this week; Topics, Schedule, etc...

- Code Review
- Redux Thunk Middleware
- Working with asynchronous actions (functions)
- Lab Preview


## Learning Objectives
* Students will be able to create thunk middleware for redux
* Students will be able to create asynchronous actions

## Readings
* [Async Actions](https://redux.js.org/advanced/async-actions#async-action-creators)

## Redux Thunk
Redux thunk middleware allows you to dispatch function actions as well as function actions. Function actions will have access to `dispatch`, and `getState`. Function actions can trigger async events and dispatch new actions when they are completed. This is often used to make AJAX requests to the a HTTP server.
<file_sep>'use strict';

const bitmap = module.exports = {};

function Bmp(buffer) {
  this.allData = buffer;
  this.sig = buffer.toString('utf-8', 0, 2);
  this.fileSize = buffer.readUInt32LE(2);
  this.offset = buffer.readUInt32LE(10);
  this.width = buffer.readUInt32LE(18);
  this.height = buffer.readUInt32LE(22);
  this.colorArray = buffer.slice(54, this.offset);
  this.pixelArray = buffer.slice(this.offset);
}



bitmap.parse = function(buffer, callback) {
  if(!buffer) return callback(`Error: buffer is ${buffer}`);
  let imgBuff;
  try {
    imgBuff = new Bmp(buffer);
  }
  catch(e){
    imgBuff = {sig:null};
  }
  if (imgBuff.sig !== 'BM') return callback('Error: is not a Windows format bitmap');
  callback(null, imgBuff);
};
<file_sep>'use strict';

let storage = require('../../lib/storage');
let fs = require('fs');
require('jest');

let testData = { title: 'testdatarun', content: 'test data run', _id: 'testdatafile' };
let testUpdate = { title: 'testupdaterun', content: 'test data run', _id: 'testdatafile' }
let testWrong = { title: 'testwrongrun', content: 'test data run', _id: 'invalidid'}
storage.create('Note', testData);
describe('Storage Module', () => {
  describe('#create', () => {
    it('Should create a file if passed valid arguments', () => {
      expect(fs.readdirSync(`${__dirname}/../../data/Note`)).toContain('testdatafile.json');
    });
  });
  describe('#update', () => {
    it('Should properly update the file given new information', () => {
      return storage.update('Note', testData._id, testUpdate)
        .then(file => {
          expect(file.title).toBe('testupdaterun');  
        });
    });
    it('Should return a validation error if the id in the file does not match the requested file', () => {
      return storage.update('Note', testData._id, testWrong)
        .catch(err => {
          expect(err).toBeInstanceOf(Error);
        });
    });
  });
  describe('#fetch', () => {
    it('Should return an array of file names', () => {
      return storage.fetch('Note')
        .then(file => {
          expect(Array.isArray(file)).toBeTruthy();
        });
    });
  });
  describe('#fetchOne', () => {
    it('Should return valid data contained in a specific file', () => {
      return storage.fetchOne('Note', testData._id)
        .then(file => {
          file = JSON.parse(file.toString());
          expect(file.content).toBe('test data run');
        });
    });
  });
  describe('#destroy', () => {
    it('Should successfully delete a file from the storage directory', () => {
      return storage.destroy('Note', testData._id)
        .then(() => {
          return storage.fetch('Note')
            .then(files => {
              expect(files).not.toContain('testdatafile');
            });
        });
    });
  });
});<file_sep>#Lab 31 Redux


in this app a category should contain at least the following properties
id a uuid
timestamp a date from when the category was created
name a string that is the name of the category
budget a number that is the total amount of $ in the category
feel free to add more to your categories

Dashboard Component
should be displayed on the / route
should use react-redux's connect to map state and dispatchable methods to props
should display a CategoryForm for adding categories to the app state
should display a CategoryItem for each category in the app state
CategoryForm Component
should expect an onComplete prop to be a function
that function should be invoked with the CategoryForms state when the form is submitted
should expect a buttonText prop to configure the submit buttons text
should support an optional category prop that will initialize the state of the form
CategoryItem Component
should display the category's name and budget
should display a delete button
onClick the category should be removed from the application state
should display a CategoryForm
onComplete the form should update the component in the application state

## Installing
```
npm install
```
This will install the required depencencies

## Running the application
```
npm run watch
```
This will start the webpack dev server so that the app has a build.

Then you can go to 
```
http://localhost:8080/
```
in the web browser. This will display the app.

## Testing
There is no testing at this time.









## Authors

* **<NAME>** - *RND* 



## License

This project is licensed under the MIT License - 

## Acknowledgments

* <NAME>
* Google
*<file_sep>'use strict'

const debug = require('debug')('http:storage')

// Example setup for promisifying the fs module (any callback based module/api)
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'), {suffix: 'Prom'})
// fs.readFile(path, callback)
// fs.readFileProm(path).then().catch()
// fs.readDir

const storage = module.exports = {}

// memory = {
//   'Notes': {
//     '1234.5678.9012': {
//       '_id': '1234.5678.9012',
//       'title': '',
//       'content': '',
//     },
//   },
//   'Categories': {
//     ...
//   },
// }

storage.create = function(schema, item) {
  debug('Created a new thing')

  return new Promise((resolve, reject) => {
    if(!schema) return reject(new Error('Cannot create a new item; Schema required'))

    let jsonData = JSON.stringify(item)

    return fs.writeFileProm(`${__dirname}/../data/${schema}/${item._id}.json`, jsonData)
    .then(() => resolve(jsonData))
    .catch(reject)
  })
}

storage.fetchOne = function(schema, itemId) {
  return new Promise((resolve, reject) => {
    if(!schema) return reject(new Error('400, Cannot find record. Schema required.'))
    if(!itemId) return reject(new Error('400, Cannot find record. Item ID required.'))

    return fs.readFileProm(`${__dirname}/../data/${schema}/${itemId}.json`)
    .then(data => resolve(data.toString()))
    .catch(reject)
  })
}

storage.fetchAll = function(schema) {
  return new Promise((resolve, reject) => {
    if(!schema) return reject(new Error('400, Cannot find record. Schema required.'))

    return fs.readdirProm(`${__dirname}/../data/${schema}`)
    .then(data => data.map(id => id.split('.')[0]))
    .then(ids => resolve(ids))
    .catch(reject)
  })
}

storage.update = function(schema, itemId, item) {
  return new Promise((resolve, reject) => {
    if(!schema) return reject(new Error('Cannot update. Schema required.'))
    if(!itemId) return reject(new Error('Cannot update. Item ID required.'))
    if(!item) return reject(new Error('Cannot update. Item required.'))
    if(item._id !== itemId) return reject(new Error('Cannot update. Invalid ID'))

    return fs.readFileProm(`${__dirname}/../data/${schema}/${item._id}.json`)
    .then(data => data.toString())
    .then(json => JSON.parse(json))
    .then(oldData => {
      return {
        title: item.title || oldData.title,
        content: item.content || oldData.content,
        _id: oldData._id,
      }
    })
    .then(JSON.stringify)
    .then(json => fs.writeFileProm(`${__dirname}/../data/${schema}/${item._id}.json`, json))
    .then(resolve)
    .catch(reject)
  })
}

storage.delete = function(schema, itemId) {

}<file_sep>'use strict'

const superagent = require('superagent')
const server = require('../../lib/server')
const Track = require('../../model/track')
require('jest')

describe('POST /api/v1/track', function() {
  beforeAll(() => this.mockTrack = {title: 'shark in the dark', artist: 'slug'})
  beforeAll(() => server.start())
  afterAll(() => server.stop())
  afterAll(() => Promise.all([Track.remove()]))

  describe('valid requests', () => {
    beforeAll(() => {
      return superagent.post(`:${process.env.PORT}/api/v1/track`)
      .send(this.mockTrack)
      .then(res => this.response = res)
    })


    it('should return a status code of 201 CREATED', () => {
      expect(this.response.status).toBe(201)
    })
  })
  describe('invalid request', () => {

  })
})<file_sep>'use strict'

// function concat(num, str) {
//   return new Promise((resolve, reject) => {
//     if(!num || !str) return reject(new Error('there be a problem!'))

//     return resolve(num + str)
//   })
// }

// console.log(concat(1, 'hello'))

const fs = require('fs')

let firstRead = fs.readFile(`${__dirname}/promise.js`, (err, data) => {
  return new Promise((resolve, reject) => {
    if(err) return reject(new Error('barf'))
    return resolve(data.toString())
  })
})

firstRead
  .then()
  .then()
  .then()
  .then()
  .then()
  .then()
  .catch()


fs.readFile(`${__dirname}/promise.js`, (err, data) => {
  if(err) throw new Error('barf')

  console.log(data.toString())
})<file_sep>'use strict';

class TreeNode{
  constructor(value,left=null,right=null){
    this.value = value;
    this.left = left;
    this.right = right;
  }
}

class BinaryTree{
  constructor(root=null){
    this.root = root;
  }

  inOrderTraversal(){
   if(!this.root)
     return null;
   this._inOrderTraversal(this.root);
  }

  _inOrderTraversal(root){
    // vinicio - this is a base case
    if(root === null)
      return null;

    // visit left
    this._inOrderTraversal(root.left);
    // visit root
    console.log(`Visiting ${root.value}`);
    // visit right
    this._inOrderTraversal(root.right);
  }
}

let one = new TreeNode(1);
let two = new TreeNode(2);
let three = new TreeNode(3);
let four = new TreeNode(4);
let five = new TreeNode(5);
let six = new TreeNode(6);
let seven = new TreeNode(7);
let eight = new TreeNode(8);
let nine = new TreeNode(9);

let binaryTree = new BinaryTree();
binaryTree.root = one;

one.left = two;
one.right = three;

two.left = six;

three.left = four;
three.right = five;

six.right = seven;

seven.left = eight;
seven.right = nine;

binaryTree.inOrderTraversal();
<file_sep>'use strict';

// return values => {
  //  command: 'something',
  //  ... other key:values,
// }

module.exports = (data, connected) => {
  let message = data.toString().trim().split(' ');
  console.log('message', message)
  if (message[0][0] === '@') {
    switch (message[0]) {
    case '@quit':
      return {command: 'close'};
    case '@list':
      return {command: 'list'};
    case '@nickname':
      if (connected.filter(c => c.nick === message[1]).length) return {command: 'error', err: 'Nickname Already In Use'};
      return message[2]? {command: 'error', err: '@nickname requires a name without spaces'} : {command: 'nickname', name: message[1]};
    case '@dm':
      if (connected.filter(c => c.nick === message[1]).length) return {command: 'dm', name: message[1], said: message.slice(2).join(' ')};
      else return {command: 'error', err: 'Requested user does not exist'};
    case '@jeep':
      return message[1]? {command: 'error', err: 'Jeeps cannot talk'} : {command: 'jeep'};
    case '@facepalm':
      return message[1]? {command: 'error', err: 'Are you facepalming or talking?'} : {command: 'facepalm'};
    default:
      return {command: 'error', err: 'Command does not exist'};
    }
  } else return {command: 'message', said: message.join(' ')};
};<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 44: Frontend Deployment
===

## Learning Objectives
* Students will learn about Content Distribution Networks (CDN)
* Students will learn to set up AWS Cloudfront to host their static assets

## Readingsa
* Read [AWS CloudFront](https://aws.amazon.com/cloudfront/)

## Transport Layer Security (TLS / SSL)
The Transport Layer Security(TLS) was previously the Secure Socket Layer(SSL). TLS is a crypographic protocol that provides secure communications over a computer network. TLS enables communications between computers to be private. It does this by using asymmetric cyphers to encrypt data before sending it across the network.

When a client and server make a TLS connection they negotiate a stateful connection using the following handshake.

0. The client connects to the TLS enabled server and provides a list of supported ciphers
0. The server picks a cipher that it supports and notifies the client
0. The server sends its public encryption key or a digital certificate
0. The client confirms the validity digital certificate
0. The client generates and sends sessions keys used for the connection

#### Asymmetric Cypher
An asymmetric cypher is a cryptographic algorithm that uses separate keys for encrypting and decrypting data. These keys are often referred to as public and private keys. The public key is used to encrypt the data and the private key is used to decrypt the data. An analogy for this might be if a store owner had a two types of keys keys to her store several for locking it up (copies of a public key), and one for opening it (a private key). All her employees could have access to the key that locks the store, but once the store was locked she would be the only one that could open it.

#### Digital Certificate
A digital certificate is an document used to prove the ownership of a public key. The certificate contains the servers name,  the trusted certificate authority, and the public encryption key. A certification authority is an entity that both issues and verifies digital certificates.

## HTTPS
HTTPS is an HTTP connection encrypted by TLS or SSL. HTTPS is supported by browsers and is used to authenticate the visited website and protect the privacy/integrity of the exchanged data.

## Content Delivery Network (CDN)
A CDN is a geographically distributed network of proxy servers and data centers. Its job is to distribute static assets to spatially relative end users and provide high availability and performance.
<file_sep># 14 Mongo Populate
This app creates, reads, updates, and deletes files using MongoDB as it's database and Mongoose as middleware.

---
## Intalling and Getting Started
To use this app, for and git clone this repository to your local computer. Navigate to the `lab-melanie` directory and enter `npm install` in your command line, this will install all necessary dependencies.

Either use the Postman app or Httpie to have the ability to create and modify bikes. The following examples will be demonstrated with Httpie.

#### Create a Rider
In your terminal type:
```
http POST :3000/api/v1/rider name=<name>
```
Be sure to use single quotes if the descriptions contain more than one word.

#### Get a Rider
In your terminal type:
```
http GET :3000/api/v1/rider
```
This will return all riders and their IDs, which will be needed to create a bicycle.

#### Create a Bicycle
In your terminal type:
```
http POST :3000/api/v1/bike year=<year> color=<color> make=<make> category=<category> rider=<rider ID (see above)>
```
Be sure to use single quotes if the descriptions contain more than one word.

If your filepath is incorrect, you will recieve an error message, otherwise you will see a status code of 201.

#### Get a Bike (or all bikes)
To get a specific bike, type in your command line:
```
http GET :3000/api/v1/bike/<bike id>
```
This will return the information about the bicycle and it's rider.

To get all bikes:
```
http GET :3000/api/v1/bike
```

This will return a list of all bike ids.

#### Update a Rider
In your command line, type:
```
http PUT :3000/api/v1/rider/<rider ID> name=<new name>
```

#### Update a Bike
In your command line, type:
```
http PUT :3000/api/v1/bike/<bike id> year=<new year> color=<new color> make=<new make> category=<new category>
```
Just as creating a bike, be sure to use single quotes if the descriptions are longer than one word.

#### Delete a Rider
In your command line, type:
```http DELETE :3000/api/v1/rider/<rider ID>
```

#### Delete a Bike
In your command line, type:
```
http DELETE :3000/api/v1/bike/<bike id>
```
This removes the bike from the database and it's relationship to the rider.

---

## Data Structures

### Route-Rider Module
This contains five methods that routes requests and responses from storage:
* `.post` - sends info from the http request to mongo to create a rider and sends a response back to the viewer
* `.get` - this has two methods, one that uses a specific id of a rider to read the file and send the response back to the viewer, the other only needs the schema (in this case `rider`) and returns the response from mongo as a list of rider ids
* `.put` - takes info from the http request and updates a rider in storage, then sends a response back to the viewer
* `.delete` - takes in the http request with a specific rider id, sends it to mongo to `remove` the file, then sends a status message back to the viewer

### Route-Bike Module
This contains five methods that routes requests and responses from storage:
* `.post` - sends info from the http request to mongo to create a bike and sends a response back to the viewer
* `.get` - this has two methods, one that uses a specific id of a bike to read the file and send the response back to the viewer, the other only needs the schema (in this case `bike`) and returns the response from mongo as a list of bike ids
* `.put` - takes info from the http request and updates a bike in storage, then sends a response back to the viewer
* `.delete` - takes in the http request with a specific bike id, sends it to mongo to `remove` the file and it's relationship to a rider, then sends a status message back to the viewer

---

## Tests
The test directory is separated into four subdirectories: 

`integration-bike` contains files to test each http method, `POST`, `GET`, `PUT`, `DELETE`.

`integration-rider` contains files to test each http method, `POST`, `GET`, `PUT`, `DELETE`.

`lib` contains the jest port configuration

`unit-tests` contains files to test modules that the router and server rely on for requests and responses including:

 * `bike` - builds a bike object
 * `rider` - builds a rider object
 * `error-handler` - customizes error messages and returns the corresponding response<file_sep>'use strict';

const server = require('../../lib/server.js');
const superagent = require('superagent');
const mock = require('../lib/mock.js');
require('jest');

describe('GET', function() {
  beforeAll(server.start);
  afterAll(server.stop);
  afterAll(mock.rider.removeAll);
  afterAll(mock.bike.removeAll);

  describe('Valid req/res', () => {
    beforeAll(() => {
      return mock.rider.createMany(5)
        .then(res => this.riderData = res);
    });
    it('should return a status 200 given a valid ID', () => {
      return superagent.get(`:4000/api/v1/rider/${this.riderData[0]._id}`)
        .then(res => expect(res.status).toEqual(200));
    });
    it('should return a rider from the database', () => {
      return superagent.get(`:4000/api/v1/rider/${this.riderData[0]._id}`)
        .then(res => expect(res.body.name).toBe(this.riderData[0].name));
    });
  });

  describe('Invalid req/res', () => {
    it('should return a status code 400 without schema', () => {
      return superagent.get(':4000/api/v1/bike')
        .send()
        .catch(err => {
          expect(err.status).toBe(404);
        });
    });
    it('should return a 404 given an incorrect path', () => {
      return superagent.get(':4000/api/v1/doesnotexist')
        .send({title: '', content: ''})
        .catch(err => {
          expect(err.status).toBe(404);
        });
    });
  });
});<file_sep>// import './styles/main.scss'

import React from 'react'
import ReactDom from 'react-dom'
import superagent from 'superagent'

const API_URL = 'https://pokeapi.co/api/v2'

class SearchForm extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      val: '',
    }
    this.handleChange = this.handleChange.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleChange(e) {
    this.setState({val: e.target.value})
  }

  handleSubmit(e) {
    e.preventDefault()
    // console.log(this.props.get_set_app)
    this.props.update_state(this.state.val)
  }

  render() {
    return (
      <form
        className="search-form"
        onSubmit={this.handleSubmit}>

        <input
          type="text"
          name="pokemon-name"
          value={this.state.val}
          onChange={this.handleChange}
          placeholder="Bulbasaur"/>

        <button type="submit">Search</button>

        {/* <Navbar get_set_app={this.props.get_set_app}/> */}
      </form>
    )
  }
}


class Results extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div className="results">
        {this.props.pokemon ?
          <section className="pokemon-data">
            {console.log(this.props.pokemon)}
            <h2>{this.props.pokemon.name}</h2>
            <img
              src={this.props.pokemon.sprites.front_default}
              alt={this.props.pokemon.name}/>
          </section>
          :
          undefined
        }

        {this.props.error ?
          <section className="pokemon-error">
            <h2>You broke it.</h2>
          </section>
          :
          undefined
        }
      </div>
    )
  }
}




class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      pokemon: null,
      searchError: null,
    }
    this.searchApi = this.searchApi.bind(this)
    this.updateState = this.updateState.bind(this)
  }

  updateState(name) {
    this.searchApi(name)
    .then(res => this.setState({pokemon: res.body, searchError: null}))
    .catch(err => this.setState({pokemon: null, searchError: err}))
  }

  searchApi(name) {
    return superagent.get(`${API_URL}/pokemon/${name}`)
  }

  render() {
    return (
      <div className="application">
        <SearchForm update_state={this.updateState}/>
        <Results pokemon={this.state.pokemon} error={this.state.searchError}/>
      </div>
    )
  }
}

ReactDom.render(<App />, document.getElementById('root'))
<file_sep>'use strict'

const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'), {suffix: 'Prom'})

const storage = module.exports = {}

storage.create = (schema, item) => {
  let json = JSON.stringify(item)
  return fs.writeFileProm(`${__dirname}/../data/${schema}/${item._id}.json`, json)
  .then(() => item)
}

storage.fetchOne = (schema, itemId) =>
  fs.readFileProm(`${__dirname}/../data/${schema}/${itemId}.json`)

storage.fetchAll = (schema) => {
}

storage.update = (schema, itemId, item) => {
}

storage.destroy = (schema, itemId) => {
}
<file_sep>### TCP Chat Server Lab

# Cmd Module

1. Parser is a function that takes in a buffer of data, turns it into a string and parses commands from the front of the string by seperating each "word" of the string and checking the first for an "@" command, it then verifies a valid command was given and returns an object with the information required for the chosen command or message type.

      This function is O(n) on average case operation.

      It requires two inputs, a valid buffer of data and an array of currently connected clients.


# Client Module

1. Client is a constructor function that takes in a socket provided by server connection and instantiates a Client object with a randomized uuid value as a nickname, a random user number, and an assigned socket.

      This function is O(1) on average case operation.

      It requires a single input, a valid socket.


# Server Module

The Server entry point file, this file handles all events emitted by processes. These events include the following:

  1. Connection: On connection the server assigns a socket to the connection and calls for new client creation on that socket as well as assigns listeners for available commands.

  2. Data: On submission of data from any connected client this sends that data into the command parser module and emits an event based on that data sending the data along to that event.

  3. List: When the data event emits an @list command this creates a list of connected users for the client who executed it.

  4. Nickname: When the data event emits an @nickname command this changes the clients nickname based on the name passed after the command.

  5. Message: When the data event emits a message event because no @ command was used this passes the entire block of information provided as a message to the server.

  6. Direct Message: When the data event emits an @dm command this targets the 2nd word of the message as a name of a user and attempts to send rest of the message to them.

  7. Close: When the data event emits an @quit command it closes the connection of the requesting client.

  8. Error: This event is emitted if the requested command is invalid in some way, it passes a message back to the Client saying what needs to be corrected.

  9. Jeep & Facepalm: These are easter egg events emitted when @jeep or @facepalm are used as a command with nothing following it.<file_sep>'use strict'

const uuid = require('uuid/v4')
const debug = require('debug')('http:note-constructor')

module.exports = function(title, content) {
  this.title = title
  this.content = content
  this._id = uuid()
  debug(`Created a note: ${this}`)
}<file_sep>'use strict';

const Rider = require('../../model/rider.js');
require('jest');

describe('Rider Module', function() {
  let newRider = new Rider();
  describe('Rider schema', () => {
    it('should create a object', () => {
      expect(newRider).toBeInstanceOf(Object);
    });
  });
});<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 38: File Reader API
====

## Daily Plan
- Notes:
    - Anything top of mind
    - Reminder: 1215p Guest Lectures in the Event Space
        - Weds: <NAME>: TypeScript
        - Thurs: <NAME>: React Native

- Code Review
- Passing of the Projector Ceremonies!

![magic](http://www.reactiongifs.com/r/mgc.gif)

- File Reader API
- Adding profiles and settings to your users!
- Lab Preview

## Learning Objectives
* Students will learn to use the `FileReader` API to preview image files

## Readings
* Read [Using files in web applications](https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications)
* Skim [FileReader.readAsDataURL docs](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL)

## Previewing images
Using the HTML5 FileReader API, browser applications can now ask users to read local files, and then read the contents of those files. Input tags of type file can retrieve files from the user. Those files can then be loaded through the a `FileReader`. Once a FileReader has loaded the contents of a file it can then be processed as an ArrayBuffer, BinaryString, DataURL, or Text. After a user selects a photo it can be previewed, by loading the contents using a FileReader and then passing a DataURL into an `<img>` tag.
<file_sep>'use strict'

const HashTable = module.exports = function(size=1024) {
  this.size = size
  this.memory = [...Array(this.size)] // => [SLL, SLL, SLL]
}

HashTable.prototype.hashKey = function(key) {
  let hash = key.split('').reduce((a, b) => a + b.charCodeAt(0), 0) % this.size
  return hash
}

HashTable.prototype.set = function(key, value) {
  // Implement the collision detection and handle that through a SLL
  // Stretch goal => Implement with buckets as binary trees

  this.memory[this.hashKey(key)] = value
}

HashTable.prototype.get = function(key) {
  // Implement the lookup for your buckets and their respective data structures
  return this.memory[this.hashKey(key)]
}

HashTable.prototype.remove = function(key) {
  let address = this.hashKey(key)

  return this.memory[address] ? delete this.memory[address] : new Error('Invalid Key.')
}


<file_sep>'use strict'

// Application Dependencies
const cors = require('cors')
const express = require('express')
const mongoose = require('mongoose')
const debug = require('debug')('http:server')
const errorHandler = require('./error-handler')

// Application Setup
const PORT = process.env.PORT
const router = express.Router()
const app = express()
const MONGODB_URI = process.env.MONGODB_URI

// Middleware
require('../route/route-track')(router)
require('../route/route-album')(router)
app.use(cors())
app.use('/api/v1', router)

// 404 Error Handler
app.all('/*', (req, res) => errorHandler(new Error('PATH ERROR. Route does not exist'), res))

// Server Controls
let server = module.exports = {}
server.start = () => {
  return new Promise((resolve, reject) => {
    if(server.isOn) return reject('shit hit the fan')

    server.http = app.listen(PORT, () => {
      console.log('server up', PORT)
      mongoose.connect(MONGODB_URI)
      server.isOn = true
      return resolve(server)
    })
  })
}

server.stop = () => {
  return new Promise((resolve, reject) => {
    if(!server.isOn) return reject()

    server.http.close(() => {
      console.log('server down')
      mongoose.disconnect()
      server.isOn = false
      return resolve()
    })
  })
}
<file_sep>'use strict'

const Note = require('../model/note')
const storage = require('../lib/storage')
const bodyParser = require('body-parser').json()
const errorHandler = require('../lib/error-handler')

module.exports = function(router) {
  router.post('/note', bodyParser, (req, res) => {
    new Note(req.body.title, req.body.content)
    .then(note => storage.create('note', note))
    .then(item => res.status(201).json(item))
    .catch(err => errorHandler(err, res))
  })
  router.get('/note/:_id', (req, res) => {
    storage.fetchOne('note', req.params._id)
    .then(buffer => buffer.toString())
    .then(json => JSON.parse(json))
    .then(note => res.status(200).json(note))
    .catch(err => errorHandler(err, res))
  })
  // router.get()
  // router.put()
  // router.delete()

}<file_sep>'use strict';

class TreeNode{
  constructor(value,left=null,right=null){
    this.value = value;
    this.left = left;
    this.right = right;
  }
}

class BST{
  constructor(root=null){
    this.root = root;
  }

  insert(nodeToInsert){
    if(this.root === null)
      this.root = nodeToInsert;
    else
      this._insert(this.root,nodeToInsert);
  }

  _insert(root,nodeToInsert){
    if(nodeToInsert.value < root.value){
      // Vinicio - going left
      if(!root.left)
          root.left = nodeToInsert;
      else
          this._insert(root.left,nodeToInsert);
    } else {
      // Vinicio - going right
      if(!root.right)
        root.right = nodeToInsert;
      else
        this._insert(root.right,nodeToInsert);
    }
  }

  find(value){
    return this._find(this.root,value);

  }

  _find(root,value){
    if(!root)
        return null;
    else if(root.value === value)
      return root;
    else if(root.value < value)
     return this._find(root.right,value);
    else
      return this._find(root.left,value);
  }
}

let bst = new BST();
bst.insert(new TreeNode(5));
bst.insert(new TreeNode(2));
bst.insert(new TreeNode(8));
bst.insert(new TreeNode(16));

console.log(bst.find(8));
console.log(bst.find(16));
console.log(bst.find(100));









<file_sep>
![cf](http://i.imgur.com/7v5ASc8.png) 21: Backend Project
===

# Day one milestone objectives
* Work as a team to design the models for you application on a whiteboard
  * You should have at least two more models than your team member count
  * Number your models in the order that they need to be built
  * Choose the two most important non auth models to be your MVP
* Work as a team to designe the routes for you application on a whiteboard
* Setup travis-ci continuous integration and heroku continuous deployment
* Write the auth layer of your application

# Day two milestone objectives
* Build your two MVP models with routes and 90% code coverage
* If you achieve 90% code coverage for routes of a model start on a streach model

# Day three milestone objectives
* Build your two stretch models with routes and 90% code coverage
* If you achieve 90% code coverage for routes of a model start on another streach model

# Day four milestone objectives
* Finsh any loose ends
* Write doumentation for all features of your application
* Pratice your presintation<file_sep>'use strict'

// const events = require('events')
// const EE = events.EventEmitter
// const ee = new EE()

const EE = require('events').EventEmitter
const ee = new EE()

// Defines a custom event and listener
ee.on('myEvent', function () {
  console.log('I ran "myEvent"')
})

// Manually triggers the event, which runs the defined callback
ee.emit('myEvent')

// My event now needs to receive data as arguments when emitted
ee.on('dataEvent', function (data) {
  console.log('Received data', data)
})


function runEvents() {
  ee.emit('myEvent')
  ee.emit('dataEvent', { data: 'data to send to the callback' })
}

runEvents()<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 19: Continuos Integration and Deployment
===

## Daily Plan
- Notes:
    - Anything top of mind?

- Code Review _How did tests go?_
- Continuous Integration _w/Travis-CI_
- Heroku Deployment _Lets deploy your RESTful APIs_
- Lab Preview

## Learning Objectives
* Students will be able to deploy their application on Heroku with a continuos delivery pipeline
* Students will be able to configure TravisCI to run their tests on all pushes to GitHub
* Students will learn about Continuous Integration
* Students will learn about Continuous Delivery

## Resources
* Read [Deploying NodeJS Apps on Heroku](https://devcenter.heroku.com/articles/deploying-nodejs)
* Read [Getting started with NodeJS on TravisCI](https://docs.travis-ci.com/user/languages/javascript-with-nodejs)

## Continuous Integration
Continuous Integration (CI) is the process of regularly merging individually developed features of code into a shared repository as frequently as they are made. In the most basic setup a team could simply use Git to merge code into a master branch. However more advanced CI patterns can be developed, that automate static analysis (linting), running unit and integration tests, testing platform support, enforcing code reviews, and much more.

## Continuous Delivery
Continuous Delivery (CD) is the process of deploying software in short cycles, by ensuring that software can be deployed at any time. CD pairs very wil with advanced CI setups that help ensure the core product is always a stable code base.

## Heroku Deployment
- enable your repository to work with TravisCI
  - *note: you may have to sync your account for TravisCI to show the repo as an option*
- add your environment variables to TravisCI by clicking on the **Settings** option in the **More options** drop-down
- log into the Heroku dashboard
- create a new app
- create a staging app *(ex: cfgram-staging)*
- click on the **Resources** tab
- in the **Add-ons** section, type *mongo* and choose the mLab option and associated free price plan
  - *note: you will need to provide a credit card with Heroku to do this - even with the free option*
- click on the **Settings** tab
- click on the **Reveal Config Vars** button and add your environment variables
  - *note: you do not need to add the MONGODB_URI variable as this was added by Heroku when you provisioned the DB - there's also no need to add a PORT, Heroku will handle this for you*
- click on the **Deploy** tab
- create a new pipeline called **staging**
- click the button to connect your application to GitHub
- in the **Automatic deploys** field, choose **staging** as your deployment branch *(you'll need to already have a `staging` branch pushed to GitHub)* and click the button to **Enable Automatic Deploys**
- **repeat** the following steps to create a production pipeline
  - *note: be sure to name the application "myapp-production", add it to a production pipeline, and enable automatic deploys to deploy to your `master` branch*<file_sep>'use strict'

require('dotenv').config()

const debug = require('debug')('http:index')
require('./lib/server').start()
<file_sep>import './styles/main.scss'

import React from 'react'
import faker from 'faker'
// const {say, list} = require('cowsay-browser')
// const say = require('cowsay-browser').say
// const list = require('cowsay-browser').list
import cowsay from 'cowsay-browser'
import ReactDom from 'react-dom'

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      cows: [],
      current: '',
      content: cowsay.say({text: 'click the button...'}),
    }

    // cowsay.list((err, cows) => {
    //   let current = cows[0]
    //   this.setState({ cows, current })
    // })

    this.handleClick = this.handleClick.bind(this)
  }

  componentWillMount() {
    cowsay.list((err, cows) => {
      let current = cows[0]
      this.setState({cows, current})
    })
  }

  handleClick(e) {
    let current = e.target.value || this.state.current
    let text = faker.random.words(4)
    this.setState({current, content: cowsay.say({text, f: current})})
  }

  render() {
    return (
      <div className="application">
        {console.log('hello')}
        <h1>Welcome to cowville!</h1>
        <select onChange={this.handleClick}>
          {this.state.cows.map((cow, i) => {
            return <option value={cow} key={i}>{cow}</option>
          })}
        </select>
        <button onClick={this.handleClick}>click for {this.state.current}</button>
        <pre>
          {this.state.content}
        </pre>
      </div>
    )
  }
}

ReactDom.render(<App />, document.getElementById('root'))
<file_sep>'use strict'

const events = require('./lib/events')
const mod = require('./lib/module')

let eventIWantToRunAnytimeIWant = mod(events)

eventIWantToRunAnytimeIWant('data from somewhere else, Tim.')

<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 11: ExpressJS
===

## Daily Plan
- Notes:
    - Anything top of mind?
    - Week ahead, week behind
        - quick note about last week's workload

- Code Review?
- Express Framework
    - API Data Flow
- Lab Preview

## Learning Objectives
* Students will learn about ExpressJS
* Students will be able to create RESTful HTTP servers through the use of Express


## Resources
* Skim [express api docs](http://expressjs.com/en/4x/api.html)
* Read [express routing](http://expressjs.com/en/guide/routing.html)

## Express
ExpressJS is a lightweight framework for building web servers. ExpressJS extends the NodeJS `http` module with a minimal feature set that enables developers to build quickly build powerful web applications. Express features include routing with url params, error handling, a static server, cookie and link helpers, convenience methods for sending json and jsonp, location and redirect management, request parsing, server side rendering, and a framework for creating middleware to extend express.
<file_sep>'use strict';

const fs = require('fs');
const reader = module.exports = {};

reader.read = function(path, callback) {
  fs.readFile(path, (err, fd) => {
    if(err) {
      console.error(err);
      return callback(err);
    }
    return callback(null, fd);
  });
};

reader.write = function(bmpObj, filePath, callback) {
  fs.writeFile(filePath, bmpObj.allData, err => {
    if(err) return callback(err);
    console.log(`File created: ${filePath}`);
    return callback(null);
  });
};
<file_sep>![cf](http://i.imgur.com/7v5ASc8.png) 42: OAuth Continued
===

## Learning Objectives
* Students will learn Front End Oauth Workflow

## Readings
* [Google OAuth frontend](https://developers.google.com/identity/protocols/OAuth2UserAgent)
<file_sep># 04 Bitmap Project

This is an application that offers a selection of transformations to apply to a bitmap image.


## dazzle! - a command line bitmap transformer

---

The dazzle command line utility allows the user to transform a bitmap image using any of the nine transform methods.  A new copy of the image is created with the supplied name.

### dazzle takes three arguments

  - <bitmap_file_path>  the path to a bitmap image to transform

  - <new-file-name>   the name for the new bitmap image without an extension

  - <transform-method>  name of the transform method

```
 dazzle  bitmap_file_path file  new_file_name file transform_method

 ```

### Installation

This is a node js project that can be installed and run as a command line tool.  

  1. Clone or fork this repository.

  2. In terminal, navigate to the root of the project.

  3. Enter
  `npm install`

  4. Enter
  `npm link`

  5. You are now ready to use dazzle!


  ---




### Transform Methods:

  - `random`  Randomize the color palette of the image

  - `reverse`  Description of -a flag

  - `boostGreen`  Sets the green values to 255

  - `boostRed`	Sets the red values to 255

  - `boostBlue`	Sets the blue values to 255

  - `redChannel`	 Creates a gray scale image based on the value of the red value

  - `blackWhite`	Creates a gray scale image based on the average value of the rgb values

  - `invert`   Inverts the rgb values

  - `invert2`  Inverts every fourth bit in the color palette

  - `invert3`  Inverts every third bit in the color palette

  - `invert4`  Inverts every other bit in the color palette

### Example

  ```
  dazzle ~/users/home/pictures/test.bmp dazed boostGreen

  ```
#### Dazzle man page

```
man dazzle

```

---

### Reader Module

The reader module requires a file system module and contains two functions. The read and write function takes in an arity of two, the file path and callback. The read method reads the image file past in and passes the information to the bitmap module. The write method takes the transformed object representing the image and writes a new file based on the path provided in the argument.  The callback in the read file sends the file data of the original image to the bitmap module.

##### Reader Functions:

* `read` - takes the file data of the image from the file path given and the callback sends the information to the bitmap module.

* `write` - takes the file data of the new image from the bitmap module and creates a new file.

---

### Transform Module

The transform module contains functions to change the color array or pixel array in a bitmap image. All transform module functions have an arity of two, each taking in the object representing a bitmap image (created from the bitmap module) and a callback to send the transformed file data back to the reader module.

##### Transform Functions:

* `random` - takes each bit in the color array and assigns a random number (between 0 and 255) to the RGBa values. The new image file created will be different each time this function is called.

* `invert` - alters the color array to the opposite RGBa value (ex: 255 becomes 0).

* `reverse` - alters the pixel array and flips the image both vertically and horizontally.

* `boostGreen` - alters all green values in the color array to 255.

* `boostRed` - alters all red values in the color array to 255.

* `boostBlue` - alters all blue values in the color array to 255.

* `redChannel` - alters each green and blue value in the color array to equal the red value. This returns a grayscale image based on the red channel.

* `blackWhite` - alters each red green and blue value in the color array to the average of all three and returns a grayscale image.

* `invert2` - alters every 4th bit in the color array to it's opposite value.

* `invert3` - alters every 3rd bit in the color array to it's opposite value.

* `invert4` - alters every other bit in the color array to it's opposite value.



## TESTING

---

### index.test.js

  - Test that the app wil not run without arguments.

  - Test that the app does not run with less than two arguments.

  - Test that the app wil not run with out a valid transform method.


### reader.test.js

#### reader.read

  - Test that the reader function can read a file.

  - Test that the reader function will send an error message if the file does not exist.

  - Test the the reader function will send an error if the file path is missing.

#### reader.write

  - Test that the write function can create a file.

  - Test that the write function can write to a file.

  - Test that the write function can return an error message if the directory does not exist


### bitmap.test.js

  - Test that the object will return an error if the buffer is null.

  - Test that the constructor can create an object from a buffer

  - Test that the constructor will return an error message if the buffer is not from a bit map.


### transform.test.js

#### transform.random

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that the colorArray no longer matches the original

#### transform.reverse

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test the the pixelArray is the reverse of the original

#### transform.boostGreen

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that all the green values are 255

#### transform.boostRed

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that all the red values are 255

#### transform.boostBlue

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that all the blue values are 255

#### transform.redChannel

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that all the values are equal to the red value

#### transform.blackWhite

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that the values are the average of all the values

#### transform.invert

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that the values of each color are the inverse of the original

#### transform.invert2

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that every 4th value is the inverse of the original


#### transform.invert3

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that every 3th value is the inverse of the original

#### transform.invert4

  - Test that the object passed to the transform was created by the Bmp object constructor.

  - Test that the object has the pixelArray and colorArray properties.

  - Test that the pixelArray and colorArray properties have values.

  - Test that every other value is the inverse of the original
<file_sep>'use strict'

const Album = require('./album')
const mongoose = require('mongoose')
const debug = require('debug')('http:model-track')

const Track = mongoose.Schema({
  "speechiness": {type: Number},
  "key": {type: Number},
  "time_signature": {type: Number},
  "liveness": {type: Number},
  "loudness": {type: Number},
  "duration_ms": {type: Number},
  "danceability": {type: Number},
  "duration": {type: Number},
  "valence": {type: Number},
  "acousticness": {type: Number},
  "spotify_id": {type: String},
  "volume_number": {type: Number},
  "energy": {type: Number},
  "tempo": {type: Number},
  "instrumentalness": {type: Number},
  "mode": {type: Number},
  "number": {type: Number},
  "artist": {type: String, required: true},
  "title": {type: String, required: true},
  "album": {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'album'},
}, { timestamps: true })

Track.pre('save', function(next) {
  Album.findById(this.album)
  .then(album => {
    // album.tracks = [...new Set(album.tracks).add(this._id)]
    let trackIdSet = new Set(album.tracks)
    trackIdSet.add(this._id)
    album.tracks = [...trackIdSet]
  })
  .then(next)
  .catch(() => next(new Error('Validation Error. Failed to create track because Album does not exist')))
})

Track.post('remove', function(doc, next) {
  Album.findById(doc.album)
  .then(album => {
    album.tracks = album.tracks.filter(track => track._id !== doc._id)
    return album.save()
  })
  .then(next)
  .catch(next)
})

module.exports = mongoose.model('track', Track)<file_sep>import {combineReducers} from 'redux'
import albums from './album'
import tracks from './track'

export default combineReducers({albums, tracks})
<file_sep>import React from 'react'
import Adapter from 'enzyme-adapter-react-16'
import {configure, shallow, mount} from 'enzyme'
import CategoryForm from '../component/category/category-form/category-form'
require('jest')

configure({adapter: new Adapter()})

describe('<CategoryForm />', function() {
  describe('Shallow Mounting', function() {
    beforeAll(() => {
      let wrapper = shallow(<CategoryForm />)

      this.wrapper = wrapper
    })
    afterAll(() => this.wrapper.unmount())

    it('should render a category form component', () => {
      console.log(this.wrapper.html())
      expect(this.wrapper.length).toBe(1)
      expect(this.wrapper.find('.category-form').length).toBe(1)
    })

    it('should have a default state object with a title property assigned an empty string', () => {
      expect(this.wrapper.state().title).toEqual('')
    })

    it('should change the state object when form input is provided', () => {
      let event = {target: { name: 'title', value: 'hello' }}
      this.wrapper.find('.category-form input').simulate('change', event)
      expect(this.wrapper.state().title).toEqual('hello')

      // wrapper.instance().handleChange(event)
    })
  })

  describe('Full Mounting', function() {
    beforeAll(() => {
      this.wrapper = mount(<CategoryForm />)
      this.wrapper.setProps({onComplete: jest.fn()})
    })
    afterAll(() => this.wrapper.unmount())

    it('should reset the state.title value to empty string on form submit', () => {
      this.wrapper.setState({title: 'goodbye world'})
      expect(this.wrapper.state().title).toEqual('goodbye world')
      this.wrapper.simulate('submit', {preventDefault: () => {}})
      expect(this.wrapper.state().title).toEqual('')
    })

    it('should have called onComplete in the previous assertion', () => {
      expect(this.wrapper.props().onComplete).toHaveBeenCalled()
    })
  })
})
<file_sep>'use strict'

const fs = require('fs')
const reader = module.exports = {}


reader.read = function(paths, cb) {
  // let one = paths[0]
  // let two = paths[1]
  // let three = paths[2]
  // shorthand destructuring
  let [one, two, three] = paths
  let results = []

  fs.readFile(one, (err, data) => {
    if(err) {
      console.error(err)
      return cb(err)
    }

    results.push(data.toString())
    fs.readFile(two, (err, data) => {
      if(err) {
        console.error(err)
        return cb(err)
      }

      results.push(data.toString())
      fs.readFile(three, (err, data) => {
        if(err) {
          console.error(err)
          return cb(err)
        }

        results.push(data.toString())
        return cb(null, results)
      })
    })
  })
}


// Does not maintain the correct order of files read and file results
// reader.read = function(paths, cb) {
//   // let one = paths[0]
//   // let two = paths[1]
//   // let three = paths[2]
//   // shorthand destructuring
//   let [one, two, three] = paths
//   let results = []

//   fs.readFile(one, (err, data) => {
//     if(err) {
//       console.error(err)
//       return cb(err)
//     }

//     results.push(data.toString('utf-8', 0, 32))
//   })

//   fs.readFile(two, (err, data) => {
//     if(err) {
//       console.error(err)
//       return cb(err)
//     }

//     results.push(data.toString('utf-8', 0, 32))
//   })

//   fs.readFile(three, (err, data) => {
//     if(err) {
//       console.error(err)
//       return cb(err)
//     }

//     results.push(data.toString('utf-8', 0, 32))
//     return cb(null, results)
//   })
// }<file_sep>import ExpenseCreateForm from '../expense/expense-create-form/expense-create-form'
import ExpenseList from '../expense/expense-list/expense-list'
import ExpenseItem from '../expense/expense-item/expense-item'

export const ExpenseCreateForm
export const ExpenseList
export const ExpenseItem
<file_sep>'use strict'

// Write a function that takes N as it's only argument
// and returns the sum total of 0 to N

function sumIterative(n) {
  let agg = 0
  let x = n

  for(n; n > 0; n--) {
    agg += n
  }

  return agg
}

function recurse() {
  if(count === 10) return
  count++
  recurse()
}


function sumRecursive(n) {
  if(!n) return 1
  return n + sumRecursive(n - 1)
}

let sumOneLineRecursive = n => n === 0 ? 0 : n + sumRecursive(n - 1)<file_sep>'use strict'

const math = module.exports = {}

math.floor = function(num) {
  if(typeof num !== 'number') return new Error('barf')
  return Math.floor(num)
}

// math.ceiling = function(num) {
//   return Math.ceil(num)
// }

// math.absolute = function(num) {
//   return Math.abs(num)
// }<file_sep>'use strict';

const mongoose = require('mongoose');
const Rider = require('./rider.js');

const Bike = mongoose.Schema({
  'year': {type: Number},
  'color': {type: String},
  'make': {type: String, required: true},
  'category': {type: String, required: true},
  'rider': {type: mongoose.Schema.Types.ObjectId, required: true, ref: 'riders'},
}, {timestamps: true});

Bike.pre('save', function(next) {
  Rider.findById(this.rider)
    .then(rider => {
      let bikeIds = new Set(rider.bikes);
      bikeIds.add(this._id);
      rider.bikes = [...bikeIds];
      Rider.findByIdAndUpdate(this.rider, {rider: rider.bikes});
    })
    .then(next)
    .catch(() => next(new Error('Validation Error. Failed to save Bike.')));
});

Bike.post('remove', function(doc, next) {
  Rider.findById(doc.rider)
    .then(rider => {
      rider.bikes = rider.bikes.filter(a => a.toString() !== doc._id.toString());
      Rider.findByIdAndUpdate(this.rider, {rider: rider.bikes});
    })
    .then(next)
    .catch(next);
});

module.exports = mongoose.model('bikes', Bike);<file_sep>'use strict'

require('jest')

describe('testing dummy', function() {
  it('should return true', () => expect(true).toBeTruthy())
})<file_sep>'use strict';

const Rider = require('../model/rider.js');
const bodyParser = require('body-parser').json();
const errorHandler = require('../lib/error-handler.js');

module.exports = function(router) {
  router.route('/rider/:_id?')
    .get((req, res) => {

      if(req.params._id) {
        return Rider.findById(req.params._id)
          .then(rider => res.status(200).json(rider))
          .catch(err => errorHandler(err, res));
      }
      return Rider.find()
        .then(rider => rider.map(a => ({_id: a._id, name: a.name})))
        .then(rider => res.status(200).json(rider))
        .catch(err => errorHandler(err, res));
    })
    .post(bodyParser, (req, res) => {
      new Rider(req.body).save()
        .then(rider => res.status(201).json(rider))
        .catch(err => errorHandler(err, res));
    })
    .put(bodyParser, (req, res) => {
      return Rider.findOneAndUpdate(req.params._id, req.body, {upsert: true, runValidators: true})
        .then(() => res.sendStatus(204))
        .catch(err => errorHandler(err, res));

    })
    .delete((req, res) => {
      return Rider.findByIdAndRemove(req.params._id)
        .then(() => res.sendStatus(204))
        .catch(err => errorHandler(err, res));

    });
};