<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import Box from './Box';
import Tiles from './Tiles';
import Tile from './Tile';
import Button from './Button';
import Previous from './icons/base/Previous';
import Next from './icons/base/Next';
import { findScrollParents } from '../utils/DOM';
import CSSClassnames from '../utils/CSSClassnames';
import Intl from '../utils/Intl';
import { announce } from '../utils/Announcer';
import Props from '../utils/Props';

const CLASS_ROOT = CSSClassnames.CAROUSEL;

export default class Carousel extends Component {

  constructor(props, context) {
    super(props, context);

    this._onSelect = this._onSelect.bind(this);
    this._stopAutoplay = this._stopAutoplay.bind(this);
    this._startAutoplay = this._startAutoplay.bind(this);
    this._onResize = this._onResize.bind(this);
    this._slidePrev = this._slidePrev.bind(this);
    this._slideNext = this._slideNext.bind(this);
    this._handleScroll = this._handleScroll.bind(this);

    this.state = {
      activeIndex: props.activeIndex || 0,
      hideControls: ! props.persistentNav,
      priorIndex: 0,
      sequence: 1,
      width: 0,
      slide: false
    };
  }

  componentDidMount () {
    if (this.carouselRef) {
      this.setState({
        width: this.carouselRef.offsetWidth
      });

      window.addEventListener('resize', this._onResize);

      const Hammer = require('hammerjs');
      this.hammer = new Hammer(this.carouselRef);
      this._updateHammer();

      this._handleScroll();
      const scrollParents = findScrollParents(this.carouselRef);
      scrollParents.forEach((scrollParent) => {
        scrollParent.addEventListener('scroll', this._handleScroll);
      }, this);
    }
  }

  componentWillReceiveProps(nextProps) {
    if ((nextProps.activeIndex || 0 === nextProps.activeIndex) &&
      this.state.activeIndex !== nextProps.activeIndex) {
      this.setState({ activeIndex: nextProps.activeIndex });
    }
  }

  componentDidUpdate () {
    this._updateHammer();
  }

  componentWillUnmount () {
    clearInterval(this._slideAnimation);

    window.removeEventListener('resize', this._onResize);

    const scrollParents = findScrollParents(this.carouselRef);
    scrollParents.forEach((scrollParent) => {
      scrollParent.removeEventListener('scroll', this._handleScroll);
    }, this);

    this._unmountHammer();
  }

  _unmountHammer () {
    if (this.hammer) {
      this.hammer.stop();
      this.hammer.destroy();
    }
    this.hammer = undefined;
  }

  _updateHammer () {
    if (this.hammer) {
      this.hammer.get('swipe').set({
        direction: Hammer.DIRECTION_HORIZONTAL
      });

      this.hammer.off('panend');
      this.hammer.on('panend', (event) => {
        if (event.direction === 4) {
          this._slidePrev();
        } else if (event.direction === 2) {
          this._slideNext();
        }
      });
    }
  }

  _handleScroll () {
    const { autoplay } = this.props;
    const { slide } = this.state;
    const viewportHeight = document.documentElement.clientHeight;
    const carouselTopPosition = this.carouselRef.getBoundingClientRect().top;
    const carouselHeight = this.carouselRef.offsetHeight;
    const startScroll = viewportHeight - (carouselHeight / 2);

    if (autoplay && carouselTopPosition <= startScroll &&
      carouselTopPosition >= -carouselHeight / 2) {
      if (slide === false) {
        this._setSlideInterval();
        this.setState({
          slide: true
        });
      }
    } else {
      clearInterval(this._slideAnimation);
      this.setState({
        slide: false
      });
    }
  }

  _setSlideInterval () {
    const { autoplaySpeed } = this.props;
    clearInterval(this._slideAnimation);
    this._slideAnimation = setInterval(function () {
      const { children, infinite } = this.props;
      const { activeIndex } = this.state;
      const { intl } = this.context;
      const numSlides = children.length;
      const index = (activeIndex + 1) % numSlides;
      const announceFunc = () => {
        const slideNumber = Intl.getMessage(intl, 'Slide Number', {
          slideNumber: this.state.activeIndex + 1
        });
        const activatedMessage = Intl.getMessage(intl, 'Activated');
        announce(`${slideNumber} ${activatedMessage}`, 'polite');
      };

      if (! this.props.hasOwnProperty('activeIndex')) {
        this.setState({
          activeIndex: index
        }, announceFunc );
      }
      if (!infinite && activeIndex === numSlides - 1) {
        clearInterval(this._slideAnimation);
      }

      if (this.props.onActive) {
        this.props.onActive(index);
        announceFunc();
      }
    }.bind(this), autoplaySpeed);
  }

