<commit_before>angular.module('fundoo.services', []).factory('createDialog', ["$document", "$compile", "$rootScope", "$controller", "$timeout",
  function ($document, $compile, $rootScope, $controller, $timeout) {
    var defaults = {
      id: null,
      template: null,
      templateUrl: null,
      title: 'Default Title',
      backdrop: true,
      success: {label: 'OK', fn: null},
      cancel: {label: 'Close', fn: null},
      controller: null, //just like route controller declaration
      backdropClass: "modal-backdrop",
      backdropCancel: true,
      footerTemplate: null,
      hideFooter:false,
      modalClass: "modal",
      cancelOnEsc:true,
      css: {
        top: '100px',
        left: '30%',
        margin: '0 auto'
      }
    };
    var body = $document.find('body');

    return function Dialog(templateUrl/*optional*/, options, passedInLocals) {

      // Handle arguments if optional template isn't provided.
      if(angular.isObject(templateUrl)){
        passedInLocals = options;
        options = templateUrl;
      } else {
        options.templateUrl = templateUrl;
      }

      options = angular.extend({}, defaults, options); //options defined in constructor

      var key;
      var idAttr = options.id ? ' id="' + options.id + '" ' : '';
      var defaultFooter = '<button class="btn" ng-click="$modalCancel()">{{$modalCancelLabel}}</button>' +
        '<button class="btn btn-primary" ng-click="$modalSuccess()">{{$modalSuccessLabel}}</button>';
      var footerTemplate = options.hideFooter ? '' : '
' + (options.footerTemplate || defaultFooter) + '
';
      var modalBody = (function(){
        if(options.template){
          if(angular.isString(options.template)){
            // Simple string template
            return '
' + options.template + '
';
          } else {
            // jQuery/JQlite wrapped object
            return '
' + options.template.html() + '
';
          }
        } else {
          // Template url
          return '

'
        }
      })();
      //We don't have the scope we're gonna use yet, so just get a compile function for modal
      var modalEl = angular.element(
                '
' +
                    '
' +
                    '
' +
                    '
' +
                    '        <button type="button" class="close" ng-click="$modalCancel()">×</button>' +
                    '
{{$title}}
' +
                    '
' +
                    modalBody +
                    footerTemplate +
                    '
' +
                    '
' +
                    '
');

      for(key in options.css) {
        modalEl.css(key, options.css[key]);
      }
      var divHTML = "
";
      var backdropEl = angular.element(divHTML);
      backdropEl.addClass(options.backdropClass);
      backdropEl.addClass('fade in');

      var handleEscPressed = function (event) {
        if (event.keyCode === 27 && options.cancelOnEsc) {
          scope.$modalCancel();
        }
      };

      var closeFn = function () {
        body.unbind('keydown', handleEscPressed);
        modalEl.remove();
        if (options.backdrop) {
          backdropEl.remove();
        }
      };

      body.bind('keydown', handleEscPressed);

      var ctrl, locals,
        scope = options.scope || $rootScope.$new();

      scope.$title = options.title;
      scope.$modalClose = closeFn;
      scope.$modalCancel = function () {
        var callFn = options.cancel.fn || closeFn;
        callFn.call(this);
        scope.$modalClose();
      };
      scope.$modalSuccess = function () {
        var callFn = options.success.fn || closeFn;
        var ret = callFn.call(this);
        console.log(ret);
        if (ret!==false) {
          scope.$modalClose();
        }
      };
      scope.$modalSuccessLabel = options.success.label;
      scope.$modalCancelLabel = options.cancel.label;

      if (options.controller) {
        locals = angular.extend({$scope: scope}, passedInLocals);
        ctrl = $controller(options.controller, locals);
        // Yes, ngControllerController is not a typo
        modalEl.contents().data('$ngControllerController', ctrl);
      }

      $compile(modalEl)(scope);
      $compile(backdropEl)(scope);
      body.append(modalEl);
      if (options.backdrop) body.append(backdropEl);

      $timeout(function () {
        modalEl.addClass('in');
      }, 200);
    };
  }]);
<commit_msg>Check if the function return is promise, resolve and then close or not window<commit_after>angular.module('fundoo.services', []).factory('createDialog', ["$document", "$compile", "$rootScope", "$controller", "$timeout",
  function ($document, $compile, $rootScope, $controller, $timeout) {
    var defaults = {
      id: null,
      template: null,
      templateUrl: null,
      title: 'Default Title',
      backdrop: true,
      success: {label: 'OK', fn: null},
      cancel: {label: 'Close', fn: null},
      controller: null, //just like route controller declaration
      backdropClass: "modal-backdrop",
      backdropCancel: true,
      footerTemplate: null,
      hideFooter:false,
      modalClass: "modal",
      cancelOnEsc:true,
      css: {
        top: '100px',
        left: '30%',
        margin: '0 auto'
      }
    };
    var body = $document.find('body');

    return function Dialog(templateUrl/*optional*/, options, passedInLocals) {

      // Handle arguments if optional template isn't provided.
      if(angular.isObject(templateUrl)){
        passedInLocals = options;
        options = templateUrl;
      } else {
        options.templateUrl = templateUrl;
      }

      options = angular.extend({}, defaults, options); //options defined in constructor

      var key;
      var idAttr = options.id ? ' id="' + options.id + '" ' : '';
      var defaultFooter = '<button class="btn" ng-click="$modalCancel()">{{$modalCancelLabel}}</button>' +
        '<button class="btn btn-primary" ng-click="$modalSuccess()">{{$modalSuccessLabel}}</button>';
      var footerTemplate = options.hideFooter ? '' : '
' + (options.footerTemplate || defaultFooter) + '
';
      var modalBody = (function(){
        if(options.template){
          if(angular.isString(options.template)){
            // Simple string template
            return '
' + options.template + '
';
          } else {
            // jQuery/JQlite wrapped object
            return '
' + options.template.html() + '
';
          }
        } else {
          // Template url
          return '

'
        }
      })();
      //We don't have the scope we're gonna use yet, so just get a compile function for modal
      var modalEl = angular.element(
                '
' +
                    '
' +
                    '
' +
                    '
' +
                    '        <button type="button" class="close" ng-click="$modalCancel()">×</button>' +
                    '
{{$title}}
' +
                    '
' +
                    modalBody +
                    footerTemplate +
                    '
' +
                    '
' +
                    '
');

      for(key in options.css) {
        modalEl.css(key, options.css[key]);
      }
      var divHTML = "
";
      var backdropEl = angular.element(divHTML);
      backdropEl.addClass(options.backdropClass);
      backdropEl.addClass('fade in');

      var handleEscPressed = function (event) {
        if (event.keyCode === 27 && options.cancelOnEsc) {
          scope.$modalCancel();
        }
      };

      var closeFn = function () {
        body.unbind('keydown', handleEscPressed);
        modalEl.remove();
        if (options.backdrop) {
          backdropEl.remove();
        }
      };

      body.bind('keydown', handleEscPressed);

      var ctrl, locals,
        scope = options.scope || $rootScope.$new();

      scope.$title = options.title;
      scope.$modalClose = closeFn;
      scope.$modalCancel = function () {
        var callFn = options.cancel.fn || closeFn;
        callFn.call(this);
        scope.$modalClose();
      };
      scope.$modalSuccess = function () {
        var callFn = options.success.fn || closeFn;
        var ret = callFn.call(this);
        if (typeof ret.then === 'function') {
          ret.then(function(result){
            if (result!==false) { scope.$modalClose(); }
          })
        }else{
          if (ret!==false) {
            scope.$modalClose();
          }
        }
      };
      scope.$modalSuccessLabel = options.success.label;
      scope.$modalCancelLabel = options.cancel.label;

      if (options.controller) {
        locals = angular.extend({$scope: scope}, passedInLocals);
        ctrl = $controller(options.controller, locals);
        // Yes, ngControllerController is not a typo
        modalEl.contents().data('$ngControllerController', ctrl);
      }

      $compile(modalEl)(scope);
      $compile(backdropEl)(scope);
      body.append(modalEl);
      if (options.backdrop) body.append(backdropEl);

      $timeout(function () {
        modalEl.addClass('in');
      }, 200);
    };
  }]);
<|endoftext|>


<commit_before>export default {
  cloneUrl: 'https://github.com/atom/atom.git',
  forkUrl: 'git@github.com:decaffeinate-examples/atom.git',
  useDefaultConfig: true,
  testCommand: `
    set -e
    export NODE_VERSION=6.9.4 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
    if [ -e /sbin/start-stop-daemon ]; then
      /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
    fi
    script/build --create-debian-package --create-rpm-package --compress-artifacts
    script/test
  `,
  expectConversionSuccess: true,
  expectTestSuccess: false,
};
<commit_msg>Clear node_modules at the start of atom tests (#37)<commit_after>export default {
  cloneUrl: 'https://github.com/atom/atom.git',
  forkUrl: 'git@github.com:decaffeinate-examples/atom.git',
  useDefaultConfig: true,
  testCommand: `
    set -e
    rm -rf node_modules
    export NODE_VERSION=6.9.4 DISPLAY=:99.0 CC=clang CXX=clang++ npm_config_clang=1
    if [ -e /sbin/start-stop-daemon ]; then
      /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16
    fi
    script/build --create-debian-package --create-rpm-package --compress-artifacts
    script/test
  `,
  expectConversionSuccess: true,
  expectTestSuccess: false,
};
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var sdk = require('../../../index');
var MatrixClientPeg = require('../../../MatrixClientPeg');
var Modal = require("../../../Modal");
var dis = require("../../../dispatcher");
var rate_limited_func = require('../../../ratelimitedfunc');

var linkify = require('linkifyjs');
var linkifyElement = require('linkifyjs/element');
var linkifyMatrix = require('../../../linkify-matrix');
import AccessibleButton from '../elements/AccessibleButton';
import {CancelButton} from './SimpleRoomHeader';

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomHeader',

    propTypes: {
        room: React.PropTypes.object,
        oobData: React.PropTypes.object,
        editing: React.PropTypes.bool,
        saving: React.PropTypes.bool,
        inRoom: React.PropTypes.bool,
        collapsedRhs: React.PropTypes.bool,
        onSettingsClick: React.PropTypes.func,
        onSaveClick: React.PropTypes.func,
        onSearchClick: React.PropTypes.func,
        onLeaveClick: React.PropTypes.func,
    },

    getDefaultProps: function() {
        return {
            editing: false,
            inRoom: false,
            onSaveClick: function() {},
        };
    },

    componentDidMount: function() {
        var cli = MatrixClientPeg.get();
        cli.on("RoomState.events", this._onRoomStateEvents);

        // When a room name occurs, RoomState.events is fired *before*
        // room.name is updated. So we have to listen to Room.name as well as
        // RoomState.events.
        if (this.props.room) {
            this.props.room.on("Room.name", this._onRoomNameChange);
        }
    },

    componentDidUpdate: function() {
        if (this.refs.topic) {
            linkifyElement(this.refs.topic, linkifyMatrix.options);
        }
    },

    componentWillUnmount: function() {
        if (this.props.room) {
            this.props.room.removeListener("Room.name", this._onRoomNameChange);
        }
        var cli = MatrixClientPeg.get();
        if (cli) {
            cli.removeListener("RoomState.events", this._onRoomStateEvents);
        }
    },

    _onRoomStateEvents: function(event, state) {
        if (!this.props.room || event.getRoomId() != this.props.room.roomId) {
            return;
        }

        // redisplay the room name, topic, etc.
        this._rateLimitedUpdate();
    },

    _rateLimitedUpdate: new rate_limited_func(function() {
        this.forceUpdate();
    }, 500),

    _onRoomNameChange: function(room) {
        this.forceUpdate();
    },

    onAvatarPickerClick: function(ev) {
        if (this.refs.file_label) {
            this.refs.file_label.click();
        }
    },

    onAvatarSelected: function(ev) {
        var self = this;
        var changeAvatar = this.refs.changeAvatar;
        if (!changeAvatar) {
            console.error("No ChangeAvatar found to upload image to!");
            return;
        }
        changeAvatar.onFileSelected(ev).catch(function(err) {
            var errMsg = (typeof err === "string") ? err : (err.error || "");
            var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
            console.error("Failed to set avatar: " + errMsg);
            Modal.createDialog(ErrorDialog, {
                title: "Error",
                description: "Failed to set avatar.",
            });
        }).done();
    },

    onShowRhsClick: function(ev) {
        dis.dispatch({ action: 'show_right_panel' });
    },

    /**
     * After editing the settings, get the new name for the room
     *
     * Returns undefined if we didn't let the user edit the room name
     */
    getEditedName: function() {
        var newName;
        if (this.refs.nameEditor) {
            newName = this.refs.nameEditor.getRoomName();
        }
        return newName;
    },

    /**
     * After editing the settings, get the new topic for the room
     *
     * Returns undefined if we didn't let the user edit the room topic
     */
    getEditedTopic: function() {
        var newTopic;
        if (this.refs.topicEditor) {
            newTopic = this.refs.topicEditor.getTopic();
        }
        return newTopic;
    },

    render: function() {
        var RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
        var ChangeAvatar = sdk.getComponent("settings.ChangeAvatar");
        var TintableSvg = sdk.getComponent("elements.TintableSvg");
        const EmojiText = sdk.getComponent('elements.EmojiText');

        var header;
        var name = null;
        var searchStatus = null;
        var topic_el = null;
        var cancel_button = null;
        var spinner = null;
        var save_button = null;
        var settings_button = null;
        if (this.props.editing) {

            // calculate permissions.  XXX: this should be done on mount or something
            var user_id = MatrixClientPeg.get().credentials.userId;

            var can_set_room_name = this.props.room.currentState.maySendStateEvent(
                'm.room.name', user_id
            );
            var can_set_room_avatar = this.props.room.currentState.maySendStateEvent(
                'm.room.avatar', user_id
            );
            var can_set_room_topic = this.props.room.currentState.maySendStateEvent(
                'm.room.topic', user_id
            );
            var can_set_room_name = this.props.room.currentState.maySendStateEvent(
                'm.room.name', user_id
            );

            save_button = <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</AccessibleButton>;
            cancel_button = <CancelButton onClick={this.props.onCancelClick}/>;
        }

        if (this.props.saving) {
            var Spinner = sdk.getComponent("elements.Spinner");
            spinner =
<Spinner/>
;
        }

        if (can_set_room_name) {
            var RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
            name = <RoomNameEditor ref="nameEditor" room={this.props.room} />;
        }
        else {
            var searchStatus;
            // don't display the search count until the search completes and
            // gives us a valid (possibly zero) searchCount.
            if (this.props.searchInfo && this.props.searchInfo.searchCount !== undefined && this.props.searchInfo.searchCount !== null) {
                searchStatus =
 (~{ this.props.searchInfo.searchCount } results)
;
            }

            // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
            var settingsHint = false;
            var members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
            if (members) {
                if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
                    var name = this.props.room.currentState.getStateEvents('m.room.name', '');
                    if (!name || !name.getContent().name) {
                        settingsHint = true;
                    }
                }
            }

            var roomName = 'Join Room';
            if (this.props.oobData && this.props.oobData.name) {
                roomName = this.props.oobData.name;
            } else if (this.props.room) {
                roomName = this.props.room.name;
            }

            name =

                    <EmojiText element="div" className={ "mx_RoomHeader_nametext " + (settingsHint ? "mx_RoomHeader_settingsHint" : "") } title={ roomName }>{roomName}</EmojiText>
                    { searchStatus }

;
        }

        if (can_set_room_topic) {
            var RoomTopicEditor = sdk.getComponent("rooms.RoomTopicEditor");
            topic_el = <RoomTopicEditor ref="topicEditor" room={this.props.room} />;
        } else {
            var topic;
            if (this.props.room) {
                var ev = this.props.room.currentState.getStateEvents('m.room.topic', '');
                if (ev) {
                    topic = ev.getContent().topic;
                }
            }
            if (topic) {
                topic_el =
{ topic }
;
            }
        }

        var roomAvatar = null;
        if (can_set_room_avatar) {
            roomAvatar = (

                        <ChangeAvatar ref="changeAvatar" room={this.props.room} showUploadSection={false} width={48} height={48} />

                        <input id="avatarInput" type="file" onChange={ this.onAvatarSelected }/>

            );
        }
        else if (this.props.room || (this.props.oobData && this.props.oobData.name)) {
            roomAvatar = (

                    <RoomAvatar room={this.props.room} width={48} height={48} oobData={this.props.oobData} />

            );
        }

        var settings_button;
        if (this.props.onSettingsClick) {
            settings_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings">
                    <TintableSvg src="img/icons-settings-room.svg" width="16" height="16"/>
                </AccessibleButton>;
        }

//        var leave_button;
//        if (this.props.onLeaveClick) {
//            leave_button =
//

//                    <TintableSvg src="img/leave.svg" width="26" height="20"/>
//
;
//        }

        var forget_button;
        if (this.props.onForgetClick) {
            forget_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
                    <TintableSvg src="img/leave.svg" width="26" height="20"/>
                </AccessibleButton>;
        }

        let search_button;
        if (this.props.onSearchClick && this.props.inRoom) {
            search_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
                    <TintableSvg src="img/icons-search.svg" width="35" height="35"/>
                </AccessibleButton>;
        }

        var rightPanel_buttons;
        if (this.props.collapsedRhs) {
            rightPanel_buttons =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="Show panel">
                    <TintableSvg src="img/maximise.svg" width="10" height="16"/>
                </AccessibleButton>;
        }

        var right_row;
        if (!this.props.editing) {
            right_row =

                    { settings_button }
                    { forget_button }
                    { search_button }
                    { rightPanel_buttons }

;
        }

        header =

                        { roomAvatar }

                        { name }
                        { topic_el }

                {spinner}
                {save_button}
                {cancel_button}
                {right_row}

;

        return (

                { header }

        );
    },
});
<commit_msg>conform to Luke's comment https://github.com/matrix-org/matrix-react-sdk/pull/880#discussion_r116257726<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');
var sdk = require('../../../index');
var MatrixClientPeg = require('../../../MatrixClientPeg');
var Modal = require("../../../Modal");
var dis = require("../../../dispatcher");
var rate_limited_func = require('../../../ratelimitedfunc');

