<commit_before>import _ from 'lodash';
import ls from 'local-storage';

import player from './player';
import traktUtil from './trakt';
import ui from './ui';
import linkSupport from './supportedLinks';
import prebuffering from './prebuffering';
import path from 'path';

import PlayerActions from '../actions';
import ProgressStore from '../components/Controls/components/ProgressBar/store';
import ControlStore from '../components/Controls/store';
import ControlActions from '../components/Controls/actions';
import TimeActions from '../components/Controls/components/HumanTime/actions';
import ProgressActions from '../components/Controls/components/ProgressBar/actions';
import VisibilityActions from '../components/Visibility/actions';
import SubtitleActions from '../components/SubtitleText/actions';
import engineStore from '../../../stores/engineStore';
import torrentUtil from '../../../utils/stream/torrentUtil';
import torrentActions from '../../../actions/torrentActions';
import sources from './sources';

var events = {};

events.buffering = (perc) => {

    var itemDesc = player.itemDesc();
    if (player.secondPlay && perc == 100) {
        player.secondPlay = false;
        _.delay(() => {
            // i don't like it, but if a delay is not set it sometimes bugs
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 500);
    }
    var isLocal = (itemDesc.mrl && itemDesc.mrl.indexOf('file://') == 0);
    if (!isLocal) {
        var announcer = {};

        var engineState = engineStore.getState();
        if (engineState.torrents && engineState.infoHash && engineState.torrents[engineState.infoHash] && engineState.torrents[engineState.infoHash].torrent && !engineState.torrents[engineState.infoHash].torrent.pieces.bank.get().downloaded && perc == 0) {
            announcer.text = 'Prebuffering 0%';
        } else {
            announcer.text = 'Buffering ' + perc + '%';
        }
        clearTimeout(player.announceTimer);

        if (perc === 100) {
            if (!player.announceEffect) {
                announcer.effect = true;
            }
        } else if (player.announceEffect)
            announcer.effect = false;

        if (Object.keys(announcer).length)
            player.events.emit('announce', announcer);
    }

}

events.opening = () => {

    var itemDesc = player.itemDesc();
    var isLocal = (itemDesc.mrl && itemDesc.mrl.indexOf('file://') == 0);

    if (itemDesc.artworkURL && !itemDesc.setting.image) {
        PlayerActions.setDesc({
            image: itemDesc.artworkURL
        })
    }

    if (!isLocal) {

        var timestamp = new Date().getTime();

        if (itemDesc && itemDesc.setting.youtubeDL && itemDesc.setting.timestamp < timestamp -1000) {
            // this is a youtube-dl supported link, let's refresh it to make sure the link didn't expire

            var currentItem = player.wcjs.playlist.currentItem;
            window.currentItem = currentItem;
            player.events.emit('playlistUpdate');

            player.wcjs.stop();

            player.wcjs.playlist.mode = 0;

            sources.youtubeDL(itemDesc.setting.originalURL, info => {
                if (window.currentItem == currentItem) {
                    delete window.currentItem;
                    _.defer(() => {
                        PlayerActions.replaceMRL({
                            autoplay: true,
                            x: currentItem,
                            mrl: {
                                title: info.fulltitle ? info.fulltitle : null,
                                thumbnail: info.thumbnail ? info.thumbnail : null,
                                uri: info.url ? info.url : null,
                                youtubeDL: true
                            }
                        });
                    });
                }
            });

            return;

        } else if (itemDesc && itemDesc.setting.torrentHash && itemDesc.setting.torrentHash != engineStore.getState().infoHash) {

            window.nextHash = itemDesc.setting.torrentHash;

            window.currentItem = player.wcjs.playlist.currentItem;

            player.wcjs.playlist.mode = 0;

            player.events.emit('playlistUpdate');

            player.wcjs.stop();

            var callback = () => {
                torrentActions.clear();
                torrentUtil.init('magnet:?xt=urn:btih:' + window.nextHash).then( instance => {
                    var listener = () => {

                        if (instance.infoHash == engineStore.getState().infoHash) {
                            // just soft kill this case to remove duplicates
                            instance.softKill();
                        } else if (instance.infoHash !== window.nextHash) {
                            if (ls('removeLogic') == 2) {
                                instance.kill();
                            } else {
                                instance.softKill();
                            }
                        } else {
                            torrentActions.add(instance);
                            for (var i = 0; i < player.wcjs.playlist.itemCount; i++) {
                                var pItemDesc = player.itemDesc(i);
                                if (pItemDesc.setting && pItemDesc.setting.torrentHash && pItemDesc.setting.torrentHash == window.nextHash) {
                                    PlayerActions.replaceMRL({
                                        autoplay: (window.currentItem == i),
                                        x: i,
                                        mrl: {
                                            title: pItemDesc.setting.title,
                                            thumbnail: pItemDesc.setting.image,
                                            uri: 'http://127.0.0.1:' + instance.server.port + '/' + pItemDesc.setting.streamID
                                        }
                                    })
                                }
                            }
                            delete window.currentItem;
                        }
                    };
                    if (instance.server && instance.server.port) listener();
                    else instance.on('listening', listener);
                })
            }

            var init = _.once(callback);

            var engineState = engineStore.getState();

            if (engineState.torrents[engineState.infoHash]) {
                if (ls('removeLogic') == 2) {
                    engineState.torrents[engineState.infoHash].kill(init);
                } else {
                    engineState.torrents[engineState.infoHash].softKill(init);
                }
                _.delay( init, 1000);
            } else init();

            return;

        }

        var announcer = {};

        announcer.text = 'Opening Media';
        clearTimeout(player.announceTimer);

        if (player.announceEffect)
            announcer.effect = false;

        if (Object.keys(announcer).length)
            player.events.emit('announce', announcer);

    }

    if (player.wcjs.playlist.currentItem != player.lastItem) {
        if (player.wcjs.volume != ls('volume'))
            player.wcjs.volume = ls('volume');

        if (player.wcjs.playlist.items[player.wcjs.playlist.currentItem].artworkURL) {
            var image = player.wcjs.playlist.items[player.wcjs.playlist.currentItem].artworkURL;
        } else {
            try {
                var image = JSON.parse(player.wcjs.playlist.items[player.wcjs.playlist.currentItem].setting).image;
            } catch (e) {}
        }

//        _.defer(() => {
            PlayerActions.updateImage(image);
            ProgressActions.settingChange({
                position: 0
            });
            player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);
//        });

        player.set({
            lastItem: player.wcjs.playlist.currentItem,
            pendingFiles: []
        });

    }

}

events.stopped = () => {
    console.log('Player stopped');

    SubtitleActions.settingChange({
        text: ''
    });
    player.events.emit('foundTrakt', false);
}

events.playing = () => {

    player.wcjs.playlist.mode = 1;

    player.events.emit('playlistUpdate');

    if (!player.firstPlay) {

        player.secondPlay = true;

        _.delay(() => {
            // i don't like it, but if a delay is not set it sometimes bugs
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 500);

        // catch first play event
        prebuffering.end();

        player.wcjs.subtitles.track = 0;

        player.set({
            firstPlay: true
        });
        player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);
        var itemDesc = player.itemDesc();
        if (itemDesc.setting && itemDesc.setting.trakt && !player.foundTrakt) {
            player.events.emit('foundTrakt', true);
            var shouldScrobble = traktUtil.loggedIn ? ls.isSet('traktScrobble') ? ls('traktScrobble') : true : false;
            if (shouldScrobble) {
                traktUtil.handleScrobble('start', itemDesc, player.wcjs.position);
                if (!ls.isSet('playerNotifs') || ls('playerNotifs'))
                    player.notifier.info('Scrobbling', '', 4000);
            }
        }

        var itemDesc = itemDesc.setting;

        if (itemDesc.subtitles) {
            ControlActions.settingChange({ foundSubs: true });
            SubtitleActions.foundSubs(itemDesc.subtitles, false);
        } else if (itemDesc.path && (!ls.isSet('findSubs') || ls('findSubs')))
            SubtitleActions.findSubs(itemDesc);

        if (window.clSub) {
            // if subtitle command line arg set, load it
            var subs = player.itemDesc().setting.subtitles || {};
            subs[path.basename(window.clSub)] = window.clSub;
            PlayerActions.setDesc({
                subtitles: subs
            });
            player.wcjs.subtitles.track = 0;
            SubtitleActions.loadSub(window.clSub);
            SubtitleActions.settingChange({
                selectedSub: _.size(subs) + (player.wcjs.subtitles.count || 1),
            });
            player.notifier.info('Subtitle Loaded', '', 3000);

            delete window.clSub;
        }

    } else {
        var itemDesc = player.itemDesc();
        if (itemDesc.setting && itemDesc.setting.trakt) {
            var shouldScrobble = traktUtil.loggedIn ? ls.isSet('traktScrobble') ? ls('traktScrobble') : true : false;
            if (shouldScrobble)
                traktUtil.handleScrobble('start', itemDesc, player.wcjs.position);
        }
    }

    player.fields.audioTrack.value = player.wcjs.audio[1];
    player.events.emit('controlsUpdate');
}