  _onSelect (index) {
    if (! this.props.hasOwnProperty('activeIndex')
        && index !== this.state.activeIndex) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _stopAutoplay () {
    const { autoplay, persistentNav } = this.props;
    if (autoplay) {
      clearInterval(this._slideAnimation);
    }

    if (!persistentNav) {
      this.setState({
        hideControls: false
      });
    }
  }

  _startAutoplay () {
    const { activeIndex } = this.state;
    const { autoplay, children, infinite, persistentNav } = this.props;
    if (autoplay && (infinite || activeIndex !== children.length - 1) &&
      // making sure to only start autoplay if the focus is not inside
      // the carousel
      !this.carouselRef.contains(document.activeElement)) {
      this._setSlideInterval();
    }

    if (!persistentNav) {
      this.setState({
        hideControls: true
      });
    }
  }

  _onResize () {
    this.setState({
      width: this.carouselRef.offsetWidth
    });
  }

  _slidePrev () {
    const { children } = this.props;
    const { activeIndex } = this.state;
    const numSlides = children.length;
    const index = (activeIndex + numSlides - 1) % numSlides;

    if(! this.props.hasOwnProperty('activeIndex')) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _slideNext () {
    const { children } = this.props;
    const { activeIndex } = this.state;
    const numSlides = children.length;
    const index = (activeIndex + 1) % numSlides;

    if(! this.props.hasOwnProperty('activeIndex')) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _renderPrevButton () {
    const { infinite } = this.props;
    const { activeIndex } = this.state;
    const { intl } = this.context;
    let prevButton;
    if (infinite || activeIndex !== 0) {
      const prevMessage = Intl.getMessage(intl, 'Previous Slide');
      prevButton = (
        <Button icon={<Previous size="large" />} a11yTitle={prevMessage}
          className={`${CLASS_ROOT}__arrow ${CLASS_ROOT}__arrow--prev`}
          onClick={this._slidePrev} />
      );
    }

    return prevButton;
  }

  _renderNextButton () {
    const { children, infinite } = this.props;
    const { activeIndex } = this.state;
    const { intl } = this.context;
    let nextButton;
    if (infinite || activeIndex !== children.length - 1) {
      const nextMessage = Intl.getMessage(intl, 'Next Slide');
      nextButton = (
        <Button icon={<Next size="large" />} a11yTitle={nextMessage}
          className={`${CLASS_ROOT}__arrow ${CLASS_ROOT}__arrow--next`}
          onClick={this._slideNext} />
      );
    }

    return nextButton;
  }

  render () {
    const { a11yTitle, children, className, ...props } = this.props;
    delete props.activeIndex;
    delete props.onActive;
    const restProps = Props.omit({...props}, Object.keys(Carousel.propTypes));
    const { activeIndex, hideControls, width } = this.state;
    const { intl } = this.context;
    const classes = classnames(
      CLASS_ROOT, {
        [`${CLASS_ROOT}--hide-controls`]: hideControls
      },
      className
    );

    const trackWidth = width * children.length;
    const trackOffset = width * activeIndex;

    const tiles = React.Children.map(children, (child, index) => {
      const ariaHidden = activeIndex !== index ? true : false;
      return (
        <Tile className={`${CLASS_ROOT}__item`} aria-hidden={ariaHidden}>
          {child}
        </Tile>
      );
    });

    const controls = React.Children.map(children, (child, index) => {
      const active = index === activeIndex;
      const controlClasses = classnames(
        `${CLASS_ROOT}__control`, {
          [`${CLASS_ROOT}__control--active`]: active
        }
      );
      const activateMessage = Intl.getMessage(intl, 'Activate');
      const slideNumberMessage = Intl.getMessage(intl, 'Slide Number', {
        slideNumber: index + 1
      });

      let currentlyActiveMessage = '';
      if (active) {
        currentlyActiveMessage = (
          `(${Intl.getMessage(intl, 'Currently Active')})`
        );
      }
      return (
        <Button plain={true} onClick={this._onSelect.bind(this, index)}
          a11yTitle={
            `${activateMessage} ${slideNumberMessage} ${currentlyActiveMessage}`
          }>
          <svg className={controlClasses} viewBox="0 0 24 24" version="1.1">
            <circle cx={12} cy={12} r={6} />
          </svg>
        </Button>
      );
    }, this);

    const carouselMessage = a11yTitle || Intl.getMessage(intl, 'Carousel');
    return (

 this.carouselRef = ref} {...restProps}
        className={classes} role='group' aria-label={carouselMessage}
        onFocus={this._stopAutoplay} onBlur={this._startAutoplay}
        onMouseOver={this._stopAutoplay} onMouseOut={this._startAutoplay}>
        <div className={`${CLASS_ROOT}__track`}
          style={{
            width: (trackWidth && trackWidth > 0) ? trackWidth : '',
            marginLeft: - trackOffset,
            marginRight: - (trackWidth - trackOffset - width)
          }}>
          <Tiles fill={true} responsive={false} wrap={false} direction="row">
            {tiles}
          </Tiles>

        {this._renderPrevButton()}
        {this._renderNextButton()}
        <Box className={CLASS_ROOT + "__controls"} direction="row"
          justify="center" responsive={false}>
          {controls}
        </Box>

    );
  }
}

Carousel.contextTypes = {
  intl: PropTypes.object
};

Carousel.defaultProps = {
  autoplay: true,
  autoplaySpeed: 5000,
  infinite: true,
  persistentNav: true
};

Carousel.propTypes = {
  a11yTitle: PropTypes.string,
  activeIndex: PropTypes.number,
  autoplay: PropTypes.bool,
  autoplaySpeed: PropTypes.number,
  infinite: PropTypes.bool,
  onActive: PropTypes.func,
  persistentNav: PropTypes.bool
};
<commit_msg>Carousel: removing unnecessary announce for onActive call.<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import Box from './Box';
import Tiles from './Tiles';
import Tile from './Tile';
import Button from './Button';
import Previous from './icons/base/Previous';
import Next from './icons/base/Next';
import { findScrollParents } from '../utils/DOM';
import CSSClassnames from '../utils/CSSClassnames';
import Intl from '../utils/Intl';
import { announce } from '../utils/Announcer';
import Props from '../utils/Props';

const CLASS_ROOT = CSSClassnames.CAROUSEL;

export default class Carousel extends Component {

  constructor(props, context) {
    super(props, context);

    this._onSelect = this._onSelect.bind(this);
    this._stopAutoplay = this._stopAutoplay.bind(this);
    this._startAutoplay = this._startAutoplay.bind(this);
    this._onResize = this._onResize.bind(this);
    this._slidePrev = this._slidePrev.bind(this);
    this._slideNext = this._slideNext.bind(this);
    this._handleScroll = this._handleScroll.bind(this);

    this.state = {
      activeIndex: props.activeIndex || 0,
      hideControls: ! props.persistentNav,
      priorIndex: 0,
      sequence: 1,
      width: 0,
      slide: false
    };
  }

  componentDidMount () {
    if (this.carouselRef) {
      this.setState({
        width: this.carouselRef.offsetWidth
      });

      window.addEventListener('resize', this._onResize);

      const Hammer = require('hammerjs');
      this.hammer = new Hammer(this.carouselRef);
      this._updateHammer();

      this._handleScroll();
      const scrollParents = findScrollParents(this.carouselRef);
      scrollParents.forEach((scrollParent) => {
        scrollParent.addEventListener('scroll', this._handleScroll);
      }, this);
    }
  }

  componentWillReceiveProps(nextProps) {
    if ((nextProps.activeIndex || 0 === nextProps.activeIndex) &&
      this.state.activeIndex !== nextProps.activeIndex) {
      this.setState({ activeIndex: nextProps.activeIndex });
    }
  }

  componentDidUpdate () {
    this._updateHammer();
  }

  componentWillUnmount () {
    clearInterval(this._slideAnimation);

    window.removeEventListener('resize', this._onResize);

    const scrollParents = findScrollParents(this.carouselRef);
    scrollParents.forEach((scrollParent) => {
      scrollParent.removeEventListener('scroll', this._handleScroll);
    }, this);

    this._unmountHammer();
  }

  _unmountHammer () {
    if (this.hammer) {
      this.hammer.stop();
      this.hammer.destroy();
    }
    this.hammer = undefined;
  }

  _updateHammer () {
    if (this.hammer) {
      this.hammer.get('swipe').set({
        direction: Hammer.DIRECTION_HORIZONTAL
      });

      this.hammer.off('panend');
      this.hammer.on('panend', (event) => {
        if (event.direction === 4) {
          this._slidePrev();
        } else if (event.direction === 2) {
          this._slideNext();
        }
      });
    }
  }

  _handleScroll () {
    const { autoplay } = this.props;
    const { slide } = this.state;
    const viewportHeight = document.documentElement.clientHeight;
    const carouselTopPosition = this.carouselRef.getBoundingClientRect().top;
    const carouselHeight = this.carouselRef.offsetHeight;
    const startScroll = viewportHeight - (carouselHeight / 2);

    if (autoplay && carouselTopPosition <= startScroll &&
      carouselTopPosition >= -carouselHeight / 2) {
      if (slide === false) {
        this._setSlideInterval();
        this.setState({
          slide: true
        });
      }
    } else {
      clearInterval(this._slideAnimation);
      this.setState({
        slide: false
      });
    }
  }

  _setSlideInterval () {
    const { autoplaySpeed } = this.props;
    clearInterval(this._slideAnimation);
    this._slideAnimation = setInterval(function () {
      const { children, infinite } = this.props;
      const { activeIndex } = this.state;
      const { intl } = this.context;
      const numSlides = children.length;
      const index = (activeIndex + 1) % numSlides;
      const announceFunc = () => {
        const slideNumber = Intl.getMessage(intl, 'Slide Number', {
          slideNumber: this.state.activeIndex + 1
        });
        const activatedMessage = Intl.getMessage(intl, 'Activated');
        announce(`${slideNumber} ${activatedMessage}`, 'polite');
      };

      if (! this.props.hasOwnProperty('activeIndex')) {
        this.setState({
          activeIndex: index
        }, announceFunc );
      }
      if (!infinite && activeIndex === numSlides - 1) {
        clearInterval(this._slideAnimation);
      }

      if (this.props.onActive) {
        this.props.onActive(index);
      }
    }.bind(this), autoplaySpeed);
  }

  _onSelect (index) {
    if (! this.props.hasOwnProperty('activeIndex')
        && index !== this.state.activeIndex) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _stopAutoplay () {
    const { autoplay, persistentNav } = this.props;
    if (autoplay) {
      clearInterval(this._slideAnimation);
    }

    if (!persistentNav) {
      this.setState({
        hideControls: false
      });
    }
  }

  _startAutoplay () {
    const { activeIndex } = this.state;
    const { autoplay, children, infinite, persistentNav } = this.props;
    if (autoplay && (infinite || activeIndex !== children.length - 1) &&
      // making sure to only start autoplay if the focus is not inside
      // the carousel
      !this.carouselRef.contains(document.activeElement)) {
      this._setSlideInterval();
    }

    if (!persistentNav) {
      this.setState({
        hideControls: true
      });
    }
  }

  _onResize () {
    this.setState({
      width: this.carouselRef.offsetWidth
    });
  }

  _slidePrev () {
    const { children } = this.props;
    const { activeIndex } = this.state;
    const numSlides = children.length;
    const index = (activeIndex + numSlides - 1) % numSlides;

    if(! this.props.hasOwnProperty('activeIndex')) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _slideNext () {
    const { children } = this.props;
    const { activeIndex } = this.state;
    const numSlides = children.length;
    const index = (activeIndex + 1) % numSlides;

    if(! this.props.hasOwnProperty('activeIndex')) {
      this.setState({
        activeIndex: index
      });
    }

    if (this.props.onActive) {
      this.props.onActive(index);
    }
  }

  _renderPrevButton () {
    const { infinite } = this.props;
    const { activeIndex } = this.state;
    const { intl } = this.context;
    let prevButton;
    if (infinite || activeIndex !== 0) {
      const prevMessage = Intl.getMessage(intl, 'Previous Slide');
      prevButton = (
        <Button icon={<Previous size="large" />} a11yTitle={prevMessage}
          className={`${CLASS_ROOT}__arrow ${CLASS_ROOT}__arrow--prev`}
          onClick={this._slidePrev} />
      );
    }

    return prevButton;
  }

  _renderNextButton () {
    const { children, infinite } = this.props;
    const { activeIndex } = this.state;
    const { intl } = this.context;
    let nextButton;
    if (infinite || activeIndex !== children.length - 1) {
      const nextMessage = Intl.getMessage(intl, 'Next Slide');
      nextButton = (
        <Button icon={<Next size="large" />} a11yTitle={nextMessage}
          className={`${CLASS_ROOT}__arrow ${CLASS_ROOT}__arrow--next`}
          onClick={this._slideNext} />
      );
    }

    return nextButton;
  }

  render () {
    const { a11yTitle, children, className, ...props } = this.props;
    delete props.activeIndex;
    delete props.onActive;
    const restProps = Props.omit({...props}, Object.keys(Carousel.propTypes));
    const { activeIndex, hideControls, width } = this.state;
    const { intl } = this.context;
    const classes = classnames(
      CLASS_ROOT, {
        [`${CLASS_ROOT}--hide-controls`]: hideControls
      },
      className
    );

    const trackWidth = width * children.length;
    const trackOffset = width * activeIndex;

    const tiles = React.Children.map(children, (child, index) => {
      const ariaHidden = activeIndex !== index ? true : false;
      return (
        <Tile className={`${CLASS_ROOT}__item`} aria-hidden={ariaHidden}>
          {child}
        </Tile>
      );
    });

    const controls = React.Children.map(children, (child, index) => {
      const active = index === activeIndex;
      const controlClasses = classnames(
        `${CLASS_ROOT}__control`, {
          [`${CLASS_ROOT}__control--active`]: active
        }
      );
      const activateMessage = Intl.getMessage(intl, 'Activate');
      const slideNumberMessage = Intl.getMessage(intl, 'Slide Number', {
        slideNumber: index + 1
      });

      let currentlyActiveMessage = '';
      if (active) {
        currentlyActiveMessage = (
          `(${Intl.getMessage(intl, 'Currently Active')})`
        );
      }
      return (
        <Button plain={true} onClick={this._onSelect.bind(this, index)}
          a11yTitle={
            `${activateMessage} ${slideNumberMessage} ${currentlyActiveMessage}`
          }>
          <svg className={controlClasses} viewBox="0 0 24 24" version="1.1">
            <circle cx={12} cy={12} r={6} />
          </svg>
        </Button>
      );
    }, this);

    const carouselMessage = a11yTitle || Intl.getMessage(intl, 'Carousel');
    return (

 this.carouselRef = ref} {...restProps}
        className={classes} role='group' aria-label={carouselMessage}
        onFocus={this._stopAutoplay} onBlur={this._startAutoplay}
        onMouseOver={this._stopAutoplay} onMouseOut={this._startAutoplay}>
        <div className={`${CLASS_ROOT}__track`}
          style={{
            width: (trackWidth && trackWidth > 0) ? trackWidth : '',
            marginLeft: - trackOffset,
            marginRight: - (trackWidth - trackOffset - width)
          }}>
          <Tiles fill={true} responsive={false} wrap={false} direction="row">
            {tiles}
          </Tiles>

        {this._renderPrevButton()}
        {this._renderNextButton()}
        <Box className={CLASS_ROOT + "__controls"} direction="row"
          justify="center" responsive={false}>
          {controls}
        </Box>

    );
  }
}

Carousel.contextTypes = {
  intl: PropTypes.object
};

Carousel.defaultProps = {
  autoplay: true,
  autoplaySpeed: 5000,
  infinite: true,
  persistentNav: true
};

Carousel.propTypes = {
  a11yTitle: PropTypes.string,
  activeIndex: PropTypes.number,
  autoplay: PropTypes.bool,
  autoplaySpeed: PropTypes.number,
  infinite: PropTypes.bool,
  onActive: PropTypes.func,
  persistentNav: PropTypes.bool
};
<|endoftext|>


<commit_before>import test from 'ava';
import fs from 'fs';
import secureRandom from 'secure-random';
import path from 'path';
import bluebird from 'bluebird';
import wipe from '../dist/file-wipe';
bluebird.promisifyAll(fs);

const exampleFile = path.join(process.cwd(), 'example.txt');

test.before(async t => {
  //Create some random data
  let data = secureRandom(1337, {type: 'Buffer'});
  //Create a temporary test file from the data.
  await fs.writeFileAsync(exampleFile, data);
});

test('wiping', async t => {

  t.throws(
    wipe(exampleFile)
    .then(() => fs.statAsync(exampleFile))
    //File should be wiped.
  , /(ENOENT)/);
});<commit_msg>Refactor code<commit_after>import test from 'ava';
import fs from 'fs';
import secureRandom from 'secure-random';
import path from 'path';
import bluebird from 'bluebird';
import wipe from '../dist/file-wipe';
bluebird.promisifyAll(fs);

const exampleFile = path.join(process.cwd(), 'example.txt');

test.before(async t => {
  //Create some random data
  let data = secureRandom(1337, {type: 'Buffer'});
  //Create a temporary test file from the data.
  await fs.writeFileAsync(exampleFile, data);
});

test('wiping', async t => {

  t.throws(
    wipe(exampleFile)
    .then(() => fs.statAsync(exampleFile))
    //File should be wiped.
  , /(ENOENT)/);
});<|endoftext|>


<commit_before>import React from 'react';
import { mount } from 'enzyme';
import Menu from '..';

const SubMenu = Menu.SubMenu;

describe('Menu', () => {
  it('should accept defaultOpenKeys in mode horizontal', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="horizontal">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept defaultOpenKeys in mode inline', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="inline">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept defaultOpenKeys in mode vertical', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="vertical">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode horizontal', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="horizontal">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode inline', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="inline">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode vertical', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="vertical">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });
});
<commit_msg>Add test case for Menu openKeys undefined bug<commit_after>import React from 'react';
import { mount } from 'enzyme';
import Menu from '..';

const SubMenu = Menu.SubMenu;

describe('Menu', () => {
  it('should accept defaultOpenKeys in mode horizontal', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="horizontal">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept defaultOpenKeys in mode inline', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="inline">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept defaultOpenKeys in mode vertical', () => {
    const wrapper = mount(
      <Menu defaultOpenKeys={['1']} mode="vertical">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode horizontal', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="horizontal">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode inline', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="inline">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  it('should accept openKeys in mode vertical', () => {
    const wrapper = mount(
      <Menu openKeys={['1']} mode="vertical">
        <SubMenu key="1" title="submenu1">
          <Menu.Item key="submenu1">Option 1</Menu.Item>
          <Menu.Item key="submenu2">Option 2</Menu.Item>
        </SubMenu>
        <Menu.Item key="2">menu2</Menu.Item>
      </Menu>
    );
    expect(wrapper.find('.ant-menu-sub').at(0).hasClass('ant-menu-hidden')).not.toBe(true);
  });

  // https://github.com/ant-design/ant-design/pulls/4677
  // https://github.com/ant-design/ant-design/issues/4692
  // TypeError: Cannot read property 'indexOf' of undefined
  it('pr #4677 and issue #4692', () => {
    const wrapper = mount(
      <Menu mode="horizontal">
        <SubMenu title="submenu">
          <Menu.Item key="1">menu1</Menu.Item>
          <Menu.Item key="2">menu2</Menu.Item>
        </SubMenu>
      </Menu>
    );
    wrapper.update();
    // just expect no error emit
  });
});
<|endoftext|>


<commit_before>
'use strict';

/**
 * @ngdoc function
 * @name Teem.controller:ProjectsCtrl
 * @description
 * # ProjectsCtrl
 * Controller of the Teem
 */

angular.module('Teem')
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/teems/featured', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      // Transition from old paths
      .when('/projects/:id/:new?', {
        redirectTo: function(params) {
          return '/teems/' + params.id;
        }
      })
      .when('/teems/:id/:new?', {
        templateUrl: 'projects/project.html',
        controller: 'ProjectCtrl',
        // Change between tabs without re-rendering the view
        reloadOnSearch: false
      })
      // Getting a project from projects widget
      .when('/communities/:communityId/teems/fetch/:id', {
        controller: 'FetchProject',
        template: ''
      })
      // Old stuff
      .when('/communities/:communityId/teems/:id', {
        redirectTo: function(params) {
          return '/teems/' + params.id;
        }
      })
      .when('/communities/:communityId/teems/:id/:tab', {
        redirectTo: function(params) {
          return '/teems/' + params.id + '?tab=' + params.tab;
        }
      });
  }])
  .controller('FetchProject', [
  'ProjectsSvc', 'Url', '$route', '$location', 'SessionSvc',
  function(ProjectsSvc, Url, $route, $location, SessionSvc) {

    var communityId = Url.decode($route.current.params.communityId),
        localId     = $route.current.params.id;

    SessionSvc.onLoad(() => {

      ProjectsSvc.all({
        community: communityId,
        localId: localId
      }).then(function(projects) {

        var project = projects[0];

        if (project) {
          $location.path(project.path());
          return;
        }

        ProjectsSvc.create({
          communityId:  communityId
        }).then(function(project) {
          project.localId = localId;

          $location.path(project.path());
        });
      });
    });
  }])
  .controller('ProjectCtrl', [
  'SessionSvc', '$scope', '$rootScope', '$location', '$route', '$timeout', 'swellRT', '$filter',
  'SharedState', 'ProjectsSvc', 'Loading', '$window', 'NewForm', 'CommunitiesSvc', 'User', 'Selector',
  function (SessionSvc, $scope, $rootScope, $location, $route, $timeout, swellRT, $filter,
  SharedState, ProjectsSvc, Loading, $window, NewForm, CommunitiesSvc, User, Selector) {

    // Prevent users from forging the form parameter
    // and set the form order
    const Forms = [ 'image', 'details', 'share', 'congrats' ];

    // Hack to hide the navbar
    // We should be using the class .has-navbar-top automatically added by
    // mobile-angular-ui, it should be removed when the navbar is removed
    // by ui-content-for, but it is not happening
    $rootScope.noNavbarTop = true;
    $scope.$on('$destroy', () => {
      $rootScope.noNavbarTop = false;
    });

    var editingTitle = false;

    // FIXME Defined here instead of inside pad because when pad scope is destroyed,
    // `editing` variable can't be accessed, and it is used outside pad.
    $scope.pad = {
      editing: false,
      saving: false,
      outline: []
    };
    $scope.pic = {};

    $scope.editOff = function() {
      angular.element(document.querySelector('pad')).scope().editOff();
    };

    $scope.invite = {
      list : [],
      selected : []
    };

    var initialize = function(){
      Loading.show(ProjectsSvc.findByUrlId($route.current.params.id)).
        then(function(project) {
          $scope.project = project;
          Selector.populateUserSelector($scope.invite.list, $scope.project.communities);

          $rootScope.og = {
            title: project.title,
            description: project.pad.text().substring(0, 200),
            url: project.url(),
            image: project.logoUrl()
          };

          if($location.search().tab === 'chat' && !$scope.project.isParticipant()){
            SharedState.setOne('projectTab', 'pad');
          }

          CommunitiesSvc.all({ ids: project.communities }).then(function (communities) {
            $timeout(function() {
              $scope.communities = communities;
            });
          });
          $timeout();
        });
    };

    SessionSvc.onLoad(initialize);

    function currentTab() {
      return $location.search().tab || 'pad';
    }

    SharedState.initialize($scope, 'projectTab', {
      defaultValue: currentTab()
    });

    function swipeToProjectTab(tab) {
      return function(event) {
        if (event.pointerType === 'touch') {
          SharedState.set('projectTab', tab);
        }
      };
    }

    $scope.swipeToPad = swipeToProjectTab('pad');
    $scope.swipeToNeeds = swipeToProjectTab('needs');
    $scope.swipeToChat = swipeToProjectTab('chat');

    $scope.hmManagerOpt = '{"cssProps": {"userSelect": true}}';
    $scope.hmRecognizerOpt = '{"threshold": 200}';

    SharedState.initialize($scope, 'hiddenTabs');
    $scope.areTabsHidden = function() {
      return SharedState.isActive('hiddenTabs') && $window.innerHeight < 400;
    };

    if($route.current.params.form === 'new'){
      SharedState.turnOn('hiddenTabs');
    }

    NewForm.initialize($scope, 'project');

    $scope.form = function () {
      var f = $route.current.params.form;

      if (f && Forms.indexOf(f) >= 0) {
        return f;
      }
    };

    $scope.formStep = function() {
      return Forms.indexOf($route.current.params.form) + 1;
    };

    $scope.nextForm = function () {
      var index = Forms.indexOf($route.current.params.form) + 1;

      if (index > 0 && index < Forms.length) {
        return Forms[index];
      }

      return null;
    };

    $scope.goToNextForm = function () {
      if ($scope.form() === 'image' && $scope.pic.croppedPicture) {
        $scope.uploadProjectPhoto($filter('dataUriToBlob')($scope.pic.croppedPicture));
      }
      $location.search('form', $scope.nextForm());
    };

    $scope.uploadProjectPhoto = function(file) {
      $scope.project.image = new swellRT.FileObject(file);
    };

    $scope.editingTitle = function() {
      return editingTitle || $scope.isNew();
    };

    $scope.infoTip = function(close) {
      if (close) {
        localStorage.setItem('clickToTap', true);
      }
      return !localStorage.getItem('clickToTap');
    };

    $scope.showEditTitle = function() {
      editingTitle = true;
    };

    $scope.hideEditTitle = function() {
      editingTitle = false;
    };

    $scope.createProject = function() {
      let params = {};

      ProjectsSvc.create(params, function(p) {
        $location.path(p.path()).search('form', 'image');
      });
    };

    $scope.$on('mobile-angular-ui.state.changed.projectTab', function(e, newVal, oldVal) {
      $scope.project.setTimestampAccess(oldVal);
      $scope.project.setTimestampAccess(newVal);

      $location.search({ tab: newVal});

      $scope.pad.editing = false;
    });

      $scope.$on('$routeChangeStart', function(event, next, current) {
      if (current.params.tab !== undefined && $scope.project!== undefined) {
        $scope.project.setTimestampAccess(current.params.tab);
      }
    });

    $scope.cancelProject = function() {
      SharedState.turnOff('modal.confirm');

      $scope.project.delete();

      $location.path('/home/teems');
    };

    $scope.hasChanged = function(section){

      if(!$scope.project || ! $scope.project.lastChange(section) ||
        !$scope.project.isParticipant()){
        return false;
      }

      var lastChange = $scope.project.lastChange(section);
      var lastAccess;
          if ($scope.project.getTimestampAccess() &&
            $scope.project.getTimestampAccess()[section]) {
            lastAccess = new Date(($scope.project.getTimestampAccess()[section]).last);
          } else {
            lastAccess = new Date(0);
          }
      return lastChange > lastAccess;
    };

    $scope.communitySelector = {
      options: [],
      config: {
        create: function(input, callback) {
          CommunitiesSvc.create({ name: input }, (community) => {
            callback(community);
          });
        },
        load: function(query, callback) {
          CommunitiesSvc.all({ nameLike: query }, (communities) => {
            callback(communities);
          });
        },
        valueField: 'id',
        labelField: 'name',
        searchField: 'name',
        maxOptions: 10,
        onChange: function(ids) {
          $scope.communities = $scope.communitySelector.options.filter(community => ids.includes(community.id));
          Selector.populateUserSelector($scope.invite.list, $scope.project.communities);
        },
        plugins: ['remove_button'],
        onDropdownOpen(dropdown){
          dropdown[0].scrollIntoView();
        },
        closeAfterSelect: true
      }
    };
    $scope.locationSelector = {
      options: [],
      config: {
        mode: 'single',
        openOnFocus: false,
        delimiter: null,
        plugins: {
          'placecomplete': {
            placeholder: '',
            //selectDetails: (placeResult) => {
              // placeResult.displayText contains something like "Madrid, Spain"
            //}
          }
        }
      }
    };

    SessionSvc.onLoad(function() {
      CommunitiesSvc.participating({ projectCount: true }).then(function(communities){
        $scope.communitySelector.options = angular.extend([], $scope.communities, communities);
      });
    });

    $scope.userSelectorConfig = Selector.config.users;

    $scope.inviteUsers = function(){
      Selector.invite($scope.invite.selected, $scope.project);
      $scope.invite.selected = [];
      SharedState.turnOff('modal.share');
    };

    $scope.cancelInvite = function(){
      $scope.invite.selected = [];
      SharedState.turnOff('modal.share');
    };

    $scope.focusTitleInput = function() {
      $('.title-input').focus();
    };

    $scope.createProjectFormInvalid = function() {
      // There should be a better way to implement this
      try {
        let form = angular.element('[name="createProjectForm"]');

        return form.scope().createProjectForm.$invalid;
      } catch(e) {
        return false;
      }

    };

    $scope.archiveProject = function() {
      // TODO
    };

  }])
  .directive(
    'hideTabs',
    function (SharedState, $timeout) {
      return {
        restrict: 'A',
        link: function(scope, element) {
          element.on('focus', function() {
            SharedState.turnOn('hiddenTabs');
            $timeout();
          });
          element.on('blur', function() {
            SharedState.turnOff('hiddenTabs');
            $timeout();
          });
          scope.$on('$destroy', function() {
            element.off('focus');
            element.off('blur');
          });
        }
      };
    });
<commit_msg>Remove obsolete new project stuff<commit_after>
'use strict';

/**
 * @ngdoc function
 * @name Teem.controller:ProjectsCtrl
 * @description
 * # ProjectsCtrl
 * Controller of the Teem
 */

angular.module('Teem')
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/teems/featured', {
        templateUrl: 'projects/index.html',
        controller: 'ProjectsCtrl'
      })
      // Transition from old paths
      .when('/projects/:id/:new?', {
        redirectTo: function(params) {
          return '/teems/' + params.id;
        }
      })
      .when('/teems/:id', {
        templateUrl: 'projects/project.html',
        controller: 'ProjectCtrl',
        // Change between tabs without re-rendering the view
        reloadOnSearch: false
      })
      // Getting a project from projects widget
      .when('/communities/:communityId/teems/fetch/:id', {
        controller: 'FetchProject',
        template: ''
      })
      // Old stuff
      .when('/communities/:communityId/teems/:id', {
        redirectTo: function(params) {
          return '/teems/' + params.id;
        }
      })
      .when('/communities/:communityId/teems/:id/:tab', {
        redirectTo: function(params) {
          return '/teems/' + params.id + '?tab=' + params.tab;
        }
      });
  }])
  .controller('FetchProject', [
  'ProjectsSvc', 'Url', '$route', '$location', 'SessionSvc',
  function(ProjectsSvc, Url, $route, $location, SessionSvc) {

    var communityId = Url.decode($route.current.params.communityId),
        localId     = $route.current.params.id;

    SessionSvc.onLoad(() => {

      ProjectsSvc.all({
        community: communityId,
        localId: localId
      }).then(function(projects) {

        var project = projects[0];

        if (project) {
          $location.path(project.path());
          return;
        }

        ProjectsSvc.create({
          communityId:  communityId
        }).then(function(project) {
          project.localId = localId;

          $location.path(project.path());
        });
      });
    });
  }])
  .controller('ProjectCtrl', [
  'SessionSvc', '$scope', '$rootScope', '$location', '$route', '$timeout', 'swellRT', '$filter',
  'SharedState', 'ProjectsSvc', 'Loading', '$window', 'NewForm', 'CommunitiesSvc', 'User', 'Selector',
  function (SessionSvc, $scope, $rootScope, $location, $route, $timeout, swellRT, $filter,
  SharedState, ProjectsSvc, Loading, $window, NewForm, CommunitiesSvc, User, Selector) {

    // Prevent users from forging the form parameter
    // and set the form order
    const Forms = [ 'image', 'details', 'share', 'congrats' ];

    // Hack to hide the navbar
    // We should be using the class .has-navbar-top automatically added by
    // mobile-angular-ui, it should be removed when the navbar is removed
    // by ui-content-for, but it is not happening
    $rootScope.noNavbarTop = true;
    $scope.$on('$destroy', () => {
      $rootScope.noNavbarTop = false;
    });

    var editingTitle = false;

    // FIXME Defined here instead of inside pad because when pad scope is destroyed,
    // `editing` variable can't be accessed, and it is used outside pad.
    $scope.pad = {
      editing: false,
      saving: false,
      outline: []
    };
    $scope.pic = {};

    $scope.editOff = function() {
      angular.element(document.querySelector('pad')).scope().editOff();
    };

    $scope.invite = {
      list : [],
      selected : []
    };

    var initialize = function(){
      Loading.show(ProjectsSvc.findByUrlId($route.current.params.id)).
        then(function(project) {
          $scope.project = project;
          Selector.populateUserSelector($scope.invite.list, $scope.project.communities);

          $rootScope.og = {
            title: project.title,
            description: project.pad.text().substring(0, 200),
            url: project.url(),
            image: project.logoUrl()
          };

          if($location.search().tab === 'chat' && !$scope.project.isParticipant()){
            SharedState.setOne('projectTab', 'pad');
          }

          CommunitiesSvc.all({ ids: project.communities }).then(function (communities) {
            $timeout(function() {
              $scope.communities = communities;
            });
          });
          $timeout();
        });
    };

    SessionSvc.onLoad(initialize);

    function currentTab() {
      return $location.search().tab || 'pad';
    }

    SharedState.initialize($scope, 'projectTab', {
      defaultValue: currentTab()
    });

    function swipeToProjectTab(tab) {
      return function(event) {
        if (event.pointerType === 'touch') {
          SharedState.set('projectTab', tab);
        }
      };
    }

    $scope.swipeToPad = swipeToProjectTab('pad');
    $scope.swipeToNeeds = swipeToProjectTab('needs');
    $scope.swipeToChat = swipeToProjectTab('chat');

    $scope.hmManagerOpt = '{"cssProps": {"userSelect": true}}';
    $scope.hmRecognizerOpt = '{"threshold": 200}';

    SharedState.initialize($scope, 'hiddenTabs');
    $scope.areTabsHidden = function() {
      return SharedState.isActive('hiddenTabs') && $window.innerHeight < 400;
    };

    $scope.form = function () {
      var f = $route.current.params.form;

      if (f && Forms.indexOf(f) >= 0) {
        return f;
      }
    };

    $scope.formStep = function() {
      return Forms.indexOf($route.current.params.form) + 1;
    };

    $scope.nextForm = function () {
      var index = Forms.indexOf($route.current.params.form) + 1;

      if (index > 0 && index < Forms.length) {
        return Forms[index];
      }

      return null;
    };

    $scope.goToNextForm = function () {
      if ($scope.form() === 'image' && $scope.pic.croppedPicture) {
        $scope.uploadProjectPhoto($filter('dataUriToBlob')($scope.pic.croppedPicture));
      }
      $location.search('form', $scope.nextForm());
    };

    $scope.uploadProjectPhoto = function(file) {
      $scope.project.image = new swellRT.FileObject(file);
    };

    $scope.editingTitle = function() {
      return editingTitle || $scope.isNew();
    };

    $scope.infoTip = function(close) {
      if (close) {
        localStorage.setItem('clickToTap', true);
      }
      return !localStorage.getItem('clickToTap');
    };

    $scope.showEditTitle = function() {
      editingTitle = true;
    };

    $scope.hideEditTitle = function() {
      editingTitle = false;
    };

    $scope.createProject = function() {
      let params = {};

      ProjectsSvc.create(params, function(p) {
        $location.path(p.path()).search('form', 'image');
      });
    };

    $scope.$on('mobile-angular-ui.state.changed.projectTab', function(e, newVal, oldVal) {
      $scope.project.setTimestampAccess(oldVal);
      $scope.project.setTimestampAccess(newVal);

      $location.search({ tab: newVal});

      $scope.pad.editing = false;
    });

      $scope.$on('$routeChangeStart', function(event, next, current) {
      if (current.params.tab !== undefined && $scope.project!== undefined) {
        $scope.project.setTimestampAccess(current.params.tab);
      }
    });

    $scope.cancelProject = function() {
      SharedState.turnOff('modal.confirm');

      $scope.project.delete();

      $location.path('/home/teems');
    };

    $scope.hasChanged = function(section){

      if(!$scope.project || ! $scope.project.lastChange(section) ||
        !$scope.project.isParticipant()){
        return false;
      }

      var lastChange = $scope.project.lastChange(section);
      var lastAccess;
          if ($scope.project.getTimestampAccess() &&
            $scope.project.getTimestampAccess()[section]) {
            lastAccess = new Date(($scope.project.getTimestampAccess()[section]).last);
          } else {
            lastAccess = new Date(0);
          }
      return lastChange > lastAccess;
    };

    $scope.communitySelector = {
      options: [],
      config: {
        create: function(input, callback) {
          CommunitiesSvc.create({ name: input }, (community) => {
            callback(community);
          });
        },
        load: function(query, callback) {
          CommunitiesSvc.all({ nameLike: query }, (communities) => {
            callback(communities);
          });
        },
        valueField: 'id',
        labelField: 'name',
        searchField: 'name',
        maxOptions: 10,
        onChange: function(ids) {
          $scope.communities = $scope.communitySelector.options.filter(community => ids.includes(community.id));
          Selector.populateUserSelector($scope.invite.list, $scope.project.communities);
        },
        plugins: ['remove_button'],
        onDropdownOpen(dropdown){
          dropdown[0].scrollIntoView();
        },
        closeAfterSelect: true
      }
    };
    $scope.locationSelector = {
      options: [],
      config: {
        mode: 'single',
        openOnFocus: false,
        delimiter: null,
        plugins: {
          'placecomplete': {
            placeholder: '',
            //selectDetails: (placeResult) => {
              // placeResult.displayText contains something like "Madrid, Spain"
            //}
          }
        }
      }
    };

    SessionSvc.onLoad(function() {
      CommunitiesSvc.participating({ projectCount: true }).then(function(communities){
        $scope.communitySelector.options = angular.extend([], $scope.communities, communities);
      });
    });

    $scope.userSelectorConfig = Selector.config.users;

    $scope.inviteUsers = function(){
      Selector.invite($scope.invite.selected, $scope.project);
      $scope.invite.selected = [];
      SharedState.turnOff('modal.share');
    };

    $scope.cancelInvite = function(){
      $scope.invite.selected = [];
      SharedState.turnOff('modal.share');
    };

    $scope.focusTitleInput = function() {
      $('.title-input').focus();
    };

    $scope.createProjectFormInvalid = function() {
      // There should be a better way to implement this
      try {
        let form = angular.element('[name="createProjectForm"]');

        return form.scope().createProjectForm.$invalid;
      } catch(e) {
        return false;
      }

    };

    $scope.archiveProject = function() {
      // TODO
    };

  }])
  .directive(
    'hideTabs',
    function (SharedState, $timeout) {
      return {
        restrict: 'A',
        link: function(scope, element) {
          element.on('focus', function() {
            SharedState.turnOn('hiddenTabs');
            $timeout();
          });
          element.on('blur', function() {
            SharedState.turnOff('hiddenTabs');
            $timeout();
          });
          scope.$on('$destroy', function() {
            element.off('focus');
            element.off('blur');
          });
        }
      };
    });