var linkify = require('linkifyjs');
var linkifyElement = require('linkifyjs/element');
var linkifyMatrix = require('../../../linkify-matrix');
import AccessibleButton from '../elements/AccessibleButton';
import {CancelButton} from './SimpleRoomHeader';

linkifyMatrix(linkify);

module.exports = React.createClass({
    displayName: 'RoomHeader',

    propTypes: {
        room: React.PropTypes.object,
        oobData: React.PropTypes.object,
        editing: React.PropTypes.bool,
        saving: React.PropTypes.bool,
        inRoom: React.PropTypes.bool,
        collapsedRhs: React.PropTypes.bool,
        onSettingsClick: React.PropTypes.func,
        onSaveClick: React.PropTypes.func,
        onSearchClick: React.PropTypes.func,
        onLeaveClick: React.PropTypes.func,
    },

    getDefaultProps: function() {
        return {
            editing: false,
            inRoom: false,
            onSaveClick: function() {},
        };
    },

    componentDidMount: function() {
        var cli = MatrixClientPeg.get();
        cli.on("RoomState.events", this._onRoomStateEvents);

        // When a room name occurs, RoomState.events is fired *before*
        // room.name is updated. So we have to listen to Room.name as well as
        // RoomState.events.
        if (this.props.room) {
            this.props.room.on("Room.name", this._onRoomNameChange);
        }
    },

    componentDidUpdate: function() {
        if (this.refs.topic) {
            linkifyElement(this.refs.topic, linkifyMatrix.options);
        }
    },

    componentWillUnmount: function() {
        if (this.props.room) {
            this.props.room.removeListener("Room.name", this._onRoomNameChange);
        }
        var cli = MatrixClientPeg.get();
        if (cli) {
            cli.removeListener("RoomState.events", this._onRoomStateEvents);
        }
    },

    _onRoomStateEvents: function(event, state) {
        if (!this.props.room || event.getRoomId() != this.props.room.roomId) {
            return;
        }

        // redisplay the room name, topic, etc.
        this._rateLimitedUpdate();
    },

    _rateLimitedUpdate: new rate_limited_func(function() {
        this.forceUpdate();
    }, 500),

    _onRoomNameChange: function(room) {
        this.forceUpdate();
    },

    onAvatarPickerClick: function(ev) {
        if (this.refs.file_label) {
            this.refs.file_label.click();
        }
    },

    onAvatarSelected: function(ev) {
        var self = this;
        var changeAvatar = this.refs.changeAvatar;
        if (!changeAvatar) {
            console.error("No ChangeAvatar found to upload image to!");
            return;
        }
        changeAvatar.onFileSelected(ev).catch(function(err) {
            var errMsg = (typeof err === "string") ? err : (err.error || "");
            var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
            console.error("Failed to set avatar: " + errMsg);
            Modal.createDialog(ErrorDialog, {
                title: "Error",
                description: "Failed to set avatar.",
            });
        }).done();
    },

    onShowRhsClick: function(ev) {
        dis.dispatch({ action: 'show_right_panel' });
    },

    /**
     * After editing the settings, get the new name for the room
     *
     * Returns undefined if we didn't let the user edit the room name
     */
    getEditedName: function() {
        var newName;
        if (this.refs.nameEditor) {
            newName = this.refs.nameEditor.getRoomName();
        }
        return newName;
    },

    /**
     * After editing the settings, get the new topic for the room
     *
     * Returns undefined if we didn't let the user edit the room topic
     */
    getEditedTopic: function() {
        var newTopic;
        if (this.refs.topicEditor) {
            newTopic = this.refs.topicEditor.getTopic();
        }
        return newTopic;
    },

    render: function() {
        var RoomAvatar = sdk.getComponent("avatars.RoomAvatar");
        var ChangeAvatar = sdk.getComponent("settings.ChangeAvatar");
        var TintableSvg = sdk.getComponent("elements.TintableSvg");
        const EmojiText = sdk.getComponent('elements.EmojiText');

        var header;
        var name = null;
        var searchStatus = null;
        var topic_el = null;
        var cancel_button = null;
        var spinner = null;
        var save_button = null;
        var settings_button = null;
        if (this.props.editing) {

            // calculate permissions.  XXX: this should be done on mount or something
            var user_id = MatrixClientPeg.get().credentials.userId;

            var can_set_room_name = this.props.room.currentState.maySendStateEvent(
                'm.room.name', user_id
            );
            var can_set_room_avatar = this.props.room.currentState.maySendStateEvent(
                'm.room.avatar', user_id
            );
            var can_set_room_topic = this.props.room.currentState.maySendStateEvent(
                'm.room.topic', user_id
            );
            var can_set_room_name = this.props.room.currentState.maySendStateEvent(
                'm.room.name', user_id
            );

            save_button = <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</AccessibleButton>;
            cancel_button = <CancelButton onClick={this.props.onCancelClick}/>;
        }

        if (this.props.saving) {
            var Spinner = sdk.getComponent("elements.Spinner");
            spinner =
<Spinner/>
;
        }

        if (can_set_room_name) {
            var RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
            name = <RoomNameEditor ref="nameEditor" room={this.props.room} />;
        }
        else {
            var searchStatus;
            // don't display the search count until the search completes and
            // gives us a valid (possibly zero) searchCount.
            if (this.props.searchInfo && this.props.searchInfo.searchCount !== undefined && this.props.searchInfo.searchCount !== null) {
                searchStatus =
 (~{ this.props.searchInfo.searchCount } results)
;
            }

            // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
            var settingsHint = false;
            var members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
            if (members) {
                if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
                    var name = this.props.room.currentState.getStateEvents('m.room.name', '');
                    if (!name || !name.getContent().name) {
                        settingsHint = true;
                    }
                }
            }

            var roomName = 'Join Room';
            if (this.props.oobData && this.props.oobData.name) {
                roomName = this.props.oobData.name;
            } else if (this.props.room) {
                roomName = this.props.room.name;
            }

            name =

                    <EmojiText element="div" className={"mx_RoomHeader_nametext " + (settingsHint ? "mx_RoomHeader_settingsHint" : "")} title={roomName}>{ roomName }</EmojiText>
                    { searchStatus }

;
        }

        if (can_set_room_topic) {
            var RoomTopicEditor = sdk.getComponent("rooms.RoomTopicEditor");
            topic_el = <RoomTopicEditor ref="topicEditor" room={this.props.room} />;
        } else {
            var topic;
            if (this.props.room) {
                var ev = this.props.room.currentState.getStateEvents('m.room.topic', '');
                if (ev) {
                    topic = ev.getContent().topic;
                }
            }
            if (topic) {
                topic_el =
{ topic }
;
            }
        }

        var roomAvatar = null;
        if (can_set_room_avatar) {
            roomAvatar = (

                        <ChangeAvatar ref="changeAvatar" room={this.props.room} showUploadSection={false} width={48} height={48} />

                        <input id="avatarInput" type="file" onChange={ this.onAvatarSelected }/>

            );
        }
        else if (this.props.room || (this.props.oobData && this.props.oobData.name)) {
            roomAvatar = (

                    <RoomAvatar room={this.props.room} width={48} height={48} oobData={this.props.oobData} />

            );
        }

        var settings_button;
        if (this.props.onSettingsClick) {
            settings_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings">
                    <TintableSvg src="img/icons-settings-room.svg" width="16" height="16"/>
                </AccessibleButton>;
        }

//        var leave_button;
//        if (this.props.onLeaveClick) {
//            leave_button =
//

//                    <TintableSvg src="img/leave.svg" width="26" height="20"/>
//
;
//        }

        var forget_button;
        if (this.props.onForgetClick) {
            forget_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
                    <TintableSvg src="img/leave.svg" width="26" height="20"/>
                </AccessibleButton>;
        }

        let search_button;
        if (this.props.onSearchClick && this.props.inRoom) {
            search_button =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
                    <TintableSvg src="img/icons-search.svg" width="35" height="35"/>
                </AccessibleButton>;
        }

        var rightPanel_buttons;
        if (this.props.collapsedRhs) {
            rightPanel_buttons =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="Show panel">
                    <TintableSvg src="img/maximise.svg" width="10" height="16"/>
                </AccessibleButton>;
        }

        var right_row;
        if (!this.props.editing) {
            right_row =

                    { settings_button }
                    { forget_button }
                    { search_button }
                    { rightPanel_buttons }

;
        }

        header =

                        { roomAvatar }

                        { name }
                        { topic_el }

                {spinner}
                {save_button}
                {cancel_button}
                {right_row}

;

        return (

                { header }

        );
    },
});
<|endoftext|>