events.paused = () => {
    player.events.emit('playlistUpdate');
    player.events.emit('controlsUpdate');
    traktUtil.handleScrobble('pause', player.itemDesc(), player.wcjs.position);
}

events.resetUI = () => {

    ControlActions.settingChange({
        foundSubs: false
    });
    TimeActions.settingChange({
        currentTime: '00:00',
        totalTime: '00:00',
        length: 0
    });
    ProgressActions.settingChange({
        position: 0,
        cache: 0
    });
    SubtitleActions.settingChange({
        subtitle: [],
        selectedSub: 1,
        trackSub: -1,
        text: ''
    });
    player.events.emit('resizeNow', {
        aspect: 'Default',
        crop: 'Default',
        zoom: 1
    });
    player.events.emit('foundTrakt', false);
}

events.mediaChanged = () => {

    prebuffering.end();
    prebuffering.start(player);

    events.resetUI();

    VisibilityActions.settingChange({
        subtitles: false
    });
    player.set({
        foundTrakt: false,
        firstPlay: false,
        audioChannel: 1,
        audioTrack: 1
    });

    ui.defaultSettings();

    player.events.emit('playlistUpdate');

    player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);

}

events.error = () => {

    console.log('Player encountered an error.');

    var itemDesc = player.itemDesc();

    traktUtil.handleScrobble('stop', itemDesc, player.wcjs.position);

    console.log(itemDesc);

}

events.ended = () => {
    console.log('Playback ended');

    var position = ProgressStore.getState().position;

    player.events.emit('foundTrakt', false);
    traktUtil.handleScrobble('stop', player.itemDesc(), position);

    if (player.wcjs.time > 0) {
        if (typeof player.lastItem !== 'undefined' && position && position < 0.95) {

            console.log('Playback Ended Prematurely');
            console.log('Last Known Position: ', position);
            console.log('Last Known Item: ', player.lastItem);
            console.log('Reconnecting ...');

            player.wcjs.playlist.currentItem = player.lastItem;
            player.wcjs.playlist.play();
            player.wcjs.position = position;
        }
    }
}

events.close = () => {

    events.resetUI();

    VisibilityActions.settingChange({
        uiShown: true,
        playlist: false,
        subtitles: false,
        settings: false
    });
    player.events.emit('setTitle', '');

    if (ControlStore.getState().fullscreen)
        ControlActions.toggleFullscreen();

    player.set({
        pendingFiles: [],
        files: [],
        audioChannel: 1,
        audioTrack: 1,
        lastItem: -1
    });

    ui.defaultSettings();
    if (player.wcjs) {
        traktUtil.handleScrobble('stop', player.itemDesc(), player.wcjs.position);
        player.wcjs.stop();
        player.wcjs.playlist.clear();
    }
    PlayerActions.togglePowerSave(false);

}

module.exports = events;<commit_msg>[OSX/Linux] Fix Video Not Starting Sometimes #111<commit_after>import _ from 'lodash';
import ls from 'local-storage';

import player from './player';
import traktUtil from './trakt';
import ui from './ui';
import linkSupport from './supportedLinks';
import prebuffering from './prebuffering';
import path from 'path';

import PlayerActions from '../actions';
import ProgressStore from '../components/Controls/components/ProgressBar/store';
import ControlStore from '../components/Controls/store';
import ControlActions from '../components/Controls/actions';
import TimeActions from '../components/Controls/components/HumanTime/actions';
import ProgressActions from '../components/Controls/components/ProgressBar/actions';
import VisibilityActions from '../components/Visibility/actions';
import SubtitleActions from '../components/SubtitleText/actions';
import engineStore from '../../../stores/engineStore';
import torrentUtil from '../../../utils/stream/torrentUtil';
import torrentActions from '../../../actions/torrentActions';
import sources from './sources';

var events = {};

events.buffering = (perc) => {

    var itemDesc = player.itemDesc();
    if (player.secondPlay && perc == 100) {
        player.secondPlay = false;
        _.delay(() => {
            // i don't like it, but if a delay is not set it sometimes bugs
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 500);
    }
    var isLocal = (itemDesc.mrl && itemDesc.mrl.indexOf('file://') == 0);
    if (!isLocal) {
        var announcer = {};

        var engineState = engineStore.getState();
        if (engineState.torrents && engineState.infoHash && engineState.torrents[engineState.infoHash] && engineState.torrents[engineState.infoHash].torrent && !engineState.torrents[engineState.infoHash].torrent.pieces.bank.get().downloaded && perc == 0) {
            announcer.text = 'Prebuffering 0%';
        } else {
            announcer.text = 'Buffering ' + perc + '%';
        }
        clearTimeout(player.announceTimer);

        if (perc === 100) {
            if (!player.announceEffect) {
                announcer.effect = true;
            }
        } else if (player.announceEffect)
            announcer.effect = false;

        if (Object.keys(announcer).length)
            player.events.emit('announce', announcer);
    }

}

events.opening = () => {

    var itemDesc = player.itemDesc();
    var isLocal = (itemDesc.mrl && itemDesc.mrl.indexOf('file://') == 0);

    if (itemDesc.artworkURL && !itemDesc.setting.image) {
        PlayerActions.setDesc({
            image: itemDesc.artworkURL
        })
    }

    if (!isLocal) {

        var timestamp = new Date().getTime();

        if (itemDesc && itemDesc.setting.youtubeDL && itemDesc.setting.timestamp < timestamp -1000) {
            // this is a youtube-dl supported link, let's refresh it to make sure the link didn't expire

            var currentItem = player.wcjs.playlist.currentItem;
            window.currentItem = currentItem;
            player.events.emit('playlistUpdate');

            player.wcjs.stop();

            player.wcjs.playlist.mode = 0;

            sources.youtubeDL(itemDesc.setting.originalURL, info => {
                if (window.currentItem == currentItem) {
                    delete window.currentItem;
                    _.defer(() => {
                        PlayerActions.replaceMRL({
                            autoplay: true,
                            x: currentItem,
                            mrl: {
                                title: info.fulltitle ? info.fulltitle : null,
                                thumbnail: info.thumbnail ? info.thumbnail : null,
                                uri: info.url ? info.url : null,
                                youtubeDL: true
                            }
                        });
                    });
                }
            });

            return;

        } else if (itemDesc && itemDesc.setting.torrentHash && itemDesc.setting.torrentHash != engineStore.getState().infoHash) {

            window.nextHash = itemDesc.setting.torrentHash;

            window.currentItem = player.wcjs.playlist.currentItem;

            player.wcjs.playlist.mode = 0;

            player.events.emit('playlistUpdate');

            player.wcjs.stop();

            var callback = () => {
                torrentActions.clear();
                torrentUtil.init('magnet:?xt=urn:btih:' + window.nextHash).then( instance => {
                    var listener = () => {

                        if (instance.infoHash == engineStore.getState().infoHash) {
                            // just soft kill this case to remove duplicates
                            instance.softKill();
                        } else if (instance.infoHash !== window.nextHash) {
                            if (ls('removeLogic') == 2) {
                                instance.kill();
                            } else {
                                instance.softKill();
                            }
                        } else {
                            torrentActions.add(instance);
                            for (var i = 0; i < player.wcjs.playlist.itemCount; i++) {
                                var pItemDesc = player.itemDesc(i);
                                if (pItemDesc.setting && pItemDesc.setting.torrentHash && pItemDesc.setting.torrentHash == window.nextHash) {
                                    PlayerActions.replaceMRL({
                                        autoplay: (window.currentItem == i),
                                        x: i,
                                        mrl: {
                                            title: pItemDesc.setting.title,
                                            thumbnail: pItemDesc.setting.image,
                                            uri: 'http://127.0.0.1:' + instance.server.port + '/' + pItemDesc.setting.streamID
                                        }
                                    })
                                }
                            }
                            delete window.currentItem;
                        }
                    };
                    if (instance.server && instance.server.port) listener();
                    else instance.on('listening', listener);
                })
            }

            var init = _.once(callback);

            var engineState = engineStore.getState();

            if (engineState.torrents[engineState.infoHash]) {
                if (ls('removeLogic') == 2) {
                    engineState.torrents[engineState.infoHash].kill(init);
                } else {
                    engineState.torrents[engineState.infoHash].softKill(init);
                }
                _.delay( init, 1000);
            } else init();

            return;

        }

        var announcer = {};

        announcer.text = 'Opening Media';
        clearTimeout(player.announceTimer);

        if (player.announceEffect)
            announcer.effect = false;

        if (Object.keys(announcer).length)
            player.events.emit('announce', announcer);

    }

    if (player.wcjs.playlist.currentItem != player.lastItem) {
        if (player.wcjs.volume != ls('volume'))
            player.wcjs.volume = ls('volume');

        if (player.wcjs.playlist.items[player.wcjs.playlist.currentItem].artworkURL) {
            var image = player.wcjs.playlist.items[player.wcjs.playlist.currentItem].artworkURL;
        } else {
            try {
                var image = JSON.parse(player.wcjs.playlist.items[player.wcjs.playlist.currentItem].setting).image;
            } catch (e) {}
        }

        _.defer(() => {
            PlayerActions.updateImage(image);
        });
        _.delay(() => {
            PlayerActions.updateImage(image);
        }, 1000)

        ProgressActions.settingChange({
            position: 0
        });
        player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);

        player.set({
            lastItem: player.wcjs.playlist.currentItem,
            pendingFiles: []
        });

    }

}