<|endoftext|>


<commit_before>const ipcRenderer = window.require('electron').ipcRenderer;
import { UPDATE_SETTING } from '../actions';

export default store => next => action => {

  switch (action.type) {
    case UPDATE_SETTING:
      if (action.setting === 'openAtStartup') {
        // ipcRenderer.send('app-quit');
        if (action.value) {
          ipcRenderer.send('startup-enable');
        } else {
          ipcRenderer.send('startup-disable');
        }
      }
  }

  return next(action);
};
<commit_msg>Clean Up<commit_after>const ipcRenderer = window.require('electron').ipcRenderer;
import { UPDATE_SETTING } from '../actions';

export default store => next => action => {

  switch (action.type) {
    case UPDATE_SETTING:
      if (action.setting === 'openAtStartup') {
        if (action.value) {
          ipcRenderer.send('startup-enable');
        } else {
          ipcRenderer.send('startup-disable');
        }
      }
  }

  return next(action);
};
<|endoftext|>


<commit_before>/**
 * Created by Dominic Böttger on 09.06.14.
 * INSPIRATIONlabs GmbH
 * http://www.inspirationlabs.com
 */
/**
 * Created by Dominic Böttger on 11.05.2014
 * INSPIRATIONlabs GmbH
 * http://www.inspirationlabs.com
 */
