<commit_before>import "../styles/DraggableTrack.css"
import {drag} from 'd3-drag';
import {select} from 'd3-selection';

import React from 'react';
import {mouse,event} from 'd3-selection';

export class DraggableDiv extends React.Component {
    constructor(props) {
        super(props);

        this.dragTopRight = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragTopRightFunc.bind(this));
        this.dragTopLeft = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragTopLeftFunc.bind(this));
        this.dragBottomRight = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragBottomRightFunc.bind(this));
        this.dragBottomLeft = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragBottomLeftFunc.bind(this));

        this.dragBottom = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragBottomFunc.bind(this));
        this.dragTop = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragTopFunc.bind(this));
        this.dragLeft = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragLeftFunc.bind(this));
        this.dragRight = drag()
                              .on('start', this.dragStart.bind(this))
                              .on('drag', this.dragRightFunc.bind(this));

        this.minWidth = 10;
        this.minHeight = 10;
        this.bottomHandleWidth = 20;

        this.state = {
            uid: props.uid,
            width: props.width,
            height: props.height,
            top: props.top,
            left: props.left
        }

        this.domBody = select('body').node()
    }

    componentWillReceiveProps(newProps) {
        if ('width' in newProps) {
            this.setState({width: newProps.width});
        }

        if ('height' in newProps) {
            this.setState({height: newProps.height});
        }

    }

    componentDidMount() {
        /*
        select(this.neHandle).call(this.dragTopRight);
        select(this.nwHandle).call(this.dragTopLeft);
        select(this.swHandle).call(this.dragBottomLeft);
        select(this.seHandle).call(this.dragBottomRight);
        */

        select(this.bottomHandle).call(this.dragBottom);
        select(this.topHandle).call(this.dragTop);

        select(this.leftHandle).call(this.dragLeft);
        select(this.rightHandle).call(this.dragRight);

        /*
        select(this.closeHandle).on('click', this.closeClicked.bind(this));
        select(this.rotateHandle).on('click', this.rotateClicked.bind(this));
        */
    }

    dragBottomFunc() {
        let ms = mouse(this.domBody);

        let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newState = {
            'height': newHeight};
        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged()
    }

    dragLeftFunc() {
        let ms = mouse(this.domBody);

        let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
        newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

        let newState = {
            'left': newLeft,
            'width': newWidth
        };
        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged()
    }

    dragTopFunc() {
        let ms = mouse(this.domBody);
        //console.log('ms:', ms);

        let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
        newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

        let newState = {'top': newTop,
            'height': newHeight };

        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged();
    }

    dragRightFunc() {
        let ms = mouse(this.domBody);

        let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newState = {
            'width': newWidth
        };

        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged();
    }

    dragBottomLeftFunc() {
        let ms = mouse(this.domBody);

        let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
        newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

        let newState = {'top': this.state.top,
            'left': newLeft,
            'width': newWidth,
            'height': newHeight};
        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged()
    }

    dragBottomRightFunc() {
        let ms = mouse(this.domBody);

        let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newState = {'top': this.state.top,
            'left': this.state.left,
            'width': newWidth,
            'height': newHeight };
        this.setState(newState);

        event.sourceEvent.stopPropagation();
        this.sizeChanged();
    }

    dragTopRightFunc() {
        let ms = mouse(this.domBody);
        //console.log('ms:', ms);

        let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
        newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

        let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newState = {'top': newTop,
            'left': this.state.left,
            'width': newWidth,
            'height': newHeight };

        this.setState(newState);
        //console.log('newHeight:', newHeight);

        event.sourceEvent.stopPropagation();
        this.sizeChanged();
    }

    dragTopLeftFunc() {
        let ms = mouse(this.domBody);

        let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
        newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

        let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
        newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

        let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
        newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

        let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
        newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

        let newState =  {'top': newTop,
                    'left': newLeft,
                    'width': newWidth,
                    'height': newHeight }

        this.setState(newState);

        event.sourceEvent.stopPropagation();

        this.sizeChanged();
    }

    dragStart() {
        this.dragStartMousePos = mouse(this.domBody);

        this.dragStartWidth = this.state.width;
        this.dragStartHeight = this.state.height;

        this.dragStartTop = this.state.top;
        this.dragStartLeft = this.state.left;

        event.sourceEvent.stopPropagation();

    }

    sizeChanged() {
        if ('sizeChanged' in this.props) {
            this.props.sizeChanged(this.state);
        }
    }

    rotateClicked() {
        this.props.trackRotated(this.state.uid);
    }

    closeClicked() {
        this.props.trackClosed(this.state.uid);
    }

    render() {
            let divStyle = { top: this.state.top,
                             left: this.state.left,
                             width: this.state.width,
                             height: this.state.height,
                             'backgroundColor': 'transparent',
                             "boxSizing": "border-box",
                             opacity: this.props.opacity };

            let resizeWidth = 10;
            let resizeHeight = 10;

            let bottomStyle = { position: 'absolute',
                            left: this.state.width / 2 - resizeWidth / 2,
                            bottom: 1,
                            width: resizeWidth,
                            opacity: 0.2,
                            height: 4,
                            borderBottom: '1px solid black',
                            borderTop: '1px solid black',
                            cursor: 'row-resize'};
            let topStyle = { position: 'absolute',
                            left: this.state.width / 2 - resizeWidth / 2,
                            top: 1,
                            width: resizeWidth,
                            opacity: 0.2,
                            height: 4,
                            borderBottom: '1px solid black',
                            borderTop: '1px solid black',
                            cursor: 'row-resize'};
            let leftStyle = { position: 'absolute',
                            left: 1,
                            top: this.state.height / 2 - resizeHeight / 2,
                            opacity: 0.2,
                            width: 4,
                            height: resizeHeight,
                            borderLeft: '1px solid black',
                            borderRight: '1px solid black',
                            cursor: 'col-resize'};
            let rightStyle = { position: 'absolute',
                            right: 1,
                            opacity: 0.2,
                            top: this.state.height / 2 - resizeHeight / 2,
                            width: 4,
                            height: resizeHeight,
                            borderLeft: '1px solid black',
                            borderRight: '1px solid black',
                            cursor: 'col-resize'};

            let resizeHandleDivs = {
                'bottom': (

 this.bottomHandle = c} />
                ),
                'top': (

 this.topHandle = c} />
                ),
                'right': (

 this.rightHandle = c} />
                ),
                'left': (

 this.leftHandle = c} />
                )
            }
            let resizeHandles = [...this.props.resizeHandles].map(x => resizeHandleDivs[x]);

            return (

 this.divContainer = c} className={this.props.className}>

                        {resizeHandles}

                   );
    }
}

export default DraggableDiv;
<commit_msg>Awesomefy code style. Fix all ESLint issues<commit_after>import { drag } from 'd3-drag';
import { event, mouse, select } from 'd3-selection';
import PropTypes from 'prop-types';
import React from 'react';

import '../styles/DraggableTrack.css';