events.stopped = () => {
    console.log('Player stopped');

    SubtitleActions.settingChange({
        text: ''
    });
    player.events.emit('foundTrakt', false);
}

events.playing = () => {

    player.wcjs.playlist.mode = 1;

    player.events.emit('playlistUpdate');

    if (!player.firstPlay) {

        player.secondPlay = true;

        // i hate this, but otherwise it bugs
        _.delay(() => {
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 500);

        _.delay(() => {
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 1000);

        _.delay(() => {
            PlayerActions.updateImage(player.itemDesc().setting.image);
        }, 1500);

        // catch first play event
        prebuffering.end();

        player.wcjs.subtitles.track = 0;

        player.set({
            firstPlay: true
        });
        player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);
        var itemDesc = player.itemDesc();
        if (itemDesc.setting && itemDesc.setting.trakt && !player.foundTrakt) {
            player.events.emit('foundTrakt', true);
            var shouldScrobble = traktUtil.loggedIn ? ls.isSet('traktScrobble') ? ls('traktScrobble') : true : false;
            if (shouldScrobble) {
                traktUtil.handleScrobble('start', itemDesc, player.wcjs.position);
                if (!ls.isSet('playerNotifs') || ls('playerNotifs'))
                    player.notifier.info('Scrobbling', '', 4000);
            }
        }

        var itemDesc = itemDesc.setting;

        if (itemDesc.subtitles) {
            ControlActions.settingChange({ foundSubs: true });
            SubtitleActions.foundSubs(itemDesc.subtitles, false);
        } else if (itemDesc.path && (!ls.isSet('findSubs') || ls('findSubs')))
            SubtitleActions.findSubs(itemDesc);

        if (window.clSub) {
            // if subtitle command line arg set, load it
            var subs = player.itemDesc().setting.subtitles || {};
            subs[path.basename(window.clSub)] = window.clSub;
            PlayerActions.setDesc({
                subtitles: subs
            });
            player.wcjs.subtitles.track = 0;
            SubtitleActions.loadSub(window.clSub);
            SubtitleActions.settingChange({
                selectedSub: _.size(subs) + (player.wcjs.subtitles.count || 1),
            });
            player.notifier.info('Subtitle Loaded', '', 3000);

            delete window.clSub;
        }

    } else {
        var itemDesc = player.itemDesc();
        if (itemDesc.setting && itemDesc.setting.trakt) {
            var shouldScrobble = traktUtil.loggedIn ? ls.isSet('traktScrobble') ? ls('traktScrobble') : true : false;
            if (shouldScrobble)
                traktUtil.handleScrobble('start', itemDesc, player.wcjs.position);
        }
    }

    player.fields.audioTrack.value = player.wcjs.audio[1];
    player.events.emit('controlsUpdate');
}

events.paused = () => {
    player.events.emit('playlistUpdate');
    player.events.emit('controlsUpdate');
    traktUtil.handleScrobble('pause', player.itemDesc(), player.wcjs.position);
}

events.resetUI = () => {

    ControlActions.settingChange({
        foundSubs: false
    });
    TimeActions.settingChange({
        currentTime: '00:00',
        totalTime: '00:00',
        length: 0
    });
    ProgressActions.settingChange({
        position: 0,
        cache: 0
    });
    SubtitleActions.settingChange({
        subtitle: [],
        selectedSub: 1,
        trackSub: -1,
        text: ''
    });
    player.events.emit('resizeNow', {
        aspect: 'Default',
        crop: 'Default',
        zoom: 1
    });
    player.events.emit('foundTrakt', false);
}

events.mediaChanged = () => {

    prebuffering.end();
    prebuffering.start(player);

    events.resetUI();

    VisibilityActions.settingChange({
        subtitles: false
    });
    player.set({
        foundTrakt: false,
        firstPlay: false,
        audioChannel: 1,
        audioTrack: 1
    });

    ui.defaultSettings();

    player.events.emit('playlistUpdate');

    player.events.emit('setTitle', player.wcjs.playlist.items[player.wcjs.playlist.currentItem].title);

}

events.error = () => {

    console.log('Player encountered an error.');

    var itemDesc = player.itemDesc();

    traktUtil.handleScrobble('stop', itemDesc, player.wcjs.position);

    console.log(itemDesc);

}

events.ended = () => {
    console.log('Playback ended');

    var position = ProgressStore.getState().position;

    player.events.emit('foundTrakt', false);
    traktUtil.handleScrobble('stop', player.itemDesc(), position);

    if (player.wcjs.time > 0) {
        if (typeof player.lastItem !== 'undefined' && position && position < 0.95) {

            console.log('Playback Ended Prematurely');
            console.log('Last Known Position: ', position);
            console.log('Last Known Item: ', player.lastItem);
            console.log('Reconnecting ...');

            player.wcjs.playlist.currentItem = player.lastItem;
            player.wcjs.playlist.play();
            player.wcjs.position = position;
        }
    }
}

events.close = () => {

    events.resetUI();

    VisibilityActions.settingChange({
        uiShown: true,
        playlist: false,
        subtitles: false,
        settings: false
    });
    player.events.emit('setTitle', '');

    if (ControlStore.getState().fullscreen)
        ControlActions.toggleFullscreen();

    player.set({
        pendingFiles: [],
        files: [],
        audioChannel: 1,
        audioTrack: 1,
        lastItem: -1
    });

    ui.defaultSettings();
    if (player.wcjs) {
        traktUtil.handleScrobble('stop', player.itemDesc(), player.wcjs.position);
        player.wcjs.stop();
        player.wcjs.playlist.clear();
    }
    PlayerActions.togglePowerSave(false);

}

module.exports = events;<|endoftext|>


<commit_before>var util = require('./util.test');

module.exports = function() {

	util.request('http://rawfile.test.whistlejs.com/index.html?doNotParseJson', function(res, body) {
		console.log(body);
	});

	util.request({
		method: 'post',
		url: 'https://rawfile.test.whistlejs.com/?doNotParseJson'
	}, function(res, body) {
		console.log(body);
	});
};<commit_msg>test: rawfile<commit_after>var util = require('./util.test');

module.exports = function() {

	util.request('http://raw.test.whistlejs.com/index.html?doNotParseJson', function(res, body) {
		res.statusCode.should.equal(500);
		body.should.equal('test');
		res.headers.should.have.property('content-type', 'text/plain');
	});

	util.request({
		method: 'post',
		url: 'https://raw.test.whistlejs.com/?doNotParseJson'
	}, function(res, body) {
		res.statusCode.should.equal(500);
		body.should.equal('test');
		res.headers.should.have.property('content-type', 'text/plain');
	});
};<|endoftext|>


<commit_before>import React, {Component} from "react";
import _ from "lodash";
import {Link} from "react-router";
import {HumanReadableMs} from "../";

function PlayAllButton({storyId, momentId}) {
  const url = `/stories/story/${storyId}/moment/${momentId}`;
  return (

        <Link className="btn btn-lg btn-primary" to={url}>
          Play All

        </Link>

  );
}

function NoMomentsNotice() {
  return (

      This story does not have any moments yet

  );
}

export function StoryCard({
  showPlayAll = false,
  storyId,
  firstMomentId,
  title,
  description
}) {
  return (

          {title}

          {description}

        {showPlayAll && _.isNumber(firstMomentId)
          ? <PlayAllButton momentId={firstMomentId} storyId={storyId} />
          : <NoMomentsNotice />}

  );
}

export function MomentCard({id, storyId, title, met_start, content}) {
  const url = `/stories/story/${storyId}/moment/${id}`;
  return (

            {title}

            {HumanReadableMs({ms: met_start, date: true})}

            {content}

            <Link to={url} className="btn btn-lg btn-primary">

            </Link>

  );
}

export function LandmarkCard({id, title, met_start}) {
  return (

            {title}

            {HumanReadableMs({ms: met_start})}

  );
}

export default class StoryTimeline extends Component {
  //const {landmarks} = this.props;
  checkDay(){
    var mstart;
    var mend;
    const day = this.props.missionDay;

    let landmarks = []; //TEMPORARY UNTIL WE GET LANDMARKS SORTED OUT :)
    const moments = this.props.story.momentList;
    const cards = _.sortBy(moments.concat(landmarks), "met_start");

    var targetcards = [];
    switch(day){
      case "1":
        mstart = 0;
        mend = 55680000;
        break;
      case "2":
        mstart = 55680001;
        mend = 142080000;
        break;
      case "3":
        mstart = 142080001;
        mend = 228479999;
        break;
      case "4":
        mstart = 228480000;
        mend = 314879998;
        break;
      case "5":
        mstart = 314879999;
        mend = 401279997;
        break;
      case "6":
        mstart = 401279998;
        mend = 487679996;
        break;
      case "7":
        mstart = 487679997;
        mend = 574079995;
        break;
      case "8":
        mstart = 574079996;
        mend = 660479994;
        break;
      case "9":
        mstart = 660479995;
        mend = 746879993;
        break;
      default:
        mstart = -746879993;
        mend = 746879993;
    }

    //DT - fills targetcards with moments that start, end or pass through the selected day (e.g. a moment that starts on day 1 then ends on day 4 would register for days 1,2,3, and 4)
    targetcards = _.filter(
      cards,function(card){
        return card == null || (card.met_start != null && ((card.met_start >= mstart && card.met_start <= mend) || (card.met_start < mstart && card.met_end > mstart)));
      }
    );

    if(_.isEmpty(targetcards)){
      return (

 No moments on this day

      );
    }
    return targetcards.map((card) => {
      if(_.has(card, "description")){
        return (
          <MomentCard
            key={card.id}
            id={card.id}
            storyId={this.props.story.id}
            title={card.title}
            content={card.description}
            met_start={card.met_start}
            time={card.time} />
        );
      } else {
        return (
          <LandmarkCard
            key={card.id}
            id={card.id}
            title={card.title}
            met_start={card.met_start}
            time={card.time} />
        );
      }
    });
  }
  render() {
    let landmarks = []; //TEMPORARY UNTIL WE GET LANDMARKS SORTED OUT :)
    const moments = this.props.story.momentList;

    const {story} = this.props;
    const {momentList} = story;

    const isMomentListEmpty = _.isEmpty(momentList);
    const showPlayAll = !isMomentListEmpty;
    const firstMomentId = (_.head(momentList) || {}).id;

    return (

            <StoryCard showPlayAll={showPlayAll}
                   storyId={story.id}
                   firstMomentId={firstMomentId}
                   {...story} />

          {this.checkDay()}

    );
  }
}
<commit_msg>fixed minor issues<commit_after>import React, {Component} from "react";
import _ from "lodash";
import {Link} from "react-router";
import {HumanReadableMs} from "../";

function PlayAllButton({storyId, momentId}) {
  const url = `/stories/story/${storyId}/moment/${momentId}`;
  return (

        <Link className="btn btn-lg btn-primary" to={url}>
          Play All

        </Link>

  );
}

function NoMomentsNotice() {
  return (

      This story does not have any moments yet

  );
}

export function StoryCard({
  showPlayAll = false,
  storyId,
  firstMomentId,
  title,
  description
}) {
  return (

          {title}

          {description}

        {showPlayAll && _.isNumber(firstMomentId)
          ? <PlayAllButton momentId={firstMomentId} storyId={storyId} />
          : <NoMomentsNotice />}

  );
}

export function MomentCard({id, storyId, title, met_start, content}) {
  const url = `/stories/story/${storyId}/moment/${id}`;
  return (

            {title}

            {HumanReadableMs({ms: met_start, date: true})}

            {content}

            <Link to={url} className="btn btn-lg btn-primary">

            </Link>

  );
}

export function LandmarkCard({id, title, met_start}) {
  return (

            {title}

            {HumanReadableMs({ms: met_start})}

  );
}

export default class StoryTimeline extends Component {
  //const {landmarks} = this.props;
  checkDay(){
    var mstart;
    var mend;
    const day = this.props.missionDay;

    let landmarks = []; //TEMPORARY UNTIL WE GET LANDMARKS SORTED OUT :)
    const moments = this.props.story.momentList;
    const cards = _.sortBy(moments.concat(landmarks), "met_start");

    var targetcards = [];
    switch(day){
      case "1":
        mstart = 0;
        mend = 55680000;
        break;
      case "2":
        mstart = 55680001;
        mend = 142080000;
        break;
      case "3":
        mstart = 142080001;
        mend = 228479999;
        break;
      case "4":
        mstart = 228480000;
        mend = 314879998;
        break;
      case "5":
        mstart = 314879999;
        mend = 401279997;
        break;
      case "6":
        mstart = 401279998;
        mend = 487679996;
        break;
      case "7":
        mstart = 487679997;
        mend = 574079995;
        break;
      case "8":
        mstart = 574079996;
        mend = 660479994;
        break;
      case "9":
        mstart = 660479995;
        mend = 746879993;
        break;
      default:
        mstart = -746879993;
        mend = 746879993;
    }

    //DT - fills targetcards with moments that start, end or pass through the selected day (e.g. a moment that starts on day 1 then ends on day 4 would register for days 1,2,3, and 4)
    targetcards = _.filter(
      cards,function(card){
        return card == null || (card.met_start != null && ((card.met_start >= mstart && card.met_start <= mend) || (card.met_start < mstart && card.met_end > mstart)));
      }
    );

    if(_.isEmpty(targetcards)){
      return (

 No moments on this day

      );
    }
    return targetcards.map((card) => {
      if(_.has(card, "description")){
        return (
          <MomentCard
            key={card.id}
            id={card.id}
            storyId={this.props.story.id}
            title={card.title}
            content={card.description}
            met_start={card.met_start}
            time={card.time} />
        );
      } else {
        return (
          <LandmarkCard
            key={card.id}
            id={card.id}
            title={card.title}
            met_start={card.met_start}
            time={card.time} />
        );
      }
    });
  }
  render() {
    const {story} = this.props;
    const {momentList} = story;

    const isMomentListEmpty = _.isEmpty(momentList);
    const showPlayAll = !isMomentListEmpty;
    const firstMomentId = (_.head(momentList) || {}).id;

    return (

            <StoryCard showPlayAll={showPlayAll}
                   storyId={story.id}
                   firstMomentId={firstMomentId}
                   {...story} />

          {this.checkDay()}

    );
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import {Text, View} from 'react-native';
import {Badge} from 'react-native-elements';
import {mergeStyles, stylePropType} from '@indec/react-native-commons/util';
import {includes, toString} from 'lodash';

import {TextBox} from '..';
import styles from './styles';

const getBadge = (number, badgeStyle) => {
    const parsedNumber = toString(number);
    return (
        !includes(parsedNumber, '.') ? (
            <Badge
                containerStyle={badgeStyle.primaryContainer}
                text={badgeStyle.primaryText}
                value={number}
            />
        ) : (
            <Badge
                containerStyle={badgeStyle.secondaryContainer}
                text={badgeStyle.secondaryText}
                value={number}
            />
        )
    );
};

const TextWithBadge = ({question: {number, text, infoAfterText}, style}) => {
    const computedStyles = mergeStyles(styles, style);
    return (
        <View style={computedStyles.text.container}>
            <View style={computedStyles.text.textWithBadgeContainer}>
                {number && getBadge(number, computedStyles.badge)}
                <Text style={computedStyles.text.text}>
                    {text}
                </Text>
            </View>
            {infoAfterText && <TextBox text={infoAfterText} style={computedStyles.textBox}/>}
        </View>
    );
};

TextWithBadge.displayName = 'textWithBadge';

TextWithBadge.propTypes = {
    question: PropTypes.shape({
        text: PropTypes.string.isRequired,
        number: PropTypes.number,
        infoAfterText: PropTypes.string
    }).isRequired,
    style: stylePropType
};

TextWithBadge.defaultProps = {
    style: null
};

export default TextWithBadge;
<commit_msg>style(textWithBadge): add disabled style to TextWithBadge component (#50)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import {Text, View} from 'react-native';
import {Badge} from 'react-native-elements';
import {mergeStyles, stylePropType} from '@indec/react-native-commons/util';
import {includes, toString} from 'lodash';

import {TextBox} from '..';
import styles from './styles';
import commonStyles from '../commonStyles';

const getBadge = (number, badgeStyle) => {
    const parsedNumber = toString(number);
    return (
        !includes(parsedNumber, '.') ? (
            <Badge
                containerStyle={badgeStyle.primaryContainer}
                text={badgeStyle.primaryText}
                value={number}
            />
        ) : (
            <Badge
                containerStyle={badgeStyle.secondaryContainer}
                text={badgeStyle.secondaryText}
                value={number}
            />
        )
    );
};

const TextWithBadge = ({question: {number, text, infoAfterText}, style, disabled}) => {
    const computedStyles = mergeStyles(styles, style);
    return (
        <View style={disabled ? commonStyles.disabledContainer : computedStyles.text.container}>
            <View style={computedStyles.text.textWithBadgeContainer}>
                {number && getBadge(number, computedStyles.badge)}
                <Text style={computedStyles.text.text}>
                    {text}
                </Text>
            </View>
            {infoAfterText && <TextBox text={infoAfterText} style={computedStyles.textBox}/>}
        </View>
    );
};

TextWithBadge.displayName = 'textWithBadge';

TextWithBadge.propTypes = {
    question: PropTypes.shape({
        text: PropTypes.string.isRequired,
        number: PropTypes.number,
        infoAfterText: PropTypes.string
    }).isRequired,
    style: stylePropType,
    disabled: PropTypes.bool
};

TextWithBadge.defaultProps = {
    style: null,
    disabled: false
};

export default TextWithBadge;
<|endoftext|>


<commit_before>'use strict';
require('../lib/loadConfig.js');
var expect = require('code').expect;
var Lab = require('lab');
var lab = exports.lab = Lab.script();
var describe = lab.describe;
var beforeEach = lab.beforeEach;
var afterEach = lab.afterEach;
var it = lab.test;

var mongoose = require('mongoose');

var app = require('../lib/app.js');
var mongo = require('../lib/helpers/mongo.js');
var Reservations = require('../lib/models/reservations/class.js');
var guests = require('./guests-fixtures.js');
var rooms = require('./rooms-fixtures.js');

var R = require('./reservations-fixtures.js');

describe('Reservations', function() {
  var ctx = {};
  beforeEach(function(done) {
    ctx = {};
    done();
  });
  beforeEach(function(done) {
    app.start(done);
  });
  beforeEach(function(done) {
    mongo.dropDatabase(done);
  });
  beforeEach(function(done) {
    guests.createBasicGuest(function(err, guest) {
      if (err) { return done(err); }
      ctx.guest = guest;
      done();
    });
  });
  beforeEach(function(done) {
    rooms.createBasicRoom(function(err, room) {
      if (err) { return done(err); }
      ctx.room = room;
      done();
    });
  });
  afterEach(function(done) {
    app.stop(done);
  });
  describe('POST /Reservations', function() {
    describe('valid', function() {
      it('should create reservation without room', function(done) {
        R.createBasicReservation(ctx.guest, done);
      });
      it('should create reservation with room', function(done) {
        var data = R.getTestData();
        data.rooms = [ctx.room._id];
        data.guests = [ctx.guest._id];
        R.postReservation(data, done);
      });
    }); // valid
    describe('invalid', function() {
      describe('missing keys', function() {
        ['checkIn', 'checkOut', 'rate', 'paymentType', 'status', 'roomsRequested']
          .forEach(function(key) {
          it('should error if missing ' + key, function(done) {
            var info = R.getTestData();
            delete info[key];
            info.guests = [ctx.guest._id];
            R.postReservation(info, function(err, res, body) {
              if (err) {
                return done(err);
              }
              expect(res.statusCode).to.equal(400);
              expect(body.name).to.equal('ValidationError');
              expect(body.errors[key]).to.exist();
              done();
            });
          });
        });
      });
      it('should error if guest does not exist', function(done) {
        var data = R.getTestData();
        data.guests = [new mongoose.Types.ObjectId()];

        R.postReservation(data, function(err, res, body) {
          expect(res.statusCode).to.equal(400);
          expect(body.output.payload.message).to.equal('guest not found');
          Reservations.find({}, function(err, body) {
            if (err) { return done(err); }
            expect(body.length).to.equal(0);
            done();
          });
        });
      });
      it('should error if guest invalid type', function(done) {
        var data = R.getTestData();
        data.guests = ['fake'];

        R.postReservation(data, function(err, res, body) {
          expect(res.statusCode).to.equal(400);
          expect(body.name).to.equal('CastError');
          expect(body.path).to.equal('guests');
          Reservations.find({}, function(err, body) {
            if (err) { return done(err); }
            expect(body.length).to.equal(0);
            done();
          });
        });
      });
      describe('room errors', function() {
        it('should error if no rooms left and no room specified', function(done) {
          R.createBasicReservation(ctx.guest, function(err) {
            if (err) { return done(err); }
            var data = R.getTestData();
            data.guests = [ctx.guest._id];
            R.postReservation(data, function(err, res, body) {
              expect(res.statusCode).to.equal(409);
              expect(body.output.payload.message).to.equal('no more rooms avalible');
              Reservations.find({}, function(err, body) {
                if (err) { return done(err); }
                expect(body.length).to.equal(1);
                done();
              });
            });
          });
        });
        it('should error if rooms already reserved', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = [ctx.room._id];
          R.postReservation(data, function(err) {
            if (err) { return done(err); }
            R.postReservation(data, function(err, res, body) {
              expect(res.statusCode).to.equal(409);
              expect(body.output.payload.message).to.equal('room already reserved');
              Reservations.find({}, function(err, body) {
                if (err) { return done(err); }
                expect(body.length).to.equal(1);
                done();
              });
            });
          });
        });
        it('should error if room does not exist', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = [new mongoose.Types.ObjectId()];

          R.postReservation(data, function(err, res, body) {
            expect(res.statusCode).to.equal(400);
            expect(body.output.payload.message).to.equal('room not found');
            Reservations.find({}, function(err, body) {
              if (err) { return done(err); }
              expect(body.length).to.equal(0);
              done();
            });
          });
        });
        it('should error if room invalid type', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = ['fake'];

          R.postReservation(data, function(err, res, body) {
            expect(res.statusCode).to.equal(400);
            expect(body.name).to.equal('CastError');
            expect(body.path).to.equal('rooms');
            Reservations.find({}, function(err, body) {
              if (err) { return done(err); }
              expect(body.length).to.equal(0);
              done();
            });
          });
        });
      });
    }); // invalid
  }); // POST /Reservations
  describe('GET /Reservations', function() {
    describe('valid', function() {
      var r2 = {
        checkIn: R.stripeTime(new Date()).getTime(),
        checkOut: R.stripeTime(R.addDays(new Date(), R.testReservationLength)).getTime(),
        rate: R.testRate,
        paymentType: R.C.paymentType.creditCard,
        status: R.C.status.notIn,
        roomsRequested: 1,
        comment: 'dog'
      };
      var r3 = {
        checkIn: R.stripeTime(R.addDays(new Date(), 1)).getTime(),
        checkOut: R.stripeTime(R.addDays(new Date(), 6)).getTime(),
        rate: R.testRate,
        paymentType: R.C.paymentType.cash,
        status: R.C.status.canceled,
        roomsRequested: 1,
        comment: 'pet'
      };
      beforeEach(function(done) {
        rooms.createRandomRoom(2, function(err, room) {
          if (err) { return done(err); }
          ctx.room2 = room;
          r2.rooms = [room._id];
          done();
        });
      });
      beforeEach(function(done) {
        rooms.createRandomRoom(3, function(err, room) {
          if (err) { return done(err); }
          ctx.room3 = room;
          done();
        });
      });
      beforeEach(function(done) {
        R.createBasicReservation(ctx.guest, done);
      });
      beforeEach(function(done) {
        guests.createRandomGuest(function(err, guest) {
          if (err) { return done(err); }
          ctx.guest2 = guest;
          r2.guests = [guest._id];
          done();
        });
      });
      beforeEach(function(done) {
        guests.createRandomGuest(function(err, guest) {
          if (err) { return done(err); }
          ctx.guest3 = guest;
          r3.guests = [guest._id];
          done();
        });
      });
      beforeEach(function(done) {
        R.postReservation(r2, function(err, res, body) {
          if (err) { return done(err); }
          ctx.reservation2 = body;
          ctx.reservation2.guests = ctx.guest2;
          done();
        });
      });
      beforeEach(function(done) {
        R.postReservation(r3, function(err, body) {
          if (err) { return done(err); }
          ctx.reservation3 = body;
          ctx.reservation3.guests = ctx.guest3;
          done();
        });
      });
      it('should get Reservation from paymentType', function(done) {
        R.getReservation({
          paymentType: R.C.paymentType.creditCard
        }, function(err, res, body) {
          if (err) { return done(err); }
          body = JSON.parse(body);
          expect(body).to.have.length(1);
          R.expectArrayToContainReservation(body, ctx.reservation2);
          done();
        });
      });
      it('should get Reservations from status', function(done) {
        R.getReservation({
          status: R.C.status.notIn
        }, function(err, res, body) {
          if (err) { return done(err); }
          body = JSON.parse(body);
          expect(body).to.have.length(2);
          R.expectArrayToContainReservation(body, R.getTestData());
          R.expectArrayToContainReservation(body, ctx.reservation2);
          done();
        });
      });
      describe('room with guest', function() {
        it('should get reservation by guest', function(done) {
          R.getReservation({
            guests: ctx.guest2._id
          }, function(err, res, body) {
            if (err) { return done(err); }
            body = JSON.parse(body);
            expect(body).to.have.length(1);
            R.expectArrayToContainReservation(body, ctx.reservation2);
            done();
          });
        });
      });
      it('should get reservation by room');
    }); // valid
  }); // GET /Reservations
  describe('DELETE /Reservation/:id', function() {
    describe('valid', function() {
      it('should delete Reservation', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.deleteReservation(Reservation._id, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.getReservation({number: R.getTestData().number}, function(err, res, body) {
              if (err) { return done(err); }
              body = JSON.parse(body);
              expect(body).to.be.empty();
              done();
            });
          });
        });
      });
      it('should do nothing if no id found', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.deleteReservation(Reservation._id, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.deleteReservation(Reservation._id, function(err, res) {
              if (err) { return done(err); }
              expect(res.statusCode).to.equal(200);
              done();
            });
          });
        });
      });
    }); // valid
    describe('invalid', function() {
      it('should error if no id sent', function(done) {
        R.deleteReservation('', function(err, res) {
          if (err) { return done(err); }
          expect(res.statusCode).to.equal(404);
          done();
        });
      });
    }); // invalid
  }); // DELETE /Reservation/:id'
  describe('PATCH /Reservation/:id', function() {
    describe('valid', function() {
      var testVals = {
        'checkIn': new Date().getTime(),
        'checkOut': R.stripeTime(R.addDays(new Date(), 9)).getTime(),
        'rate': 5,
        'paymentType': R.C.paymentType.creditCard,
        'cardNumber': 2352463,
        'status': R.C.status.checkOut,
        'comment': 'something'
      };
      function testUpdates (key) {
        return function (done) {
          R.createBasicReservation(ctx.guest, function(err, Reservation) {
            if (err) { return done(err); }
            var update = {};
            update[key] = testVals[key];
            R.patchReservation(Reservation._id, update, function(err, res) {
              if (err) { return done(err); }
              expect(res.statusCode).to.equal(200);
              R.getReservation({_id: Reservation._id}, function(err, res, body) {
                if (err) { return done(err); }
                body = JSON.parse(body);
                expect(body).to.have.length(1);
                expect(body[0][key]).to.equal(testVals[key]);
                done();
              });
            });
          });
        };
      }
      for (var item in testVals) {
        it('should update ' + item, testUpdates(item));
      }
      it('should update all', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.patchReservation(Reservation._id, testVals, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.getReservation({_id: Reservation._id}, function(err, res, body) {
              if (err) { return done(err); }
              body = JSON.parse(body);
              expect(body).to.have.length(1);
              expect(body[0]).to.deep.include(testVals);
              done();
            });
          });
        });
      });
    }); // valid
  }); // PATCH /Reservation/:id
});<commit_msg>add test for reservation with room<commit_after>'use strict';
require('../lib/loadConfig.js');
var expect = require('code').expect;
var Lab = require('lab');
var lab = exports.lab = Lab.script();
var describe = lab.describe;
var beforeEach = lab.beforeEach;
var afterEach = lab.afterEach;
var it = lab.test;