var should = require('should'),
  util = require('util'),
  EventEmitter = require('events').EventEmitter,
  express = require('express'),
  mlcl_database = require('mlcl_database'),
  mlcl_elastic = require('mlcl_elastic'),
  request = require('request'),
  mlcl_elements = require('mlcl_elements'),
  txtReadPath = __dirname + '/testfiles/1.txt',
  //testBin = __dirname + '/testfiles/binary.bin',
  //outputPath =  __dirname + '/testfiles/output.txt',
  //pdfFile = __dirname + '/testfiles/test.pdf',
  //pngFile = __dirname + '/testfiles/test.png',
  //jpgFile = __dirname + '/testfiles/test.jpg',
  //pngFileDe = __dirname + '/testfiles/test_de.png',
  fs = require('fs'),
  path = require('path'),
  mlcl_files = require('../');

describe('mlcl_elastic', function() {
  var mlcl;
  var molecuel;
  var mongo;
  var elastic;
  var elements;
  var files;

  before(function(done) {
    // init fake molecuel
    mlcl = function() {
      return this;
    };
    util.inherits(mlcl, EventEmitter);
    molecuel = new mlcl();

    molecuel.config = { };
    molecuel.config.search = {
      hosts: ['http://localhost:9200'],
      prefix: 'mlcl-files-unit'
    };
    molecuel.config.database = {
      type: 'mongodb',
      uri: 'mongodb://localhost/mlcl-files-unit'
    };

    molecuel.config.elements = {
      schemaDir: __dirname + '/definitions'
    };

    mongo = mlcl_database(molecuel);
    elements = mlcl_elements(molecuel);
    elastic = mlcl_elastic(molecuel);
    files = mlcl_files(molecuel);
    done();
  });

  describe('files', function() {
    var elements;
    var app;

    it('should initialize db connection', function(done) {
      molecuel.once('mlcl::elements::init:post', function(ele) {
        elements = ele;
        ele.should.be.a.object;
        done();
      });
      molecuel.emit('mlcl::core::init:post', molecuel);
    });

    it('should initialize the middleware', function(done) {
      app = express();
      molecuel.emit('mlcl::core::middlewareRegister:post', molecuel, app);
      //elements.initApplication(app);
      app.post('/file/upload', files.upload );
      app.listen(8000);
      done();
    });

    describe('upload', function() {
      it('should upload a file successfully', function(done) {
        var r = request.post('http://localhost:8000/file/upload', function optionalCallback (err, httpResponse, body) {
          should.not.exists(err);
          should.exist(body);
          var myres = JSON.parse(body);
          myres.should.be.an.Object;
          myres.files.should.be.an.Object;
          myres.files[0].should.be.an.Object;
          done();
        });
        var form = r.form();
        form.append('files', fs.createReadStream(path.join(txtReadPath)));
      });
    });

    after(function(done) {
      elements.database.database.connection.db.dropDatabase(function(error) {
        should.not.exists(error);
        elements.elastic.deleteIndex('*', function(error) {
          should.not.exists(error);
          done();
        });
      });
    });
  });
});
<commit_msg>timeout<commit_after>/**
 * Created by Dominic Böttger on 09.06.14.
 * INSPIRATIONlabs GmbH
 * http://www.inspirationlabs.com
 */