<commit_before>"use strict";

var http = require('http')
  , stewardess = require('./index')

var handle = stewardess(
  function(req, res, next) {
    req.startTime = process.hrtime();
    next();
  },
  function(req, res, next) {
    console.log(req.url + ' requested');
    next();
  },
  function(req, res, next) {
    if (req.headers && /^curl/.test(req.headers['user-agent'])) {
      req.isCurl = true;
    }
    next();
  },
  function(req, res, next) {
    if (req.isCurl) {
      res.end('yur usin curl!');
    } else {
      res.end('oh hai');
    }
    next();
  }
)
.before(function(req, res) {
  req.i = req.i + 1 || 1;
  req.lastStart = process.hrtime();
})
.after(function(req, res) {
  var t = process.hrtime(req.lastStart);
  console.log('middleware ' + req.i + ' took %d seconds and %d nanoseconds', t[0], t[1]);
})
.done(function(req, res) {
  var t = process.hrtime(req.startTime);
  console.log(req.url + ' served in %d seconds and %d nanoseconds', t[0], t[1]);
})
.done(function(req, res) {
  console.log(req.url + ' served with status ' + res.statusCode);
  console.log();
})
.bind();

http.Server(handle).listen(8080);
<commit_msg>fixing herp derp<commit_after>"use strict";

var http = require('http')
  , stewardess = require('../index')

var handle = stewardess(
  function(req, res, next) {
    req.startTime = process.hrtime();
    next();
  },
  function(req, res, next) {
    console.log(req.url + ' requested');
    next();
  },
  function(req, res, next) {
    if (req.headers && /^curl/.test(req.headers['user-agent'])) {
      req.isCurl = true;
    }
    next();
  },
  function(req, res, next) {
    if (req.isCurl) {
      res.end('yur usin curl!');
    } else {
      res.end('oh hai');
    }
    next();
  }
)
.before(function(req, res) {
  req.i = req.i + 1 || 1;
  req.lastStart = process.hrtime();
})
.after(function(req, res) {
  var t = process.hrtime(req.lastStart);
  console.log('middleware ' + req.i + ' took %d seconds and %d nanoseconds', t[0], t[1]);
})
.done(function(req, res) {
  var t = process.hrtime(req.startTime);
  console.log(req.url + ' served in %d seconds and %d nanoseconds', t[0], t[1]);
})
.done(function(req, res) {
  console.log(req.url + ' served with status ' + res.statusCode);
  console.log();
})
.bind();

http.Server(handle).listen(8080);
<|endoftext|>