var mongoose = require('mongoose');

var app = require('../lib/app.js');
var mongo = require('../lib/helpers/mongo.js');
var Reservations = require('../lib/models/reservations/class.js');
var guests = require('./guests-fixtures.js');
var rooms = require('./rooms-fixtures.js');

var R = require('./reservations-fixtures.js');

describe('Reservations', function() {
  var ctx = {};
  beforeEach(function(done) {
    ctx = {};
    done();
  });
  beforeEach(function(done) {
    app.start(done);
  });
  beforeEach(function(done) {
    mongo.dropDatabase(done);
  });
  beforeEach(function(done) {
    guests.createBasicGuest(function(err, guest) {
      if (err) { return done(err); }
      ctx.guest = guest;
      done();
    });
  });
  beforeEach(function(done) {
    rooms.createBasicRoom(function(err, room) {
      if (err) { return done(err); }
      ctx.room = room;
      done();
    });
  });
  afterEach(function(done) {
    app.stop(done);
  });
  describe('POST /Reservations', function() {
    describe('valid', function() {
      it('should create reservation without room', function(done) {
        R.createBasicReservation(ctx.guest, done);
      });
      it('should create reservation with room', function(done) {
        var data = R.getTestData();
        data.rooms = [ctx.room._id];
        data.guests = [ctx.guest._id];
        R.postReservation(data, done);
      });
    }); // valid
    describe('invalid', function() {
      describe('missing keys', function() {
        ['checkIn', 'checkOut', 'rate', 'paymentType', 'status', 'roomsRequested']
          .forEach(function(key) {
          it('should error if missing ' + key, function(done) {
            var info = R.getTestData();
            delete info[key];
            info.guests = [ctx.guest._id];
            R.postReservation(info, function(err, res, body) {
              if (err) {
                return done(err);
              }
              expect(res.statusCode).to.equal(400);
              expect(body.name).to.equal('ValidationError');
              expect(body.errors[key]).to.exist();
              done();
            });
          });
        });
      });
      it('should error if guest does not exist', function(done) {
        var data = R.getTestData();
        data.guests = [new mongoose.Types.ObjectId()];

        R.postReservation(data, function(err, res, body) {
          expect(res.statusCode).to.equal(400);
          expect(body.output.payload.message).to.equal('guest not found');
          Reservations.find({}, function(err, body) {
            if (err) { return done(err); }
            expect(body.length).to.equal(0);
            done();
          });
        });
      });
      it('should error if guest invalid type', function(done) {
        var data = R.getTestData();
        data.guests = ['fake'];

        R.postReservation(data, function(err, res, body) {
          expect(res.statusCode).to.equal(400);
          expect(body.name).to.equal('CastError');
          expect(body.path).to.equal('guests');
          Reservations.find({}, function(err, body) {
            if (err) { return done(err); }
            expect(body.length).to.equal(0);
            done();
          });
        });
      });
      describe('room errors', function() {
        it('should error if no rooms left and no room specified', function(done) {
          R.createBasicReservation(ctx.guest, function(err) {
            if (err) { return done(err); }
            var data = R.getTestData();
            data.guests = [ctx.guest._id];
            R.postReservation(data, function(err, res, body) {
              expect(res.statusCode).to.equal(409);
              expect(body.output.payload.message).to.equal('no more rooms avalible');
              Reservations.find({}, function(err, body) {
                if (err) { return done(err); }
                expect(body.length).to.equal(1);
                done();
              });
            });
          });
        });
        it('should error if rooms already reserved', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = [ctx.room._id];
          R.postReservation(data, function(err) {
            if (err) { return done(err); }
            R.postReservation(data, function(err, res, body) {
              expect(res.statusCode).to.equal(409);
              expect(body.output.payload.message).to.equal('room already reserved');
              Reservations.find({}, function(err, body) {
                if (err) { return done(err); }
                expect(body.length).to.equal(1);
                done();
              });
            });
          });
        });
        it('should error if room does not exist', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = [new mongoose.Types.ObjectId()];

          R.postReservation(data, function(err, res, body) {
            expect(res.statusCode).to.equal(400);
            expect(body.output.payload.message).to.equal('room not found');
            Reservations.find({}, function(err, body) {
              if (err) { return done(err); }
              expect(body.length).to.equal(0);
              done();
            });
          });
        });
        it('should error if room invalid type', function(done) {
          var data = R.getTestData();
          data.guests = [ctx.guest._id];
          data.rooms = ['fake'];

          R.postReservation(data, function(err, res, body) {
            expect(res.statusCode).to.equal(400);
            expect(body.name).to.equal('CastError');
            expect(body.path).to.equal('rooms');
            Reservations.find({}, function(err, body) {
              if (err) { return done(err); }
              expect(body.length).to.equal(0);
              done();
            });
          });
        });
      });
    }); // invalid
  }); // POST /Reservations
  describe('GET /Reservations', function() {
    describe('valid', function() {
      var r2 = {
        checkIn: R.stripeTime(new Date()).getTime(),
        checkOut: R.stripeTime(R.addDays(new Date(), R.testReservationLength)).getTime(),
        rate: R.testRate,
        paymentType: R.C.paymentType.creditCard,
        status: R.C.status.notIn,
        roomsRequested: 1,
        comment: 'dog'
      };
      var r3 = {
        checkIn: R.stripeTime(R.addDays(new Date(), 1)).getTime(),
        checkOut: R.stripeTime(R.addDays(new Date(), 6)).getTime(),
        rate: R.testRate,
        paymentType: R.C.paymentType.cash,
        status: R.C.status.canceled,
        roomsRequested: 1,
        comment: 'pet'
      };
      beforeEach(function(done) {
        rooms.createRandomRoom(2, function(err, room) {
          if (err) { return done(err); }
          ctx.room2 = room;
          r2.rooms = [room._id];
          done();
        });
      });
      beforeEach(function(done) {
        rooms.createRandomRoom(3, function(err, room) {
          if (err) { return done(err); }
          ctx.room3 = room;
          done();
        });
      });
      beforeEach(function(done) {
        R.createBasicReservation(ctx.guest, done);
      });
      beforeEach(function(done) {
        guests.createRandomGuest(function(err, guest) {
          if (err) { return done(err); }
          ctx.guest2 = guest;
          r2.guests = [guest._id];
          done();
        });
      });
      beforeEach(function(done) {
        guests.createRandomGuest(function(err, guest) {
          if (err) { return done(err); }
          ctx.guest3 = guest;
          r3.guests = [guest._id];
          done();
        });
      });
      beforeEach(function(done) {
        R.postReservation(r2, function(err, res, body) {
          if (err) { return done(err); }
          ctx.reservation2 = body;
          ctx.reservation2.guests = ctx.guest2;
          done();
        });
      });
      beforeEach(function(done) {
        R.postReservation(r3, function(err, body) {
          if (err) { return done(err); }
          ctx.reservation3 = body;
          ctx.reservation3.guests = ctx.guest3;
          done();
        });
      });
      it('should get Reservation from paymentType', function(done) {
        R.getReservation({
          paymentType: R.C.paymentType.creditCard
        }, function(err, res, body) {
          if (err) { return done(err); }
          body = JSON.parse(body);
          expect(body).to.have.length(1);
          R.expectArrayToContainReservation(body, ctx.reservation2);
          done();
        });
      });
      it('should get Reservations from status', function(done) {
        R.getReservation({
          status: R.C.status.notIn
        }, function(err, res, body) {
          if (err) { return done(err); }
          body = JSON.parse(body);
          expect(body).to.have.length(2);
          R.expectArrayToContainReservation(body, R.getTestData());
          R.expectArrayToContainReservation(body, ctx.reservation2);
          done();
        });
      });
      describe('reservation with guest', function() {
        it('should get reservation by guest', function(done) {
          R.getReservation({
            guests: ctx.guest2._id
          }, function(err, res, body) {
            if (err) { return done(err); }
            body = JSON.parse(body);
            expect(body).to.have.length(1);
            R.expectArrayToContainReservation(body, ctx.reservation2);
            done();
          });
        });
      });
      describe('reservation with room', function() {
        it('should get reservation by room', function(done) {
          R.getReservation({
            rooms: ctx.room2._id
          }, function(err, res, body) {
            if (err) { return done(err); }
            body = JSON.parse(body);
            expect(body).to.have.length(1);
            R.expectArrayToContainReservation(body, ctx.reservation2);
            done();
          });
        });
      });
    }); // valid
  }); // GET /Reservations
  describe('DELETE /Reservation/:id', function() {
    describe('valid', function() {
      it('should delete Reservation', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.deleteReservation(Reservation._id, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.getReservation({number: R.getTestData().number}, function(err, res, body) {
              if (err) { return done(err); }
              body = JSON.parse(body);
              expect(body).to.be.empty();
              done();
            });
          });
        });
      });
      it('should do nothing if no id found', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.deleteReservation(Reservation._id, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.deleteReservation(Reservation._id, function(err, res) {
              if (err) { return done(err); }
              expect(res.statusCode).to.equal(200);
              done();
            });
          });
        });
      });
    }); // valid
    describe('invalid', function() {
      it('should error if no id sent', function(done) {
        R.deleteReservation('', function(err, res) {
          if (err) { return done(err); }
          expect(res.statusCode).to.equal(404);
          done();
        });
      });
    }); // invalid
  }); // DELETE /Reservation/:id'
  describe('PATCH /Reservation/:id', function() {
    describe('valid', function() {
      var testVals = {
        'checkIn': new Date().getTime(),
        'checkOut': R.stripeTime(R.addDays(new Date(), 9)).getTime(),
        'rate': 5,
        'paymentType': R.C.paymentType.creditCard,
        'cardNumber': 2352463,
        'status': R.C.status.checkOut,
        'comment': 'something'
      };
      function testUpdates (key) {
        return function (done) {
          R.createBasicReservation(ctx.guest, function(err, Reservation) {
            if (err) { return done(err); }
            var update = {};
            update[key] = testVals[key];
            R.patchReservation(Reservation._id, update, function(err, res) {
              if (err) { return done(err); }
              expect(res.statusCode).to.equal(200);
              R.getReservation({_id: Reservation._id}, function(err, res, body) {
                if (err) { return done(err); }
                body = JSON.parse(body);
                expect(body).to.have.length(1);
                expect(body[0][key]).to.equal(testVals[key]);
                done();
              });
            });
          });
        };
      }
      for (var item in testVals) {
        it('should update ' + item, testUpdates(item));
      }
      it('should update all', function(done) {
        R.createBasicReservation(ctx.guest, function(err, Reservation) {
          if (err) { return done(err); }
          R.patchReservation(Reservation._id, testVals, function(err, res) {
            if (err) { return done(err); }
            expect(res.statusCode).to.equal(200);
            R.getReservation({_id: Reservation._id}, function(err, res, body) {
              if (err) { return done(err); }
              body = JSON.parse(body);
              expect(body).to.have.length(1);
              expect(body[0]).to.deep.include(testVals);
              done();
            });
          });
        });
      });
    }); // valid
  }); // PATCH /Reservation/:id
});<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import styled from 'styled-components';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import isNaN from 'lodash/isNaN';
import noop from 'lodash/noop';

