<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';

import React from 'react';
import classNames from 'classnames';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from "../../../Modal";
import dis from "../../../dispatcher";
import RateLimitedFunc from '../../../ratelimitedfunc';

import * as linkify from 'linkifyjs';
import linkifyElement from 'linkifyjs/element';
import linkifyMatrix from '../../../linkify-matrix';
import AccessibleButton from '../elements/AccessibleButton';
import ManageIntegsButton from '../elements/ManageIntegsButton';
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,
        onCancelClick: React.PropTypes.func,
    },

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

    componentDidMount: function() {
        const 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);
        }
        const 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 RateLimitedFunc(function() {
        /* eslint-disable babel/no-invalid-this */
        this.forceUpdate();
    }, 500),

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

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

    onAvatarSelected: function(ev) {
        const changeAvatar = this.refs.changeAvatar;
        if (!changeAvatar) {
            console.error("No ChangeAvatar found to upload image to!");
            return;
        }
        changeAvatar.onFileSelected(ev).catch(function(err) {
            const errMsg = (typeof err === "string") ? err : (err.error || "");
            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
            console.error("Failed to set avatar: " + errMsg);
            Modal.createTrackedDialog('Failed to set avatar', '', ErrorDialog, {
                title: _t("Error"),
                description: _t("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
     *
     * @return {?string} newName or undefined if we didn't let the user edit the room name
     */
    getEditedName: function() {
        let newName;
        if (this.refs.nameEditor) {
            newName = this.refs.nameEditor.getRoomName();
        }
        return newName;
    },

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

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

        let name = null;
        let searchStatus = null;
        let topicElement = null;
        let cancelButton = null;
        let spinner = null;
        let saveButton = null;
        let settingsButton = null;

        let canSetRoomName;
        let canSetRoomAvatar;
        let canSetRoomTopic;
        if (this.props.editing) {
            // calculate permissions.  XXX: this should be done on mount or something
            const userId = MatrixClientPeg.get().credentials.userId;

            canSetRoomName = this.props.room.currentState.maySendStateEvent('m.room.name', userId);
            canSetRoomAvatar = this.props.room.currentState.maySendStateEvent('m.room.avatar', userId);
            canSetRoomTopic = this.props.room.currentState.maySendStateEvent('m.room.topic', userId);

            saveButton = (
                <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>
                    {_t("Save")}
                </AccessibleButton>
            );
        }

        if (this.props.onCancelClick) {
            cancelButton = <CancelButton onClick={this.props.onCancelClick}/>;
        }

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

        if (canSetRoomName) {
            const RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
            name = <RoomNameEditor ref="nameEditor" room={this.props.room} />;
        } else {
            // 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 =

                    { _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }

;
            }

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

            let roomName = _t("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;
            }

            const emojiTextClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
            name =

                    <EmojiText dir="auto" element="div" className={emojiTextClasses} title={roomName}>{ roomName }</EmojiText>
                    { searchStatus }

;
        }

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

{ topic }
;
            }
        }

        let roomAvatar = null;
        if (canSetRoomAvatar) {
            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} />

            );
        }

        if (this.props.onSettingsClick) {
            settingsButton =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title={_t("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"/>
//
;
//        }

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

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

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

        let rightRow;
        let manageIntegsButton;
        if(this.props.room && this.props.room.roomId) {
            manageIntegsButton = <ManageIntegsButton
                roomId={this.props.room.roomId}
            />;
        }

        if (!this.props.editing) {
            rightRow =

                    { settingsButton }
                    { manageIntegsButton }
                    { forgetButton }
                    { searchButton }
                    { rightPanelButtons }

;
        }

        return (

                            { roomAvatar }

                            { name }
                            { topicElement }

                    {spinner}
                    {saveButton}
                    {cancelButton}
                    {rightRow}

        );
    },
});
<commit_msg>Remove spurious cancel button<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';

import React from 'react';
import classNames from 'classnames';
import sdk from '../../../index';
import { _t } from '../../../languageHandler';
import MatrixClientPeg from '../../../MatrixClientPeg';
import Modal from "../../../Modal";
import dis from "../../../dispatcher";
import RateLimitedFunc from '../../../ratelimitedfunc';

import * as linkify from 'linkifyjs';
import linkifyElement from 'linkifyjs/element';
import linkifyMatrix from '../../../linkify-matrix';
import AccessibleButton from '../elements/AccessibleButton';
import ManageIntegsButton from '../elements/ManageIntegsButton';
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,
        onCancelClick: React.PropTypes.func,
    },

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

    componentDidMount: function() {
        const 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);
        }
        const 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 RateLimitedFunc(function() {
        /* eslint-disable babel/no-invalid-this */
        this.forceUpdate();
    }, 500),

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

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

    onAvatarSelected: function(ev) {
        const changeAvatar = this.refs.changeAvatar;
        if (!changeAvatar) {
            console.error("No ChangeAvatar found to upload image to!");
            return;
        }
        changeAvatar.onFileSelected(ev).catch(function(err) {
            const errMsg = (typeof err === "string") ? err : (err.error || "");
            const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
            console.error("Failed to set avatar: " + errMsg);
            Modal.createTrackedDialog('Failed to set avatar', '', ErrorDialog, {
                title: _t("Error"),
                description: _t("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
     *
     * @return {?string} newName or undefined if we didn't let the user edit the room name
     */
    getEditedName: function() {
        let newName;
        if (this.refs.nameEditor) {
            newName = this.refs.nameEditor.getRoomName();
        }
        return newName;
    },

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

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

        let name = null;
        let searchStatus = null;
        let topicElement = null;
        let cancelButton = null;
        let spinner = null;
        let saveButton = null;
        let settingsButton = null;

        let canSetRoomName;
        let canSetRoomAvatar;
        let canSetRoomTopic;
        if (this.props.editing) {
            // calculate permissions.  XXX: this should be done on mount or something
            const userId = MatrixClientPeg.get().credentials.userId;

            canSetRoomName = this.props.room.currentState.maySendStateEvent('m.room.name', userId);
            canSetRoomAvatar = this.props.room.currentState.maySendStateEvent('m.room.avatar', userId);
            canSetRoomTopic = this.props.room.currentState.maySendStateEvent('m.room.topic', userId);

            saveButton = (
                <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>
                    {_t("Save")}
                </AccessibleButton>
            );
        }

        if (this.props.onCancelClick) {
            cancelButton = <CancelButton onClick={this.props.onCancelClick}/>;
        }

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

        if (canSetRoomName) {
            const RoomNameEditor = sdk.getComponent("rooms.RoomNameEditor");
            name = <RoomNameEditor ref="nameEditor" room={this.props.room} />;
        } else {
            // 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 =

                    { _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }

;
            }

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

            let roomName = _t("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;
            }

            const emojiTextClasses = classNames('mx_RoomHeader_nametext', { mx_RoomHeader_settingsHint: settingsHint });
            name =

                    <EmojiText dir="auto" element="div" className={emojiTextClasses} title={roomName}>{ roomName }</EmojiText>
                    { searchStatus }

;
        }

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

{ topic }
;
            }
        }

        let roomAvatar = null;
        if (canSetRoomAvatar) {
            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} />

            );
        }

        if (this.props.onSettingsClick) {
            settingsButton =
                <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title={_t("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"/>
//
;
//        }

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

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

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

        let rightRow;
        let manageIntegsButton;
        if(this.props.room && this.props.room.roomId) {
            manageIntegsButton = <ManageIntegsButton
                roomId={this.props.room.roomId}
            />;
        }

        if (!this.props.editing) {
            rightRow =

                    { settingsButton }
                    { manageIntegsButton }
                    { forgetButton }
                    { searchButton }
                    { rightPanelButtons }

;
        }

        return (

                            { roomAvatar }

                            { name }
                            { topicElement }

                    {spinner}
                    {saveButton}
                    {cancelButton}
                    {rightRow}

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


<commit_before>'use strict'

var net = require('net')
  , request = require('../index')
  , tape = require('tape')

var port = 6768
  , called = false
  , proxiedHost = 'google.com'
  , data = ''

var s = require('net').createServer(function(sock) {
  called = true
  sock.once('data', function (c) {
    data += c

    sock.write('HTTP/1.1 200 OK\r\n\r\n')

    sock.once('data', function (c) {
      data += c

      sock.write('HTTP/1.1 200 OK\r\n')
      sock.write('content-type: text/plain\r\n')
      sock.write('content-length: 5\r\n')
      sock.write('\r\n')
      sock.end('derp\n')
    })
  })
})

tape('setup', function(t) {
  s.listen(port, function() {
    t.end()
  })
})

tape('proxy', function(t) {
  request({
    tunnel: true,
    url: 'http://' + proxiedHost,
    proxy: 'http://localhost:' + port,
    headers: {
      'Proxy-Authorization' : 'Basic dXNlcjpwYXNz',
      'authorization'       : 'Token deadbeef',
      'dont-send-to-proxy'  : 'ok',
      'dont-send-to-dest'   : 'ok',
      'accept'              : 'yo',
      'user-agent'          : 'just another foobar'
    },
    proxyHeaderExclusiveList: ['Dont-send-to-dest']
  }, function(err, res, body) {
    t.equal(err, null)
    t.equal(res.statusCode, 200)
    t.equal(body, 'derp\n')
    var re = new RegExp([
      'CONNECT google.com:80 HTTP/1.1',
      'Proxy-Authorization: Basic dXNlcjpwYXNz',
      'dont-send-to-dest: ok',
      'accept: yo',
      'user-agent: just another foobar',
      'host: google.com:80',
      'Connection: close',
      '',
      'GET / HTTP/1.1',
      'authorization: Token deadbeef',
      'dont-send-to-proxy: ok',
      'accept: yo',
      'user-agent: just another foobar',
      'host: google.com',
    ].join('\r\n'))
    t.equal(true, re.test(data))
    t.equal(called, true, 'the request must be made to the proxy server')
    t.end()
  })
})

tape('cleanup', function(t) {
  s.close(function() {
    t.end()
  })
})
<commit_msg>Fixing lint error.<commit_after>'use strict'

var net = require('net')
  , request = require('../index')
  , tape = require('tape')

var port = 6768
  , called = false
  , proxiedHost = 'google.com'
  , data = ''

var s = require('net').createServer(function(sock) {
  called = true
  sock.once('data', function (c) {
    data += c

    sock.write('HTTP/1.1 200 OK\r\n\r\n')

    sock.once('data', function (c) {
      data += c

      sock.write('HTTP/1.1 200 OK\r\n')
      sock.write('content-type: text/plain\r\n')
      sock.write('content-length: 5\r\n')
      sock.write('\r\n')
      sock.end('derp\n')
    })
  })
})

tape('setup', function(t) {
  s.listen(port, function() {
    t.end()
  })
})

tape('proxy', function(t) {
  request({
    tunnel: true,
    url: 'http://' + proxiedHost,
    proxy: 'http://localhost:' + port,
    headers: {
      'Proxy-Authorization' : 'Basic dXNlcjpwYXNz',
      'authorization'       : 'Token deadbeef',
      'dont-send-to-proxy'  : 'ok',
      'dont-send-to-dest'   : 'ok',
      'accept'              : 'yo',
      'user-agent'          : 'just another foobar'
    },
    proxyHeaderExclusiveList: ['Dont-send-to-dest']
  }, function(err, res, body) {
    t.equal(err, null)
    t.equal(res.statusCode, 200)
    t.equal(body, 'derp\n')
    var re = new RegExp([
      'CONNECT google.com:80 HTTP/1.1',
      'Proxy-Authorization: Basic dXNlcjpwYXNz',
      'dont-send-to-dest: ok',
      'accept: yo',
      'user-agent: just another foobar',
      'host: google.com:80',
      'Connection: close',
      '',
      'GET / HTTP/1.1',
      'authorization: Token deadbeef',
      'dont-send-to-proxy: ok',
      'accept: yo',
      'user-agent: just another foobar',
      'host: google.com'
    ].join('\r\n'))
    t.equal(true, re.test(data))
    t.equal(called, true, 'the request must be made to the proxy server')
    t.end()
  })
})

tape('cleanup', function(t) {
  s.close(function() {
    t.end()
  })
})
<|endoftext|>


<commit_before>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2016 Massachusetts Institute of Technology
 * All rights reserved.
 *
 * 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';

goog.provide('Blockly.Blocks.event');

goog.require('Blockly.Blocks');
goog.require('Blockly.Colours');
goog.require('Blockly.constants');
goog.require('Blockly.ScratchBlocks.VerticalExtensions');

Blockly.Blocks['event_whenflagclicked'] = {
  /**
   * Block for when flag clicked.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenflagclicked",
      "message0": "when %1 clicked",
      "args0": [
        {
          "type": "field_image",
          "src": Blockly.mainWorkspace.options.pathToMedia + "green-flag.svg",
          "width": 24,
          "height": 24,
          "alt": "flag",
          "flip_rtl": true
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenthisspriteclicked'] = {
  /**
   * Block for when this sprite clicked.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when this sprite clicked",
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenbroadcastreceived'] = {
  /**
   * Block for when broadcast received.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenbroadcastreceived",
      "message0": "when I receive %1",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "BROADCAST_OPTION",
          "options": [
            ['message1', 'message1'],
            ['message2', 'message2'],
            ['new message', 'new message']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenbackdropswitchesto'] = {
  /**
   * Block for when the current backdrop switched to a selected backdrop.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when backdrop switches to %1",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "BACKDROP",
          "options": [
              ['backdrop1', 'BACKDROP1']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whengreaterthan'] = {
  /**
   * Block for when loudness/timer/video motion is greater than the value.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when %1 > %2",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "WHENGREATERTHANMENU",
          "options": [
              ['timer', 'TIMER']
          ]
        },
        {
          "type": "input_value",
          "name": "VALUE"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_broadcast_menu'] = {
  /**
   * Broadcast drop-down menu.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit(
      {
        "message0": "%1",
        "args0": [
          {
            "type": "field_dropdown",
            "name": "BROADCAST_OPTION",
            "options": [
              ['message1', 'message1'],
              ['message2', 'message2'],
              ['new message', 'new message']
            ]
          }
        ],
        "colour": Blockly.Colours.event.secondary,
        "colourSecondary": Blockly.Colours.event.secondary,
        "colourTertiary": Blockly.Colours.event.tertiary,
        "extensions": ["output_string"]
      });
  }
};

Blockly.Blocks['event_broadcast'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_broadcast",
      "message0": "broadcast %1",
      "args0": [
        {
          "type": "input_value",
          "name": "BROADCAST_OPTION"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_statement"]
    });
  }
};

Blockly.Blocks['event_broadcastandwait'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "broadcast %1 and wait",
      "args0": [
        {
          "type": "input_value",
          "name": "BROADCAST_OPTION"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_statement"]
    });
  }
};

Blockly.Blocks['event_whenkeypressed'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenkeypressed",
      "message0": "when %1 key pressed",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "KEY_OPTION",
          "options": [
            ['space', 'space'],
            ['left arrow', 'left arrow'],
            ['right arrow', 'right arrow'],
            ['down arrow', 'down arrow'],
            ['up arrow', 'up arrow'],
            ['any', 'any'],
            ['a', 'a'],
            ['b', 'b'],
            ['c', 'c'],
            ['d', 'd'],
            ['e', 'e'],
            ['f', 'f'],
            ['g', 'g'],
            ['h', 'h'],
            ['i', 'i'],
            ['j', 'j'],
            ['k', 'k'],
            ['l', 'l'],
            ['m', 'm'],
            ['n', 'n'],
            ['o', 'o'],
            ['p', 'p'],
            ['q', 'q'],
            ['r', 'r'],
            ['s', 's'],
            ['t', 't'],
            ['u', 'u'],
            ['v', 'v'],
            ['w', 'w'],
            ['x', 'x'],
            ['y', 'y'],
            ['z', 'z'],
            ['0', '0'],
            ['1', '1'],
            ['2', '2'],
            ['3', '3'],
            ['4', '4'],
            ['5', '5'],
            ['6', '6'],
            ['7', '7'],
            ['8', '8'],
            ['9', '9']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};
<commit_msg>Don't flip the green flag in RTL<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2016 Massachusetts Institute of Technology
 * All rights reserved.
 *
 * 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';

goog.provide('Blockly.Blocks.event');

goog.require('Blockly.Blocks');
goog.require('Blockly.Colours');
goog.require('Blockly.constants');
goog.require('Blockly.ScratchBlocks.VerticalExtensions');

Blockly.Blocks['event_whenflagclicked'] = {
  /**
   * Block for when flag clicked.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenflagclicked",
      "message0": "when %1 clicked",
      "args0": [
        {
          "type": "field_image",
          "src": Blockly.mainWorkspace.options.pathToMedia + "green-flag.svg",
          "width": 24,
          "height": 24,
          "alt": "flag"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenthisspriteclicked'] = {
  /**
   * Block for when this sprite clicked.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when this sprite clicked",
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenbroadcastreceived'] = {
  /**
   * Block for when broadcast received.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenbroadcastreceived",
      "message0": "when I receive %1",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "BROADCAST_OPTION",
          "options": [
            ['message1', 'message1'],
            ['message2', 'message2'],
            ['new message', 'new message']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whenbackdropswitchesto'] = {
  /**
   * Block for when the current backdrop switched to a selected backdrop.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when backdrop switches to %1",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "BACKDROP",
          "options": [
              ['backdrop1', 'BACKDROP1']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_whengreaterthan'] = {
  /**
   * Block for when loudness/timer/video motion is greater than the value.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "when %1 > %2",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "WHENGREATERTHANMENU",
          "options": [
              ['timer', 'TIMER']
          ]
        },
        {
          "type": "input_value",
          "name": "VALUE"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};

Blockly.Blocks['event_broadcast_menu'] = {
  /**
   * Broadcast drop-down menu.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit(
      {
        "message0": "%1",
        "args0": [
          {
            "type": "field_dropdown",
            "name": "BROADCAST_OPTION",
            "options": [
              ['message1', 'message1'],
              ['message2', 'message2'],
              ['new message', 'new message']
            ]
          }
        ],
        "colour": Blockly.Colours.event.secondary,
        "colourSecondary": Blockly.Colours.event.secondary,
        "colourTertiary": Blockly.Colours.event.tertiary,
        "extensions": ["output_string"]
      });
  }
};

Blockly.Blocks['event_broadcast'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_broadcast",
      "message0": "broadcast %1",
      "args0": [
        {
          "type": "input_value",
          "name": "BROADCAST_OPTION"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_statement"]
    });
  }
};

Blockly.Blocks['event_broadcastandwait'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "message0": "broadcast %1 and wait",
      "args0": [
        {
          "type": "input_value",
          "name": "BROADCAST_OPTION"
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_statement"]
    });
  }
};

Blockly.Blocks['event_whenkeypressed'] = {
  /**
   * Block to send a broadcast.
   * @this Blockly.Block
   */
  init: function() {
    this.jsonInit({
      "id": "event_whenkeypressed",
      "message0": "when %1 key pressed",
      "args0": [
        {
          "type": "field_dropdown",
          "name": "KEY_OPTION",
          "options": [
            ['space', 'space'],
            ['left arrow', 'left arrow'],
            ['right arrow', 'right arrow'],
            ['down arrow', 'down arrow'],
            ['up arrow', 'up arrow'],
            ['any', 'any'],
            ['a', 'a'],
            ['b', 'b'],
            ['c', 'c'],
            ['d', 'd'],
            ['e', 'e'],
            ['f', 'f'],
            ['g', 'g'],
            ['h', 'h'],
            ['i', 'i'],
            ['j', 'j'],
            ['k', 'k'],
            ['l', 'l'],
            ['m', 'm'],
            ['n', 'n'],
            ['o', 'o'],
            ['p', 'p'],
            ['q', 'q'],
            ['r', 'r'],
            ['s', 's'],
            ['t', 't'],
            ['u', 'u'],
            ['v', 'v'],
            ['w', 'w'],
            ['x', 'x'],
            ['y', 'y'],
            ['z', 'z'],
            ['0', '0'],
            ['1', '1'],
            ['2', '2'],
            ['3', '3'],
            ['4', '4'],
            ['5', '5'],
            ['6', '6'],
            ['7', '7'],
            ['8', '8'],
            ['9', '9']
          ]
        }
      ],
      "category": Blockly.Categories.event,
      "extensions": ["colours_event", "shape_hat"]
    });
  }
};
<|endoftext|>


<commit_before>/*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 3000;

__karma__.loaded = function () {};

var baseDir = '/base';
var specFiles = Object.keys(window.__karma__.files).filter(isMaterialSpecFile);

// Configure the base path and map the different node packages.
System.config({
  baseURL: baseDir,
  paths: {
    'node:*': 'node_modules/*'
  },
  map: {
    'rxjs': 'node:rxjs',
    'main': 'main.js',

    // Angular specific mappings.
    '@angular/core': 'node:@angular/core/bundles/core.umd.js',
    '@angular/core/testing': 'node:@angular/core/bundles/core-testing.umd.js',
    '@angular/common': 'node:@angular/common/bundles/common.umd.js',
    '@angular/common/testing': 'node:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler': 'node:@angular/compiler/bundles/compiler.umd.js',
    '@angular/compiler/testing': 'node:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/http': 'node:@angular/http/bundles/http.umd.js',
    '@angular/http/testing': 'node:@angular/http/bundles/http-testing.umd.js',
    '@angular/forms': 'node:@angular/forms/bundles/forms.umd.js',
    '@angular/forms/testing': 'node:@angular/forms/bundles/forms-testing.umd.js',
    '@angular/animations': 'node:@angular/animations/bundles/animations.umd.js',
    '@angular/animations/browser': 'node:@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations':
      'node:@angular/platform-browser/bundles/platform-browser-animations.umd',
    '@angular/platform-browser':
      'node:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser/testing':
      'node:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/platform-browser-dynamic/testing':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',

    // Path mappings for local packages that can be imported inside of tests.
    '@angular/material': 'dist/packages/material/index.js',
    '@angular/cdk': 'dist/packages/cdk/index.js',
  },
  packages: {
    // Thirdparty barrels.
    'rxjs': {main: 'index'},

    // Set the default extension for the root package, because otherwise the demo-app can't
    // be built within the production mode. Due to missing file extensions.
    '.': {
      defaultExtension: 'js'
    }
  }
});

// Configure the Angular test bed and run all specs once configured.
 configureTestBed()
  .then(runMaterialSpecs)
  .then(__karma__.start, __karma__.error);

/** Runs the Angular Material specs in Karma. */
function runMaterialSpecs() {
  // By importing all spec files, Karma will run the tests directly.
  return Promise.all(specFiles.map(function(fileName) {
    return System.import(fileName);
  }));
}

/** Whether the specified file is part of Angular Material. */
function isMaterialSpecFile(path) {
  return path.slice(-8) === '.spec.js' && path.indexOf('node_modules') === -1;
}

/** Configures Angular's TestBed. */
function configureTestBed() {
  return Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
  ]).then(function (providers) {
    var testing = providers[0];
    var testingBrowser = providers[1];

    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

    testing.TestBed.initTestEnvironment(
      testingBrowser.BrowserDynamicTestingModule,
      testingBrowser.platformBrowserDynamicTesting()
    );
  });
}
<commit_msg>build: report ngOnDestroy exceptions in unti tests (#5036)<commit_after>/*global jasmine, __karma__, window*/
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 3000;

__karma__.loaded = function () {};

var baseDir = '/base';
var specFiles = Object.keys(window.__karma__.files).filter(isMaterialSpecFile);

// Configure the base path and map the different node packages.
System.config({
  baseURL: baseDir,
  paths: {
    'node:*': 'node_modules/*'
  },
  map: {
    'rxjs': 'node:rxjs',
    'main': 'main.js',

    // Angular specific mappings.
    '@angular/core': 'node:@angular/core/bundles/core.umd.js',
    '@angular/core/testing': 'node:@angular/core/bundles/core-testing.umd.js',
    '@angular/common': 'node:@angular/common/bundles/common.umd.js',
    '@angular/common/testing': 'node:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler': 'node:@angular/compiler/bundles/compiler.umd.js',
    '@angular/compiler/testing': 'node:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/http': 'node:@angular/http/bundles/http.umd.js',
    '@angular/http/testing': 'node:@angular/http/bundles/http-testing.umd.js',
    '@angular/forms': 'node:@angular/forms/bundles/forms.umd.js',
    '@angular/forms/testing': 'node:@angular/forms/bundles/forms-testing.umd.js',
    '@angular/animations': 'node:@angular/animations/bundles/animations.umd.js',
    '@angular/animations/browser': 'node:@angular/animations/bundles/animations-browser.umd.js',
    '@angular/platform-browser/animations':
      'node:@angular/platform-browser/bundles/platform-browser-animations.umd',
    '@angular/platform-browser':
      'node:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser/testing':
      'node:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/platform-browser-dynamic/testing':
      'node:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',

    // Path mappings for local packages that can be imported inside of tests.
    '@angular/material': 'dist/packages/material/index.js',
    '@angular/cdk': 'dist/packages/cdk/index.js',
  },
  packages: {
    // Thirdparty barrels.
    'rxjs': {main: 'index'},

    // Set the default extension for the root package, because otherwise the demo-app can't
    // be built within the production mode. Due to missing file extensions.
    '.': {
      defaultExtension: 'js'
    }
  }
});

// Configure the Angular test bed and run all specs once configured.
 configureTestBed()
  .then(runMaterialSpecs)
  .then(__karma__.start, __karma__.error);

/** Runs the Angular Material specs in Karma. */
function runMaterialSpecs() {
  // By importing all spec files, Karma will run the tests directly.
  return Promise.all(specFiles.map(function(fileName) {
    return System.import(fileName);
  }));
}

/** Whether the specified file is part of Angular Material. */
function isMaterialSpecFile(path) {
  return path.slice(-8) === '.spec.js' && path.indexOf('node_modules') === -1;
}

/** Configures Angular's TestBed. */
function configureTestBed() {
  return Promise.all([
    System.import('@angular/core/testing'),
    System.import('@angular/platform-browser-dynamic/testing')
  ]).then(function (providers) {
    var testing = providers[0];
    var testingBrowser = providers[1];

    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;

    var testBed = testing.TestBed.initTestEnvironment(
      testingBrowser.BrowserDynamicTestingModule,
      testingBrowser.platformBrowserDynamicTesting()
    );

    patchTestBedToDestroyFixturesAfterEveryTest(testBed);
  });
}

/**
 * Monkey-patches TestBed.resetTestingModule such that any errors that occur during component
 * destruction are thrown instead of silently logged. Also runs TestBed.resetTestingModule after
 * each unit test.
 *
 * Without this patch, the combination of two behaviors is problematic for Angular Material:
 * - TestBed.resetTestingModule catches errors thrown on fixture destruction and logs them without
 *     the errors ever being thrown. This means that any component errors that occur in ngOnDestroy
 *     can encounter errors silently and still pass unit tests.
 * - TestBed.resetTestingModule is only called *before* a test is run, meaning that even *if* the
 *    aforementioned errors were thrown, they would be reported for the wrong test (the test that's
 *    about to start, not the test that just finished).
 */
function patchTestBedToDestroyFixturesAfterEveryTest(testBed) {
  // Original resetTestingModule function of the TestBed.
  var _resetTestingModule = testBed.resetTestingModule;

  // Monkey-patch the resetTestingModule to destroy fixtures outside of a try/catch block.
  // With https://github.com/angular/angular/commit/2c5a67134198a090a24f6671dcdb7b102fea6eba
  // errors when destroying components are no longer causing Jasmine to fail.
  testBed.resetTestingModule = function() {
    try {
      this._activeFixtures.forEach(function (fixture) { fixture.destroy(); });
    } finally {
      this._activeFixtures = [];
      // Regardless of errors or not, run the original reset testing module function.
      _resetTestingModule.call(this);
    }
  };

  // Angular's testing package resets the testing module before each test. This doesn't work well
  // for us because it doesn't allow developers to see what test actually failed.
  // Fixing this by resetting the testing module after each test.
  // https://github.com/angular/angular/blob/master/packages/core/testing/src/before_each.ts#L25
  afterEach(function() {
    testBed.resetTestingModule();
  });
}
<|endoftext|>


<commit_before>/*eslint-env node, mocha*/
const { expect }  = require('chai');
const MemoryStore = require('../../lib/memory');

describe('lib/memory-store.js', function() {

  let store = null;

  beforeEach(function() {
    store = MemoryStore();
  });

  describe('::upsert', function() {

    it('should insert a new value', function() {

      const bucket = 'test';
      const data   = { foo: 'bar', boo: 'fuck' };
      const keys   = [ 'boo' ];

      return store.upsert(bucket, keys, data)

        .then((x) => {

          expect(x).to.be.a('string');

          return store.getById(bucket, x);

        })

        .then((x) => {

          expect(x.foo).to.eql('bar');
          expect(x.boo).to.eql('fuck');

        });

    });

    it ('should update an existing value', function() {

      const bucket = 'test';
      const data   = { foo: 'random thing', bar_key: 'blah' };
      const update = { foo: 'another thing', bar_key: 'blah' };
      const keys   = [ 'bar_key' ];

      return store.insert(bucket, data)

        .then(() => store.upsert(bucket, keys, update))

        .then(store.getById(bucket))

        .then((x) => {

          expect(x.foo).to.eql('another thing');
          expect(x.bar_key).to.eql('blah');

        });

    });

  });

});
<commit_msg>Added a handful of tests to memory store.<commit_after>/*eslint-env node, mocha*/
const { expect }  = require('chai');
const demand = require('must');
const MemoryStore = require('../../lib/memory');

describe('lib/memory-store.js', function() {

  let store = null;

  beforeEach(function() {
    store = MemoryStore();
  });

  describe('::upsert', function() {

    it('should insert a new value', function() {

      const bucket = 'test';
      const data   = { foo: 'bar', boo: 'fuck' };
      const keys   = [ 'boo' ];

      return store.upsert(bucket, keys, data)

        .then((x) => {

          expect(x).to.be.a('string');

          return store.getById(bucket, x);

        })

        .then((x) => {

          expect(x.foo).to.eql('bar');
          expect(x.boo).to.eql('fuck');

        });

    });

    it ('should update an existing value', function() {

      const bucket = 'test';
      const data   = { foo: 'random thing', bar_key: 'blah' };
      const update = { foo: 'another thing', bar_key: 'blah' };
      const keys   = [ 'bar_key' ];

      return store.insert(bucket, data)

        .then(() => store.upsert(bucket, keys, update))

        .then(store.getById(bucket))

        .then((x) => {

          expect(x.foo).to.eql('another thing');
          expect(x.bar_key).to.eql('blah');

        });

    });

    it ('should throw an error when invalid bucket', function() {

      const bucket = 'test';
      const other_bucket = 'nottest';
      const data   = { foo: 'random thing', bar_key: 'blah' };
      const update = { foo: 'another thing', bar_key: 'blah' };
      const keys   = [ 'bar_key' ];

      return store.insert(bucket, data)

        .then(() => store.upsert(bucket, keys, update))

        // test with invalid bucket
        .then(store.getById(other_bucket))

        .then((x) => {

          expect(x.foo).to.eql('another thing');
          expect(x.bar_key).to.eql('blah');

        })

        .catch((err) => {

          // should throw an error for missing bucket
          (err.name).must.eql('Error');
          (err.message).must.eql(`Invalid Bucket: ${other_bucket}`);

        });

    });

  });

  describe('::projectAll', function() {

    it('should return proper projected keys', function() {

      const bucket = 'test';
      const data1  = { foo: 'random thing', bar_key: 'blah' };
      const data2  = { foo: 'another thing', bar_key: 'derp' };
      const data3  = { foo: 'yet another thing', bar_key: 'foo' };
      const keys   = [ 'bar_key' ];

      return store.insert(bucket, data1)
        .then(() => store.insert(bucket, data2))
        .then(() => store.insert(bucket, data3))

        .then(() => store.projectAll(bucket, keys))

        .then((x) => {

          x.must.have.length(3);
          x[0].must.include('blah');
          x[1].must.include('derp');
          x[2].must.include('foo');

        });

    });

  });

  describe('::findOneBy', function() {

    it('should get one item by prop and value', function() {

      const bucket = 'test';
      const data1 = { foo: 'random', bar_key: 'blah' };
      const data2 = { foo: 'randomer', bar_key: 'derp' };
      const proj = [ 'bar_key' ];

      return store.insert(bucket, data1)
        .then(() => store.insert(bucket, data2))

        .then(() => store.findOneBy(bucket, proj, 'bar_key', 'blah'))

        .then((x) => {

          x.must.be.an.object();
          x.must.include('blah');

        });

    });

    it('should return an error if it returns more than one obj', function() {

      const bucket = 'test';
      const data1 = { foo: 'random', bar_key: 'blah' };
      const data2 = { foo: 'randomer', bar_key: 'derp' };
      const data3 = { foo: 'randomest', bar_key: 'derp' };
      const proj = [ 'bar_key' ];

      return store.insert(bucket, data1)
        .then(() => store.insert(bucket, data2))
        .then(() => store.insert(bucket, data3))

        .then(() => store.findOneBy(bucket, proj, 'bar_key', 'derp'))

        .then((x) => {

          console.log(x);

        })
        .catch((e) => {

          (e.name).must.eql('TooManyRecords');

        });

    });

  });

});
<|endoftext|>


<commit_before>import should from 'should/as-function';
import sinon from 'sinon';
import _ from 'lodash';
import Syncano from '../../src/syncano';
import Request from '../../src/request';

describe('Request', function() {
  let config = null;
  let request = null;
  let stubs = null;

  beforeEach(function() {
    const methods = [
      'type',
      'accept',
      'timeout',
      'set',
      'query',
      'send',
      'attach',
      'end'
    ];

    stubs = _.reduce(methods, (result, method) => {
      result[`_${method}`] = (method === 'end') ? sinon.stub().yields(null, {ok: true}) : sinon.spy();
      result[method] = (...args) => {
        result[`_${method}`](...args);
        return result;
      }
      return result;
    }, {_init: sinon.spy()})

    config = Syncano({
      accountKey: '123'
    });

    request = Request
      .setRequestHandler(function(...args) {
        stubs._init(...args);
        return stubs;
      })
      .setConfig(config)();
  });

  describe('#buildUrl()', function() {

    it('should check "path" type', function() {
      should(function() {
        request.buildUrl(1);
      }).throw(new Error('"path" needs to be a string.'));
    });

    it('should ignore already joined path', function() {
      const expected = `${config.getBaseUrl()}v1/api/`;
      const outcome = request.buildUrl(expected);

      should(outcome).be.equal(expected);
    });

    it('should joined path with base url', function() {
      const path = 'v1/api/';
      const expected = `${config.getBaseUrl()}${path}`;
      const outcome = request.buildUrl(path);

      should(outcome).be.equal(expected);
    });

  });

  describe('#makeRequest()', function() {

    it('should validate "methodName" attribute', function() {
      should(request.makeRequest(null, '')).be.rejectedWith('Invalid request method: "null".');
      should(request.makeRequest('DUMMY', '')).be.rejectedWith('Invalid request method: "DUMMY".');
    });

    it('should validate "path" attribute', function() {
      should(request.makeRequest('GET', '')).be.rejectedWith('"path" is required.');
    });

    it('should change request type if attachment is present', function() {
      request.makeRequest('GET', '/v1/', {attachments: {a: 1, b: 2}}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.withArgs('form').calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(2);
    });

    it('should set proper headers if user key is present', function() {
      request.getConfig().setUserKey('321');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];

      should(spyCall).be.an.Object();
      should(spyCall).have.property('X-API-KEY').which.is.String().equal('123');
      should(spyCall).have.property('X-USER-KEY').which.is.String().equal('321');
    });

    it('should set proper headers if social token is present', function() {
      request.getConfig().setSocialToken('456').setAccountKey('123');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];
      should(spyCall).be.an.Object();
      should(spyCall).have.property('Authorization').which.is.String().equal('Token 456');
    });

    it('should set proper headers if accunt key is present', function() {
      request.getConfig().setAccountKey('111');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];
      should(spyCall).be.an.Object();
      should(spyCall).have.property('Authorization').which.is.String().equal('Token 111');
    });

    it('should set defaults', function() {
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.withArgs('GET', 'https://api.syncano.io/v1/').calledOnce).be.true();
      should(stubs._type.withArgs('json').calledOnce).be.true();
      should(stubs._accept.withArgs('json').calledOnce).be.true();
      should(stubs._timeout.withArgs(15000).calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);
    });

  });

  describe('#setRequestHandler()', function() {

    it('should allow to set request handler', function() {
      const handler = 1;
      const request = Request();

      should(request.getRequestHandler()).be.a.Function();
      request.setRequestHandler(handler);
      should(request.getRequestHandler()).be.equal(handler);
    })

  });

  describe('#getRequestHandler()', function() {

    it('should allow to get request handler', function() {
      should(Request().getRequestHandler()).be.a.Function();
    });

  });

  describe('#setRequestHandler() (STATIC)', function() {

    it('should allow to set request handler', function() {
      const handler = 1;
      const request = Request.setRequestHandler(handler);

      should(request.getRequestHandler()).be.equal(handler);
    })

  });

  describe('#getRequestHandler() (STATIC)', function() {

    it('should allow to get request handler', function() {
      should(Request.getRequestHandler()).be.a.Function();
    });

  });

});
<commit_msg>[LIB-478] tests<commit_after>import should from 'should/as-function';
import sinon from 'sinon';
import _ from 'lodash';
import Syncano from '../../src/syncano';
import Request from '../../src/request';

describe('Request', function() {
  let config = null;
  let request = null;
  let stubs = null;

  beforeEach(function() {
    const methods = [
      'type',
      'accept',
      'timeout',
      'set',
      'query',
      'send',
      'attach',
      'field',
      'end'
    ];

    stubs = _.reduce(methods, (result, method) => {
      result[`_${method}`] = (method === 'end') ? sinon.stub().yields(null, {ok: true}) : sinon.spy();
      result[method] = (...args) => {
        result[`_${method}`](...args);
        return result;
      }
      return result;
    }, {_init: sinon.spy()})

    config = Syncano({
      accountKey: '123'
    });

    request = Request
      .setRequestHandler(function(...args) {
        stubs._init(...args);
        return stubs;
      })
      .setConfig(config)();
  });

  describe('#buildUrl()', function() {

    it('should check "path" type', function() {
      should(function() {
        request.buildUrl(1);
      }).throw(new Error('"path" needs to be a string.'));
    });

    it('should ignore already joined path', function() {
      const expected = `${config.getBaseUrl()}v1/api/`;
      const outcome = request.buildUrl(expected);

      should(outcome).be.equal(expected);
    });

    it('should joined path with base url', function() {
      const path = 'v1/api/';
      const expected = `${config.getBaseUrl()}${path}`;
      const outcome = request.buildUrl(path);

      should(outcome).be.equal(expected);
    });

  });

  describe('#makeRequest()', function() {

    it('should validate "methodName" attribute', function() {
      should(request.makeRequest(null, '')).be.rejectedWith('Invalid request method: "null".');
      should(request.makeRequest('DUMMY', '')).be.rejectedWith('Invalid request method: "DUMMY".');
    });

    it('should validate "path" attribute', function() {
      should(request.makeRequest('GET', '')).be.rejectedWith('"path" is required.');
    });

    it('should change request type if attachment is present', function() {
      request.makeRequest('GET', '/v1/', {payload: {
        a: Syncano.file(1),
        b: Syncano.file(2),
        c: 2,
        d: 3
      }}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.withArgs('form').calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.false();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(2);
      should(stubs._field.callCount).be.equal(2);
    });

    it('should set proper headers if user key is present', function() {
      request.getConfig().setUserKey('321');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];

      should(spyCall).be.an.Object();
      should(spyCall).have.property('X-API-KEY').which.is.String().equal('123');
      should(spyCall).have.property('X-USER-KEY').which.is.String().equal('321');
    });

    it('should set proper headers if social token is present', function() {
      request.getConfig().setSocialToken('456').setAccountKey('123');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];
      should(spyCall).be.an.Object();
      should(spyCall).have.property('Authorization').which.is.String().equal('Token 456');
    });

    it('should set proper headers if accunt key is present', function() {
      request.getConfig().setAccountKey('111');
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.calledOnce).be.true();
      should(stubs._type.calledOnce).be.true();
      should(stubs._accept.calledOnce).be.true();
      should(stubs._timeout.calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);

      let spyCall = stubs._set.getCall(0).args[0];
      should(spyCall).be.an.Object();
      should(spyCall).have.property('Authorization').which.is.String().equal('Token 111');
    });

    it('should set defaults', function() {
      request.makeRequest('GET', '/v1/', {}, () => {});

      should(stubs._init.withArgs('GET', 'https://api.syncano.io/v1/').calledOnce).be.true();
      should(stubs._type.withArgs('json').calledOnce).be.true();
      should(stubs._accept.withArgs('json').calledOnce).be.true();
      should(stubs._timeout.withArgs(15000).calledOnce).be.true();
      should(stubs._set.calledOnce).be.true();
      should(stubs._query.calledOnce).be.true();
      should(stubs._send.calledOnce).be.true();
      should(stubs._end.calledOnce).be.true();
      should(stubs._attach.callCount).be.equal(0);
    });

  });

  describe('#setRequestHandler()', function() {

    it('should allow to set request handler', function() {
      const handler = 1;
      const request = Request();

      should(request.getRequestHandler()).be.a.Function();
      request.setRequestHandler(handler);
      should(request.getRequestHandler()).be.equal(handler);
    })

  });

  describe('#getRequestHandler()', function() {

    it('should allow to get request handler', function() {
      should(Request().getRequestHandler()).be.a.Function();
    });

  });

  describe('#setRequestHandler() (STATIC)', function() {

    it('should allow to set request handler', function() {
      const handler = 1;
      const request = Request.setRequestHandler(handler);

      should(request.getRequestHandler()).be.equal(handler);
    })

  });

  describe('#getRequestHandler() (STATIC)', function() {

    it('should allow to get request handler', function() {
      should(Request.getRequestHandler()).be.a.Function();
    });

  });

});
<|endoftext|>


<commit_before>// middleware-test.js
//
// Test the middleware module
//
// Copyright 2012, StatusNet Inc.
//
// 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.

var assert = require('assert'),
    vows = require('vows');

vows.describe('middleware module interface').addBatch({
    'When we check for a test suite': {
        topic: function() {
            return false;
        },
        'there is one': function(tsExists) {
            assert.isTrue(tsExists);
        }
    }
}).export(module);

<commit_msg>add the middleware tests<commit_after>// middleware-test.js
//
// Test the middleware module
//
// Copyright 2012, StatusNet Inc.
//
// 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.

var assert = require('assert'),
    vows = require('vows'),
    methodContext = require('./lib/methods').methodContext;

vows.describe('middleware module interface').addBatch({
    'When we require the middleware module': {
        topic: function() {
            return require('../lib/middleware');
        },
        'there is one': function(mw) {
            assert.isObject(mw);
        },
        'and we check its exports': methodContext(['reqUser',
                                                   'sameUser',
                                                   'maybeAuth',
                                                   'mustAuth',
                                                   'noUser',
                                                   'getCurrentUser',
                                                   'getSessionUser',
                                                   'checkCredentials'])
    }
}).export(module);

<|endoftext|>