<commit_before>describe('resizable-sidebar.js', function () {
  beforeEach(function () {
    var html = ''
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '              '
    html += '
'
    html += '
'
    html += '              '
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'

    setFixtures(html);
    $('div.container-fluid.resizable-sidebar').resizableSidebar();
    spyOn($, 'ajax'); // we're not testing the backend
  });

  it('hide sidebar', function () {
    $('.resize-left').click();

    expect($('#left')).not.toHaveClass('col-md-2');
    expect($('#left')).not.toHaveClass('col-md-pull-10');
    expect($('#left')).toHaveClass('hidden-lg');
    expect($('#left')).toHaveClass('hidden-md');

    expect($('#right')).not.toHaveClass('col-md-10');
    expect($('#right')).not.toHaveClass('col-md-push-2');
    expect($('#right')).toHaveClass('col-md-12');
    expect($('#right')).toHaveClass('col-md-push-0');
  });

  it('show sidebar', function () {
    $('.resize-left').click();
    $('.resize-right').click();

    expect($('#left')).not.toHaveClass('hidden-md');
    expect($('#left')).not.toHaveClass('hidden-lg');
    expect($('#left')).toHaveClass('col-md-2');
    expect($('#left')).toHaveClass('col-md-pull-10');

    expect($('#right')).not.toHaveClass('col-md-12');
    expect($('#right')).not.toHaveClass('col-md-push-0');
    expect($('#right')).toHaveClass('col-md-10');
    expect($('#right')).toHaveClass('col-md-push-2');
  });

  it('broaden sidebar', function () {
    for (var i=2; i<=5; i++) {
      expect($('#left')).not.toHaveClass('col-md-' + (i-1));
      expect($('#left')).not.toHaveClass('col-md-pull-' + (11-i));
      expect($('#left')).toHaveClass('col-md-' + i);
      expect($('#left')).toHaveClass('col-md-pull-' + (12-i));

      expect($('#right')).not.toHaveClass('col-md-' + (13-i));
      expect($('#right')).not.toHaveClass('col-md-push-' + (i+1));
      expect($('#right')).toHaveClass('col-md-' + (12-i));
      expect($('#right')).toHaveClass('col-md-push-' + i);

      $('.resize-right').click();
    }
  });

  it('narrow sidebar', function () {
    for (var i=5; i<=2; i--) {
      expect($('#left')).not.toHaveClass('col-md-' + (i+1));
      expect($('#left')).not.toHaveClass('col-md-pull-' + (13-i));
      expect($('#left')).toHaveClass('col-md-' + i);
      expect($('#left')).toHaveClass('col-md-pull-' + (12-i));

      expect($('#right')).not.toHaveClass('col-md-' + (11-i));
      expect($('#right')).not.toHaveClass('col-md-push-' + (i-1));
      expect($('#right')).toHaveClass('col-md-' + (12-i));
      expect($('#right')).toHaveClass('col-md-push-' + i);

      $('.resize-right').click();
    }
  });

  it('extend sidebar limit', function () {
    for (var i=0; i<5; i++) {
      $('.resize-right').click();
    }
    expect($('#left')).toHaveClass('col-md-5');
    expect($('#left')).toHaveClass('col-md-pull-7');
    expect($('#right')).toHaveClass('col-md-7');
    expect($('#right')).toHaveClass('col-md-push-5');
  });

});<commit_msg>fix resizable_sidebar_spec - narrow sidebar<commit_after>describe('resizable-sidebar.js', function () {
  beforeEach(function () {
    var html = ''
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '              '
    html += '
'
    html += '
'
    html += '              '
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'
    html += '
'

    setFixtures(html);
    $('div.container-fluid.resizable-sidebar').resizableSidebar();
    spyOn($, 'ajax'); // we're not testing the backend
  });

  it('hide sidebar', function () {
    $('.resize-left').click();

    expect($('#left')).not.toHaveClass('col-md-2');
    expect($('#left')).not.toHaveClass('col-md-pull-10');
    expect($('#left')).toHaveClass('hidden-lg');
    expect($('#left')).toHaveClass('hidden-md');

    expect($('#right')).not.toHaveClass('col-md-10');
    expect($('#right')).not.toHaveClass('col-md-push-2');
    expect($('#right')).toHaveClass('col-md-12');
    expect($('#right')).toHaveClass('col-md-push-0');
  });

  it('show sidebar', function () {
    $('.resize-left').click();
    $('.resize-right').click();

    expect($('#left')).not.toHaveClass('hidden-md');
    expect($('#left')).not.toHaveClass('hidden-lg');
    expect($('#left')).toHaveClass('col-md-2');
    expect($('#left')).toHaveClass('col-md-pull-10');

    expect($('#right')).not.toHaveClass('col-md-12');
    expect($('#right')).not.toHaveClass('col-md-push-0');
    expect($('#right')).toHaveClass('col-md-10');
    expect($('#right')).toHaveClass('col-md-push-2');
  });

  it('broaden sidebar', function () {
    for (var i=2; i<=5; i++) {
      expect($('#left')).not.toHaveClass('col-md-' + (i-1));
      expect($('#left')).not.toHaveClass('col-md-pull-' + (11-i));
      expect($('#left')).toHaveClass('col-md-' + i);
      expect($('#left')).toHaveClass('col-md-pull-' + (12-i));

      expect($('#right')).not.toHaveClass('col-md-' + (13-i));
      expect($('#right')).not.toHaveClass('col-md-push-' + (i+1));
      expect($('#right')).toHaveClass('col-md-' + (12-i));
      expect($('#right')).toHaveClass('col-md-push-' + i);

      $('.resize-right').click();
    }
  });

  it('narrow sidebar', function () {
    for (var i=2; i<5; i++) {
      $('.resize-right').click();
    }

    for (var i=5; i>=2; i--) {
      expect($('#left')).not.toHaveClass('col-md-' + (i+1));
      expect($('#left')).not.toHaveClass('col-md-pull-' + (13-i));
      expect($('#left')).toHaveClass('col-md-' + i);
      expect($('#left')).toHaveClass('col-md-pull-' + (12-i));

      expect($('#right')).not.toHaveClass('col-md-' + (11-i));
      expect($('#right')).not.toHaveClass('col-md-push-' + (i-1));
      expect($('#right')).toHaveClass('col-md-' + (12-i));
      expect($('#right')).toHaveClass('col-md-push-' + i);

      $('.resize-left').click();
    }
  });

  it('extend sidebar limit', function () {
    for (var i=0; i<5; i++) {
      $('.resize-right').click();
    }
    expect($('#left')).toHaveClass('col-md-5');
    expect($('#left')).toHaveClass('col-md-pull-7');
    expect($('#right')).toHaveClass('col-md-7');
    expect($('#right')).toHaveClass('col-md-push-5');
  });

});
<|endoftext|>


<commit_before>"use strict";

let Promise = require("bluebird");
let coroutine = Promise.coroutine;
let assert = require("chai").assert;
let sessions = require("./util/shared").sessions;
let data = require("./util/shared").data;
let delay = require("./util/delay");

describe("removing a user from a team", function() {

    it("should remove the user from the team", coroutine(function*() {
        yield sessions[0]("DELETE",
            "/teams/current/users/id/" + data.users[1]._id
        );
        let users = yield sessions[0]("GET", "/teams/current/users");
        assert.equal(users.length, 1, "the user was deleted");
        assert.equal(users[0]._id, data.users[0]._id,
            "the correct user was deleted"
        );
    }));

    it("should remove the user from groups", coroutine(function*() {
        let user1 = yield sessions[0]("GET", "/users/id/" + data.users[1]._id);
        assert.equal(user1.groups.length, 0, "user was removed from all groups");
    }));

    before(coroutine(function*() {
        yield sessions[0]("POST", "/announcements", {
            content: "stuff",
            audience: {
                users: [data.users[0]._id, data.users[1]._id],
                groups: [],
            },
        });
    }));

    it("should remove the user from announcement hidden groups", coroutine(function*() {
        let announcements = yield sessions[0]("GET", "/announcements");
        assert.equal(announcements[0].audience.users.length, 1,
            "a user was removed from announcement hidden group"
        );
        assert.equal(announcements[0].audience.users[0], data.users[0]._id,
            "the correct user was removed from announcement hidden group"
        );
    }));

    // TODO: add tests for more hidden groups other than just in announcements

});
<commit_msg>Fix test<commit_after>"use strict";

let Promise = require("bluebird");
let coroutine = Promise.coroutine;
let assert = require("chai").assert;
let sessions = require("./util/shared").sessions;
let data = require("./util/shared").data;
let delay = require("./util/delay");

describe("removing a user from a team", function() {

    it("should remove the user from the team", coroutine(function*() {
        yield sessions[0]("DELETE",
            "/teams/current/users/id/" + data.users[1]._id
        );
        let users = yield sessions[0]("GET", "/teams/current/users");
        assert.equal(users.length, 1, "the user was deleted");
        assert.equal(users[0]._id, data.users[0]._id,
            "the correct user was deleted"
        );
    }));

    it("should remove the user from groups", coroutine(function*() {
        let user1 = yield sessions[0]("GET", "/users/id/" + data.users[1]._id);
        assert.equal(user1.groups.length, 0, "user was removed from all groups");
    }));

    before(coroutine(function*() {
        yield sessions[0]("POST", "/announcements", {
            content: "stuff",
            audience: {
                users: [data.users[0]._id, data.users[1]._id],
                groups: [],
            },
        });
    }));

    it("should remove the user from announcement hidden groups", coroutine(function*() {
        let announcements = yield sessions[0]("GET", "/announcements");
        assert.equal(announcements[0].audience.users.length, 1,
            "a user was removed from announcement hidden group"
        );
        assert.equal(announcements[0].audience.users[0]._id, data.users[0]._id,
            "the correct user was removed from announcement hidden group"
        );
    }));

    // TODO: add tests for more hidden groups other than just in announcements

});
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

const CBG_READINGS_ONE_DAY = 86400000 / (1000 * 60 * 5);

import _ from 'lodash';
import bows from 'bows';
import { extent } from 'd3-array';
import { scaleLinear } from 'd3-scale';
import { utcDay } from 'd3-time';
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import * as actions from '../../redux/actions/';
import CBGTrendsContainer from './CBGTrendsContainer';
import * as datetime from '../../utils/datetime';

export class TrendsContainer extends React.Component {
  static propTypes = {
    activeDays: PropTypes.shape({
      monday: PropTypes.bool.isRequired,
      tuesday: PropTypes.bool.isRequired,
      wednesday: PropTypes.bool.isRequired,
      thursday: PropTypes.bool.isRequired,
      friday: PropTypes.bool.isRequired,
      saturday: PropTypes.bool.isRequired,
      sunday: PropTypes.bool.isRequired,
    }).isRequired,
    // new data structure to replace bgClasses
    bgBounds: PropTypes.shape({
      veryHighThreshold: PropTypes.number.isRequired,
      targetUpperBound: PropTypes.number.isRequired,
      targetLowerBound: PropTypes.number.isRequired,
      veryLowThreshold: PropTypes.number.isRequired,
    }).isRequired,
    // legacy data structure for representing target range, &c
    // needed for passed-in legacy tideline smbg component but will phase out!
    bgClasses: PropTypes.shape({
      'very-high': PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      high: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      target: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      low: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      'very-low': PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
    }).isRequired,
    bgUnits: PropTypes.oneOf(['mg/dL', 'mmol/L']).isRequired,
    extentSize: PropTypes.oneOf([7, 14, 28]).isRequired,
    initialDatetimeLocation: PropTypes.string,
    showingSmbg: PropTypes.bool.isRequired,
    showingCbg: PropTypes.bool.isRequired,
    smbgRangeOverlay: PropTypes.bool.isRequired,
    smbgGrouped: PropTypes.bool.isRequired,
    smbgLines: PropTypes.bool.isRequired,
    smbgTrendsComponent: PropTypes.func.isRequired,
    timePrefs: PropTypes.shape({
      timezoneAware: PropTypes.bool.isRequired,
      timezoneName: PropTypes.string.isRequired,
    }).isRequired,
    yScaleClampTop: PropTypes.object.isRequired,
    // data (crossfilter dimensions)
    cbgByDate: PropTypes.object.isRequired,
    cbgByDayOfWeek: PropTypes.object.isRequired,
    smbgByDate: PropTypes.object.isRequired,
    smbgByDayOfWeek: PropTypes.object.isRequired,
    // handlers
    onDatetimeLocationChange: PropTypes.func.isRequired,
    onSelectDay: PropTypes.func.isRequired,
    onSwitchBgDataSource: PropTypes.func.isRequired,
    // viz state
    viz: PropTypes.shape({
      trends: PropTypes.shape({
        focusedCbgSlice: PropTypes.object,
        focusedCbgSliceKeys: PropTypes.array,
        touched: PropTypes.bool.isRequired,
      }).isRequired,
    }).isRequired,
    // actions
    focusTrendsCbgSlice: PropTypes.func.isRequired,
    markTrendsViewed: PropTypes.func.isRequired,
    unfocusTrendsCbgSlice: PropTypes.func.isRequired,
  };