export class DraggableDiv extends React.Component {
  constructor(props) {
    super(props);

    this.dragTopRight = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragTopRightFunc.bind(this));
    this.dragTopLeft = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragTopLeftFunc.bind(this));
    this.dragBottomRight = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragBottomRightFunc.bind(this));
    this.dragBottomLeft = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragBottomLeftFunc.bind(this));

    this.dragBottom = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragBottomFunc.bind(this));
    this.dragTop = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragTopFunc.bind(this));
    this.dragLeft = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragLeftFunc.bind(this));
    this.dragRight = drag()
      .on('start', this.dragStart.bind(this))
      .on('drag', this.dragRightFunc.bind(this));

    this.minWidth = 10;
    this.minHeight = 10;
    this.bottomHandleWidth = 20;

    this.state = {
      uid: this.props.uid,
      width: this.props.width,
      height: this.props.height,
      top: this.props.top,
      left: this.props.left
    }

    this.domBody = select('body').node()
  }

  /* -------------------------- Life Cycle Methods -------------------------- */

  componentDidMount() {
    select(this.bottomHandle).call(this.dragBottom);
    select(this.topHandle).call(this.dragTop);

    select(this.leftHandle).call(this.dragLeft);
    select(this.rightHandle).call(this.dragRight);
  }

  componentWillReceiveProps(newProps) {
    if ('width' in newProps) {
      this.setState({width: newProps.width});
    }

    if ('height' in newProps) {
      this.setState({height: newProps.height});
    }
  }

  /* ---------------------------- Custom Methods ---------------------------- */

  dragBottomFunc() {
    let ms = mouse(this.domBody);

    let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newState = {
      'height': newHeight};
    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged()
  }

  dragLeftFunc() {
    let ms = mouse(this.domBody);

    let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
    newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

    let newState = {
      'left': newLeft,
      'width': newWidth
    };
    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged()
  }

  dragTopFunc() {
    let ms = mouse(this.domBody);
    //console.log('ms:', ms);

    let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
    newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

    let newState = {'top': newTop,
      'height': newHeight };

    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged();
  }

  dragRightFunc() {
    let ms = mouse(this.domBody);

    let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newState = {
      'width': newWidth
    };

    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged();
  }

  dragBottomLeftFunc() {
    let ms = mouse(this.domBody);

    let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
    newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

    let newState = {'top': this.state.top,
      'left': newLeft,
      'width': newWidth,
      'height': newHeight};
    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged()
  }

  dragBottomRightFunc() {
    let ms = mouse(this.domBody);

    let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newHeight = this.dragStartHeight + (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newState = {'top': this.state.top,
      'left': this.state.left,
      'width': newWidth,
      'height': newHeight };
    this.setState(newState);

    event.sourceEvent.stopPropagation();
    this.sizeChanged();
  }

  dragTopRightFunc() {
    let ms = mouse(this.domBody);
    //console.log('ms:', ms);

    let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
    newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

    let newWidth = this.dragStartWidth + (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newState = {'top': newTop,
      'left': this.state.left,
      'width': newWidth,
      'height': newHeight };

    this.setState(newState);
    //console.log('newHeight:', newHeight);

    event.sourceEvent.stopPropagation();
    this.sizeChanged();
  }

  dragTopLeftFunc() {
    let ms = mouse(this.domBody);

    let newWidth = this.dragStartWidth - (ms[0] - this.dragStartMousePos[0]);
    newWidth = newWidth > this.minWidth ? newWidth : this.minWidth;

    let newLeft = this.dragStartLeft + ms[0] - this.dragStartMousePos[0];
    newLeft = newWidth > this.minWidth ? newLeft : this.dragStartLeft + this.dragStartWidth - this.minWidth;

    let newHeight = this.dragStartHeight - (ms[1] - this.dragStartMousePos[1]);
    newHeight = newHeight > this.minHeight ? newHeight : this.minHeight;

    let newTop = this.dragStartTop + ms[1] - this.dragStartMousePos[1];
    newTop = newHeight > this.minHeight ? newTop : this.dragStartTop + this.dragStartHeight - this.minHeight;

    let newState =  {'top': newTop,
          'left': newLeft,
          'width': newWidth,
          'height': newHeight }

    this.setState(newState);

    event.sourceEvent.stopPropagation();

    this.sizeChanged();
  }

  dragStart() {
    this.dragStartMousePos = mouse(this.domBody);

    this.dragStartWidth = this.state.width;
    this.dragStartHeight = this.state.height;

    this.dragStartTop = this.state.top;
    this.dragStartLeft = this.state.left;

    event.sourceEvent.stopPropagation();

  }

  sizeChanged() {
    if ('sizeChanged' in this.props) {
      this.props.sizeChanged(this.state);
    }
  }

  rotateClicked() {
    this.props.trackRotated(this.state.uid);
  }

  closeClicked() {
    this.props.trackClosed(this.state.uid);
  }

  /* ------------------------------ Rendering ------------------------------- */

  render() {
    const divStyle = {
      top: this.state.top,
      left: this.state.left,
      width: this.state.width,
      height: this.state.height,
      backgroundColor: 'transparent',
      boxSizing: "border-box",
      opacity: this.props.opacity
    };

    const resizeWidth = 10;
    const resizeHeight = 10;

    const bottomStyle = {
      position: 'absolute',
      left: this.state.width / 2 - resizeWidth / 2,
      bottom: 1,
      width: resizeWidth,
      opacity: 0.2,
      height: 4,
      borderBottom: '1px solid black',
      borderTop: '1px solid black',
      cursor: 'row-resize'
    };
    const topStyle = {
      position: 'absolute',
      left: this.state.width / 2 - resizeWidth / 2,
      top: 1,
      width: resizeWidth,
      opacity: 0.2,
      height: 4,
      borderBottom: '1px solid black',
      borderTop: '1px solid black',
      cursor: 'row-resize'
    };
    const leftStyle = {
      position: 'absolute',
      left: 1,
      top: this.state.height / 2 - resizeHeight / 2,
      opacity: 0.2,
      width: 4,
      height: resizeHeight,
      borderLeft: '1px solid black',
      borderRight: '1px solid black',
      cursor: 'col-resize'
    };
    const rightStyle = {
      position: 'absolute',
      right: 1,
      opacity: 0.2,
      top: this.state.height / 2 - resizeHeight / 2,
      width: 4,
      height: resizeHeight,
      borderLeft: '1px solid black',
      borderRight: '1px solid black',
      cursor: 'col-resize'
    };

    const resizeHandleDivs = {
      'bottom': (

 this.bottomHandle = c}
          style={bottomStyle}
        />
      ),
      'top': (

 this.topHandle = c}
          style={topStyle}
        />
      ),
      'right': (

 this.rightHandle = c}
          style={rightStyle}
        />
      ),
      'left': (

 this.leftHandle = c}
          style={leftStyle}
        />
      )
    }
    const resizeHandles = [...this.props.resizeHandles].map(x => resizeHandleDivs[x]);

    return (

 this.divContainer = c}
        style={divStyle}
      >
        {resizeHandles}

    );
  }
}

DraggableDiv.propTypes = {
  className: PropTypes.string,
  height: PropTypes.number,
  left: PropTypes.number,
  opacity: PropTypes.number,
  resizeHandles: PropTypes.object,
  sizeChanged: PropTypes.func,
  top: PropTypes.number,
  trackClosed: PropTypes.func,
  trackRotated: PropTypes.func,
  uid: PropTypes.string,
  width: PropTypes.number
}

export default DraggableDiv;
<|endoftext|>


<commit_before>'use strict';

Crafty.defineScene('Space', function () {
  // constructor
  Crafty.background('#111');

  var showPlayerHud = function (playerIndex) {
    var x = 10 + (playerIndex * 350);
    var player = players[playerIndex].player;

    var score = Crafty.e('2D, Canvas, Text')
      .attr({ x: x, y: 10, w: 150 }).text('Score: ' + player.points)
      .textColor(player.color())
      .textFont({
        size: '20px',
        weight: 'bold',
        family: 'Courier new'
      });
    player.bind('UpdatePoints', function (e) {
      score.text('Score: ' + e.points);
    });

    var lives = Crafty.e('2D, Canvas, Text')
      .attr({ x: x, y: 30, w: 150 }).text('Lives: ' + player.lives)
      .textColor(player.color())
      .textFont({
        size: '20px',
        weight: 'bold',
        family: 'Courier new'
      });
    player.bind('UpdateLives', function (e) {
      if (e.lives === 0) {
        lives.text('Game Over');
      } else {
        lives.text('Lives: ' + e.lives);
      }
    });

    players[playerIndex].score = score;
    players[playerIndex].lives = lives;
  };

  Crafty.e('Keyboard')
    .bind('KeyDown', function (e) {
      if (e.key === Crafty.keys.SPACE) {
        spawnPlayer('keyboard', 1);
        this.destroy();
      }
    });
  Crafty.e('Gamepad')
    .gamepad(0)
    .bind('GamepadKeyChange', function (e) {
      if (e.button === 0 && e.pressed) {
        spawnPlayer('gamepad', 0);
        this.destroy();
      }
    });
  Crafty.e('Gamepad')
    .gamepad(1)
    .bind('GamepadKeyChange', function (e) {
      if (e.button === 0 && e.pressed) {
        spawnPlayer('gamepad', 1);
        this.destroy();
      }
    });

  var players = [];
  var playerColors = ['#F00', '#0F0', '#F0F'];

  var spawnPlayer = function (controlType, controlIndex) {
    var player = Crafty.e('Player')
      .attr({ x: 140, y: 320, playerIndex: players.length })
      .color(playerColors[players.length]);

    players.push({
      controlType: controlType,
      controlIndex: controlIndex,
      player: player
    });
    showPlayerHud(players.length - 1);
    Crafty.trigger('PlayerStart', player);

    if (controlType === 'keyboard') {
      if (controlIndex === 1) {
        player.addComponent('Multiway, Keyboard')
          .multiway({ y: 3, x: 1 }, {
            UP_ARROW: -90,
            DOWN_ARROW: 90,
            LEFT_ARROW: 180,
            RIGHT_ARROW: 0
          })
          .bind('KeyDown', function (e) {
            if (e.key === Crafty.keys.SPACE) { this.shoot(); }
          });
      }
    }
    if (controlType === 'gamepad') {
      player.addComponent('GamepadMultiway, Gamepad')
        .gamepad(controlIndex)
        .gamepadMultiway({
          speed: { y: 3, x: 1 },
          gamepadIndex: controlIndex
        })
        .bind('GamepadKeyChange', function (e) {
          if (e.button === 0 && e.pressed) { this.shoot(); }
        });
    }
  };

  // Create edges around playfield to 'capture' the player
  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 50, w: 900, h: 2});

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 750, w: 900, h: 2});

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 50, w: 2, h: 730 });

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 910, y: 50, w: 2, h: 730 });

  var gamespeed = 0.4; // pixels / milisecond
  var nextEnemySpawn = 5000;
  var startTime = null;
  Crafty.bind('PlayerStart', function () {
    if (players.length === 1) {
      startTime = (new Date()).getTime();

      Crafty.bind('EnterFrame', function () {
        // TODO: Refactor this to be able to act on game pauses

        var x = ((new Date()).getTime() - startTime) * gamespeed;
        if (nextEnemySpawn < x) {
          var y = Crafty.math.randomInt(40, 720);

          Crafty.e('Enemy').enemy({ x: 1200, y: y });
          nextEnemySpawn += Crafty.math.randomInt(100, 2000);
          console.log('Time to spawn!');
        }
      });
    }
  });

  Crafty.bind('PlayerDied', function (player) {
    Crafty.enterScene('GameOver', { score: 'later!' });
  });

}, function () {
  // destructor
  Crafty.unbind('EnterFrame');
});
<commit_msg>Fix jshint<commit_after>'use strict';