import { actions } from 'modules/toast';
import { colors } from 'style/theme';

const DEFAULT_TIMEOUT = 4000;

const Toast = styled.div`
  position: relative;
  width: 300px;
  border-radius: 5px;
  background: ${colors.background_menu};
  color: ${colors.font_primary};
  padding: 20px 20px 35px;
  margin: 0 0 15px;
  cursor: pointer;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);

  ${props => props.type === 'info' && `border-top: 10px solid ${colors.blue}`};
  ${props => props.type === 'success' && `border-top: 10px solid ${colors.green}`};
  ${props => props.type === 'alert' && `border-top: 10px solid ${colors.red}`};

  &:after {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    content: 'click to close';
    text-align: center;
    padding: 8px;
    font-size: 10px;
    font-style: italic;
    color: rgba(255, 255, 255, 0.3);
  }

  &:last-child {
    margin: 0;
  }

  &.toast-enter {
    transform: scale(0.8);
    opacity: 0.01;
  }

  &.toast-enter.toast-enter-active {
    transform: scale(1);
    opacity: 1;
    transition: transform 0.5s, opacity 0.5s;
  }

  &.toast-leave {
    transform: scale(0.8);
    opacity: 1;
  }

  &.toast-leave.toast-leave-active {
    transform: scale(0);
    opacity: 0.01;
    transition: transform 0.3s, opacity 0.3s;
  }

  .Toast__header {
    font-size: 16px;
    font-weight: 500;
    margin: 0 0 15px;
  }

  .Toast__content {
    font-size: 14px;
    font-weight: 400;
    line-height: 1.5;
  }
`;