/**
 * Created by Dominic Böttger on 11.05.2014
 * INSPIRATIONlabs GmbH
 * http://www.inspirationlabs.com
 */
var should = require('should'),
  util = require('util'),
  EventEmitter = require('events').EventEmitter,
  express = require('express'),
  mlcl_database = require('mlcl_database'),
  mlcl_elastic = require('mlcl_elastic'),
  request = require('request'),
  mlcl_elements = require('mlcl_elements'),
  txtReadPath = __dirname + '/testfiles/1.txt',
  //testBin = __dirname + '/testfiles/binary.bin',
  //outputPath =  __dirname + '/testfiles/output.txt',
  //pdfFile = __dirname + '/testfiles/test.pdf',
  //pngFile = __dirname + '/testfiles/test.png',
  //jpgFile = __dirname + '/testfiles/test.jpg',
  //pngFileDe = __dirname + '/testfiles/test_de.png',
  fs = require('fs'),
  path = require('path'),
  mlcl_files = require('../');

describe('mlcl_elastic', function() {
  var mlcl;
  var molecuel;
  var mongo;
  var elastic;
  var elements;
  var files;

  before(function(done) {
    // init fake molecuel
    mlcl = function() {
      return this;
    };
    util.inherits(mlcl, EventEmitter);
    molecuel = new mlcl();

    molecuel.config = { };
    molecuel.config.search = {
      hosts: ['http://localhost:9200'],
      prefix: 'mlcl-files-unit'
    };
    molecuel.config.database = {
      type: 'mongodb',
      uri: 'mongodb://localhost/mlcl-files-unit'
    };

    molecuel.config.elements = {
      schemaDir: __dirname + '/definitions'
    };

    mongo = mlcl_database(molecuel);
    elements = mlcl_elements(molecuel);
    elastic = mlcl_elastic(molecuel);
    files = mlcl_files(molecuel);
    done();
  });

  describe('files', function() {
    var elements;
    var app;

    it('should initialize db connection', function(done) {
      molecuel.once('mlcl::elements::init:post', function(ele) {
        elements = ele;
        ele.should.be.a.object;
        done();
      });
      molecuel.emit('mlcl::core::init:post', molecuel);
    });

    it('should initialize the middleware', function(done) {
      app = express();
      molecuel.emit('mlcl::core::middlewareRegister:post', molecuel, app);
      //elements.initApplication(app);
      app.post('/file/upload', files.upload );
      app.listen(8000);
      done();
    });

    describe('upload', function() {
      it('should upload a file successfully', function(done) {
        this.timeout(5000);
        var r = request.post('http://localhost:8000/file/upload', function optionalCallback (err, httpResponse, body) {
          should.not.exists(err);
          should.exist(body);
          var myres = JSON.parse(body);
          myres.should.be.an.Object;
          myres.files.should.be.an.Object;
          myres.files[0].should.be.an.Object;
          done();
        });
        var form = r.form();
        form.append('files', fs.createReadStream(path.join(txtReadPath)));
      });
    });

    after(function(done) {
      elements.database.database.connection.db.dropDatabase(function(error) {
        should.not.exists(error);
        elements.elastic.deleteIndex('*', function(error) {
          should.not.exists(error);
          done();
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/* A panel filled with buttons. */
ButtonPanel.prototype = Object.create(Phaser.Group.prototype);
ButtonPanel.prototype.constructor = ButtonPanel;
/**
 *
 */
function ButtonPanel (amount, representations, options) {
	Phaser.Group.call(this, game, null); // Parent constructor.
	this.x = options.x || 0;
	this.y = options.y || 0;
	var buttonOptions = {
		background: options.background,
		color: options.color
	};

	options.method = options.method || GLOBAL.METHOD.count;
	options.vertical = options.vertical || false;
	options.size = options.size || (options.vertical ? game.world.height : game.world.width);
	options.maxButtonSize = options.maxButtonSize || 75;
	if (options.method === GLOBAL.METHOD.incrementalSteps) {
		buttonOptions.min = 1;
		buttonOptions.max = amount;
		amount = 4;
	}

	var buttonSize = options.size/amount;
	if (buttonSize > options.maxButtonSize) { buttonSize = options.maxButtonSize; }
	var widthLeft = options.size - buttonSize*amount;
	var paddingSize = widthLeft/amount;
	if (paddingSize > buttonSize/2) { paddingSize = buttonSize/2; }
	var margin = (options.size - amount*buttonSize - (amount-1)*paddingSize)/2;
	var fullSize = paddingSize+buttonSize;

	buttonOptions.size = buttonSize;
	var i;

	// Set up the buttons that should be in the panel.
	if (options.method === GLOBAL.METHOD.incrementalSteps) {
		buttonOptions.onClick = options.onClick;
		var change = new NumberButton(1, representations, buttonOptions);
		buttonOptions.onClick = function () { change.number--; };
		this.add(new TextButton('-', buttonOptions));
		this.add(change);
		buttonOptions.onClick = function () { change.number++; };
		this.add(new TextButton('+', buttonOptions));
		buttonOptions.onClick = function () { change.bg.events.onInputDown.dispatch(); };
		this.add(new TextButton('v', buttonOptions));
	} else {
		buttonOptions.onClick = options.onClick;
		buttonOptions.vertical = !options.vertical;
		for (i = 1; i <= amount; i++) {
			this.add(new NumberButton(i, representations, buttonOptions));
		}
	}

	// Reverse the order of the buttons if needed.
	if (options.reversed) { this.reverse(); }

	// Set up the x and y positions.
	if (options.vertical) {
		for (i = 0; i < this.length; i++) { this.children[i].y = margin + fullSize*i; }
	} else {
		for (i = 0; i < this.length; i++) { this.children[i].x = margin + fullSize*i; }
	}

	return this;
}

ButtonPanel.prototype.reset = function () {
	for (var i = 0; i < this.children.length; i++) {
		this.children[i].reset();
	}
};

ButtonPanel.prototype.highlight = function (duration) {
	var t = new TimelineMax();
	for (var i = 0; i < this.children.length; i++) {
		t.add(this.children[i].highlight(duration), 0);
	}
	return t;
};

ButtonPanel.prototype.disable = function (value) {
	for (var i = 0; i < this.children.length; i++) {
		this.children[i].disabled = value;
	}
};<commit_msg>ButtonPanel now has options min and max<commit_after>ButtonPanel.prototype = Object.create(Phaser.Group.prototype);
ButtonPanel.prototype.constructor = ButtonPanel;
/**
 * Create a panel filled with buttons.
 * See NumberButton and GeneralButton for more information.
 * @param {Number} amount - The number of buttons (NOTE, this will be overwritten if you set options min or max)
 * @param {Number|Array} representations - The representations to use on the buttons.
 * @param {Object} options - options for the panel:
 *        {Number} x - The x position (default is 0)
 *        {Number} y - The y position (default is 0)
 *        {Number} size - The size of the panel (default is game width or height, depending on if vertical is set)
 *        {Number} method - The method of the panel (default is GLOBAL.METHOD.count)
 *        {Boolean} vertical - If the panel should be vertical (default is false)
 *        {Boolean} reversed - If the panel should display the buttons in reverse (default is false)
 *        {Number} min - The smallest number on the panel (default is 1)
 *        {Number} max - The biggest number on the panel (default is min + amount - 1)
 *        {Function} onClick - What should happen when clicking the button
 *        {String} background - The sprite key for the button backgrounds
 *        {String} color - The color of the representation
 *        {Number} maxButtonSize - The maximum size of the buttons (default is 75)
 *                                 NOTE: The button size is always calculated to not overlap
 */
function ButtonPanel (amount, representations, options) {
	Phaser.Group.call(this, game, null); // Parent constructor.
	this.x = options.x || 0;
	this.y = options.y || 0;
	this.min = options.min || 1;
	this.max = options.max || (this.min + amount - 1);
	this.amount = this.max - this.min + 1;

	options.vertical = options.vertical || false;
	options.size = options.size || (options.vertical ? game.world.height : game.world.width);
	options.method = options.method || GLOBAL.METHOD.count;
	options.maxButtonSize = options.maxButtonSize || 75;

	var buttonOptions = {
		background: options.background,
		color: options.color,
		onClick: options.onClick
	};
	if (options.method === GLOBAL.METHOD.incrementalSteps) {
		buttonOptions.min = this.min;
		buttonOptions.max = this.max;
		this.amount = 4; // Since we have these buttons: (-) (number) (+) (ok)
	}

	var buttonSize = options.size/this.amount;
	if (buttonSize > options.maxButtonSize) { buttonSize = options.maxButtonSize; }
	var widthLeft = options.size - buttonSize*this.amount;
	var paddingSize = widthLeft/this.amount;
	if (paddingSize > buttonSize/2) { paddingSize = buttonSize/2; }
	var margin = (options.size - this.amount*buttonSize - (this.amount-1)*paddingSize)/2;
	var fullSize = paddingSize+buttonSize;

	buttonOptions.size = buttonSize;
	var i;

	// Set up the buttons that should be in the panel.
	if (options.method === GLOBAL.METHOD.incrementalSteps) {
		var change = new NumberButton(1, representations, buttonOptions);
		buttonOptions.onClick = function () { change.number--; };
		this.add(new TextButton('-', buttonOptions));
		this.add(change);
		buttonOptions.onClick = function () { change.number++; };
		this.add(new TextButton('+', buttonOptions));
		buttonOptions.onClick = function () { change.bg.events.onInputDown.dispatch(); };
		this.add(new TextButton('v', buttonOptions));
	} else {
		buttonOptions.vertical = !options.vertical;
		for (i = this.min; i <= this.max; i++) {
			this.add(new NumberButton(i, representations, buttonOptions));
		}
	}

	// Reverse the order of the buttons if needed.
	if (options.reversed) { this.reverse(); }

	// Set up the x and y positions.
	if (options.vertical) {
		for (i = 0; i < this.length; i++) { this.children[i].y = margin + fullSize*i; }
	} else {
		for (i = 0; i < this.length; i++) { this.children[i].x = margin + fullSize*i; }
	}

	return this;
}

ButtonPanel.prototype.reset = function () {
	for (var i = 0; i < this.length; i++) {
		this.children[i].reset();
	}
};

ButtonPanel.prototype.highlight = function (duration) {
	var t = new TimelineMax();
	for (var i = 0; i < this.length; i++) {
		t.add(this.children[i].highlight(duration), 0);
	}
	return t;
};

ButtonPanel.prototype.disable = function (value) {
	for (var i = 0; i < this.length; i++) {
		this.children[i].disabled = value;
	}
};<|endoftext|>


<commit_before>var b2cloud = require('../index.js');
var expect = require('expect.js');
var assert = require('assert');

describe('B2Cloud', function() {
  this.timeout(20000);
  describe('Auth', function () {
    var time;

    it('should authorize with b2cloud using promises', function (done) {
      this.timeout(5000);
      return b2cloud.auth.getBasicAuth().then(function (res) {
        expect(res).to.only.have.keys('accountId', 'apiUrl', 'authorizationToken', 'downloadUrl', 'expires');
        done();
        time = new Date();
      });
    });

    it('should authorize with b2cloud using a callback', function (done) {
      b2cloud.auth.getBasicAuth(function(err, auth) {
        expect(auth).to.only.have.keys('accountId', 'apiUrl', 'authorizationToken', 'downloadUrl', 'expires');
        done();
      });
    });

    it('should cache the login token to improve performance', function() {
      b2cloud.auth.getBasicAuth(function() {
        // Typically logins take 100-600ms, cache usually responds in 1ms
        expect(new Date() - time).to.be.below(20);
      });
    });
  });

  describe('Bucket', function () {

    var bucketName;
    var bucket;
    var file;
    // Used for caching test
    var startTime;

    before(function(done) {
      this.timeout(15000);
      require('crypto').randomBytes(8, function (ex, buf) {
        bucketName = "test" + buf.toString('hex');
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function (res) {
          bucket = res;
          return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName);
        }).then(function(res) {
          file = res;
          done();
        });
      });
    });

    after(function(done) {
      this.timeout(15000);
      return b2cloud.file.deleteFileVersion(file.fileName, file.fileId).then(function() {
        return b2cloud.bucket.deleteBucket(bucket.bucketId)
      }).then(function() {
        done();
      }).catch(function(err) {
        console.warn('could not delete files out of bucket');
        done();
      })
    });

    it('should create and delete bucket with b2cloud using promises', function (done) {
      // These operations can be quite slow.
      this.timeout(10000);
      require('crypto').randomBytes(8, function(ex, buf) {
        var bucketName = buf.toString('hex');
        var testBucket;
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function(bucket) {
          testBucket = bucket;
          expect(bucket).to.only.have.keys('accountId', 'bucketId', 'bucketName', 'bucketType');
          return bucket;
        }).then(function(bucket) {
          return b2cloud.bucket.deleteBucket(bucket.bucketId);
        }).then(function(bucket) {
          expect(bucket).to.eql(testBucket);
          done();
        });
      });
    });

    it('should be able to get a bucket object by bucket name', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.getBucketByName(bucketName).then(function(res) {
        expect(res).to.eql(bucket);
        startTime = new Date();
        done();
      });
    });

    it('should be able to get a bucket object by bucket name using a callback', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.getBucketByName(bucketName, function(err, res) {
        expect(res).to.eql(bucket);
        done();
      });
    });

    it('should use bucket cache when fetching buckets by name', function(done) {
      return b2cloud.bucket.getBucketByName(bucketName).then(function(res) {
        expect(new Date() - startTime).to.be.below(20);
        done();
      });
    });

    it('should list all files inside a bucket using a promise', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.listBucketFiles(bucketName).then(function(res) {
        expect(res.files.length).to.eql(1);
        expect(res.files[0].fileId).to.eql(file.fileId);
        done();
      });
    });

    it('should list all files inside a bucket using a callback', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.listBucketFiles(bucketName, function(err, res) {
        expect(res.files.length).to.eql(1);
        expect(res.files[0].fileId).to.eql(file.fileId);
        done();
      });
    });
  });

  describe('File', function () {
    var bucketName;
    var bucket;
    before(function(done) {
      this.timeout(10000);
      require('crypto').randomBytes(8, function (ex, buf) {
        bucketName = buf.toString('hex');
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function (res) {
          bucket = res;
          done();
        });
      });
    });

    after(function(done) {
      return b2cloud.bucket.deleteBucket(bucket.bucketId).then(function() {
        done();
      });
    });

    it('should be able to get a uploadUrl by bucketName', function (done) {
      this.timeout(5000);
      return b2cloud.file.getUploadUrl(bucketName).then(function(res) {
        expect(res).to.only.have.keys('authorizationToken', 'bucketId', 'uploadUrl');
        done();
      });
    });

    it('should be able to get a uploadUrl by bucketName using a callback', function (done) {
      this.timeout(5000);
      return b2cloud.file.getUploadUrl(bucketName, function(err, res) {
        expect(res).to.only.have.keys('authorizationToken', 'bucketId', 'uploadUrl');
        done();
      });
    });

    it('should be able to upload and delete a file', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
        return b2cloud.file.deleteFileVersion(res.fileName, res.fileId);
      }).then(function(res) {
        expect(res.fileId).to.eql(file.fileId);
        done();
      }).catch(function(err) {
        console.log(err);
        done();
      });
    });

    it('should be able to get information about a file', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
      }).then(function(res) {
        return b2cloud.file.getFileInfo(file.fileId);
      }).then(function(res) {
        expect(res.contentSha1).to.eql('29c4a53c491737d82688bbe0c1d27829d0adbdd5');
        expect(res.contentType).to.eql('image/gif');
        expect(res.fileName).to.eql('backblaze-logo.gif');
        return b2cloud.file.deleteFileVersion(file.fileName, file.fileId);
      }).then(function() {
        done();
      });
    });

    it('should be able to get information about a file using a callback', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
      }).then(function(res) {
        b2cloud.file.getFileInfo(file.fileId, function(err, res) {

        });
        return b2cloud.file.getFileInfo(file.fileId);
      }).then(function(res) {
        expect(res.contentSha1).to.eql('29c4a53c491737d82688bbe0c1d27829d0adbdd5');
        expect(res.contentType).to.eql('image/gif');
        expect(res.fileName).to.eql('backblaze-logo.gif');
        return b2cloud.file.deleteFileVersion(file.fileName, file.fileId);
      }).then(function() {
        done();
      });
    });

    it('should be able to upload and delete a file using callbacks', function(done) {
      this.timeout(35000);
      var file;
      b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName, function(err, upload) {
        file = upload;
        b2cloud.file.deleteFileVersion(upload.fileName, upload.fileId, function(err, res) {
          expect(res.fileId).to.eql(upload.fileId);
          done(err);
        });
      });
    });

    it('should be able to upload, download and delete a file', function(done) {
      this.timeout(100000);
      var file;
      var fs = require('fs');
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
        return b2cloud.file.downloadFile(file.fileName, bucketName, '/tmp/backblaze.gif', {
          start:0,
          end: 99
        });
      }).then(function() {
        return b2cloud.file.deleteFileVersion(file.fileName, file.fileId);
      }).then(function(res) {
        expect(res.fileId).to.eql(file.fileId);
        done();
      }).catch(function(err) {
        console.warn(err);
        done();
      })
    });
  });
});<commit_msg>fixed unit tests for callback<commit_after>var b2cloud = require('../index.js');
var expect = require('expect.js');
var assert = require('assert');