Crafty.defineScene('Space', function () {
  // constructor
  Crafty.background('#111');

  var showPlayerHud = function (playerIndex) {
    var x = 10 + (playerIndex * 350);
    var player = players[playerIndex].player;

    var score = Crafty.e('2D, Canvas, Text')
      .attr({ x: x, y: 10, w: 150 }).text('Score: ' + player.points)
      .textColor(player.color())
      .textFont({
        size: '20px',
        weight: 'bold',
        family: 'Courier new'
      });
    player.bind('UpdatePoints', function (e) {
      score.text('Score: ' + e.points);
    });

    var lives = Crafty.e('2D, Canvas, Text')
      .attr({ x: x, y: 30, w: 150 }).text('Lives: ' + player.lives)
      .textColor(player.color())
      .textFont({
        size: '20px',
        weight: 'bold',
        family: 'Courier new'
      });
    player.bind('UpdateLives', function (e) {
      if (e.lives === 0) {
        lives.text('Game Over');
      } else {
        lives.text('Lives: ' + e.lives);
      }
    });

    players[playerIndex].score = score;
    players[playerIndex].lives = lives;
  };

  Crafty.e('Keyboard')
    .bind('KeyDown', function (e) {
      if (e.key === Crafty.keys.SPACE) {
        spawnPlayer('keyboard', 1);
        this.destroy();
      }
    });
  Crafty.e('Gamepad')
    .gamepad(0)
    .bind('GamepadKeyChange', function (e) {
      if (e.button === 0 && e.pressed) {
        spawnPlayer('gamepad', 0);
        this.destroy();
      }
    });
  Crafty.e('Gamepad')
    .gamepad(1)
    .bind('GamepadKeyChange', function (e) {
      if (e.button === 0 && e.pressed) {
        spawnPlayer('gamepad', 1);
        this.destroy();
      }
    });

  var players = [];
  var playerColors = ['#F00', '#0F0', '#F0F'];

  var spawnPlayer = function (controlType, controlIndex) {
    var player = Crafty.e('Player')
      .attr({ x: 140, y: 320, playerIndex: players.length })
      .color(playerColors[players.length]);

    players.push({
      controlType: controlType,
      controlIndex: controlIndex,
      player: player
    });
    showPlayerHud(players.length - 1);
    Crafty.trigger('PlayerStart', player);

    if (controlType === 'keyboard') {
      if (controlIndex === 1) {
        player.addComponent('Multiway, Keyboard')
          .multiway({ y: 3, x: 1 }, {
            UP_ARROW: -90,
            DOWN_ARROW: 90,
            LEFT_ARROW: 180,
            RIGHT_ARROW: 0
          })
          .bind('KeyDown', function (e) {
            if (e.key === Crafty.keys.SPACE) { this.shoot(); }
          });
      }
    }
    if (controlType === 'gamepad') {
      player.addComponent('GamepadMultiway, Gamepad')
        .gamepad(controlIndex)
        .gamepadMultiway({
          speed: { y: 3, x: 1 },
          gamepadIndex: controlIndex
        })
        .bind('GamepadKeyChange', function (e) {
          if (e.button === 0 && e.pressed) { this.shoot(); }
        });
    }
  };

  // Create edges around playfield to 'capture' the player
  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 50, w: 900, h: 2});

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 750, w: 900, h: 2});

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 10, y: 50, w: 2, h: 730 });

  Crafty.e('2D, Canvas, Edge')
    .attr({x: 910, y: 50, w: 2, h: 730 });

  var gamespeed = 0.4; // pixels / milisecond
  var nextEnemySpawn = 5000;
  var startTime = null;
  Crafty.bind('PlayerStart', function () {
    if (players.length === 1) {
      startTime = (new Date()).getTime();

      Crafty.bind('EnterFrame', function () {
        // TODO: Refactor this to be able to act on game pauses

        var x = ((new Date()).getTime() - startTime) * gamespeed;
        if (nextEnemySpawn < x) {
          var y = Crafty.math.randomInt(40, 720);

          Crafty.e('Enemy').enemy({ x: 1200, y: y });
          nextEnemySpawn += Crafty.math.randomInt(100, 2000);
          console.log('Time to spawn!');
        }
      });
    }
  });

  Crafty.bind('PlayerDied', function () {
    Crafty.enterScene('GameOver', { score: 'later!' });
  });

}, function () {
  // destructor
  Crafty.unbind('EnterFrame');
});
<|endoftext|>


<commit_before>'use strict';

angular.module('fec3App')
    .service('dalService', function($filter, $http) {
        var that = this;
        this.demo = false;

        if (that.demo) {
            this.secondAuthenURL = "https://sso-devt.true.th:11443/"; //DEV
            //this.secondAuthenURL = "https://xxo-uat.true.th:11443/SSORESTFul/"; //UAT
            //this.secondAuthenURL = "https://xxo-uat.true.th:11443/SSORESTFul/";//PRO
        } else {
            //for get by env
            this.secondAuthenURL = getSecondAuthenURL();
        }

        this.callServiceGet = function(target, headers, fnCallback) {
            var requestData = {
                target: target
            };
            var httpRequest = {
                method: "POST",
                url: getURL('services/gateway/get.service'),
                data: requestData,
                timeout: 180000
            };
            if (headers != null) {
                httpRequest.headers = headers;
            }
            if (localStorage.getItem('orderId')) {
                httpRequest.headers = {
                    'WEB_METHOD_CHANNEL': 'WEBUI',
                    'E2E_REFID': localStorage.getItem('orderId')
                };
            }
            //console.log(httpRequest);
            $http(httpRequest).success(function(data) {
                console.log('success ::: callServiceGet');
                console.log(requestData.target);
                console.log(data);

                if (data.status == "SUCCESSFUL") {
                    fnCallback({
                        status: true,
                        data: data,
                        error: "",
                        msgErr: ""
                    });
                } else {
                    fnCallback({
                        status: false,
                        data: data,
                        error: "ERROR",
                        msgErr: ""
                    });

                }
            }).error(function(data, status, errorJSON) {
                console.log('error ::: callServiceGet');
                console.log(requestData.target);
                console.log("ERROR");
                console.log(status, data, errorJSON);
                fnCallback({
                    status: false,
                    data: data,
                    error: status,
                    msgErr: status == 0 ? "Can not connect!" : ""
                });

            });
        };

        this.callServicePost = function(data, headers, fnCallback) {
            console.log(data);
            var httpRequest = {
                method: "POST",
                url: getURL('services/gateway/post.service'),
                data: data,
                timeout: 180000
            };

            if (headers != null) {
                //httpRequest.headers = headers;
            }
            if (localStorage.getItem('orderId')) {
                httpRequest.headers = {
                    'WEB_METHOD_CHANNEL': 'WEBUI',
                    'E2E_REFID': localStorage.getItem('orderId')
                };
            }
            $http(httpRequest).success(function(data) {
                console.log(data);
                if (data.status == "SUCCESSFUL") {
                    fnCallback({
                        status: true,
                        data: data,
                        error: "",
                        msgErr: ""
                    });
                } else {
                    fnCallback({
                        status: false,
                        data: data,
                        error: "ERROR",
                        msgErr: ""
                    });

                }
            }).error(function(dataErr, status) {
                console.log("ERROR");
                console.log(status, dataErr);
                fnCallback({
                    status: false,
                    data: "",
                    error: status,
                    msgErr: status == 0 ? "Can not connect!" : ""
                });

            });
        };

        this.second_authen = function(trx_id, fnCallback) {
            var target = 'security/identity/second_authen?trx_id=' + trx_id + '&app_id=WEBUI';
            var headers = {
                'WEB_METHOD_CHANNEL': 'WEBUI'
            };
            if (!that.demo) {
                that.callServiceGet(target, headers, function(result) {
                    fnCallback(result.data);
                });
            } else {
                var data = {
                    "status": "SUCCESSFUL",
                    "trx-id": "6OKMIN4J8HDZ",
                    "process-instance": "psaapdv1 (instance: SFF_node1)",
                    "response-data": [{
                        "loginName": "UserTSM4",
                        "employeeId": "10000004",
                        "authRes": {
                            "app": "WEBUI",
                            "info": "COMPANY=True Information Technology company limited;;DEPARTMENT=Information Technology (Infrastructure);;DIVISION=--;;EMPLOYEEID=10000004;;ENGLISHNAME=User Test4;;FIRSTNAME=User;;INITIALS=Mr.;;LOGINNAME=UserTSM4;;MAIL=usr_tsm4@Truecorp.co.th;;POSITION=IT Security Administration;;ROLES=CN=R-TSM-USER2,OU=Groups,DC=essoad,DC=th|CN=R-INCT-SALESUP,OU=Unused,OU=Groups,DC=essoad,DC=th;;SECTION=IT Security Administration;;SHOPCODE=80000001|80000001|80000005|80000008;;SURNAME=Test4;;THAINAME=นาย ไทย test4",
                            "responseCode": "200",
                            "responseDesc": "Success",
                            "trxID": "71e5603394694c40a744739188496b83"
                        }
                    }]
                };
                var data2 = {
                    "status": "UNSUCCESSFUL",
                    "display-messages": [{
                        "message": "",
                        "message-code": "1",
                        "message-type": "ERROR",
                        "en-message": "Data not found",
                        "th-message": "Data not found",
                        "technical-message": ""
                    }, {
                        "message": "",
                        "message-code": "1",
                        "message-type": "ERROR",
                        "en-message": "สิทธิการใช้งานต่างประเทศจะถูกยกเลิก",
                        "th-message": "สิทธิการใช้งานต่างประเทศจะถูกยกเลิก",
                        "technical-message": ""
                    }],
                    "trx-id": "6OKMIN4J8HDZ",
                    "process-instance": "psaapdv1 (instance: SFF_node1)",
                    "response-data": [{
                        "loginName": "UserTSM4",
                        "employeeId": "10000004",
                        "authRes": {
                            "app": "WEBUI",
                            "info": "COMPANY=True Information Technology company limited;;DEPARTMENT=Information Technology (Infrastructure);;DIVISION=--;;EMPLOYEEID=10000004;;ENGLISHNAME=User Test4;;FIRSTNAME=User;;INITIALS=Mr.;;LOGINNAME=UserTSM4;;MAIL=usr_tsm4@Truecorp.co.th;;POSITION=IT Security Administration;;ROLES=CN=R-TSM-USER2,OU=Groups,DC=essoad,DC=th|CN=R-INCT-SALESUP,OU=Unused,OU=Groups,DC=essoad,DC=th;;SECTION=IT Security Administration;;SHOPCODE=80000001|80000001|80000005|80000008;;SURNAME=Test4;;THAINAME=นาย ไทย test4",
                            "responseCode": "200",
                            "responseDesc": "Success",
                            "trxID": "71e5603394694c40a744739188496b83"
                        }
                    }]
                };
                if (trx_id == "4EONTQNYU4VZ") {
                    fnCallback(data);
                } else {
                    fnCallback(data2);
                }

            }

        };
    });<commit_msg>update onDemo<commit_after>'use strict';