  static defaultProps = {
    yScaleClampTop: {
      'mg/dL': 400,
      'mmol/L': 22.5,
    },
  };

  constructor(props) {
    super(props);
    this.log = bows('TrendsContainer');
    this.state = {
      currentCbgData: [],
      currentSmbgData: [],
      dateDomain: null,
      mostRecent: null,
      xScale: null,
      yScale: null,
    };
  }

  componentWillMount() {
    // find BG domain (for yScale construction)
    const { cbgByDate, cbgByDayOfWeek, smbgByDate, smbgByDayOfWeek } = this.props;
    const allBg = cbgByDate.filterAll().top(Infinity).concat(smbgByDate.filterAll().top(Infinity));
    const bgDomain = extent(allBg, d => d.value);

    const { bgBounds, bgUnits, yScaleClampTop } = this.props;
    const upperBound = yScaleClampTop[bgUnits];
    const yScaleDomain = [bgDomain[0], upperBound];
    if (bgDomain[0] > bgBounds.targetLowerBound) {
      yScaleDomain[0] = bgBounds.targetLowerBound;
    }
    const yScale = scaleLinear().domain(yScaleDomain).clamp(true);

    // find initial date domain (based on initialDatetimeLocation or current time)
    const { extentSize, initialDatetimeLocation, timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    const mostRecent = datetime.timezoneAwareCeiling(new Date().valueOf(), timezone);
    const end = initialDatetimeLocation ?
      datetime.timezoneAwareCeiling(initialDatetimeLocation, timezone) : mostRecent;
    const start = utcDay.offset(end, -extentSize);
    const dateDomain = [start.toISOString(), end.toISOString()];

    // filter data according to current activeDays and dateDomain
    this.initialFiltering(cbgByDate, cbgByDayOfWeek, dateDomain);
    this.initialFiltering(smbgByDate, smbgByDayOfWeek, dateDomain);
    this.setState({
      bgDomain: { lo: bgDomain[0], hi: bgDomain[1] },
      currentCbgData: cbgByDate.top(Infinity).reverse(),
      currentSmbgData: smbgByDate.top(Infinity).reverse(),
      dateDomain: { start: dateDomain[0], end: dateDomain[1] },
      mostRecent: mostRecent.toISOString(),
      xScale: scaleLinear().domain([0, 864e5]),
      yScale,
    }, this.determineDataToShow);
    this.props.onDatetimeLocationChange(dateDomain, end === mostRecent);
  }

  /*
   * NB: we don't do as much here as one might expect
   * because we're using the "expose component functions"
   * strategy of communicating between components
   * (https://facebook.github.io/react/tips/expose-component-functions.html)
   * this is the legacy of blip's interface with the d3.chart-architected
   * smbg version of trends view and thus only remains
   * as a temporary compatibility interface
   */
  componentWillReceiveProps(nextProps) {
    if (!_.isEqual(nextProps.activeDays, this.props.activeDays)) {
      const { cbgByDayOfWeek, smbgByDayOfWeek } = this.props;
      this.refilterByDayOfWeek(cbgByDayOfWeek, nextProps.activeDays);
      this.refilterByDayOfWeek(smbgByDayOfWeek, nextProps.activeDays);
      this.setState({
        currentCbgData: cbgByDayOfWeek.top(Infinity).reverse(),
        currentSmbgData: smbgByDayOfWeek.top(Infinity).reverse(),
      });
    }
  }

  getCurrentDay() {
    const { timePrefs } = this.props;
    const { dateDomain: { end } } = this.state;
    return datetime.localNoonBeforeTimestamp(
      end,
      datetime.getTimezoneFromTimePrefs(timePrefs)
    ).toISOString();
  }

  setExtent(newDomain) {
    const { cbgByDate, smbgByDate } = this.props;
    const { mostRecent } = this.state;
    this.refilterByDate(cbgByDate, newDomain);
    this.refilterByDate(smbgByDate, newDomain);
    this.setState({
      currentCbgData: cbgByDate.top(Infinity).reverse(),
      currentSmbgData: smbgByDate.top(Infinity).reverse(),
      dateDomain: { start: newDomain[0], end: newDomain[1] },
    });
    this.props.onDatetimeLocationChange(newDomain, newDomain[1] >= mostRecent);
  }

  goBack() {
    const { dateDomain: { start: newEnd }, mostRecent } = this.state;
    const { timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    const start = datetime.timezoneAwareOffset(newEnd, timezone, {
      amount: -this.props.extentSize,
      units: 'days',
    }).toISOString();
    const newDomain = [start, newEnd];
    this.setExtent(newDomain);
  }

  goForward() {
    const { dateDomain: { end: newStart }, mostRecent } = this.state;
    const end = utcDay.offset(new Date(newStart), this.props.extentSize).toISOString();
    const newDomain = [newStart, end];
    this.setExtent(newDomain);
  }

  goToMostRecent() {
    const { mostRecent: end } = this.state;
    const start = utcDay.offset(new Date(end), -this.props.extentSize).toISOString();
    const newDomain = [start, end];
    this.setExtent(newDomain);
  }

  refilterByDate(dataByDate, dateDomain) {
    dataByDate.filter(dateDomain);
  }

  refilterByDayOfWeek(dataByDayOfWeek, activeDays) {
    dataByDayOfWeek.filterFunction(this.filterActiveDaysFn(activeDays));
  }

  initialFiltering(dataByDate, dataByDayOfWeek, dateDomain) {
    const { activeDays } = this.props;
    // clear old filters
    dataByDayOfWeek.filterAll();

    // filter by day of week (Monday, Tuesday, etc.)
    dataByDayOfWeek.filterFunction(this.filterActiveDaysFn(activeDays));

    // filter within date domain
    dataByDate.filter(dateDomain);
  }

  filterActiveDaysFn(activeDays) {
    return (d) => (activeDays[d]);
  }

  determineDataToShow() {
    const { viz: { trends: { touched } } } = this.props;
    if (touched) {
      return;
    }
    const { currentCbgData } = this.state;
    const { extentSize, showingCbg } = this.props;
    const minimumCbgs = (extentSize * CBG_READINGS_ONE_DAY) / 2;
    if (showingCbg && currentCbgData.length < minimumCbgs) {
      this.props.onSwitchBgDataSource();
    }
    this.props.markTrendsViewed();
  }

  render() {
    const { timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    if (this.props.showingSmbg) {
      const { smbgTrendsComponent: SMBGTrendsContainer } = this.props;
      return (
        <SMBGTrendsContainer
          bgClasses={this.props.bgClasses}
          bgDomain={[this.state.bgDomain.lo, this.state.bgDomain.hi]}
          bgUnits={this.props.bgUnits}
          boxOverlay={this.props.smbgRangeOverlay}
          data={this.state.currentSmbgData}
          grouped={this.props.smbgGrouped}
          onSelectDay={this.props.onSelectDay}
          showingLines={this.props.smbgLines}
          timezone={timezone}
        />
      );
    } else if (this.props.showingCbg) {
      return (
        <CBGTrendsContainer
          bgBounds={this.props.bgBounds}
          bgUnits={this.props.bgUnits}
          data={this.state.currentCbgData}
          focusedSlice={this.props.viz.trends.focusedCbgSlice}
          focusedSliceKeys={this.props.viz.trends.focusedCbgSliceKeys}
          focusSlice={this.props.focusTrendsCbgSlice}
          unfocusSlice={this.props.unfocusTrendsCbgSlice}
          timezone={timezone}
          xScale={this.state.xScale}
          yScale={this.state.yScale}
        />
      );
    }
    return null;
  }
}

export function mapStateToProps(state) {
  return {
    viz: state.viz,
  };
}

export function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    focusTrendsCbgSlice: actions.focusTrendsCbgSlice,
    markTrendsViewed: actions.markTrendsViewed,
    unfocusTrendsCbgSlice: actions.unfocusTrendsCbgSlice,
  }, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps,
  (stateProps, dispatchProps, ownProps) => (Object.assign({}, ownProps, stateProps, dispatchProps)),
  { withRef: true },
)(TrendsContainer);
<commit_msg>two little 🍬 for the ESLint 👹<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

const CBG_READINGS_ONE_DAY = 86400000 / (1000 * 60 * 5);

import _ from 'lodash';
import bows from 'bows';
import { extent } from 'd3-array';
import { scaleLinear } from 'd3-scale';
import { utcDay } from 'd3-time';
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import * as actions from '../../redux/actions/';
import CBGTrendsContainer from './CBGTrendsContainer';
import * as datetime from '../../utils/datetime';

export class TrendsContainer extends React.Component {
  static propTypes = {
    activeDays: PropTypes.shape({
      monday: PropTypes.bool.isRequired,
      tuesday: PropTypes.bool.isRequired,
      wednesday: PropTypes.bool.isRequired,
      thursday: PropTypes.bool.isRequired,
      friday: PropTypes.bool.isRequired,
      saturday: PropTypes.bool.isRequired,
      sunday: PropTypes.bool.isRequired,
    }).isRequired,
    // new data structure to replace bgClasses
    bgBounds: PropTypes.shape({
      veryHighThreshold: PropTypes.number.isRequired,
      targetUpperBound: PropTypes.number.isRequired,
      targetLowerBound: PropTypes.number.isRequired,
      veryLowThreshold: PropTypes.number.isRequired,
    }).isRequired,
    // legacy data structure for representing target range, &c
    // needed for passed-in legacy tideline smbg component but will phase out!
    bgClasses: PropTypes.shape({
      'very-high': PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      high: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      target: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      low: PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
      'very-low': PropTypes.shape({ boundary: PropTypes.number.isRequired }).isRequired,
    }).isRequired,
    bgUnits: PropTypes.oneOf(['mg/dL', 'mmol/L']).isRequired,
    extentSize: PropTypes.oneOf([7, 14, 28]).isRequired,
    initialDatetimeLocation: PropTypes.string,
    showingSmbg: PropTypes.bool.isRequired,
    showingCbg: PropTypes.bool.isRequired,
    smbgRangeOverlay: PropTypes.bool.isRequired,
    smbgGrouped: PropTypes.bool.isRequired,
    smbgLines: PropTypes.bool.isRequired,
    smbgTrendsComponent: PropTypes.func.isRequired,
    timePrefs: PropTypes.shape({
      timezoneAware: PropTypes.bool.isRequired,
      timezoneName: PropTypes.string.isRequired,
    }).isRequired,
    yScaleClampTop: PropTypes.object.isRequired,
    // data (crossfilter dimensions)
    cbgByDate: PropTypes.object.isRequired,
    cbgByDayOfWeek: PropTypes.object.isRequired,
    smbgByDate: PropTypes.object.isRequired,
    smbgByDayOfWeek: PropTypes.object.isRequired,
    // handlers
    onDatetimeLocationChange: PropTypes.func.isRequired,
    onSelectDay: PropTypes.func.isRequired,
    onSwitchBgDataSource: PropTypes.func.isRequired,
    // viz state
    viz: PropTypes.shape({
      trends: PropTypes.shape({
        focusedCbgSlice: PropTypes.object,
        focusedCbgSliceKeys: PropTypes.array,
        touched: PropTypes.bool.isRequired,
      }).isRequired,
    }).isRequired,
    // actions
    focusTrendsCbgSlice: PropTypes.func.isRequired,
    markTrendsViewed: PropTypes.func.isRequired,
    unfocusTrendsCbgSlice: PropTypes.func.isRequired,
  };