describe('B2Cloud', function() {
  this.timeout(20000);
  describe('Auth', function () {
    var time;

    it('should authorize with b2cloud using promises', function (done) {
      this.timeout(5000);
      return b2cloud.auth.getBasicAuth().then(function (res) {
        expect(res).to.only.have.keys('accountId', 'apiUrl', 'authorizationToken', 'downloadUrl', 'expires');
        done();
        time = new Date();
      });
    });

    it('should authorize with b2cloud using a callback', function (done) {
      b2cloud.auth.getBasicAuth(function(err, auth) {
        expect(auth).to.only.have.keys('accountId', 'apiUrl', 'authorizationToken', 'downloadUrl', 'expires');
        done();
      });
    });

    it('should cache the login token to improve performance', function() {
      b2cloud.auth.getBasicAuth(function() {
        // Typically logins take 100-600ms, cache usually responds in 1ms
        expect(new Date() - time).to.be.below(20);
      });
    });
  });

  describe('Bucket', function () {

    var bucketName;
    var bucket;
    var file;
    // Used for caching test
    var startTime;

    before(function(done) {
      this.timeout(15000);
      require('crypto').randomBytes(8, function (ex, buf) {
        bucketName = "test" + buf.toString('hex');
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function (res) {
          bucket = res;
          return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName);
        }).then(function(res) {
          file = res;
          done();
        });
      });
    });

    after(function(done) {
      this.timeout(15000);
      return b2cloud.file.deleteFileVersion(file.fileName, file.fileId).then(function() {
        return b2cloud.bucket.deleteBucket(bucket.bucketId)
      }).then(function() {
        done();
      }).catch(function(err) {
        console.warn('could not delete files out of bucket');
        done();
      })
    });

    it('should create and delete bucket with b2cloud using promises', function (done) {
      // These operations can be quite slow.
      this.timeout(10000);
      require('crypto').randomBytes(8, function(ex, buf) {
        var bucketName = buf.toString('hex');
        var testBucket;
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function(bucket) {
          testBucket = bucket;
          expect(bucket).to.only.have.keys('accountId', 'bucketId', 'bucketName', 'bucketType');
          return bucket;
        }).then(function(bucket) {
          return b2cloud.bucket.deleteBucket(bucket.bucketId);
        }).then(function(bucket) {
          expect(bucket).to.eql(testBucket);
          done();
        });
      });
    });

    it('should be able to get a bucket object by bucket name', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.getBucketByName(bucketName).then(function(res) {
        expect(res).to.eql(bucket);
        startTime = new Date();
        done();
      });
    });

    it('should be able to get a bucket object by bucket name using a callback', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.getBucketByName(bucketName, function(err, res) {
        expect(res).to.eql(bucket);
        done();
      });
    });

    it('should use bucket cache when fetching buckets by name', function(done) {
      return b2cloud.bucket.getBucketByName(bucketName).then(function(res) {
        expect(new Date() - startTime).to.be.below(20);
        done();
      });
    });

    it('should list all files inside a bucket using a promise', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.listBucketFiles(bucketName).then(function(res) {
        expect(res.files.length).to.eql(1);
        expect(res.files[0].fileId).to.eql(file.fileId);
        done();
      });
    });

    it('should list all files inside a bucket using a callback', function(done) {
      this.timeout(5000);
      return b2cloud.bucket.listBucketFiles(bucketName, function(err, res) {
        expect(res.files.length).to.eql(1);
        expect(res.files[0].fileId).to.eql(file.fileId);
        done();
      });
    });
  });

  describe('File', function () {
    var bucketName;
    var bucket;
    before(function(done) {
      this.timeout(10000);
      require('crypto').randomBytes(8, function (ex, buf) {
        bucketName = buf.toString('hex');
        return b2cloud.bucket.createBucket(bucketName, 'allPublic').then(function (res) {
          bucket = res;
          done();
        });
      });
    });

    after(function(done) {
      return b2cloud.bucket.deleteBucket(bucket.bucketId).then(function() {
        done();
      });
    });

    it('should be able to get a uploadUrl by bucketName', function (done) {
      this.timeout(5000);
      return b2cloud.file.getUploadUrl(bucketName).then(function(res) {
        expect(res).to.only.have.keys('authorizationToken', 'bucketId', 'uploadUrl');
        done();
      });
    });

    it('should be able to get a uploadUrl by bucketName using a callback', function (done) {
      this.timeout(5000);
      return b2cloud.file.getUploadUrl(bucketName, function(err, res) {
        expect(res).to.only.have.keys('authorizationToken', 'bucketId', 'uploadUrl');
        done();
      });
    });

    it('should be able to upload and delete a file', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
        return b2cloud.file.deleteFileVersion(res.fileName, res.fileId);
      }).then(function(res) {
        expect(res.fileId).to.eql(file.fileId);
        done();
      }).catch(function(err) {
        console.log(err);
        done();
      });
    });

    it('should be able to get information about a file', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
      }).then(function(res) {
        return b2cloud.file.getFileInfo(file.fileId);
      }).then(function(res) {
        expect(res.contentSha1).to.eql('29c4a53c491737d82688bbe0c1d27829d0adbdd5');
        expect(res.contentType).to.eql('image/gif');
        expect(res.fileName).to.eql('backblaze-logo.gif');
        return b2cloud.file.deleteFileVersion(file.fileName, file.fileId);
      }).then(function() {
        done();
      });
    });

    it('should be able to get information about a file using a callback', function(done) {
      this.timeout(35000);
      var file;
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
        b2cloud.file.getFileInfo(file.fileId, function(err, res) {
          expect(res.contentSha1).to.eql('29c4a53c491737d82688bbe0c1d27829d0adbdd5');
          expect(res.contentType).to.eql('image/gif');
          expect(res.fileName).to.eql('backblaze-logo.gif');
          b2cloud.file.deleteFileVersion(file.fileName, file.fileId, function(err, res) {
            done();
          });
        });
      });
    });

    it('should be able to upload and delete a file using callbacks', function(done) {
      this.timeout(35000);
      var file;
      b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName, function(err, upload) {
        file = upload;
        b2cloud.file.deleteFileVersion(upload.fileName, upload.fileId, function(err, res) {
          expect(res.fileId).to.eql(upload.fileId);
          done(err);
        });
      });
    });

    it('should be able to upload, download and delete a file', function(done) {
      this.timeout(100000);
      var file;
      var fs = require('fs');
      return b2cloud.file.uploadFile('./test/data/backblaze-logo.gif', bucketName).then(function(res) {
        file = res;
        return b2cloud.file.downloadFile(file.fileName, bucketName, '/tmp/backblaze.gif', {
          start:0,
          end: 99
        });
      }).then(function() {
        return b2cloud.file.deleteFileVersion(file.fileName, file.fileId);
      }).then(function(res) {
        expect(res.fileId).to.eql(file.fileId);
        done();
      }).catch(function(err) {
        console.warn(err);
        done();
      })
    });
  });
});<|endoftext|>