angular.module('fec3App')
    .service('dalService', function($filter, $http) {
        var that = this;
        this.demo = true;

        if (that.demo) {
            this.secondAuthenURL = "https://sso-devt.true.th:11443/"; //DEV
            //this.secondAuthenURL = "https://xxo-uat.true.th:11443/SSORESTFul/"; //UAT
            //this.secondAuthenURL = "https://xxo-uat.true.th:11443/SSORESTFul/";//PRO
        } else {
            //for get by env
            this.secondAuthenURL = getSecondAuthenURL();
        }

        this.callServiceGet = function(target, headers, fnCallback) {
            var requestData = {
                target: target
            };
            var httpRequest = {
                method: "POST",
                url: getURL('services/gateway/get.service'),
                data: requestData,
                timeout: 180000
            };
            if (headers != null) {
                httpRequest.headers = headers;
            }
            if (localStorage.getItem('orderId')) {
                httpRequest.headers = {
                    'WEB_METHOD_CHANNEL': 'WEBUI',
                    'E2E_REFID': localStorage.getItem('orderId')
                };
            }
            //console.log(httpRequest);
            $http(httpRequest).success(function(data) {
                console.log('success ::: callServiceGet');
                console.log(requestData.target);
                console.log(data);

                if (data.status == "SUCCESSFUL") {
                    fnCallback({
                        status: true,
                        data: data,
                        error: "",
                        msgErr: ""
                    });
                } else {
                    fnCallback({
                        status: false,
                        data: data,
                        error: "ERROR",
                        msgErr: ""
                    });

                }
            }).error(function(data, status, errorJSON) {
                console.log('error ::: callServiceGet');
                console.log(requestData.target);
                console.log("ERROR");
                console.log(status, data, errorJSON);
                fnCallback({
                    status: false,
                    data: data,
                    error: status,
                    msgErr: status == 0 ? "Can not connect!" : ""
                });

            });
        };

        this.callServicePost = function(data, headers, fnCallback) {
            console.log(data);
            var httpRequest = {
                method: "POST",
                url: getURL('services/gateway/post.service'),
                data: data,
                timeout: 180000
            };

            if (headers != null) {
                //httpRequest.headers = headers;
            }
            if (localStorage.getItem('orderId')) {
                httpRequest.headers = {
                    'WEB_METHOD_CHANNEL': 'WEBUI',
                    'E2E_REFID': localStorage.getItem('orderId')
                };
            }
            $http(httpRequest).success(function(data) {
                console.log(data);
                if (data.status == "SUCCESSFUL") {
                    fnCallback({
                        status: true,
                        data: data,
                        error: "",
                        msgErr: ""
                    });
                } else {
                    fnCallback({
                        status: false,
                        data: data,
                        error: "ERROR",
                        msgErr: ""
                    });

                }
            }).error(function(dataErr, status) {
                console.log("ERROR");
                console.log(status, dataErr);
                fnCallback({
                    status: false,
                    data: "",
                    error: status,
                    msgErr: status == 0 ? "Can not connect!" : ""
                });

            });
        };

        this.second_authen = function(trx_id, fnCallback) {
            var target = 'security/identity/second_authen?trx_id=' + trx_id + '&app_id=WEBUI';
            var headers = {
                'WEB_METHOD_CHANNEL': 'WEBUI'
            };
            if (!that.demo) {
                that.callServiceGet(target, headers, function(result) {
                    fnCallback(result.data);
                });
            } else {
                var data = {
                    "status": "SUCCESSFUL",
                    "trx-id": "6OKMIN4J8HDZ",
                    "process-instance": "psaapdv1 (instance: SFF_node1)",
                    "response-data": [{
                        "loginName": "UserTSM4",
                        "employeeId": "10000004",
                        "authRes": {
                            "app": "WEBUI",
                            "info": "COMPANY=True Information Technology company limited;;DEPARTMENT=Information Technology (Infrastructure);;DIVISION=--;;EMPLOYEEID=10000004;;ENGLISHNAME=User Test4;;FIRSTNAME=User;;INITIALS=Mr.;;LOGINNAME=UserTSM4;;MAIL=usr_tsm4@Truecorp.co.th;;POSITION=IT Security Administration;;ROLES=CN=R-TSM-USER2,OU=Groups,DC=essoad,DC=th|CN=R-INCT-SALESUP,OU=Unused,OU=Groups,DC=essoad,DC=th;;SECTION=IT Security Administration;;SHOPCODE=80000001|80000001|80000005|80000008;;SURNAME=Test4;;THAINAME=นาย ไทย test4",
                            "responseCode": "200",
                            "responseDesc": "Success",
                            "trxID": "71e5603394694c40a744739188496b83"
                        }
                    }]
                };
                var data2 = {
                    "status": "UNSUCCESSFUL",
                    "display-messages": [{
                        "message": "",
                        "message-code": "1",
                        "message-type": "ERROR",
                        "en-message": "Data not found",
                        "th-message": "Data not found",
                        "technical-message": ""
                    }, {
                        "message": "",
                        "message-code": "1",
                        "message-type": "ERROR",
                        "en-message": "สิทธิการใช้งานต่างประเทศจะถูกยกเลิก",
                        "th-message": "สิทธิการใช้งานต่างประเทศจะถูกยกเลิก",
                        "technical-message": ""
                    }],
                    "trx-id": "6OKMIN4J8HDZ",
                    "process-instance": "psaapdv1 (instance: SFF_node1)",
                    "response-data": [{
                        "loginName": "UserTSM4",
                        "employeeId": "10000004",
                        "authRes": {
                            "app": "WEBUI",
                            "info": "COMPANY=True Information Technology company limited;;DEPARTMENT=Information Technology (Infrastructure);;DIVISION=--;;EMPLOYEEID=10000004;;ENGLISHNAME=User Test4;;FIRSTNAME=User;;INITIALS=Mr.;;LOGINNAME=UserTSM4;;MAIL=usr_tsm4@Truecorp.co.th;;POSITION=IT Security Administration;;ROLES=CN=R-TSM-USER2,OU=Groups,DC=essoad,DC=th|CN=R-INCT-SALESUP,OU=Unused,OU=Groups,DC=essoad,DC=th;;SECTION=IT Security Administration;;SHOPCODE=80000001|80000001|80000005|80000008;;SURNAME=Test4;;THAINAME=นาย ไทย test4",
                            "responseCode": "200",
                            "responseDesc": "Success",
                            "trxID": "71e5603394694c40a744739188496b83"
                        }
                    }]
                };
                if (trx_id == "4EONTQNYU4VZ") {
                    fnCallback(data);
                } else {
                    fnCallback(data2);
                }

            }

        };
    });<|endoftext|>