class ToastWrapper extends PureComponent {
  static propTypes = {
    children: PropTypes.oneOfType([PropTypes.array, PropTypes.element, PropTypes.string]).isRequired,
    title: PropTypes.string,
    type: PropTypes.string,
    timeout: PropTypes.number,

    // Methods
    close: PropTypes.func.isRequired,
    onClose: PropTypes.func.isRequired,
  };

  static defaultProps = {
    title: '',
    type: 'info',
    timeout: DEFAULT_TIMEOUT,

    // Methods
    close: noop,
    onClose: noop,
  };

  startTimer = () => {
    const { onClose, timeout } = this.props;

    if (timeout !== false) {
      const parseTimeout = parseInt(timeout, 10);
      const computedTimeout = !isNaN(parseTimeout) ? parseTimeout : DEFAULT_TIMEOUT;
      this.timer = setTimeout(this.withClose(onClose), computedTimeout);
    }
  };

  stopTimer = () => {
    if (this.timer) {
      clearTimeout(this.timer);
    }
  };

  withClose = (action = noop) => () => {
    const { id, close } = this.props;

    action();
    close(id);
  };

  componentDidMount() {
    this.startTimer();
  }

  componentWillUnmount() {
    this.stopTimer();
  }

  render() {
    const { children, title, type, onClose } = this.props;

    return (
      <Toast type={type} onClick={this.withClose(onClose)} onMouseEnter={this.stopTimer} onMouseLeave={this.startTimer}>

{title}

{children}

      </Toast>
    );
  }
}