<commit_before>//TODO: parseName
//John A. Doe, CAI, CES, CAGA
//John (Johnnie) Doe
//John "Johnnie" Doe

//TODO: getUsableName(str, idx)
//John Doe & Jim Duncan
//John Doe, Senior Whatever

var chai = require('chai')
    , expect = chai.expect
    , human = require('..');

// `describe` makes a "suite" of tests; think of them as a group.
describe('Parsing names', function() {

    var names = [
        {
            name: 'Mr. William R. Hearst, III',
            result: {
                salutation: 'Mr.',
                firstName: 'William',
                middleName: 'R.',
                lastName: 'Hearst',
                suffix: 'III',
                fullName: 'Mr. William R. Hearst, III'
            }
        },{
            name: 'William Randolph Hearst',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                middleName: 'Randolph',
                fullName: 'William Randolph Hearst'
            }
        }, {
            name: 'William R. De La Cruz',
            result: {
                firstName: 'William',
                lastName: 'De La Cruz',
                middleName: 'R.',
                fullName: 'William R. De La Cruz'
            }
        }, {
            name: 'Mr. William R. De La Cruz III',
            result: {
                salutation: 'Mr.',
                firstName: 'William',
                suffix: 'III',
                lastName: 'De La Cruz',
                middleName: 'R.',
                fullName: 'Mr. William R. De La Cruz III'
            }
        }, {
            name: 'William De Cruz',
            result: {
                firstName: 'William',
                lastName: 'De Cruz',
                fullName: 'William De Cruz'
            }
        }, {
            name: 'William De La Cruz',
            result: {
                firstName: 'William',
                lastName: 'De La Cruz',
                fullName: 'William De La Cruz'
            }
        }, {
            name: 'William Hearst',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                fullName: 'William Hearst'
            }
        }, {
            name: 'William Hearst Jr',
            result: {
                firstName: 'William',
                suffix: 'Jr',
                lastName: 'Hearst',
                fullName: 'William Hearst Jr'
            }
        }, {
            name: 'Hearst, William Jr',
            result: {
                firstName: 'William',
                suffix: 'Jr',
                lastName: 'Hearst',
                fullName: 'William Hearst Jr'
            }
        }, {
            name: 'Hearst, William Randolph',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                middleName: 'Randolph',
                fullName: 'William Randolph Hearst'
            }
        }, {
            name: 'Hearst, William, M.D.',
            result: {
                firstName: 'William',
                suffix: 'M.D.',
                lastName: 'Hearst',
                fullName: 'William Hearst M.D.'
            }
        }
    ];

    var fullest = [
        {
            name: 'John & Peggy Sue',
            result: {
                fullName: 'Peggy Sue'
            }
        }, {
            name: 'John and Peggy Sue',
            result: {
                fullName: 'Peggy Sue'
            }
        }, {
            name: 'Jane and Mr. William R. De La Cruz III',
            result: {
                fullName: 'Mr. William R. De La Cruz III'
            }
        }
    ];

    var addresses = [
        {
            address: '123 W. Happy Day Blvd., San Francisco, CA  90501',
            result: {
                address: '123 W. Happy Day Blvd.',
                city: 'San Francisco',
                state: 'CA',
                zip: '90501',
                fullAddress: '123 W. Happy Day Blvd., San Francisco, CA  90501'
            }
        }, {
            address: '123 Happy Street, Honolulu, HI  65780',
            result: {
                address: '123 Happy Street',
                city: 'Honolulu',
                state: 'HI',
                zip: '65780',
                fullAddress: '123 Happy Street, Honolulu, HI  65780'
            }
        }, {
            address: '123 Happy Street, Suite #101, Honolulu, HI  65780',
            result: {
                address: '123 Happy Street, Suite #101',
                city: 'Honolulu',
                state: 'HI',
                zip: '65780',
                fullAddress: '123 Happy Street, Suite #101, Honolulu, HI  65780'
            }
        }
    ];

    it('Should parse all name attributes', function() {
        names.forEach(function(name, i, list){
            var parsed = human.parseName(name.name);

            expect(name.result).to.eql(parsed);
        });
    });

    it('Should parse fullest name', function() {
        fullest.forEach(function(name, i, list){
            var fullName = human.getFullestName(name.name);

            expect(name.result.fullName).to.eql(fullName);
        });
    });

    it('Should parse all address attributes', function() {
        addresses.forEach(function(address, i, list){
            var parsed = human.parseAddress(address.address);

            expect(address.result).to.eql(parsed);
        });
    });
});
<commit_msg>Add test for multiple middle names.<commit_after>//TODO: parseName
//John A. Doe, CAI, CES, CAGA
//John (Johnnie) Doe
//John "Johnnie" Doe