<commit_before>'use strict';

angular.module('yapp')
  .factory('pwdService', function($http, $location, $rootScope) {
    var p = {

      createSession: function(secret) {
        var req = {
          method: 'POST',
          url: 'http://labs.play-with-docker.com',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          data: window.encodeURIComponent(secret)
        };
        return $http(req).then(function(response) {
          let s = {id: response.data.session_id, hostname: response.data.hostname};
          localStorage.setItem('session', JSON.stringify(s));
          s.instances = {};
          return s;
        });
      },

      getSession: function() {
        let session = JSON.parse(localStorage.getItem('session'));
        if (!session) {
          return new Promise(function(resolve,reject){reject()});
        }
        return $http.get($location.protocol() + '://' + session.hostname + '/sessions/' + session.id).then(function(response) {
          session.instances = response.data.instances;
          return session;
        });
      },

      exec: function(name, data) {
        return new Promise(function(resolve, reject) {
          pwd.exec(name, data, function(err) {
            if (err) {
              console.log('exec failed:', err);
              return reject(err);
            }
              return resolve();
          });
        });
      },

      init: function(session) {
        // init the pwd session
        return  new Promise(function(resolve, reject) {
          pwd.init(session.id, {baseUrl: 'http://'+ session.hostname, ImageName: 'franela/ucp:2.1.5'}, function() {
            resolve();
          });
        })
        .then(function() {
          if (Object.keys(session.instances).length == 0) {
            waitingDialog.show('Please wait, your session will be ready in a minute.');
            let ucpInstance;
            // create UCP node
            return p.newInstance()
              .then(function(instance) {
                session.instances[instance.name] = instance;
                ucpInstance = instance;
                var ucp_cmd = [
                  '/deployucp.sh'
                ];

                return p.exec(ucpInstance.name, ucp_cmd).then(function(){
                  waitingDialog.hide();
                });

              });
              // DTR stuff
              //.then(function() {
                 //create DTR node
                //return p.newInstance()
                  //.then(function(instance) {
                    //session.instances[instance.name] = instance;
                     //setup UCP and DTR
                  //});
              //});
            } else {
              return new Promise(function(resolve, reject){resolve()});
            }
        });
      },

      newInstance: function() {
        return new Promise(function(resolve, reject) {
          pwd.createInstance(function(err, instance) {
            if (err) {
              return reject(err);
            }
              return resolve(instance);
          });
        });
      }
    };

    return p;
  });
<commit_msg>Encode secret properly<commit_after>'use strict';

angular.module('yapp')
  .factory('pwdService', function($http, $location, $rootScope) {
    var p = {

      createSession: function(secret) {
        var data = encodeURIComponent('g-recaptcha-response') + '=' + encodeURIComponent(secret);
        var req = {
          method: 'POST',
          url: 'http://localhost.com',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          data: data
        };
        return $http(req).then(function(response) {
          let s = {id: response.data.session_id, hostname: response.data.hostname};
          localStorage.setItem('session', JSON.stringify(s));
          s.instances = {};
          return s;
        });
      },

      getSession: function() {
        let session = JSON.parse(localStorage.getItem('session'));
        if (!session) {
          return new Promise(function(resolve,reject){reject()});
        }
        return $http.get($location.protocol() + '://' + session.hostname + '/sessions/' + session.id).then(function(response) {
          session.instances = response.data.instances;
          return session;
        });
      },

      exec: function(name, data) {
        return new Promise(function(resolve, reject) {
          pwd.exec(name, data, function(err) {
            if (err) {
              console.log('exec failed:', err);
              return reject(err);
            }
              return resolve();
          });
        });
      },

      init: function(session) {
        // init the pwd session
        return  new Promise(function(resolve, reject) {
          pwd.init(session.id, {baseUrl: 'http://'+ session.hostname, ImageName: 'franela/ucp:2.1.5'}, function() {
            resolve();
          });
        })
        .then(function() {
          if (Object.keys(session.instances).length == 0) {
            waitingDialog.show('Please wait, your session will be ready in a minute.');
            let ucpInstance;
            // create UCP node
            return p.newInstance()
              .then(function(instance) {
                session.instances[instance.name] = instance;
                ucpInstance = instance;
                var ucp_cmd = [
                  '/deployucp.sh'
                ];

                return p.exec(ucpInstance.name, ucp_cmd).then(function(){
                  waitingDialog.hide();
                });

              });
              // DTR stuff
              //.then(function() {
                 //create DTR node
                //return p.newInstance()
                  //.then(function(instance) {
                    //session.instances[instance.name] = instance;
                     //setup UCP and DTR
                  //});
              //});
            } else {
              return new Promise(function(resolve, reject){resolve()});
            }
        });
      },

      newInstance: function() {
        return new Promise(function(resolve, reject) {
          pwd.createInstance(function(err, instance) {
            if (err) {
              return reject(err);
            }
              return resolve(instance);
          });
        });
      }
    };

    return p;
  });
<|endoftext|>


<commit_before>'use strict';

module.exports = ['$q', '$log', '$http', '$window', authService];

function authService($q, $log, $http, $window){
  $log.debug('authService');

  let service = {};
  let token = null;

  function setToken(_token){
    $log.debug('authService.setToken()');

    if (! _token) {
      return $q.reject(new Error('no token'));
    }

    $window.localStorage.setItem('token', _token);
    token = _token;
    return $q.resolve(token);
  }

  service.getToken = function(){
    $log.debug('authService.getToken');
    if (token) {
      return $q.resolve(token);
    }
    token = $window.localStorage.getItem('token');
    if (token) return $q.resolve(token);
    return $q.reject(new Error('token not found'));
  };

  service.logout = function(){
    $log.debug('authService.logout()');

    $window.localStorage.removeItem('token');
    token = null;
    return $q.resolve();
  };

  service.signup = function(user) {
    $log.debug('authService.signup()');

    let url = `${__API_URL__}/api/signup`;
    let config = {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      }
    };

    return $http.post(url, user, config)
    .then( res => {
      $log.log('success', res.data);
      return setToken(res.data);
    })
    .catch(err => {
      $log.error('failure', err.message);
      return $q.reject(err);
    });
  };

  service.login = function(user){
    $log.debug('authService.login()');

    let url = `${__API_URL__}/api/signin`;
    let base64 = $window.btoa(`${user.username}:${user.password}`);
    let config = {
      headers: {
        Accept: 'application/json',
        Authorization: `Basic ${base64}`,
      }
    };

    return $http.get(url, config)
    .then( res => {
      $log.log('success', res.data);
      return setToken(res.data);
    })
    .catch( err => {
      $log.error(err.message);
      return $q.reject(err);
    });
  };

  return service;
}
<commit_msg>TODO about username -> email<commit_after>'use strict';

module.exports = ['$q', '$log', '$http', '$window', authService];

function authService($q, $log, $http, $window){
  $log.debug('authService');

  let service = {};
  let token = null;

  function setToken(_token){
    $log.debug('authService.setToken()');

    if (! _token) {
      return $q.reject(new Error('no token'));
    }

    $window.localStorage.setItem('token', _token);
    token = _token;
    return $q.resolve(token);
  }

  service.getToken = function(){
    $log.debug('authService.getToken');
    if (token) {
      return $q.resolve(token);
    }
    token = $window.localStorage.getItem('token');
    if (token) return $q.resolve(token);
    return $q.reject(new Error('token not found'));
  };

  service.logout = function(){
    $log.debug('authService.logout()');

    $window.localStorage.removeItem('token');
    token = null;
    return $q.resolve();
  };

  service.signup = function(user) {
    $log.debug('authService.signup()');

    let url = `${__API_URL__}/api/signup`;
    let config = {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      }
    };

    return $http.post(url, user, config)
    .then( res => {
      $log.log('success', res.data);
      return setToken(res.data);
    })
    .catch(err => {
      $log.error('failure', err.message);
      return $q.reject(err);
    });
  };

  service.login = function(user){
    $log.debug('authService.login()');

    let url = `${__API_URL__}/api/signin`;
    //TODO: username -> email
    let base64 = $window.btoa(`${user.username}:${user.password}`);
    let config = {
      headers: {
        Accept: 'application/json',
        Authorization: `Basic ${base64}`,
      }
    };

    return $http.get(url, config)
    .then( res => {
      $log.log('success', res.data);
      return setToken(res.data);
    })
    .catch( err => {
      $log.error(err.message);
      return $q.reject(err);
    });
  };

  return service;
}
<|endoftext|>


