26 | 12 verbose exit [ 1, true ]
27 |
--------------------------------------------------------------------------------
/users/test/association_test.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const assert = require('assert');
3 | const User = require('../src/user');
4 | const Comment = require('../src/comment');
5 | const BlogPost = require('../src/blogPost');
6 |
7 | describe('Assocations', () => {
8 | let joe, blogPost, comment;
9 |
10 | beforeEach((done) => {
11 | joe = new User({ name: 'Joe' });
12 | blogPost = new BlogPost({ title: 'JS is Great', content: 'Yep it really is' });
13 | comment = new Comment({ content: 'Congrats on great post' });
14 |
15 | joe.blogPosts.push(blogPost);
16 | blogPost.comments.push(comment);
17 | comment.user = joe;
18 |
19 | Promise.all([joe.save(), blogPost.save(), comment.save()])
20 | .then(() => done());
21 | });
22 |
23 | it('saves a relation between a user and a blogpost', (done) => {
24 | User.findOne({ name: 'Joe' })
25 | .populate('blogPosts')
26 | .then((user) => {
27 | assert(user.blogPosts[0].title === 'JS is Great');
28 | done();
29 | });
30 | });
31 |
32 | it('saves a full relation graph', (done) => {
33 | User.findOne({ name: 'Joe' })
34 | .populate({
35 | path: 'blogPosts',
36 | populate: {
37 | path: 'comments',
38 | model: 'comment',
39 | populate: {
40 | path: 'user',
41 | model: 'user'
42 | }
43 | }
44 | })
45 | .then((user) => {
46 | assert(user.name === 'Joe');
47 | assert(user.blogPosts[0].title === 'JS is Great');
48 | assert(user.blogPosts[0].comments[0].content === 'Congrats on great post');
49 | assert(user.blogPosts[0].comments[0].user.name === 'Joe');
50 |
51 | done();
52 | });
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/UpStarMusic/src/components/artists/Paginator.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import * as actions from '../../actions';
4 |
5 | class Paginator extends Component {
6 | back() {
7 | const { offset, limit, form: { filters: { values } } } = this.props;
8 |
9 | if (offset === 0 ) { return; }
10 |
11 | this.props.searchArtists(values, offset - 10, limit);
12 | }
13 |
14 | advance() {
15 | const { offset, limit, count, form: { filters: { values } } } = this.props;
16 |
17 | if ((offset + limit) > count) { return; }
18 |
19 | this.props.searchArtists(values, offset + 10, limit);
20 | }
21 |
22 | left() {
23 | return (
24 |
25 |
26 | chevron_left
27 |
28 |
29 | );
30 | }
31 |
32 | right() {
33 | const { offset, limit, count } = this.props;
34 |
35 | const end = ((offset + limit) >= count) ? true : false;
36 |
37 | return (
38 |
39 |
40 | chevron_right
41 |
42 |
43 | );
44 | }
45 |
46 | render() {
47 | return (
48 |
49 |
54 | {this.props.count} Records Found
55 |
56 | );
57 | }
58 | }
59 |
60 | const mapStateToProps = ({ artists, form }) => {
61 | const { limit, offset, count } = artists;
62 |
63 | return { limit, offset, count, form};
64 | };
65 |
66 | export default connect(mapStateToProps, actions)(Paginator);
67 |
--------------------------------------------------------------------------------
/UpStarMusic/bundle.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 |
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 |
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId])
10 | /******/ return installedModules[moduleId].exports;
11 |
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ exports: {},
15 | /******/ id: moduleId,
16 | /******/ loaded: false
17 | /******/ };
18 |
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 |
22 | /******/ // Flag the module as loaded
23 | /******/ module.loaded = true;
24 |
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 |
29 |
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 |
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 |
36 | /******/ // __webpack_public_path__
37 | /******/ __webpack_require__.p = "/";
38 |
39 | /******/ // Load entry module and return exports
40 | /******/ return __webpack_require__(0);
41 | /******/ })
42 | /************************************************************************/
43 | /******/ ([
44 | /* 0 */
45 | /***/ function(module, exports, __webpack_require__) {
46 |
47 | module.exports = __webpack_require__(1);
48 |
49 |
50 | /***/ },
51 | /* 1 */
52 | /***/ function(module, exports, __webpack_require__) {
53 |
54 | 'use strict';
55 |
56 | var _mongodb = __webpack_require__(2);
57 |
58 | var url = 'mongodb://localhost:27017/auth';
59 |
60 | /***/ },
61 | /* 2 */
62 | /***/ function(module, exports) {
63 |
64 | module.exports = require("mongodb");
65 |
66 | /***/ }
67 | /******/ ]);
--------------------------------------------------------------------------------
/UpStarMusic/src/seeds.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import faker from 'faker';
3 | import { Db, Server } from 'mongodb';
4 | import { GENRES } from './constants';
5 |
6 | const MINIMUM_ARTISTS = 200;
7 | const ARTISTS_TO_ADD = 15000;
8 |
9 | let artistsCollection;
10 | const db = new Db('upstar_music', new Server('localhost', 27017));
11 | db.open()
12 | .then(() => {
13 | artistsCollection = db.collection('artists');
14 | return artistsCollection.count({});
15 | })
16 | .then(count => {
17 | if (count < MINIMUM_ARTISTS) {
18 | const artists = _.times(ARTISTS_TO_ADD, () => createArtist());
19 |
20 | artistsCollection.insertMany(artists);
21 | }
22 | })
23 | .catch(e => console.log(e));
24 |
25 |
26 | function createArtist() {
27 | return {
28 | name: faker.name.findName(),
29 | age: randomBetween(15, 45),
30 | yearsActive: randomBetween(0, 15),
31 | image: faker.image.avatar(),
32 | genre: getGenre(),
33 | website: faker.internet.url(),
34 | netWorth: randomBetween(0, 5000000),
35 | labelName: faker.company.companyName(),
36 | retired: faker.random.boolean(),
37 | albums: getAlbums()
38 | };
39 | }
40 |
41 | function getAlbums() {
42 | return _.times(randomBetween(0, 5), () => {
43 | const copiesSold = randomBetween(0, 1000000);
44 |
45 | return {
46 | title: _.capitalize(faker.random.words()),
47 | date: faker.date.past(),
48 | copiesSold,
49 | numberTracks: randomBetween(1, 20),
50 | image: getAlbumImage(),
51 | revenue: copiesSold * 12.99
52 | };
53 | });
54 | }
55 |
56 | function getAlbumImage() {
57 | const types = _.keys(faker.image);
58 | const method = randomEntry(types);
59 |
60 | return faker.image[method]();
61 | }
62 |
63 | function getGenre() {
64 | return randomEntry(GENRES);
65 | }
66 |
67 | function randomEntry(array) {
68 | return array[~~(Math.random() * array.length)];
69 | }
70 |
71 | function randomBetween(min, max) {
72 | return ~~(Math.random() * (max-min)) + min;
73 | }
74 |
--------------------------------------------------------------------------------
/UpStarMusic/src/components/artists/ArtistEdit.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import * as actions from '../../actions';
4 |
5 | class ArtistEdit extends Component {
6 | constructor(props) {
7 | super(props);
8 |
9 | this.state = {};
10 | }
11 |
12 | componentWillMount() {
13 | this.props.findArtist(this.props.params.id);
14 | }
15 |
16 | componentWillReceiveProps({ artist }) {
17 | if (artist) {
18 | const { name, age, yearsActive, genre } = artist;
19 |
20 | this.setState({ name, age, yearsActive, genre });
21 | }
22 | }
23 |
24 | componentWillUpdate(nextProps) {
25 | if (nextProps.params.id !== this.props.params.id) {
26 | this.props.findArtist(nextProps.params.id);
27 | }
28 | }
29 |
30 | componentWillUnmount() {
31 | this.props.clearError();
32 | }
33 |
34 | onSubmit(event) {
35 | event.preventDefault();
36 | event.stopPropagation();
37 |
38 | this.props.editArtist(this.props.params.id, this.state);
39 | }
40 |
41 | render() {
42 | return (
43 |
77 | );
78 | }
79 | }
80 |
81 | const mapStateToProps = (state) => {
82 | return {
83 | artist: state.artists.artist,
84 | errorMessage: state.errors
85 | };
86 | };
87 |
88 | export default connect(mapStateToProps, actions)(ArtistEdit);
89 |
--------------------------------------------------------------------------------
/muber/test/controllers/drivers_controller_test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | const request = require('supertest');
3 | const mongoose = require('mongoose');
4 | const app = require('../../app');
5 |
6 | const Driver = mongoose.model('driver');
7 |
8 | describe('Drivers controller', () => {
9 | it('Post to /api/drivers creates a new driver', (done) => {
10 | Driver.count().then(count => {
11 | request(app)
12 | .post('/api/drivers')
13 | .send({ email: 'test@test.com' })
14 | .end(() => {
15 | Driver.count().then(newCount => {
16 | assert(count + 1 === newCount);
17 | done();
18 | });
19 | });
20 | });
21 | });
22 |
23 | it('Post to /api/drivers requires an email', (done) => {
24 | request(app)
25 | .post('/api/drivers')
26 | .send({})
27 | .end((err, res) => {
28 | assert(res.body.error);
29 | done();
30 | });
31 | });
32 |
33 | it('Put to /api/drivers/id can update a record', done => {
34 | const driver = new Driver({ email: 'test@test.com', driving: false });
35 |
36 | driver.save().then(() => {
37 | request(app)
38 | .put(`/api/drivers/${driver._id}`)
39 | .send({ driving: true })
40 | .end(() => {
41 | Driver.findOne({ email: 'test@test.com' })
42 | .then(driver => {
43 | assert(driver.driving === true);
44 | done();
45 | });
46 | });
47 | });
48 | });
49 |
50 | it('Delete to /api/drivers/:id can delete a record', done => {
51 | const driver = new Driver({ email: 'test@test.com' });
52 |
53 | driver.save().then(() => {
54 | request(app)
55 | .delete(`/api/drivers/${driver._id}`)
56 | .end(() => {
57 | Driver.count().then(count => {
58 | assert(count === 0);
59 | done();
60 | });
61 | });
62 | });
63 | });
64 |
65 | it('Get to /api/drivers finds drivers in a location', done => {
66 | const seattleDriver = new Driver({
67 | email: 'seattle@test.com',
68 | geometry: { type: 'Point', coordinates: [-122.4759902, 47.6147628] }
69 | });
70 | const miamiDriver = new Driver({
71 | email: 'miami@test.com',
72 | geometry: { type: 'Point', coordinates: [-80.2534507, 25.791581] }
73 | });
74 |
75 | Promise.all([seattleDriver.save(), miamiDriver.save()])
76 | .then(() => {
77 | request(app)
78 | .get('/api/drivers?lng=-80&lat=25')
79 | .end((err, response) => {
80 | assert(response.body.length === 1);
81 | assert(response.body[0].obj.email === 'miami@test.com');
82 | done();
83 | });
84 | });
85 | })
86 | });
87 |
--------------------------------------------------------------------------------
/UpStarMusic/src/components/artists/ArtistIndex.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React, { Component } from 'react';
3 | import { Link } from 'react-router';
4 | import { connect } from 'react-redux';
5 | import Paginator from './Paginator';
6 | import * as actions from '../../actions';
7 |
8 | class ArtistIndex extends Component {
9 | onChange(_id) {
10 | if (_.contains(this.props.selection, _id)) {
11 | this.props.deselectArtist(_id);
12 | } else {
13 | this.props.selectArtist(_id);
14 | }
15 | }
16 |
17 | renderList(artist) {
18 | const { _id } = artist;
19 | const classes = `collection-item avatar ${artist.retired && 'retired'}`;
20 |
21 | return (
22 |
23 |
24 | this.onChange(_id)}
29 | />
30 |
31 |
32 |
33 |
34 |
35 | {artist.name}
36 |
37 |
38 | {artist.age} years old
39 |
40 | {artist.yearsActive} years active
41 |
42 |
43 |
44 | play_arrow
45 |
46 |
47 | );
48 | }
49 |
50 | renderPaginator() {
51 | if (this.props.artists.all.length) {
52 | return ;
53 | }
54 | }
55 |
56 | renderEmptyCollection() {
57 | if (this.props.artists.all.length) { return; }
58 |
59 | return (
60 |
61 |
No records found!
62 |
Try searching again
63 |
64 | );
65 | }
66 |
67 | renderRetire() {
68 | if (this.props.selection.length) {
69 | return (
70 |
71 | this.props.setRetired(this.props.selection)}
74 | >
75 | Retire
76 |
77 | this.props.setNotRetired(this.props.selection)}
80 | >
81 | Unretire
82 |
83 |
84 | );
85 | }
86 | }
87 |
88 | render() {
89 | return (
90 |
91 | {this.renderRetire()}
92 |
93 | {this.props.artists.all.map(this.renderList.bind(this))}
94 | {this.renderEmptyCollection()}
95 |
96 |
97 | {this.renderPaginator()}
98 |
99 | );
100 | }
101 | }
102 |
103 | const mapStateToProps = ({ artists, selection }) => ({ artists, selection });
104 |
105 | export default connect(mapStateToProps, actions)(ArtistIndex);
106 |
--------------------------------------------------------------------------------
/UpStarMusic/src/components/artists/ArtistDetail.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'react-redux';
3 | import { Link } from 'react-router';
4 | import * as actions from '../../actions';
5 |
6 | class ArtistDetail extends Component {
7 | componentWillMount() {
8 | this.props.findArtist(this.props.params.id);
9 | }
10 |
11 | componentWillReceiveProps(nextProps) {
12 | if (nextProps.params.id !== this.props.params.id) {
13 | this.props.findArtist(nextProps.params.id);
14 | }
15 | }
16 |
17 | componentWillUnmount() {
18 | this.props.resetArtist();
19 | }
20 |
21 | onDeleteClick() {
22 | this.props.deleteArtist(this.props.params.id);
23 | }
24 |
25 | renderAlbums() {
26 | const { albums } = this.props.artist;
27 |
28 | if (!albums || !albums.map) { return; }
29 |
30 | return albums.map(album => {
31 | return (
32 |
33 |
34 |
35 |
36 | {album.title}
37 |
38 |
39 |
40 |
41 |
{album.copiesSold}
42 | copies sold
43 |
44 |
45 |
{album.numberTracks}
46 | tracks
47 |
48 |
49 |
50 | );
51 | });
52 | }
53 |
54 | render() {
55 | if (!this.props.artist) { return Todo: implement "FindArtist" query
; }
56 |
57 | const { artist: { name, age, genre, image, yearsActive, netWorth, labelName, _id } } = this.props;
58 |
59 | return (
60 |
61 |
62 |
Back
63 |
Edit
64 |
Delete
65 |
66 |
94 |
95 | );
96 | }
97 | }
98 |
99 | const mapStateToProps = ({ artists }) => {
100 | return { artist: artists.artist };
101 | };
102 |
103 | export default connect(mapStateToProps, actions)(ArtistDetail);
104 |
--------------------------------------------------------------------------------
/UpStarMusic/src/components/artists/ArtistFilter.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Field, reduxForm } from 'redux-form';
3 | import { connect } from 'react-redux';
4 | import { Range } from '../filters';
5 | import * as actions from '../../actions';
6 |
7 | const TEXT_FIELDS = [
8 | { label: 'Name', prop: 'name' }
9 | ];
10 |
11 | class ArtistFilter extends Component {
12 | componentWillMount() {
13 | if (this.props.filters) {
14 | this.props.searchArtists({
15 | name: '',
16 | ...this.props.filters
17 | });
18 | } else {
19 | this.props.searchArtists({
20 | name: '',
21 | sort: 'name'
22 | });
23 | }
24 | }
25 |
26 | componentDidMount() {
27 | this.props.setAgeRange();
28 | this.props.setYearsActiveRange();
29 | }
30 |
31 | handleSubmit(formProps) {
32 | this.props.searchArtists({
33 | name: '',
34 | ...formProps
35 | });
36 | }
37 |
38 | renderInputs() {
39 | return TEXT_FIELDS.map(({ label, prop }) =>
40 |
41 |
48 |
49 | );
50 | }
51 |
52 | render() {
53 | const { handleSubmit } = this.props;
54 |
55 | return (
56 |
102 | );
103 | }
104 | }
105 |
106 | const mapStateToProps = (state) => {
107 | const { filterCriteria } = state;
108 |
109 | return {
110 | yearsActive: filterCriteria.yearsActive,
111 | ageRange: filterCriteria.age,
112 | filters: state.form.filters && state.form.filters.values
113 | };
114 | };
115 |
116 | export default connect(mapStateToProps, actions)(reduxForm({
117 | destroyOnUnmount: false,
118 | form: 'filters',
119 | initialValues: { sort: 'name' }
120 | })(ArtistFilter));
121 |
--------------------------------------------------------------------------------
/UpStarMusic/src/actions/index.js:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { hashHistory } from 'react-router';
3 | import {
4 | SET_AGE_RANGE,
5 | SET_YEARS_ACTIVE_RANGE,
6 | SEARCH_ARTISTS,
7 | FIND_ARTIST,
8 | RESET_ARTIST,
9 | CREATE_ERROR,
10 | CLEAR_ERROR,
11 | DESELECT_ARTIST,
12 | SELECT_ARTIST,
13 | RESET_SELECTION
14 | } from './types';
15 |
16 | import GetAgeRange from '../../database/queries/GetAgeRange';
17 | import GetYearsActiveRange from '../../database/queries/GetYearsActiveRange';
18 | import SearchArtists from '../../database/queries/SearchArtists';
19 | import FindArtist from '../../database/queries/FindArtist';
20 | import CreateArtist from '../../database/queries/CreateArtist';
21 | import EditArtist from '../../database/queries/EditArtist';
22 | import DeleteArtist from '../../database/queries/DeleteArtist';
23 | import SetRetired from '../../database/queries/SetRetired';
24 | import SetNotRetired from '../../database/queries/SetNotRetired';
25 |
26 | export const resetArtist = () => {
27 | return { type: RESET_ARTIST };
28 | };
29 |
30 | export const clearError = () => {
31 | return { type: CLEAR_ERROR };
32 | };
33 |
34 | export const selectArtist = id => {
35 | return { type: SELECT_ARTIST, payload: id };
36 | };
37 |
38 | export const deselectArtist = id => {
39 | return { type: DESELECT_ARTIST, payload: id };
40 | };
41 |
42 | export const setRetired = ids => (dispatch, getState) =>
43 | SetRetiredProxy(ids.map(id => id.toString()))
44 | .then(() => dispatch({ type: RESET_SELECTION }))
45 | .then(() => refreshSearch(dispatch, getState));
46 |
47 | export const setNotRetired = ids => (dispatch, getState) =>
48 | SetNotRetiredProxy(ids.map(id => id.toString()))
49 | .then(() => dispatch({ type: RESET_SELECTION }))
50 | .then(() => refreshSearch(dispatch, getState));
51 |
52 | export const setAgeRange = () => dispatch =>
53 | GetAgeRangeProxy()
54 | .then(result =>
55 | dispatch({ type: SET_AGE_RANGE, payload: result })
56 | );
57 |
58 | export const setYearsActiveRange = () => dispatch =>
59 | GetYearsActiveRangeProxy()
60 | .then(result =>
61 | dispatch({ type: SET_YEARS_ACTIVE_RANGE, payload: result })
62 | );
63 |
64 | export const searchArtists = (...criteria) => dispatch =>
65 | SearchArtistsProxy(...criteria)
66 | .then((result = []) =>
67 | dispatch({ type: SEARCH_ARTISTS, payload: result })
68 | );
69 |
70 | export const findArtist = id => dispatch =>
71 | FindArtistProxy(id)
72 | .then(artist =>
73 | dispatch({ type: FIND_ARTIST, payload: artist })
74 | );
75 |
76 | export const createArtist = props => dispatch =>
77 | CreateArtistProxy(props)
78 | .then(artist => {
79 | hashHistory.push(`artists/${artist.id}`);
80 | })
81 | .catch(error => {
82 | console.log(error);
83 | dispatch({ type: CREATE_ERROR, payload: error });
84 | });
85 |
86 | export const editArtist = (id, props) => dispatch =>
87 | EditArtistProxy(id, props)
88 | .then(() => hashHistory.push(`artists/${id}`))
89 | .catch(error => {
90 | console.log(error);
91 | dispatch({ type: CREATE_ERROR, payload: error });
92 | });
93 |
94 | export const deleteArtist = (id) => dispatch =>
95 | DeleteArtistProxy(id)
96 | .then(() => hashHistory.push('/'))
97 | .catch(error => {
98 | console.log(error);
99 | dispatch({ type: CREATE_ERROR, payload: error });
100 | });
101 |
102 |
103 | //
104 | // Faux Proxies
105 |
106 | const GetAgeRangeProxy = (...args) => {
107 | const result = GetAgeRange(...args);
108 | if (!result || !result.then) {
109 | return new Promise(() => {});
110 | }
111 | return result;
112 | };
113 |
114 | const GetYearsActiveRangeProxy = (...args) => {
115 | const result = GetYearsActiveRange(...args);
116 | if (!result || !result.then) {
117 | return new Promise(() => {});
118 | }
119 | return result;
120 | };
121 |
122 | const SearchArtistsProxy = (criteria, offset, limit) => {
123 | const result = SearchArtists(_.omit(criteria, 'sort'), criteria.sort, offset, limit);
124 | if (!result || !result.then) {
125 | return new Promise(() => {});
126 | }
127 | return result;
128 | };
129 |
130 | const FindArtistProxy = (...args) => {
131 | const result = FindArtist(...args);
132 | if (!result || !result.then) {
133 | return new Promise(() => {});
134 | }
135 | return result;
136 | };
137 |
138 | const CreateArtistProxy = (...args) => {
139 | const result = CreateArtist(...args);
140 | if (!result || !result.then) {
141 | return new Promise(() => {});
142 | }
143 | return result;
144 | };
145 |
146 | const EditArtistProxy = (...args) => {
147 | const result = EditArtist(...args);
148 | if (!result || !result.then) {
149 | return new Promise(() => {});
150 | }
151 | return result;
152 | };
153 |
154 | const DeleteArtistProxy = (...args) => {
155 | const result = DeleteArtist(...args);
156 | if (!result || !result.then) {
157 | return new Promise(() => {});
158 | }
159 | return result;
160 | };
161 |
162 | const SetRetiredProxy = (_ids) => {
163 | const result = SetRetired(_ids);
164 | if (!result || !result.then) {
165 | return new Promise(() => {});
166 | }
167 | return result;
168 | };
169 |
170 | const SetNotRetiredProxy = (_ids) => {
171 | const result = SetNotRetired(_ids);
172 | if (!result || !result.then) {
173 | return new Promise(() => {});
174 | }
175 | return result;
176 | };
177 |
178 | //
179 | // Helpers
180 |
181 | const refreshSearch = (dispatch, getState) => {
182 | const { artists: { offset, limit } } = getState();
183 | const criteria = getState().form.filters.values;
184 |
185 | dispatch(searchArtists({ name: '', ...criteria }, offset, limit));
186 | };
187 |
--------------------------------------------------------------------------------