export default connect(null, { close: actions.closeToast })(ToastWrapper);
<commit_msg>Cleaned up PropTypes on ToastWrapper, added Play Midnight prefix to title<commit_after>import React, { PureComponent } from 'react';
import styled from 'styled-components';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import isNaN from 'lodash/isNaN';
import noop from 'lodash/noop';

import { actions } from 'modules/toast';
import { colors } from 'style/theme';

const DEFAULT_TIMEOUT = 4000;

const Toast = styled.div`
  position: relative;
  width: 300px;
  border-radius: 5px;
  background: ${colors.background_menu};
  color: ${colors.font_primary};
  padding: 20px 20px 35px;
  margin: 0 0 15px;
  cursor: pointer;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);

  ${props => props.type === 'info' && `border-top: 10px solid ${colors.blue}`};
  ${props => props.type === 'success' && `border-top: 10px solid ${colors.green}`};
  ${props => props.type === 'alert' && `border-top: 10px solid ${colors.red}`};

  &:after {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    content: 'click to close';
    text-align: center;
    padding: 8px;
    font-size: 10px;
    font-style: italic;
    color: rgba(255, 255, 255, 0.3);
  }

  &:last-child {
    margin: 0;
  }

  &.toast-enter {
    transform: scale(0.8);
    opacity: 0.01;
  }

  &.toast-enter.toast-enter-active {
    transform: scale(1);
    opacity: 1;
    transition: transform 0.5s, opacity 0.5s;
  }

  &.toast-leave {
    transform: scale(0.8);
    opacity: 1;
  }

  &.toast-leave.toast-leave-active {
    transform: scale(0);
    opacity: 0.01;
    transition: transform 0.3s, opacity 0.3s;
  }

  .Toast__header {
    font-size: 16px;
    font-weight: 500;
    margin: 0 0 15px;
  }

  .Toast__content {
    font-size: 14px;
    font-weight: 400;
    line-height: 1.5;
  }
`;