<commit_before>
import AWS from "aws-sdk";
import _ from "underscore";
import leftPad from "left-pad";
import {PassThrough} from "stream";
import munger from "mpeg-munger";

import BaseVertex from "./BaseVertex";
import SK from "../../sk";
import ENV from "../../env";

// TODO: library this somewhere useful
const dateStamp = function() {
  const now = new Date();
  const date = [ now.getFullYear(), now.getMonth() + 1, now.getDate() ];
  return date.map((s) => leftPad(s, 2, 0)).join("-");
};

const timeStamp = function() {
  const now = new Date();
  const time = [ now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds() ];
  return time.map((s) => leftPad(s, 2, 0)).join("-");
};

let s3Streamer;
if (ENV.AWS_ACCESS_KEY_ID && ENV.AWS_SECRET_ACCESS_KEY && ENV.AWS_USER_UPLOAD_BUCKET && ENV.AWS_USER_UPLOAD_PREFIX && ENV.AWS_USER_UPLOAD_REGION) {
  s3Streamer = new AWS.S3({
    accessKeyId: ENV.AWS_ACCESS_KEY_ID,
    secretAccessKey: ENV.AWS_SECRET_ACCESS_KEY,
    region: ENV.AWS_USER_UPLOAD_REGION,
  });
}

const CHUNK_UPLOAD_INTERVAL = 5/* min*/ * 60/* sec*/ * 1000/*ms*/;

export default class FileOutputVertex extends BaseVertex {
  constructor({id}) {
    if (!s3Streamer) {
      throw new Error("FileOutputVertex created, but missing required environment variables");
    }
    super({id});

    this.uploads = [];
    this.chunkIdx = 0;
    this.videoInputURL = this.transport.getInputURL();
    this.audioInputURL = this.transport.getInputURL();
    SK.vertices.update(id, {
      inputs: [{
        name: "default",
        sockets: [{
          url: this.videoInputURL,
          type: "video"
        }, {
          url: this.audioInputURL,
          type: "audio"
        }]
      }]
    })
    .then(() => {
      this.init();
    })
    .catch((err) => {
      this.error(err);
    });
  }

  init() {
    this.started = false;
    const date = dateStamp();
    const time = timeStamp();
    const folder = date.replace(/-/g, "/");
    const prefix = `${folder}/${date}-${time}-${this.doc.title}`;

    // Transport streams and upload streams have the same indices.
    this.transportStreams = [];

    this.count = 0;
    this.doc.inputs.forEach((input) => {
      input.sockets.forEach((socket) => {
        const filePrefix = `${prefix}-${input.name}-${socket.type}`;
        const transportStream = new this.transport.InputStream({url: socket.url});
        const mpegStream = munger(); // Just to make sure we cut files at 188-byte intervals.
        transportStream.pipe(mpegStream);
        mpegStream.once("readable", this.startIdempotent.bind(this));
        this.uploads.push({filePrefix, transportStream, mpegStream});
      });
    });
    this.uploadNextChunk();
  }

  /**
   * We don't want to sit around uploading empty files before we have the start of the stream. So,
   * this function is run when we first see some data from the transport stream.
   */
  startIdempotent() {
    if (!this.started) {
      this.started = true;
      this.uploadNextChunk();
    }
  }

  uploadNextChunk() {
    this.uploads.forEach((upload) => {
      let {filePrefix, transportStream, uploadStream, mpegStream, passThroughStream} = upload;

      // If we have an old upload stream, unpipe it.
      if (passThroughStream) {
        mpegStream.unpipe(passThroughStream);
        passThroughStream.end();
      }

      // S3's "managed uploads" advertise that they work like streams (they have pipe and unpipe)
      // but don't implement the full spec. Let's put a passthrough stream in front of it so we
      // can treat it like one.
      const fileName = `${filePrefix}-${leftPad(this.chunkIdx, 6, 0)}.ts`;
      this.info(`Uploading to ${fileName}`);

      upload.passThroughStream = PassThrough();
      mpegStream.pipe(upload.passThroughStream);
      upload.uploadStream = s3Streamer.upload({
        Bucket: ENV.AWS_USER_UPLOAD_BUCKET,
        Key: ENV.AWS_USER_UPLOAD_PREFIX + fileName,
        Body: upload.passThroughStream
      });
      upload.uploadStream.on("httpUploadProgress", (data) => {
        const kb = Math.floor(data.loaded/1024);
        this.updateSelf({
          status: "ACTIVE",
          timemark: `${kb}k uploaded`
        });
      });
      upload.uploadStream.send();
    });
    this.chunkIdx += 1;
    this.chunkTimeoutHandle = setTimeout(this.uploadNextChunk.bind(this), CHUNK_UPLOAD_INTERVAL);
  }

  cleanup() {
    super.cleanup();
    if (this.chunkTimeoutHandle) {
      clearTimeout(this.chunkTimeoutHandle);
    }
    this.transportStreams.forEach(({transportStream, passThroughStream}) => {
      transportStream.stop();
      passThroughStream.end();
    });
  }
}
<commit_msg>Fix uploading the last file chunk<commit_after>
import AWS from "aws-sdk";
import _ from "underscore";
import leftPad from "left-pad";
import {PassThrough} from "stream";
import munger from "mpeg-munger";

import BaseVertex from "./BaseVertex";
import SK from "../../sk";
import ENV from "../../env";

// TODO: library this somewhere useful
const dateStamp = function() {
  const now = new Date();
  const date = [ now.getFullYear(), now.getMonth() + 1, now.getDate() ];
  return date.map((s) => leftPad(s, 2, 0)).join("-");
};

const timeStamp = function() {
  const now = new Date();
  const time = [ now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds() ];
  return time.map((s) => leftPad(s, 2, 0)).join("-");
};

let s3Streamer;
if (ENV.AWS_ACCESS_KEY_ID && ENV.AWS_SECRET_ACCESS_KEY && ENV.AWS_USER_UPLOAD_BUCKET && ENV.AWS_USER_UPLOAD_PREFIX && ENV.AWS_USER_UPLOAD_REGION) {
  s3Streamer = new AWS.S3({
    accessKeyId: ENV.AWS_ACCESS_KEY_ID,
    secretAccessKey: ENV.AWS_SECRET_ACCESS_KEY,
    region: ENV.AWS_USER_UPLOAD_REGION,
  });
}

const CHUNK_UPLOAD_INTERVAL = 5/* min*/ * 60/* sec*/ * 1000/*ms*/;

export default class FileOutputVertex extends BaseVertex {
  constructor({id}) {
    if (!s3Streamer) {
      throw new Error("FileOutputVertex created, but missing required environment variables");
    }
    super({id});

    this.uploads = [];
    this.chunkIdx = 0;
    this.videoInputURL = this.transport.getInputURL();
    this.audioInputURL = this.transport.getInputURL();
    SK.vertices.update(id, {
      inputs: [{
        name: "default",
        sockets: [{
          url: this.videoInputURL,
          type: "video"
        }, {
          url: this.audioInputURL,
          type: "audio"
        }]
      }]
    })
    .then(() => {
      this.init();
    })
    .catch((err) => {
      this.error(err);
    });
  }

  init() {
    this.started = false;
    const date = dateStamp();
    const time = timeStamp();
    const folder = date.replace(/-/g, "/");
    const prefix = `${folder}/${date}-${time}-${this.doc.title}`;

    this.count = 0;
    this.doc.inputs.forEach((input) => {
      input.sockets.forEach((socket) => {
        const filePrefix = `${ENV.AWS_USER_UPLOAD_PREFIX}${prefix}-${input.name}-${socket.type}`;
        const transportStream = new this.transport.InputStream({url: socket.url});
        const mpegStream = munger(); // Just to make sure we cut files at 188-byte intervals.
        transportStream.pipe(mpegStream);
        mpegStream.once("readable", this.startIdempotent.bind(this));
        this.uploads.push({filePrefix, transportStream, mpegStream});
      });
    });
    this.uploadNextChunk();
  }

  /**
   * We don't want to sit around uploading empty files before we have the start of the stream. So,
   * this function is run when we first see some data from the transport stream.
   */
  startIdempotent() {
    if (!this.started) {
      this.started = true;
      this.uploadNextChunk();
    }
  }