//TODO: getUsableName(str, idx)
//John Doe & Jim Duncan
//John Doe, Senior Whatever

var chai = require('chai')
    , expect = chai.expect
    , human = require('..');

// `describe` makes a "suite" of tests; think of them as a group.
describe('Parsing names', function() {

    var names = [
        {
            name: 'Mr. William R. Hearst, III',
            result: {
                salutation: 'Mr.',
                firstName: 'William',
                middleName: 'R.',
                lastName: 'Hearst',
                suffix: 'III',
                fullName: 'Mr. William R. Hearst, III'
            }
        },{
            name: 'William Randolph Hearst',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                middleName: 'Randolph',
                fullName: 'William Randolph Hearst'
            }
        }, {
            name: 'William R. De La Cruz',
            result: {
                firstName: 'William',
                lastName: 'De La Cruz',
                middleName: 'R.',
                fullName: 'William R. De La Cruz'
            }
        }, {
            name: 'Mr. William R. De La Cruz III',
            result: {
                salutation: 'Mr.',
                firstName: 'William',
                suffix: 'III',
                lastName: 'De La Cruz',
                middleName: 'R.',
                fullName: 'Mr. William R. De La Cruz III'
            }
        }, {
            name: 'William De Cruz',
            result: {
                firstName: 'William',
                lastName: 'De Cruz',
                fullName: 'William De Cruz'
            }
        }, {
            name: 'William De La Cruz',
            result: {
                firstName: 'William',
                lastName: 'De La Cruz',
                fullName: 'William De La Cruz'
            }
        }, {
			name: 'James Hugh Calum Laurie',
			result: {
				firstName: 'James',
				middleName: 'Hugh Calum',
				lastName: 'Laurie',
				fullName: 'James Hugh Calum Laurie'
			}
		}, {
			name: 'Kiefer William Frederick Dempsey George Rufus Sutherland',
			result: {
				firstName: 'Kiefer',
				middleName: 'William Frederick Dempsey George Rufus',
				lastName: 'Sutherland',
				fullName: 'Kiefer William Frederick Dempsey George Rufus Sutherland'
			}
		}, {
            name: 'William Hearst',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                fullName: 'William Hearst'
            }
        }, {
            name: 'William Hearst Jr',
            result: {
                firstName: 'William',
                suffix: 'Jr',
                lastName: 'Hearst',
                fullName: 'William Hearst Jr'
            }
        }, {
            name: 'Hearst, William Jr',
            result: {
                firstName: 'William',
                suffix: 'Jr',
                lastName: 'Hearst',
                fullName: 'William Hearst Jr'
            }
        }, {
            name: 'Hearst, William Randolph',
            result: {
                firstName: 'William',
                lastName: 'Hearst',
                middleName: 'Randolph',
                fullName: 'William Randolph Hearst'
            }
        }, {
            name: 'Hearst, William, M.D.',
            result: {
                firstName: 'William',
                suffix: 'M.D.',
                lastName: 'Hearst',
                fullName: 'William Hearst M.D.'
            }
        }
    ];

    var fullest = [
        {
            name: 'John & Peggy Sue',
            result: {
                fullName: 'Peggy Sue'
            }
        }, {
            name: 'John and Peggy Sue',
            result: {
                fullName: 'Peggy Sue'
            }
        }, {
            name: 'Jane and Mr. William R. De La Cruz III',
            result: {
                fullName: 'Mr. William R. De La Cruz III'
            }
        }
    ];

    var addresses = [
        {
            address: '123 W. Happy Day Blvd., San Francisco, CA  90501',
            result: {
                address: '123 W. Happy Day Blvd.',
                city: 'San Francisco',
                state: 'CA',
                zip: '90501',
                fullAddress: '123 W. Happy Day Blvd., San Francisco, CA  90501'
            }
        }, {
            address: '123 Happy Street, Honolulu, HI  65780',
            result: {
                address: '123 Happy Street',
                city: 'Honolulu',
                state: 'HI',
                zip: '65780',
                fullAddress: '123 Happy Street, Honolulu, HI  65780'
            }
        }, {
            address: '123 Happy Street, Suite #101, Honolulu, HI  65780',
            result: {
                address: '123 Happy Street, Suite #101',
                city: 'Honolulu',
                state: 'HI',
                zip: '65780',
                fullAddress: '123 Happy Street, Suite #101, Honolulu, HI  65780'
            }
        }
    ];

    it('Should parse all name attributes', function() {
        names.forEach(function(name, i, list){
            var parsed = human.parseName(name.name);

            expect(name.result).to.eql(parsed);
        });
    });

    it('Should parse fullest name', function() {
        fullest.forEach(function(name, i, list){
            var fullName = human.getFullestName(name.name);

            expect(name.result.fullName).to.eql(fullName);
        });
    });

    it('Should parse all address attributes', function() {
        addresses.forEach(function(address, i, list){
            var parsed = human.parseAddress(address.address);

            expect(address.result).to.eql(parsed);
        });
    });
});
<|endoftext|>


<commit_before>function all () {
  return [
    { id: 'charity', name: 'Charity' },
    { id: 'no-wrong-door', name: 'No Wrong Door' },
    { id: 'coalition-of-relief', name: 'Coalition of Relief (mcr only)' },
    { id: 'big-change', name: 'Big Change (mcr only)' }
  ]
}

function isTagged (selectedTags, t) {
  return selectedTags !== undefined &&
  selectedTags.indexOf(t.id) >= 0
}

module.exports = {
  all: all,
  isTagged: isTagged
}
<commit_msg>2611-web-charity-tag-on-org-pages<commit_after>function all () {
  return [
    { id: 'charity', name: 'Registered Charity' },
    { id: 'no-wrong-door', name: 'No Wrong Door' },
    { id: 'coalition-of-relief', name: 'Coalition of Relief (mcr only)' },
    { id: 'big-change', name: 'Big Change (mcr only)' }
  ]
}

function isTagged (selectedTags, t) {
  return selectedTags !== undefined &&
  selectedTags.indexOf(t.id) >= 0
}

module.exports = {
  all: all,
  isTagged: isTagged
}
<|endoftext|>