  static defaultProps = {
    yScaleClampTop: {
      'mg/dL': 400,
      'mmol/L': 22.5,
    },
  };

  constructor(props) {
    super(props);
    this.log = bows('TrendsContainer');
    this.state = {
      currentCbgData: [],
      currentSmbgData: [],
      dateDomain: null,
      mostRecent: null,
      xScale: null,
      yScale: null,
    };
  }

  componentWillMount() {
    // find BG domain (for yScale construction)
    const { cbgByDate, cbgByDayOfWeek, smbgByDate, smbgByDayOfWeek } = this.props;
    const allBg = cbgByDate.filterAll().top(Infinity).concat(smbgByDate.filterAll().top(Infinity));
    const bgDomain = extent(allBg, d => d.value);

    const { bgBounds, bgUnits, yScaleClampTop } = this.props;
    const upperBound = yScaleClampTop[bgUnits];
    const yScaleDomain = [bgDomain[0], upperBound];
    if (bgDomain[0] > bgBounds.targetLowerBound) {
      yScaleDomain[0] = bgBounds.targetLowerBound;
    }
    const yScale = scaleLinear().domain(yScaleDomain).clamp(true);

    // find initial date domain (based on initialDatetimeLocation or current time)
    const { extentSize, initialDatetimeLocation, timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    const mostRecent = datetime.timezoneAwareCeiling(new Date().valueOf(), timezone);
    const end = initialDatetimeLocation ?
      datetime.timezoneAwareCeiling(initialDatetimeLocation, timezone) : mostRecent;
    const start = utcDay.offset(end, -extentSize);
    const dateDomain = [start.toISOString(), end.toISOString()];

    // filter data according to current activeDays and dateDomain
    this.initialFiltering(cbgByDate, cbgByDayOfWeek, dateDomain);
    this.initialFiltering(smbgByDate, smbgByDayOfWeek, dateDomain);
    this.setState({
      bgDomain: { lo: bgDomain[0], hi: bgDomain[1] },
      currentCbgData: cbgByDate.top(Infinity).reverse(),
      currentSmbgData: smbgByDate.top(Infinity).reverse(),
      dateDomain: { start: dateDomain[0], end: dateDomain[1] },
      mostRecent: mostRecent.toISOString(),
      xScale: scaleLinear().domain([0, 864e5]),
      yScale,
    }, this.determineDataToShow);
    this.props.onDatetimeLocationChange(dateDomain, end === mostRecent);
  }

  /*
   * NB: we don't do as much here as one might expect
   * because we're using the "expose component functions"
   * strategy of communicating between components
   * (https://facebook.github.io/react/tips/expose-component-functions.html)
   * this is the legacy of blip's interface with the d3.chart-architected
   * smbg version of trends view and thus only remains
   * as a temporary compatibility interface
   */
  componentWillReceiveProps(nextProps) {
    if (!_.isEqual(nextProps.activeDays, this.props.activeDays)) {
      const { cbgByDayOfWeek, smbgByDayOfWeek } = this.props;
      this.refilterByDayOfWeek(cbgByDayOfWeek, nextProps.activeDays);
      this.refilterByDayOfWeek(smbgByDayOfWeek, nextProps.activeDays);
      this.setState({
        currentCbgData: cbgByDayOfWeek.top(Infinity).reverse(),
        currentSmbgData: smbgByDayOfWeek.top(Infinity).reverse(),
      });
    }
  }

  getCurrentDay() {
    const { timePrefs } = this.props;
    const { dateDomain: { end } } = this.state;
    return datetime.localNoonBeforeTimestamp(
      end,
      datetime.getTimezoneFromTimePrefs(timePrefs)
    ).toISOString();
  }

  setExtent(newDomain) {
    const { cbgByDate, smbgByDate } = this.props;
    const { mostRecent } = this.state;
    this.refilterByDate(cbgByDate, newDomain);
    this.refilterByDate(smbgByDate, newDomain);
    this.setState({
      currentCbgData: cbgByDate.top(Infinity).reverse(),
      currentSmbgData: smbgByDate.top(Infinity).reverse(),
      dateDomain: { start: newDomain[0], end: newDomain[1] },
    });
    this.props.onDatetimeLocationChange(newDomain, newDomain[1] >= mostRecent);
  }

  goBack() {
    const { dateDomain: { start: newEnd } } = this.state;
    const { timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    const start = datetime.timezoneAwareOffset(newEnd, timezone, {
      amount: -this.props.extentSize,
      units: 'days',
    }).toISOString();
    const newDomain = [start, newEnd];
    this.setExtent(newDomain);
  }

  goForward() {
    const { dateDomain: { end: newStart } } = this.state;
    const end = utcDay.offset(new Date(newStart), this.props.extentSize).toISOString();
    const newDomain = [newStart, end];
    this.setExtent(newDomain);
  }

  goToMostRecent() {
    const { mostRecent: end } = this.state;
    const start = utcDay.offset(new Date(end), -this.props.extentSize).toISOString();
    const newDomain = [start, end];
    this.setExtent(newDomain);
  }

  refilterByDate(dataByDate, dateDomain) {
    dataByDate.filter(dateDomain);
  }

  refilterByDayOfWeek(dataByDayOfWeek, activeDays) {
    dataByDayOfWeek.filterFunction(this.filterActiveDaysFn(activeDays));
  }

  initialFiltering(dataByDate, dataByDayOfWeek, dateDomain) {
    const { activeDays } = this.props;
    // clear old filters
    dataByDayOfWeek.filterAll();

    // filter by day of week (Monday, Tuesday, etc.)
    dataByDayOfWeek.filterFunction(this.filterActiveDaysFn(activeDays));

    // filter within date domain
    dataByDate.filter(dateDomain);
  }

  filterActiveDaysFn(activeDays) {
    return (d) => (activeDays[d]);
  }

  determineDataToShow() {
    const { viz: { trends: { touched } } } = this.props;
    if (touched) {
      return;
    }
    const { currentCbgData } = this.state;
    const { extentSize, showingCbg } = this.props;
    const minimumCbgs = (extentSize * CBG_READINGS_ONE_DAY) / 2;
    if (showingCbg && currentCbgData.length < minimumCbgs) {
      this.props.onSwitchBgDataSource();
    }
    this.props.markTrendsViewed();
  }

  render() {
    const { timePrefs } = this.props;
    const timezone = datetime.getTimezoneFromTimePrefs(timePrefs);
    if (this.props.showingSmbg) {
      const { smbgTrendsComponent: SMBGTrendsContainer } = this.props;
      return (
        <SMBGTrendsContainer
          bgClasses={this.props.bgClasses}
          bgDomain={[this.state.bgDomain.lo, this.state.bgDomain.hi]}
          bgUnits={this.props.bgUnits}
          boxOverlay={this.props.smbgRangeOverlay}
          data={this.state.currentSmbgData}
          grouped={this.props.smbgGrouped}
          onSelectDay={this.props.onSelectDay}
          showingLines={this.props.smbgLines}
          timezone={timezone}
        />
      );
    } else if (this.props.showingCbg) {
      return (
        <CBGTrendsContainer
          bgBounds={this.props.bgBounds}
          bgUnits={this.props.bgUnits}
          data={this.state.currentCbgData}
          focusedSlice={this.props.viz.trends.focusedCbgSlice}
          focusedSliceKeys={this.props.viz.trends.focusedCbgSliceKeys}
          focusSlice={this.props.focusTrendsCbgSlice}
          unfocusSlice={this.props.unfocusTrendsCbgSlice}
          timezone={timezone}
          xScale={this.state.xScale}
          yScale={this.state.yScale}
        />
      );
    }
    return null;
  }
}

export function mapStateToProps(state) {
  return {
    viz: state.viz,
  };
}

export function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    focusTrendsCbgSlice: actions.focusTrendsCbgSlice,
    markTrendsViewed: actions.markTrendsViewed,
    unfocusTrendsCbgSlice: actions.unfocusTrendsCbgSlice,
  }, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps,
  (stateProps, dispatchProps, ownProps) => (Object.assign({}, ownProps, stateProps, dispatchProps)),
  { withRef: true },
)(TrendsContainer);
<|endoftext|>


<commit_before>const pathModule = require('path');
/*global describe, it*/
const expect = require('../unexpected-with-plugins');
const AssetGraph = require('../../lib/AssetGraph');

describe('resolvers/file', function() {
  it('should handle a test case with non-ASCII file names', async function() {
    const assetGraph = new AssetGraph({
      root: pathModule.resolve(__dirname, '../../testdata/resolvers/file/')
    });
    await assetGraph.loadAssets('spaces, unsafe chars & ñøń-ÃßÇ¡¡.html');
    await assetGraph.populate();

    expect(assetGraph, 'to contain asset');
  });
});
<commit_msg>Expand an existing file: test<commit_after>const pathModule = require('path');
/*global describe, it*/
const expect = require('../unexpected-with-plugins');
const AssetGraph = require('../../lib/AssetGraph');

describe('resolvers/file', function() {
  it('should handle a test case with non-ASCII file names', async function() {
    const assetGraph = new AssetGraph({
      root: pathModule.resolve(__dirname, '../../testdata/resolvers/file/')
    });
    await assetGraph.loadAssets('spaces, unsafe chars & ñøń-ÃßÇ¡¡.html');
    await assetGraph.populate();

    expect(assetGraph, 'to contain asset', {
      type: 'Html',
      url: `${
        assetGraph.root
      }spaces,%20unsafe%20chars%20&%20%C3%B1%C3%B8%C5%84-%C3%83%C3%9F%C3%87%C2%A1%C2%A1.html`,

      isLoaded: true
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var indexer = require('assemble-indexer');
var assemble = require('assemble-core');
var List = assemble.List;
var permalink = require('..');
var app = assemble();

app.create('post', {
  renameKey: function(key) {
    return path.basename(key, path.extname(key));
  }
});

var index = app.view({path: 'index.hbs', content: 'index'})
  .use(permalink(':index(pagination.idx):name.html', {
    index: function(i) {
      return i ? ((i + 1) + '/') : '';
    }
  }));

app.create('archives')
  .use(indexer({view: index}));

// placeholders('/site/blog/:path', {path: 'foo-bar.md'});
app.data({base: 'dist'});
app.posts({
  'a/b/c/a.txt': {locals: {base: '_gh_posts/blog'}, content: 'aaa'},
  'a/b/c/b.txt': {locals: {base: '_gh_posts/blog'}, content: 'bbb'},
  'a/b/c/c.txt': {locals: {base: '_gh_posts/blog'}, content: 'ccc'},
  'a/b/c/d.txt': {locals: {base: '_gh_posts/blog'}, content: 'ddd'},
  'a/b/c/e.txt': {locals: {base: '_gh_posts/blog'}, content: 'eee'},
  'a/b/c/f.txt': {locals: {base: '_gh_posts/blog'}, content: 'fff'},
  'a/b/c/g.txt': {locals: {base: '_gh_posts/blog'}, content: 'ggg'},
  'a/b/c/h.txt': {locals: {base: '_gh_posts/blog'}, content: 'hhh'},
  'a/b/c/i.txt': {locals: {base: '_gh_posts/blog'}, content: 'iii'},
  'a/b/c/j.txt': {locals: {base: '_gh_posts/blog'}, content: 'jjj'}
});

var list = new List(app.posts);
var pages = list.paginate({limit: 3});

app.archives.addIndices(pages);
console.log(app.views.archives);

// var view = app.posts
//   .getView('a.txt')
//   // .getView('a/b/c/a.txt')
//   .use(permalink(':dirname/:basename'))

// console.log(view.url)
<commit_msg>start updating example for updated templates methods<commit_after>'use strict';

var path = require('path');
var assemble = require('assemble-core');
var List = assemble.List;
var permalinks = require('..');
var app = assemble();

app.create('post', {
  renameKey: function(key) {
    return path.basename(key, path.extname(key));
  }
});

app.create('list')
  .addView('archives', {path: 'index.hbs', content: 'index'})
  .addView('archive', {path: 'archive.hbs', content: 'archive'});

var archives = app.group('archives', app.posts, app.lists);

// placeholders('/site/blog/:path', {path: 'foo-bar.md'});
app.data({base: 'dist'});
app.posts({
  'a/b/c/a.txt': {locals: {base: '_gh_posts/blog'}, content: 'aaa'},
  'a/b/c/b.txt': {locals: {base: '_gh_posts/blog'}, content: 'bbb'},
  'a/b/c/c.txt': {locals: {base: '_gh_posts/blog'}, content: 'ccc'},
  'a/b/c/d.txt': {locals: {base: '_gh_posts/blog'}, content: 'ddd'},
  'a/b/c/e.txt': {locals: {base: '_gh_posts/blog'}, content: 'eee'},
  'a/b/c/f.txt': {locals: {base: '_gh_posts/blog'}, content: 'fff'},
  'a/b/c/g.txt': {locals: {base: '_gh_posts/blog'}, content: 'ggg'},
  'a/b/c/h.txt': {locals: {base: '_gh_posts/blog'}, content: 'hhh'},
  'a/b/c/i.txt': {locals: {base: '_gh_posts/blog'}, content: 'iii'},
  'a/b/c/j.txt': {locals: {base: '_gh_posts/blog'}, content: 'jjj'}
});

archives.create('archives', {
  all: true,
  paginate: { limit: 3 },
  permalinks: permalinks(':index(pagination.idx):name.html', {
    index: function(i) {
      return i ? `page/${i + 1}/` : '';
    }
  })
});

Object.keys(app.views.archives).forEach(function(key) {
  var page = app.views.archives[key];
  console.log(key);
  console.log(page.data);
  console.log();
});
<|endoftext|>


<commit_before>'use strict';

describe('ProAct.Registry.StreamProvider', function () {
  var reg, res, listener;
  beforeEach(function () {
    var fProvider = new ProAct.Registry.FunctionProvider();

    res = [];

    reg = new ProAct.Registry()
            .register('s', new ProAct.Registry.StreamProvider())
            .register('l', fProvider)
            .register('f', fProvider);
    listener = function (el) {
      res.push(el);
    };
  });

  describe('#make', function () {
    describe('stream types', function () {
      it ('creates a delayed buffered sream if using name as s:test:delayed({delay})', function () {
        var stream = reg.make('s:test:delayed(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.DelayedStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a size buffered sream if using name as s:test:size({size})', function () {
        var stream = reg.make('s:test:size(5)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.SizeBufferedStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a debouncing buffered sream if using name as s:test:debouncing({delay})', function () {
        var stream = reg.make('s:test:debouncing(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.DebouncingStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a throttling buffered sream if using name as s:test:throttling({delay})', function () {
        var stream = reg.make('s:test:throttling(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.ThrottlingStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

    });
    describe('source', function () {
      it ('creates a simple stream that can be retrieved after that and used.', function () {
        var stream = reg.make('s:test');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a simple stream with source - another.', function () {
        var source = new ProAct.Stream();

        reg.make('s:test', source);
        expect(reg.get('s:test').sources[0]).toBe(source);
      });

      it ('creates a simple stream with source - another registered stream using object options.', function () {
        reg.make('s:source');
        reg.make('s:test', {into: 's:source'});

        expect(reg.get('s:test').sources[0]).toBe(reg.get('s:source'));
      });

      it ('creates a simple stream with source - another stream using object options.', function () {
        reg.make('s:source');
        reg.make('s:test', {into: reg.s('source')});

        expect(reg.get('s:test').sources[0]).toBe(reg.stream('source'));
      });

      it ('creates a simple stream with source source stream defined with the proRegQl', function () {
        reg.make('s:source');
        reg.make('s:test', '<<(s:source)');

        expect(reg.get('s:test').sources[0]).toBe(reg.stream('source'));
      });
    });

    describe('on', function () {
      it ('creates a stream with callback on trigger if passed "on" of type @($1)', function () {
        reg.make('s:test', '@($1)', function (e) {
          res.push(e);
        });

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey']);
      });

      it ('creates a stream with callback on trigger if passed "on" of type @(f:fun)', function () {
        reg.store('f:fun', function (e) {
          res.push(e);
        });
        reg.make('s:test', '@(f:fun)');

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey']);
      });

      it ('creates a stream with a source with callback on trigger if passed "on" of type @(f:fun)', function () {
        reg.store('f:fun', function (e) {
          res.push(e);
        });
        reg.make('s:source');
        reg.make('s:dest', '@(f:fun)');
        reg.make('s:test', '<<(s:source)|@(f:fun)|>>(s:dest)');

        reg.get('s:source').trigger('hey');
        expect(res.length).toBe(2);
        expect(res).toEqual(['hey', 'hey']);
      });
    });

    describe('map', function () {
      it ('creates a stream with mapping, transforming its value, passed with map($1)', function () {
        reg.make('s:test', '@($2)|map($1)', function (val) {
          return val + ' meddle!';
        }, function (el) {
          res.push(el);
        });

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey meddle!']);
      });

      it ('creates a stream with mapping, transforming its value, passed with map(f:mapper)', function () {
        reg.store('f:mapper', function (val) {
          return val + ' ' + val;
        });
        reg.make('s:test', '@($1)|map(f:mapper)', listener);

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey hey']);
      });

      it ('can use predefined mapping functions', function () {
        reg.make('s:test', '@($1)|map(-)', listener).trigger(4).trigger(-5);

        expect(res).toEqual([-4, 5]);
      });

      it ('can use complex predefined mapping expressions', function () {
        reg.make('s:test', '@($1)|map(&.&bau)', listener).trigger({bau: function () {return 5}});

        expect(res).toEqual([5]);
      });
    });

    describe('filter', function () {
      it ('creates a stream with filtering, filtering its value, using function passed with filter($1)', function () {
        reg.make('s:test', '@($1)|filter($2)', function (el) {
          res.push(el);
        }, function (val) {
          return val % 3 === 0;
        });

        reg.get('s:test').trigger(2).trigger(5).trigger(6).trigger(8);
        expect(res.length).toBe(1);
        expect(res).toEqual([6]);
      });

      it ('creates a stream with filtering, filtering its values, using filter(f:filter)', function () {
        reg.store('f:filter', function (val) {
          return val.indexOf('s') !== -1;
        });
        reg.make('s:test', '@($1)|filter(f:filter)', function (el) {
          res.push(el);
        });

        reg.get('s:test').trigger('hey').trigger('so').trigger('tanya').trigger('smerch');
        expect(res.length).toBe(2);
        expect(res).toEqual(['so', 'smerch']);
      });
    });

    describe('acc', function () {
      it ('creates a stream with accumulation, using function passed through acc($1, $2)', function () {
        reg.make('s:test', '@($1)|acc($2, $3)', function (el) {
          res.push(el);
        }, 0, function (x, y) {
          return x + y;
        });

        reg.get('s:test').trigger(1).trigger(1).trigger(1).trigger(81);
        expect(res.length).toBe(4);
        expect(res).toEqual([1, 2, 3, 84]);
      });

      it ('creates a accumulationg stream using acc($1, f:acc)', function () {
        reg.store('f:acc', function (x, y) {
          return x * y;
        });
        reg.make('s:test', '@($1)|acc($2, f:acc)', function (el) {
          res.push(el);
        }, 1);

        reg.get('s:test').trigger(1).trigger(2).trigger(3).trigger(4);
        expect(res.length).toBe(4);
        expect(res).toEqual([1, 2, 6, 24]);
      });

      it ('can use complex predefined accumulation expressions', function () {
        reg.make('s:test', '@($1)|acc(+)', listener).trigger(1).trigger(1).trigger(1);

        expect(res.length).toBe(3);
        expect(res).toEqual([1, 2, 3]);
      });
    });

    describe('order of operations', function () {
      it ('is retrieved by the "order" property in the meta object', function () {
        reg.make('s:test', {
          mapping: function (el) {
            return -el;
          },
          filtering: function (el) {
            return el >= 0;
          },
          accumulation: ['', function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          }],
          order: ['filtering', 'mapping', 'accumulation'],
          on: function (el) {
            res.push(el);
          }
        });

        reg.get('s:test').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['-1', '-1:-2']).toEqual(res);

        res = [];
        reg.make('s:test2', {
          mapping: function (el) {
            return -el;
          },
          filtering: function (el) {
            return el >= 0;
          },
          accumulation: ['', function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          }],
          order: ['mapping', 'filtering', 'accumulation'],
          on: function (el) {
            res.push(el);
          }
        });

        reg.get('s:test2').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['1', '1:1']).toEqual(res);
      });

      it ('is retrieved by the "order" in wich functions are ordered', function () {
        reg.make('s:test', 'map($1)|filter($2)|acc($3, $4)|@($5)',
          function (el) {
            return -el;
          },
          function (el) {
            return el >= 0;
          },
          '',
          function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          },
          function (el) {
            res.push(el);
          }
        );

        reg.get('s:test').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['1', '1:1']).toEqual(res);

        res = [];
        reg.make('s:test2', 'filter($2)|map($1)|acc($3, $4)|@($5)',
          function (el) {
            return -el;
          },
          function (el) {
            return el >= 0;
          },
          '',
          function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          },
          function (el) {
            res.push(el);
          }
        );

        reg.get('s:test2').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['-1', '-1:-2']).toEqual(res);
      });
    });
  });
});
<commit_msg>Fixing the specs related to streams - take 2.<commit_after>'use strict';

describe('ProAct.Registry.StreamProvider', function () {
  var reg, res, listener;
  beforeEach(function () {
    var fProvider = new ProAct.Registry.FunctionProvider();

    res = [];

    reg = new ProAct.Registry()
            .register('s', new ProAct.Registry.StreamProvider())
            .register('l', fProvider)
            .register('f', fProvider);
    listener = function (el) {
      res.push(el);
    };
  });

  describe('#make', function () {
    describe('stream types', function () {
      it ('creates a stream with specific flow queue using s:test:basic({queueName})', function () {
        var stream = reg.make('s:test:basic(test)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
        expect(reg.get('s:test').queueName).toEqual('test');
      });

      it ('creates a delayed buffered sream if using name as s:test:delayed({delay})', function () {
        var stream = reg.make('s:test:delayed(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.DelayedStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
        expect(reg.get('s:test').delay).toEqual(300);
      });

      it ('creates a delayed buffered sream with specific flow queue, if using name as s:test:delayed({queueName},{delay})', function () {
        var stream = reg.make('s:test:delayed(test,300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.DelayedStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
        expect(reg.get('s:test').delay).toEqual(300);
        expect(reg.get('s:test').queueName).toEqual('test');
      });

      it ('creates a size buffered sream if using name as s:test:size({size})', function () {
        var stream = reg.make('s:test:size(5)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.SizeBufferedStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a debouncing buffered sream if using name as s:test:debouncing({delay})', function () {
        var stream = reg.make('s:test:debouncing(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.DebouncingStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a throttling buffered sream if using name as s:test:throttling({delay})', function () {
        var stream = reg.make('s:test:throttling(300)');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(stream instanceof ProAct.ThrottlingStream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

    });
    describe('source', function () {
      it ('creates a simple stream that can be retrieved after that and used.', function () {
        var stream = reg.make('s:test');

        expect(stream instanceof ProAct.Stream).toBe(true);
        expect(reg.get('s:test')).toBe(stream);
      });

      it ('creates a simple stream with source - another.', function () {
        var source = new ProAct.Stream();

        reg.make('s:test', source);
        expect(source.listeners.change[0]).toBe(reg.get('s:test').makeListener());
      });

      it ('creates a simple stream with source - another registered stream using object options.', function () {
        reg.make('s:source');
        reg.make('s:test', {into: 's:source'});

        expect(reg.get('s:source').listeners.change[0]).toBe(reg.get('s:test').makeListener());
      });

      it ('creates a simple stream with source - another stream using object options.', function () {
        reg.make('s:source');
        reg.make('s:test', {into: reg.s('source')});

        expect(reg.stream('source').listeners.change[0]).toBe(reg.get('s:test').makeListener());
      });

      it ('creates a simple stream with source source stream defined with the proRegQl', function () {
        reg.make('s:source');
        reg.make('s:test', '<<(s:source)');

        expect(reg.stream('source').listeners.change[0]).toBe(reg.get('s:test').makeListener());
      });
    });

    describe('on', function () {
      it ('creates a stream with callback on trigger if passed "on" of type @($1)', function () {
        reg.make('s:test', '@($1)', function (e) {
          res.push(e);
        });

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey']);
      });

      it ('creates a stream with callback on trigger if passed "on" of type @(f:fun)', function () {
        reg.store('f:fun', function (e) {
          res.push(e);
        });
        reg.make('s:test', '@(f:fun)');

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey']);
      });

      it ('creates a stream with a source with callback on trigger if passed "on" of type @(f:fun)', function () {
        reg.store('f:fun', function (e) {
          res.push(e);
        });
        reg.make('s:source');
        reg.make('s:dest', '@(f:fun)');
        reg.make('s:test', '<<(s:source)|@(f:fun)|>>(s:dest)');

        reg.get('s:source').trigger('hey');
        expect(res.length).toBe(2);
        expect(res).toEqual(['hey', 'hey']);
      });
    });

    describe('map', function () {
      it ('creates a stream with mapping, transforming its value, passed with map($1)', function () {
        reg.make('s:test', '@($2)|map($1)', function (val) {
          return val + ' meddle!';
        }, function (el) {
          res.push(el);
        });

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey meddle!']);
      });

      it ('creates a stream with mapping, transforming its value, passed with map(f:mapper)', function () {
        reg.store('f:mapper', function (val) {
          return val + ' ' + val;
        });
        reg.make('s:test', '@($1)|map(f:mapper)', listener);

        reg.get('s:test').trigger('hey');
        expect(res.length).toBe(1);
        expect(res).toEqual(['hey hey']);
      });

      it ('can use predefined mapping functions', function () {
        reg.make('s:test', '@($1)|map(-)', listener).trigger(4).trigger(-5);

        expect(res).toEqual([-4, 5]);
      });

      it ('can use complex predefined mapping expressions', function () {
        reg.make('s:test', '@($1)|map(&.&bau)', listener).trigger({bau: function () {return 5}});

        expect(res).toEqual([5]);
      });
    });

    describe('filter', function () {
      it ('creates a stream with filtering, filtering its value, using function passed with filter($1)', function () {
        reg.make('s:test', '@($1)|filter($2)', function (el) {
          res.push(el);
        }, function (val) {
          return val % 3 === 0;
        });

        reg.get('s:test').trigger(2).trigger(5).trigger(6).trigger(8);
        expect(res.length).toBe(1);
        expect(res).toEqual([6]);
      });

      it ('creates a stream with filtering, filtering its values, using filter(f:filter)', function () {
        reg.store('f:filter', function (val) {
          return val.indexOf('s') !== -1;
        });
        reg.make('s:test', '@($1)|filter(f:filter)', function (el) {
          res.push(el);
        });

        reg.get('s:test').trigger('hey').trigger('so').trigger('tanya').trigger('smerch');
        expect(res.length).toBe(2);
        expect(res).toEqual(['so', 'smerch']);
      });
    });

    describe('acc', function () {
      it ('creates a stream with accumulation, using function passed through acc($1, $2)', function () {
        reg.make('s:test', '@($1)|acc($2, $3)', function (el) {
          res.push(el);
        }, 0, function (x, y) {
          return x + y;
        });

        reg.get('s:test').trigger(1).trigger(1).trigger(1).trigger(81);
        expect(res.length).toBe(4);
        expect(res).toEqual([1, 2, 3, 84]);
      });

      it ('creates a accumulationg stream using acc($1, f:acc)', function () {
        reg.store('f:acc', function (x, y) {
          return x * y;
        });
        reg.make('s:test', '@($1)|acc($2, f:acc)', function (el) {
          res.push(el);
        }, 1);

        reg.get('s:test').trigger(1).trigger(2).trigger(3).trigger(4);
        expect(res.length).toBe(4);
        expect(res).toEqual([1, 2, 6, 24]);
      });

      it ('can use complex predefined accumulation expressions', function () {
        reg.make('s:test', '@($1)|acc(+)', listener).trigger(1).trigger(1).trigger(1);

        expect(res.length).toBe(3);
        expect(res).toEqual([1, 2, 3]);
      });
    });

    describe('order of operations', function () {
      it ('is retrieved by the "order" property in the meta object', function () {
        reg.make('s:test', {
          mapping: function (el) {
            return -el;
          },
          filtering: function (el) {
            return el >= 0;
          },
          accumulation: ['', function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          }],
          order: ['filtering', 'mapping', 'accumulation'],
          on: function (el) {
            res.push(el);
          }
        });

        reg.get('s:test').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['-1', '-1:-2']).toEqual(res);

        res = [];
        reg.make('s:test2', {
          mapping: function (el) {
            return -el;
          },
          filtering: function (el) {
            return el >= 0;
          },
          accumulation: ['', function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          }],
          order: ['mapping', 'filtering', 'accumulation'],
          on: function (el) {
            res.push(el);
          }
        });

        reg.get('s:test2').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['1', '1:1']).toEqual(res);
      });

      it ('is retrieved by the "order" in wich functions are ordered', function () {
        reg.make('s:test', 'map($1)|filter($2)|acc($3, $4)|@($5)',
          function (el) {
            return -el;
          },
          function (el) {
            return el >= 0;
          },
          '',
          function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          },
          function (el) {
            res.push(el);
          }
        );

        reg.get('s:test').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['1', '1:1']).toEqual(res);

        res = [];
        reg.make('s:test2', 'filter($2)|map($1)|acc($3, $4)|@($5)',
          function (el) {
            return -el;
          },
          function (el) {
            return el >= 0;
          },
          '',
          function (i, x) {
            if (i === '') {
              return x + '';
            }
            return i + ":" + x;
          },
          function (el) {
            res.push(el);
          }
        );

        reg.get('s:test2').trigger(1).trigger(-1).trigger(2).trigger(-1);
        expect(['-1', '-1:-2']).toEqual(res);
      });
    });
  });
});
<|endoftext|>