  uploadNextChunk() {
    this.uploads.forEach((upload) => {
      let {filePrefix, transportStream, uploadStream, mpegStream, passThroughStream} = upload;

      // If we have an old upload stream, unpipe it.
      if (passThroughStream) {
        mpegStream.unpipe(passThroughStream);
        passThroughStream.end();
      }

      // S3's "managed uploads" advertise that they work like streams (they have pipe and unpipe)
      // but don't implement the full spec. Let's put a passthrough stream in front of it so we
      // can treat it like one.
      const fileName = `${filePrefix}-${leftPad(this.chunkIdx, 6, 0)}.ts`;
      this.info(`Uploading to ${fileName}`);

      upload.passThroughStream = PassThrough();
      mpegStream.pipe(upload.passThroughStream);
      upload.uploadStream = s3Streamer.upload({
        Bucket: ENV.AWS_USER_UPLOAD_BUCKET,
        Key:  fileName,
        Body: upload.passThroughStream
      });
      upload.uploadStream.on("httpUploadProgress", (data) => {
        const kb = Math.floor(data.loaded/1024);
        this.updateSelf({
          status: "ACTIVE",
          timemark: `${kb}k uploaded`
        });
      });
      upload.uploadStream.on("error", (err) => {
        this.error("Error uploading to S3", err);
      });
      upload.uploadStream.send();
    });
    this.chunkIdx += 1;
    this.chunkTimeoutHandle = setTimeout(this.uploadNextChunk.bind(this), CHUNK_UPLOAD_INTERVAL);
  }

  cleanup() {
    super.cleanup();
    if (this.chunkTimeoutHandle) {
      clearTimeout(this.chunkTimeoutHandle);
    }
    this.uploads.forEach(({transportStream, passThroughStream, mpegStream}) => {
      mpegStream.unpipe(passThroughStream);
      passThroughStream.end();
      transportStream.stop();
    });
  }
}
<|endoftext|>


<commit_before>import { List, Map, fromJS } from 'immutable';
import paletteReducer from './paletteReducer';
import framesReducer from './framesReducer';
import {
  GRID_INITIAL_COLOR,
  applyBucket as applyBucketToGrid,
  drawPixel as drawPixelToGrid
} from './pixelGrid';
import drawingToolReducer from './drawingToolReducer';
import * as types from '../actions/actionTypes';

function setInitialState(state, action) {
  const cellSize = 10;
  const frames = framesReducer(state, action);

  const initialState = {
    frames,
    cellSize,
    loading: false,
    notifications: List(),
    duration: 1
  };

  return state.merge(initialState);
}

function changeDimensions(state, action) {
  return state.merge({
    frames: framesReducer(state.get('frames'), action)
  });
}

function drawPixel(state, color, id) {
  const frames = state.get('frames');
  const newFrames = frames.updateIn(
    ['list', frames.get('activeIndex'), 'grid'],
    grid => drawPixelToGrid(grid, color, id)
  );
  return state.set('frames', newFrames);
}

function getCellColor({ color }) {
  return color || GRID_INITIAL_COLOR;
}

export function applyBucket(state, action) {
  const { id, paletteColor } = action;
  const cellColor = getCellColor(action);
  const {
    columns, rows, list, activeIndex
  } = state.get('frames').toObject();
  const activeGrid = list.getIn([activeIndex, 'grid']);

  const newGrid = applyBucketToGrid(activeGrid, {
    id, paletteColor, cellColor, columns, rows
  });

  return state.setIn(['frames', 'list', activeIndex, 'grid'], newGrid);
}

function drawCell(state, action) {
  const { id } = action;
  const drawingTool = state.get('drawingTool');
  let color = '';

  if (drawingTool === 'EYEDROPPER') {
    return state;
  } else if (drawingTool === 'BUCKET') {
    return applyBucket(state, action);
  }
  // regular cell paint
  if (drawingTool !== 'ERASER') {
    color = action.paletteColor;
  }
  return drawPixel(state, color, id);
}

function setDrawing(state, action) {
  const {
    frames, cellSize, columns, rows
  } = action;
  return state.merge({
    frames: fromJS({
      list: frames,
      columns,
      rows,
      activeIndex: 0
    }),
    cellSize
  });
}

function setCellSize(state, cellSize) {
  return state.merge({ cellSize });
}

function resetGrid(state, action) {
  return state.merge({
    frames: framesReducer(state.get('frames'), action)
  });
}

function showSpinner(state) {
  return state.merge({ loading: true });
}

function hideSpinner(state) {
  return state.merge({ loading: false });
}

function sendNotification(state, message) {
  return state.merge({
    notifications: message === '' ? List() : List([{ message, id: 0 }])
  });
}

function changeActiveFrame(state, action) {
  return state.update('frames', frames => framesReducer(frames, action));
}

function createNewFrame(state, action) {
  const frames = state.get('frames');
  return state.set('frames', framesReducer(frames, action));
}

function deleteFrame(state, action) {
  const frames = state.get('frames');
  return state.set('frames', framesReducer(frames, action));
}

function duplicateFrame(state, action) {
  const frames = state.get('frames');
  return state.set('frames', framesReducer(frames, action));
}

function setDuration(state, duration) {
  return state.merge({ duration });
}

function changeFrameInterval(state, frameIndex, interval) {
  return state.merge({
    frames: state.get('frames').updateIn(
      [frameIndex, 'interval'],
      () => interval
    )
  });
}

function updateGridBoundaries(state, action) {
  const {
    x, y, width, height
  } = action.gridElement.getBoundingClientRect();
  return state.set('gridBoundaries', {
    x, y, width, height
  });
}

function partialReducer(state, action) {
  switch (action.type) {
    case types.SET_INITIAL_STATE:
      return setInitialState(state, action);
    case types.CHANGE_DIMENSIONS:
      return changeDimensions(state, action);
    case types.DRAW_CELL:
      return drawCell(state, action);
    case types.SET_DRAWING:
      return setDrawing(state, action);
    case types.SET_CELL_SIZE:
      return setCellSize(state, action.cellSize);
    case types.SET_RESET_GRID:
      return resetGrid(state);
    case types.SHOW_SPINNER:
      return showSpinner(state);
    case types.HIDE_SPINNER:
      return hideSpinner(state);
    case types.SEND_NOTIFICATION:
      return sendNotification(state, action.message);
    case types.CHANGE_ACTIVE_FRAME:
      return changeActiveFrame(state, action);
    case types.CREATE_NEW_FRAME:
      return createNewFrame(state, action);
    case types.DELETE_FRAME:
      return deleteFrame(state, action);
    case types.DUPLICATE_FRAME:
      return duplicateFrame(state, action);
    case types.SET_DURATION:
      return setDuration(state, action.duration);
    case types.CHANGE_FRAME_INTERVAL:
      return changeFrameInterval(state, action.frameIndex, action.interval);
    case types.NEW_PROJECT:
      return setInitialState(state, action);
    case types.UPDATE_GRID_BOUNDARIES:
      return updateGridBoundaries(state, action);
    default:
  }
  return state;
}

export default function (state = Map(), action) {
  return partialReducer(state, action).merge({
    drawingTool: drawingToolReducer(state.get('drawingTool'), action),
    palette: paletteReducer(state.get('palette'), action)
  });
}
<commit_msg>decouple frame reducer and main reducer<commit_after>import { List, Map, fromJS } from 'immutable';
import paletteReducer from './paletteReducer';
import framesReducer from './framesReducer';
import {
  GRID_INITIAL_COLOR,
  applyBucket as applyBucketToGrid,
  drawPixel as drawPixelToGrid
} from './pixelGrid';
import drawingToolReducer from './drawingToolReducer';
import * as types from '../actions/actionTypes';

function setInitialState(state) {
  const cellSize = 10;

  const initialState = {
    cellSize,
    loading: false,
    notifications: List(),
    duration: 1
  };

  return state.merge(initialState);
}

function drawPixel(state, color, id) {
  const frames = state.get('frames');
  const newFrames = frames.updateIn(
    ['list', frames.get('activeIndex'), 'grid'],
    grid => drawPixelToGrid(grid, color, id)
  );
  return state.set('frames', newFrames);
}

function getCellColor({ color }) {
  return color || GRID_INITIAL_COLOR;
}

export function applyBucket(state, action) {
  const { id, paletteColor } = action;
  const cellColor = getCellColor(action);
  const {
    columns, rows, list, activeIndex
  } = state.get('frames').toObject();
  const activeGrid = list.getIn([activeIndex, 'grid']);

  const newGrid = applyBucketToGrid(activeGrid, {
    id, paletteColor, cellColor, columns, rows
  });

  return state.setIn(['frames', 'list', activeIndex, 'grid'], newGrid);
}

function drawCell(state, action) {
  const { id } = action;
  const drawingTool = state.get('drawingTool');
  let color = '';

  if (drawingTool === 'EYEDROPPER') {
    return state;
  } else if (drawingTool === 'BUCKET') {
    return applyBucket(state, action);
  }
  // regular cell paint
  if (drawingTool !== 'ERASER') {
    color = action.paletteColor;
  }
  return drawPixel(state, color, id);
}