class ToastWrapper extends PureComponent {
  static propTypes = {
    children: PropTypes.oneOfType([PropTypes.array, PropTypes.element, PropTypes.string]).isRequired,
    title: PropTypes.string,
    type: PropTypes.string,
    timeout: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),

    // Methods
    close: PropTypes.func.isRequired,
    onClose: PropTypes.func.isRequired,
  };

  static defaultProps = {
    title: '',
    type: 'info',
    timeout: DEFAULT_TIMEOUT,

    // Methods
    close: noop,
    onClose: noop,
  };

  startTimer = () => {
    const { onClose, timeout } = this.props;

    if (timeout !== false) {
      const parseTimeout = parseInt(timeout, 10);
      const computedTimeout = !isNaN(parseTimeout) ? parseTimeout : DEFAULT_TIMEOUT;
      this.timer = setTimeout(this.withClose(onClose), computedTimeout);
    }
  };

  stopTimer = () => {
    if (this.timer) {
      clearTimeout(this.timer);
    }
  };

  withClose = (action = noop) => () => {
    const { id, close } = this.props;

    action();
    close(id);
  };

  componentDidMount() {
    this.startTimer();
  }

  componentWillUnmount() {
    this.stopTimer();
  }

  render() {
    const { children, title, type, onClose } = this.props;

    return (
      <Toast type={type} onClick={this.withClose(onClose)} onMouseEnter={this.stopTimer} onMouseLeave={this.startTimer}>

Play Midnight - {title}

{children}

      </Toast>
    );
  }
}

export default connect(null, { close: actions.closeToast })(ToastWrapper);
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';

class ItemForm extends React.Component {
  constructor(){
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
    this.getItemnameRef = this.getItemnameRef.bind(this);
    this.getCategoryRef = this.getCategoryRef.bind(this);
    this.getMessageRef = this.getMessageRef.bind(this);
    this.getUrlRef = this.getUrlRef.bind(this);
    this.state = {
      itemname: '',
      category: '',
      message: '',
      url: ''
    }
  }

  getItemnameRef(ref){
    this.itemnameRef = ref;
  }

  getCategoryRef(ref){
    this.categoryRef = ref;
  }

  getMessageRef(ref){
    this.messageRef = ref;
  }

  getUrlRef(ref){
    this.urlRef = ref;
  }

  handleSubmit(e){
    e.preventDefault();
    let username = this.props.userInfo.username;
    let itemname = this.itemnameRef.value;
    let category = this.categoryRef.value;
    let url = this.urlRef.value;
    let message = this.messageRef.value;
    let self = this;

    $.ajax({
      url: '/wishlist',
      type: 'POST',
      contentType: 'application/json',
      dataType:'json',
      data: JSON.stringify({
        username: username,
        wishname: itemname,
        category: category,
        link: url,
        description: message
      }),
      success: function(data){
        self.props.updateWishlist(data);
      },
      error: function(err){
        console.log('error posting to wishlist: ', err);
      }
    });

    this.itemnameRef.value = '';
    this.categoryRef.value = '';
    this.urlRef.value = '';
    this.messageRef.value = '';
  }

  render(){
    return (
      <form ref='form'>
          Item
          <input type='text' name='itemname' className='form-control' placeholder='Item Name' ref={this.getItemnameRef} />

          Category
          <input type='text' name='category' className='form-control' placeholder='Category' ref={this.getCategoryRef} />

          Message
          <input type='text' name='message' className='form-control' placeholder='Message' ref={this.getMessageRef} />

          Link
          <input type='url' name='url' className='form-control' placeholder='Enter URL Here' ref={this.getUrlRef} />

        <button type='submit' className='btn btn-primary' onClick={this.handleSubmit}>Submit</button>
      </form>
    )
  }
}

export default ItemForm;
<commit_msg>[style] implements category image buttons<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';

class ItemForm extends React.Component {
  constructor(){
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
    this.getItemnameRef = this.getItemnameRef.bind(this);
    this.getCategoryRef = this.getCategoryRef.bind(this);
    this.getMessageRef = this.getMessageRef.bind(this);
    this.getUrlRef = this.getUrlRef.bind(this);
    this.state = {
      itemname: '',
      category: '',
      message: '',
      url: ''
    }
  }

  getItemnameRef(ref){
    this.itemnameRef = ref;
  }

  getCategoryRef(ref){
    this.categoryRef = ref;
  }

  getMessageRef(ref){
    this.messageRef = ref;
  }

  getUrlRef(ref){
    this.urlRef = ref;
  }

  handleSubmit(e){
    e.preventDefault();
    let username = this.props.userInfo.username;
    let itemname = this.itemnameRef.value;
    let category = this.categoryRef.value;
    let url = this.urlRef.value;
    let message = this.messageRef.value;
    let self = this;

    $.ajax({
      url: '/wishlist',
      type: 'POST',
      contentType: 'application/json',
      dataType:'json',
      data: JSON.stringify({
        username: username,
        wishname: itemname,
        category: category,
        link: url,
        description: message
      }),
      success: function(data){
        self.props.updateWishlist(data);
      },
      error: function(err){
        console.log('error posting to wishlist: ', err);
      }
    });

    this.itemnameRef.value = '';
    this.categoryRef.value = '';
    this.urlRef.value = '';
    this.messageRef.value = '';
  }

  render(){
    return (
      <form ref='form'>
          Item
          <input type='text' name='itemname' className='form-control' placeholder='Item Name' ref={this.getItemnameRef} />

          Category
          <input type='text' name='category' className='form-control' placeholder='Category' ref={this.getCategoryRef} />

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

              <button className="btn btn-default">

              </button>

          Message
          <input type='text' name='message' className='form-control' placeholder='Message' ref={this.getMessageRef} />

          Link
          <input type='url' name='url' className='form-control' placeholder='Enter URL Here' ref={this.getUrlRef} />

        <button type='submit' className='btn btn-primary' onClick={this.handleSubmit}>Submit</button>
      </form>
    )
  }
}

export default ItemForm;
<|endoftext|>


<commit_before>import assert from "assert";
import React from "react";

import { resolve, Resolver } from "..";

@resolve("resolved", ({ actual }) => actual)
class Test extends React.Component {
  static displayName = "Test"

  render() {
    const { expected, resolved } = this.props;

    assert.equal(resolved, expected);

    return (

        {resolved}

    );
  }
}

describe("@resolve", function() {
  it("wraps Component name", function() {
    const element = <Test />;

    assert.equal(Test.displayName, "ResolvedResolver");
  });

  context("with a scalar", function() {
    it("resolves", function() {
      return Resolver.resolve(() => <Test actual="scalar" expected="scalar" />);
    });

    it("is synchronous", function() {
      assert.equal(
        React.renderToStaticMarkup(<Test actual="scalar" expected="scalar" />),
        "
\nscalar
"
      );
    });
  });

  context("with a Promise ", function() {
    it("resolves", function() {
      return Resolver.resolve(() => <Test actual={Promise.resolve("promise")} expected="promise" />);
    });

    it("is asynchronous", function() {
      assert.equal(
        React.renderToStaticMarkup(<Test actual={Promise.resolve("promise")} expected="promise" />),
        ""
      );
    });
  });
});
<commit_msg>Remove unused variable<commit_after>import assert from "assert";
import React from "react";

import { resolve, Resolver } from "..";

@resolve("resolved", ({ actual }) => actual)
class Test extends React.Component {
  static displayName = "Test"

  render() {
    const { expected, resolved } = this.props;

    assert.equal(resolved, expected);

    return (

        {resolved}

    );
  }
}

describe("@resolve", function() {
  it("wraps Component name", function() {
    assert.equal(Test.displayName, "ResolvedResolver");
  });

  context("with a scalar", function() {
    it("resolves", function() {
      return Resolver.resolve(() => <Test actual="scalar" expected="scalar" />);
    });

    it("is synchronous", function() {
      assert.equal(
        React.renderToStaticMarkup(<Test actual="scalar" expected="scalar" />),
        "
\nscalar
"
      );
    });
  });

  context("with a Promise ", function() {
    it("resolves", function() {
      return Resolver.resolve(() => <Test actual={Promise.resolve("promise")} expected="promise" />);
    });

    it("is asynchronous", function() {
      assert.equal(
        React.renderToStaticMarkup(<Test actual={Promise.resolve("promise")} expected="promise" />),
        ""
      );
    });
  });
});
<|endoftext|>