function setDrawing(state, action) {
  const {
    frames, cellSize, columns, rows
  } = action;
  return state.merge({
    frames: fromJS({
      list: frames,
      columns,
      rows,
      activeIndex: 0
    }),
    cellSize
  });
}

function setCellSize(state, cellSize) {
  return state.merge({ cellSize });
}

function showSpinner(state) {
  return state.merge({ loading: true });
}

function hideSpinner(state) {
  return state.merge({ loading: false });
}

function sendNotification(state, message) {
  return state.merge({
    notifications: message === '' ? List() : List([{ message, id: 0 }])
  });
}

function setDuration(state, duration) {
  return state.merge({ duration });
}

function changeFrameInterval(state, frameIndex, interval) {
  return state.merge({
    frames: state.get('frames').updateIn(
      [frameIndex, 'interval'],
      () => interval
    )
  });
}

function updateGridBoundaries(state, action) {
  const {
    x, y, width, height
  } = action.gridElement.getBoundingClientRect();
  return state.set('gridBoundaries', {
    x, y, width, height
  });
}

function partialReducer(state, action) {
  switch (action.type) {
    case types.SET_INITIAL_STATE:
      return setInitialState(state);
    case types.DRAW_CELL:
      return drawCell(state, action);
    case types.SET_DRAWING:
      return setDrawing(state, action);
    case types.SET_CELL_SIZE:
      return setCellSize(state, action.cellSize);
    case types.SHOW_SPINNER:
      return showSpinner(state);
    case types.HIDE_SPINNER:
      return hideSpinner(state);
    case types.SEND_NOTIFICATION:
      return sendNotification(state, action.message);
    case types.SET_DURATION:
      return setDuration(state, action.duration);
    case types.CHANGE_FRAME_INTERVAL:
      return changeFrameInterval(state, action.frameIndex, action.interval);
    case types.NEW_PROJECT:
      return setInitialState(state);
    case types.UPDATE_GRID_BOUNDARIES:
      return updateGridBoundaries(state, action);
    default:
  }
  return state;
}

export default function (state = Map(), action) {
  return partialReducer(state, action).merge({
    drawingTool: drawingToolReducer(state.get('drawingTool'), action),
    palette: paletteReducer(state.get('palette'), action),
    frames: framesReducer(state.get('frames'), action)
  });
}
<|endoftext|>


<commit_before>/**
 * `core/user` data store: Surveys tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import {
	createTestRegistry,
	muteFetch,
} from '../../../../../tests/js/utils';
import {
	act,
} from '../../../../../tests/js/test-utils';
import { STORE_NAME } from './constants';

describe( 'core/user surveys', () => {
	let registry;

	beforeEach( () => {
		registry = createTestRegistry();
	} );

	const survey = {
		survey_payload: 'foo',
		session: 'bar',
	};
	const surveyTriggerEndpoint = /^\/google-site-kit\/v1\/core\/user\/data\/survey-trigger/;
	const surveyEventEndpoint = /^\/google-site-kit\/v1\/core\/user\/data\/survey-event/;

	describe( 'actions', () => {
		describe( 'triggerSurvey', () => {
			it( 'throws an error when parameters are missing or incorrect', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey();
				} ).toThrow( 'triggerID is required and must be a string' );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'ABCD', false );
				} ).toThrow( 'options must be an object' );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'ABCD', { ttl: 'a' } );
				} ).toThrow( 'options.ttl must be a number' );
			} );

			it( 'does not throw an error when parameters are correct', () => {
				muteFetch( surveyTriggerEndpoint, [] );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'a' );
				} ).not.toThrow();
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } );
				} ).not.toThrow();
			} );

			it( 'makes network requests to endpoints', async () => {
				muteFetch( surveyTriggerEndpoint, [] );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );

		describe( 'sendSurveyEvent', () => {
			it( 'throws an error when parameters are missing or incorrect', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent();
				} ).toThrow( 'eventID is required and must be a string' );
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'a', 'b' );
				} ).toThrow( 'eventData must be an object' );
			} );

			it( 'does not throw an error when parameters are correct', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'a' );
				} ).not.toThrow();
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'b', { foo: 'bar' } );
				} ).not.toThrow();
			} );

			it( 'makes network requests to endpoints', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				muteFetch( surveyEventEndpoint, {} );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'a', { ttl: 1 } ) );
				await act( () => registry.dispatch( STORE_NAME ).sendSurveyEvent( 'b', { foo: 'bar' } ) );
				expect( fetchMock ).toHaveFetched( surveyEventEndpoint, { body: { data: { event: { b: { foo: 'bar' } }, session: 'bar' } } } );
			} );
		} );
	} );

	describe( 'selectors', () => {
		describe( 'getCurrentSurvey', () => {
			it( 'returns null when no current survey is set', async () => {
				expect( registry.select( STORE_NAME ).getCurrentSurvey() ).toEqual( null );
			} );

			it( 'returns the current survey when it is set', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( registry.select( STORE_NAME ).getCurrentSurvey() ).toEqual( survey.survey_payload );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );
		describe( 'getCurrentSurveySession', () => {
			it( 'returns null when no current survey session is set', async () => {
				expect( registry.select( STORE_NAME ).getCurrentSurveySession() ).toEqual( null );
			} );

			it( 'returns the error once set', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( registry.select( STORE_NAME ).getCurrentSurveySession() ).toEqual( survey.session );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );
	} );
} );
<commit_msg>Update assets/js/googlesitekit/datastore/user/surveys.test.js<commit_after>/**
 * `core/user` data store: Surveys tests.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * Internal dependencies
 */
import {
	createTestRegistry,
	muteFetch,
} from '../../../../../tests/js/utils';
import {
	act,
} from '../../../../../tests/js/test-utils';
import { STORE_NAME } from './constants';

describe( 'core/user surveys', () => {
	let registry;

	beforeEach( () => {
		registry = createTestRegistry();
	} );

	const survey = {
		survey_payload: 'foo',
		session: 'bar',
	};
	const surveyTriggerEndpoint = /^\/google-site-kit\/v1\/core\/user\/data\/survey-trigger/;
	const surveyEventEndpoint = /^\/google-site-kit\/v1\/core\/user\/data\/survey-event/;

	describe( 'actions', () => {
		describe( 'triggerSurvey', () => {
			it( 'throws an error when parameters are missing or incorrect', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey();
				} ).toThrow( 'triggerID is required and must be a string' );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'ABCD', false );
				} ).toThrow( 'options must be an object' );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'ABCD', { ttl: 'a' } );
				} ).toThrow( 'options.ttl must be a number' );
			} );

			it( 'does not throw an error when parameters are correct', () => {
				muteFetch( surveyTriggerEndpoint, [] );
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'a' );
				} ).not.toThrow();
				expect( () => {
					registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } );
				} ).not.toThrow();
			} );

			it( 'makes network requests to endpoints', async () => {
				muteFetch( surveyTriggerEndpoint, [] );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );

		describe( 'sendSurveyEvent', () => {
			it( 'throws an error when parameters are missing or incorrect', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent();
				} ).toThrow( 'eventID is required and must be a string' );
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'a', 'b' );
				} ).toThrow( 'eventData must be an object' );
			} );

			it( 'does not throw an error when parameters are correct', () => {
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'a' );
				} ).not.toThrow();
				expect( () => {
					registry.dispatch( STORE_NAME ).sendSurveyEvent( 'b', { foo: 'bar' } );
				} ).not.toThrow();
			} );

			it( 'makes network requests to endpoints', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				muteFetch( surveyEventEndpoint, {} );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'a', { ttl: 1 } ) );
				await act( () => registry.dispatch( STORE_NAME ).sendSurveyEvent( 'b', { foo: 'bar' } ) );
				expect( fetchMock ).toHaveFetched( surveyEventEndpoint, { body: { data: { event: { b: { foo: 'bar' } }, session: 'bar' } } } );
			} );
		} );
	} );

	describe( 'selectors', () => {
		describe( 'getCurrentSurvey', () => {
			it( 'returns null when no current survey is set', async () => {
				expect( registry.select( STORE_NAME ).getCurrentSurvey() ).toEqual( null );
			} );

			it( 'returns the current survey when it is set', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( registry.select( STORE_NAME ).getCurrentSurvey() ).toEqual( survey.survey_payload );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );

		describe( 'getCurrentSurveySession', () => {
			it( 'returns null when no current survey session is set', async () => {
				expect( registry.select( STORE_NAME ).getCurrentSurveySession() ).toEqual( null );
			} );

			it( 'returns the error once set', async () => {
				muteFetch( surveyTriggerEndpoint, survey );
				await act( () => registry.dispatch( STORE_NAME ).triggerSurvey( 'b', { ttl: 1 } ) );
				expect( registry.select( STORE_NAME ).getCurrentSurveySession() ).toEqual( survey.session );
				expect( fetchMock ).toHaveFetched( surveyTriggerEndpoint, { body: { data: { triggerID: 'b' } } } );
			} );
		} );
	} );
} );
<|endoftext|>