<commit_before>import React, { Component } from 'react';
import { globalState } from '../state';
import SimpleMarkdown from 'simple-markdown';
import url from 'url';
import punycode from 'punycode';
import highlight from 'highlight.js';

class Divider extends Component {
  render() {
    return (

        #{this.props.name} ({this.props.id})

    );
  }
}

class Message extends Component {
  constructor() {
    super();
    this.depunycodeLink = this.depunycodeLink.bind(this);
    this.parseLink = this.parseLink.bind(this);
    this.parseMarkdown = this.parseMarkdown.bind(this);
    this.getAttachments = this.getAttachments.bind(this);
  }

  depunycodeLink(target) {
      try {
        const urlObject = url.parse(target);
        urlObject.hostname = punycode.toASCII(urlObject.hostname || '');
        return url.format(urlObject);
      } catch (e) {
        return target;
      }
  }

  parseLink(capture) {
    const target = this.depunycodeLink(capture[1]);
    return {
      type: 'link',
      content: [
        {
          type: 'text',
          content: target,
        },
      ],
      target,
      title: undefined,
    };
  }

  parseMarkdown(content) {
    const DEFAULT_RULES = {
      newline: SimpleMarkdown.defaultRules.newline,
      paragraph: SimpleMarkdown.defaultRules.paragraph,
      escape: SimpleMarkdown.defaultRules.escape,
      link: {
        ...SimpleMarkdown.defaultRules.link,
        parse: (capture, parse, state) => {
          return {
            content: parse(capture[1], state),
            target: this.depunycodeLink(SimpleMarkdown.unescapeUrl(capture[2])),
            title: capture[3],
          };
        },
        react: (node, output) => {
          const url = output(node.content)[0].replace("cdn.discordapp.com", "media.discordapp.net");
          return {url};
        }
      },
      autolink: {
        ...SimpleMarkdown.defaultRules.autolink,
        parse: this.parseLink,
      },
      url: {
        ...SimpleMarkdown.defaultRules.url,
        parse: this.parseLink,
      },
      strong: SimpleMarkdown.defaultRules.strong,
      em: SimpleMarkdown.defaultRules.em,
      u: SimpleMarkdown.defaultRules.u,
      br: {
        ...SimpleMarkdown.defaultRules.br,
        match(source) {
          return /^\n/.exec(source);
        },
        react(node, output) {
          return
;
        }
      },
      text: {
        ...SimpleMarkdown.defaultRules.text,
        react(node, output) {
          const SANITIZE_TEXT_R = /[<>&]/g;
          const SANITIZE_TEXT_CODES = {
            '<': '<',
            '>': '>',
            '&': '&'
          };
          const sanitizeText = (text) => String(text).replace(SANITIZE_TEXT_R, (chr) => SANITIZE_TEXT_CODES[chr]);
          return sanitizeText(node.content);
        }
      },

      inlineCode: {
        ...SimpleMarkdown.defaultRules.inlineCode,
        react(node, output) {
          return {node.content};
        }
      },

      // emoticon: {
      //   order: SimpleMarkdown.defaultRules.text.order,

      //   match(source) {
      //     // Match emoticons that have slashes in them that would otherwise be escaped.
      //     return /^(Â¯\\_\(ãƒ„\)_\/Â¯)/.exec(source);
      //   },

      //   parse(capture) {
      //     return {
      //       type: 'text',
      //       content: capture[1],
      //     };
      //   }
      // },

      codeBlock: {
        ...SimpleMarkdown.defaultRules.codeBlock,
        match(source) {
          return /^```(([A-z0-9\-]+?)\n+)?\n*([^]+?)\n*```/.exec(source);
        },
        parse(capture) {
          return {
            lang: (capture[2] || '').trim(),
            content: capture[3] || '',
          };
        },
        react(node, output, state) {
          if (node.lang && highlight.getLanguage(node.lang)) {
            const code = highlight.highlight(node.lang, node.content, true);
            return (

                  {code.value}

            );
          } else {
            return (

                  {output(node.content)}

            );
          }
        }
      },

      roleMention: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<@&(\d+)>/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      mention: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<@!?(\d+)>|^(@(?:everyone|here))/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      channel: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<#(\d+)>/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      customEmoji: {
        order: SimpleMarkdown.defaultRules.text.order,
        match(source) {
          return /^<:(\w+):(\d+)>/.exec(source);
        },
        parse(capture) {
          return {
            type: 'text',
            content: `:${capture[1]}:`,
          };
        }
      },

      s: {
        order: SimpleMarkdown.defaultRules.u.order,
        match: SimpleMarkdown.inlineRegex(/^~~([\s\S]+?)~~(?!_)/),
        parse: SimpleMarkdown.defaultRules.u.parse,
        react(node, output) {
          return <s>{output(node.content)}</s>;
        }
      },

      spoiler: {
        order: SimpleMarkdown.defaultRules.text.order,
        match(source) {
          return /^{{([\s\S]+?)}}/.exec(source);
        },
        parse(capture) {
          return {
            content: capture[1]
          };
        },
        react(node, output) {
          return {node.content};
        }
      }
    };

    const parse = SimpleMarkdown.parserFor(DEFAULT_RULES);
    const output = SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(DEFAULT_RULES, 'react'));
    return output(parse(content, {inline: true}));
  }

  getAttachments(attachments) {
    if (attachments.length > 0) {
      const list = attachments
        .map(a => {a.replace("cdn.discordapp.com", "media.discordapp.net")})
        .reduce((prev, curr) => [prev, ', ', curr])
      return (Attachment{attachments.length > 1 ? "s" : ""}: {list});
    } else {
      return
    }
  }

  onButton() {
    const { offsetLeft, offsetTop } = this.button;
    Archive.togglePopout(offsetLeft, offsetTop);
  }

  render() {
    const msg = this.props.message;
    const date = new Date(msg.timestamp);
    const timestamp = date.getTime();
    const isoDate = msg.timestamp.replace(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).\d{6}/, "$1 GMT+0");

    return (

 this.onButton()} ref={el => this.button = el}>

                ({msg.id})

<time className="latin12CompactTimeStamp-3v5WB3 timestampCompact-MHgFLv timestampCompactBase-26h38e" dateTime={timestamp}>[{isoDate}] </time>{msg.username}#{msg.discriminator}:
 {this.parseMarkdown(msg.content)}
{this.getAttachments(msg.attachments)}

    );
  }
}

class Popout extends Component {
  render() {
    return (
      <div role="dialog" class="noArrow-3BYQ0Z popout-3sVMXz popoutBottom-1YbShG arrowAlignmentTop-iGQczz popoutbottom theme-undefined" style={{
        'z-index': '1001',
        visibility: 'visible',
        left: `${this.props.left + 8}px`,
        top: `${this.props.top + 10}px`,
        transform: 'translateX(-50%) translateY(0%) translateZ(0px)'
      }}>

          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Raw

          </button>
          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Copy User ID

          </button>
          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Copy ID

          </button>

    )
  }
}

export default class Archive extends Component {
  constructor() {
    super();

    this.state = {
      archive: null,
      popout: null
    };

    this.groupBy = this.groupBy.bind(this);
  }

  get archiveId() {
    const match = window.location.pathname.match(/([\w-]{36})/);
    if (match) {
      return match[1];
    }
  }

  componentWillMount() {
    globalState.getArchive(this.archiveId).then((archive) => {
      this.setState({
        archive
      });
    });
  }

  groupBy(items, key) {
    return items.reduce((result, item) => ({
      ...result,
      [item[key]]: [
        ...(result[item[key]] || []),
        item,
      ]
    }), {});
  }

  static togglePopout(left, top) {
    this.setState({
      popout: <Popout left={left} top={top} />
    })
  }

  render() {
    if (!this.state.archive) {
      return
Loading...
;
    }

    let data = this.groupBy(this.state.archive.messages, "channel_id"); // group by channel
    data = Object.entries(data).sort((a, b) => a[1][0].timestamp - b[1][0].timestamp); // sort by first message chronologically

    let channels = []
    for (const [channel, messages] of data) {
      channels.push(

          <Divider name={messages[0].channel} id={channel} />
          {messages.map(m => <Message key={m.id} message={m} />)}

      )
    }

    return (

        {channels}

          {this.state.popout}

    );
  }
}
<commit_msg>fix popout maybe<commit_after>import React, { Component } from 'react';
import { globalState } from '../state';
import SimpleMarkdown from 'simple-markdown';
import url from 'url';
import punycode from 'punycode';
import highlight from 'highlight.js';

class Divider extends Component {
  render() {
    return (

        #{this.props.name} ({this.props.id})

    );
  }
}

class Message extends Component {
  constructor() {
    super();
    this.depunycodeLink = this.depunycodeLink.bind(this);
    this.parseLink = this.parseLink.bind(this);
    this.parseMarkdown = this.parseMarkdown.bind(this);
    this.getAttachments = this.getAttachments.bind(this);
  }

  depunycodeLink(target) {
      try {
        const urlObject = url.parse(target);
        urlObject.hostname = punycode.toASCII(urlObject.hostname || '');
        return url.format(urlObject);
      } catch (e) {
        return target;
      }
  }

  parseLink(capture) {
    const target = this.depunycodeLink(capture[1]);
    return {
      type: 'link',
      content: [
        {
          type: 'text',
          content: target,
        },
      ],
      target,
      title: undefined,
    };
  }

  parseMarkdown(content) {
    const DEFAULT_RULES = {
      newline: SimpleMarkdown.defaultRules.newline,
      paragraph: SimpleMarkdown.defaultRules.paragraph,
      escape: SimpleMarkdown.defaultRules.escape,
      link: {
        ...SimpleMarkdown.defaultRules.link,
        parse: (capture, parse, state) => {
          return {
            content: parse(capture[1], state),
            target: this.depunycodeLink(SimpleMarkdown.unescapeUrl(capture[2])),
            title: capture[3],
          };
        },
        react: (node, output) => {
          const url = output(node.content)[0].replace("cdn.discordapp.com", "media.discordapp.net");
          return {url};
        }
      },
      autolink: {
        ...SimpleMarkdown.defaultRules.autolink,
        parse: this.parseLink,
      },
      url: {
        ...SimpleMarkdown.defaultRules.url,
        parse: this.parseLink,
      },
      strong: SimpleMarkdown.defaultRules.strong,
      em: SimpleMarkdown.defaultRules.em,
      u: SimpleMarkdown.defaultRules.u,
      br: {
        ...SimpleMarkdown.defaultRules.br,
        match(source) {
          return /^\n/.exec(source);
        },
        react(node, output) {
          return
;
        }
      },
      text: {
        ...SimpleMarkdown.defaultRules.text,
        react(node, output) {
          const SANITIZE_TEXT_R = /[<>&]/g;
          const SANITIZE_TEXT_CODES = {
            '<': '<',
            '>': '>',
            '&': '&'
          };
          const sanitizeText = (text) => String(text).replace(SANITIZE_TEXT_R, (chr) => SANITIZE_TEXT_CODES[chr]);
          return sanitizeText(node.content);
        }
      },

      inlineCode: {
        ...SimpleMarkdown.defaultRules.inlineCode,
        react(node, output) {
          return {node.content};
        }
      },

      // emoticon: {
      //   order: SimpleMarkdown.defaultRules.text.order,

      //   match(source) {
      //     // Match emoticons that have slashes in them that would otherwise be escaped.
      //     return /^(Â¯\\_\(ãƒ„\)_\/Â¯)/.exec(source);
      //   },

      //   parse(capture) {
      //     return {
      //       type: 'text',
      //       content: capture[1],
      //     };
      //   }
      // },

      codeBlock: {
        ...SimpleMarkdown.defaultRules.codeBlock,
        match(source) {
          return /^```(([A-z0-9\-]+?)\n+)?\n*([^]+?)\n*```/.exec(source);
        },
        parse(capture) {
          return {
            lang: (capture[2] || '').trim(),
            content: capture[3] || '',
          };
        },
        react(node, output, state) {
          if (node.lang && highlight.getLanguage(node.lang)) {
            const code = highlight.highlight(node.lang, node.content, true);
            return (

                  {code.value}

            );
          } else {
            return (

                  {output(node.content)}

            );
          }
        }
      },

      roleMention: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<@&(\d+)>/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      mention: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<@!?(\d+)>|^(@(?:everyone|here))/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      channel: {
        ...SimpleMarkdown.defaultRules.text,
        match(source) {
          return /^<#(\d+)>/.exec(source);
        },
        react(node, output) {
          return {node.content};
        }
      },

      customEmoji: {
        order: SimpleMarkdown.defaultRules.text.order,
        match(source) {
          return /^<:(\w+):(\d+)>/.exec(source);
        },
        parse(capture) {
          return {
            type: 'text',
            content: `:${capture[1]}:`,
          };
        }
      },

      s: {
        order: SimpleMarkdown.defaultRules.u.order,
        match: SimpleMarkdown.inlineRegex(/^~~([\s\S]+?)~~(?!_)/),
        parse: SimpleMarkdown.defaultRules.u.parse,
        react(node, output) {
          return <s>{output(node.content)}</s>;
        }
      },

      spoiler: {
        order: SimpleMarkdown.defaultRules.text.order,
        match(source) {
          return /^{{([\s\S]+?)}}/.exec(source);
        },
        parse(capture) {
          return {
            content: capture[1]
          };
        },
        react(node, output) {
          return {node.content};
        }
      }
    };

    const parse = SimpleMarkdown.parserFor(DEFAULT_RULES);
    const output = SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(DEFAULT_RULES, 'react'));
    return output(parse(content, {inline: true}));
  }

  getAttachments(attachments) {
    if (attachments.length > 0) {
      const list = attachments
        .map(a => {a.replace("cdn.discordapp.com", "media.discordapp.net")})
        .reduce((prev, curr) => [prev, ', ', curr])
      return (Attachment{attachments.length > 1 ? "s" : ""}: {list});
    } else {
      return
    }
  }

  onButton() {
    const { offsetLeft, offsetTop } = this.button;
    this.props.popoutCB(offsetLeft, offsetTop);
  }

  render() {
    const msg = this.props.message;
    const date = new Date(msg.timestamp);
    const timestamp = date.getTime();
    const isoDate = msg.timestamp.replace(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).\d{6}/, "$1 GMT+0");

    return (

 this.onButton()} ref={el => this.button = el}>

                ({msg.id})

<time className="latin12CompactTimeStamp-3v5WB3 timestampCompact-MHgFLv timestampCompactBase-26h38e" dateTime={timestamp}>[{isoDate}] </time>{msg.username}#{msg.discriminator}:
 {this.parseMarkdown(msg.content)}
{this.getAttachments(msg.attachments)}

    );
  }
}

class Popout extends Component {
  render() {
    return (
      <div role="dialog" class="noArrow-3BYQ0Z popout-3sVMXz popoutBottom-1YbShG arrowAlignmentTop-iGQczz popoutbottom theme-undefined" style={{
        'z-index': '1001',
        visibility: 'visible',
        left: `${this.props.left + 8}px`,
        top: `${this.props.top + 10}px`,
        transform: 'translateX(-50%) translateY(0%) translateZ(0px)'
      }}>

          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Raw

          </button>
          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Copy User ID

          </button>
          <button role="menuitem" type="button" class="item-2J1YMK button-38aScr lookBlank-3eh9lL colorBrand-3pXr91 grow-q77ONN">

Copy ID

          </button>

    )
  }
}

export default class Archive extends Component {
  constructor() {
    super();

    this.state = {
      archive: null,
      popout: null
    };

    this.groupBy = this.groupBy.bind(this);
    this.togglePopout = this.togglePopout.bind(this);
  }

  get archiveId() {
    const match = window.location.pathname.match(/([\w-]{36})/);
    if (match) {
      return match[1];
    }
  }

  componentWillMount() {
    globalState.getArchive(this.archiveId).then((archive) => {
      this.setState({
        archive
      });
    });
  }

  groupBy(items, key) {
    return items.reduce((result, item) => ({
      ...result,
      [item[key]]: [
        ...(result[item[key]] || []),
        item,
      ]
    }), {});
  }

  togglePopout(left, top) {
    this.setState({
      popout: <Popout left={left} top={top} />
    })
  }

  render() {
    if (!this.state.archive) {
      return
Loading...
;
    }

    let data = this.groupBy(this.state.archive.messages, "channel_id"); // group by channel
    data = Object.entries(data).sort((a, b) => a[1][0].timestamp - b[1][0].timestamp); // sort by first message chronologically

    let channels = []
    for (const [channel, messages] of data) {
      channels.push(

          <Divider name={messages[0].channel} id={channel} />
          {messages.map(m => <Message key={m.id} message={m} popoutCB={this.togglePopout} />)}

      )
    }

    return (

        {channels}

          {this.state.popout}

    );
  }
}
<|endoftext|>


<commit_before>export default ({ app, chai }) => {
  const testSteamId = '76561198336554280'
  const testSteamName = 'KappaRoss'

  const addPlayer = (id, platform = '0') =>
    chai.request(app)
      .post('/api/v1/player/add')
      .send({ id, platform })

  const deletePlayer = (id, platform = '0') =>
    chai.request(app)
      .get(`/api/v1/player/${platform}/${id}/delete`)

  const getPlayer = (id, platform = '0') =>
    chai.request(app)
      .get(`/api/v1/player/${platform}/${id}`)

  describe('/player', () => {
    it('Should get all players', () =>
      chai.request(app)
        .get('/api/v1/player').should.eventually.have.property('status', 200)
    )

    describe('/add', () => {
      it('Should add a player', () =>
        addPlayer(testSteamId).should.eventually.have.property('status', 200)
      )

      it('Should prevent duplicate addition', () =>
        addPlayer(testSteamId).should.be.rejectedWith('Conflict')
      )

      it('Should recognize an invalid platform', () =>
        addPlayer(testSteamId, 'nintendo-wii').should.be.rejectedWith('Bad Request')
      )
    })

    describe('/:platform/:id/update', () =>
      it('Should update a player', () =>
        chai.request(app)
          .get(`/api/v1/player/0/${testSteamId}/update`)
          .then((res) => {
            res.should.have.status(200)
            res.body.data.name.should.equal(testSteamName)
          })
      ).timeout(5000) /* laggy api */
    )

    describe('/:platform/:id', () => {
      it('Should get a player', () =>
        getPlayer(testSteamId)
          .then((res) => {
            res.should.have.status(200)
            res.body.data.id.should.equal(testSteamId)
          })
      )

      it('Should recognize an invalid platform', () =>
        getPlayer(testSteamId, 'nintendo-wii')
          .should.be.rejectedWith('Bad Request')
      )
    })

    describe('/:platform/:id/delete', () => {
      it('Should delete a player', () =>
        deletePlayer(testSteamId)
          .should.eventually.have.property('status', 200)
      )

      it('Should have deleted the player', () =>
        chai.request(app)
          .get(`/api/v1/player/0/${testSteamId}`)
          .should.be.rejectedWith('Not Found')
      )

      it('Should not delete a player that does not exist', () =>
        deletePlayer(testSteamId)
          .should.be.rejectedWith('Not Found')
      )
    })
  })
}
<commit_msg>Remove the update test<commit_after>export default ({ app, chai }) => {
  const testSteamId = '76561198336554280'

  const addPlayer = (id, platform = '0') =>
    chai.request(app)
      .post('/api/v1/player/add')
      .send({ id, platform })

  const deletePlayer = (id, platform = '0') =>
    chai.request(app)
      .get(`/api/v1/player/${platform}/${id}/delete`)

  const getPlayer = (id, platform = '0') =>
    chai.request(app)
      .get(`/api/v1/player/${platform}/${id}`)

  describe('/player', () => {
    it('Should get all players', () =>
      chai.request(app)
        .get('/api/v1/player').should.eventually.have.property('status', 200)
    )

    describe('/add', () => {
      it('Should add a player', () =>
        addPlayer(testSteamId).should.eventually.have.property('status', 200)
      )

      it('Should prevent duplicate addition', () =>
        addPlayer(testSteamId).should.be.rejectedWith('Conflict')
      )

      it('Should recognize an invalid platform', () =>
        addPlayer(testSteamId, 'nintendo-wii').should.be.rejectedWith('Bad Request')
      )
    })

    describe('/:platform/:id', () => {
      it('Should get a player', () =>
        getPlayer(testSteamId)
          .then((res) => {
            res.should.have.status(200)
            res.body.data.id.should.equal(testSteamId)
          })
      )

      it('Should recognize an invalid platform', () =>
        getPlayer(testSteamId, 'nintendo-wii')
          .should.be.rejectedWith('Bad Request')
      )
    })

    describe('/:platform/:id/delete', () => {
      it('Should delete a player', () =>
        deletePlayer(testSteamId)
          .should.eventually.have.property('status', 200)
      )

      it('Should have deleted the player', () =>
        chai.request(app)
          .get(`/api/v1/player/0/${testSteamId}`)
          .should.be.rejectedWith('Not Found')
      )

      it('Should not delete a player that does not exist', () =>
        deletePlayer(testSteamId)
          .should.be.rejectedWith('Not Found')
      )
    })
  })
}
<|endoftext|>


<commit_before>import React      from 'react'
import ReactDOM   from 'react'
import A11y       from '../../src/a11y'
import { expect } from 'chai'

const onWarn = function (rule, el, cb) {
  return function (done) {
    let called = false
    const a11y = new A11y(React, {
      ReactDOM
    , reporter (info) {
        called = true
        a11y.restoreAll()
        cb(info)
      }
    , rules: {
        [rule]: 1
      }
    })

    // force a11y into sync mode dfor test
    a11y.__forceSync(true)

    // create the el
    el()

    // because of sync mode, we can callback here
    done()
  }
}

export const warns = function (rule, title, re, el) {
  it(title, onWarn(rule, el, function (info) {
    const {
      msg
    } = info

    expect(msg).to.match(re)
  }))
}

const doesntWarn = function (rule, title, re, el) {
  it(title, onWarn(rule, el, function (info) {
    const {
      msg
    } = info

    expect(msg).to.not.match(re)
  }, true))
}

export const doesnt = { warn: doesntWarn }
<commit_msg>remove superfluous flag<commit_after>import React      from 'react'
import ReactDOM   from 'react'
import A11y       from '../../src/a11y'
import { expect } from 'chai'

const onWarn = function (rule, el, cb) {
  return function (done) {
    const a11y = new A11y(React, {
      ReactDOM
    , reporter (info) {
        a11y.restoreAll()
        cb(info)
      }
    , rules: {
        [rule]: 1
      }
    })

    // force a11y into sync mode dfor test
    a11y.__forceSync(true)

    // create the el
    el()

    // because of sync mode, we can callback here
    done()
  }
}

export const warns = function (rule, title, re, el) {
  it(title, onWarn(rule, el, function (info) {
    const {
      msg
    } = info

    expect(msg).to.match(re)
  }))
}

const doesntWarn = function (rule, title, re, el) {
  it(title, onWarn(rule, el, function (info) {
    const {
      msg
    } = info

    expect(msg).to.not.match(re)
  }, true))
}

export const doesnt = { warn: doesntWarn }
<|endoftext|>


<commit_before>import {Loader as loader} from "jspm";
let System = loader();

describe("Sortable", () => {
  let Sortable;
  let sortable;
  let templatingEngine;
  let MockElement = () => {};

  before(() => {
    return System.import("aurelia-pal").then(pal => {
      pal.initializePAL((platform, feature, dom) => {
        dom.Element = MockElement;
        dom.createMutationObserver = function() { return { observe(){} }; };
        dom.createElement = function() {
          return {
            firstChild: {
              firstElementChild: {}
            }
          };
        };
        dom.createTextNode = function() { return {}; };
      });
      return System.import("aurelia-templating").then(tmpl => {
        templatingEngine = tmpl.templatingEngine;
        templatingEngine.initialize();
        return System.import("./src/sortable").then(mod => {
          Sortable = mod.Sortable;
        });
      });
    });
  });

  beforeEach(() => {
    sortable = templatingEngine.createModelForUnitTest(Sortable);
  });

  describe( "Constructor", () => {

    it("should set element", () => {
      expect(sortable.element).to.be.an("object");
    });

    it("should set drag", () => {
      return System.import("./src/drag").then(mod => {
        expect(sortable.drag).to.be.an.instanceof(mod.Drag);
      });
    });

    it("should set autoScroll", () => {
      return System.import("./src/auto-scroll").then(mod => {
        expect(sortable.autoScroll).to.be.an.instanceof(mod.AutoScroll);
      });
    });

    it("should set selector", () => {
      expect(sortable.selector).to.equal("[sortable-item]");
    });

    it("should set fromIx", () => {
      expect(sortable.fromIx).to.equal(-1);
    });

    it("should set toIx", () => {
      expect(sortable.toIx).to.equal(-1);
    });

  });

  describe( "Defaults", () =>{

    it("should set scroll speed", () => {
      expect(sortable.scrollSpeed).to.equal(10);
    });

    it("should set scroll sensitivity", () => {
      expect(sortable.scrollSensitivity).to.equal(10);
    });

    it("should set items", () => {
      expect(sortable.items).to.have.length(0);
    });

    it("should set placeholder", () => {
      expect(sortable.placeholder).to.deep.equal({ placeholderClass: "placeholder", style: {} });
    });

    it("should set axis", () => {
      expect(sortable.axis).to.have.length(0);
    });

    it("should have a bounding rect", () => {
      expect(sortable.boundingRect).to.be.a("null");
    });

    it("should have a moved function", () => {
      expect(sortable.moved).to.be.a("function");
    });

    it("should set dragZIndex", () => {
      expect(sortable.dragZIndex).to.equal(1);
    });

    it("should set disallowedDragTagNames", () => {
      expect(sortable.disallowedDragTagNames).to.deep.equal(["INPUT", "SELECT", "TEXTAREA"]);
    });

    it("should have a allowDrag function", () => {
      expect(sortable.allowDrag).to.be.a("function");
    });

    it("should have a allowMove function", () => {
      expect(sortable.allowMove).to.be.a("function");
    });

  });

  describe("activate", () => {
    let sandbox;
    let oribella;
    let removeGestureFn = () => {};
    let removeScrollFn = () => {};
    let on;
    let bindScroll;
    let closest;
    let mockElement = {};
    let mockScroll = {};

    before(() => {
      return System.import("oribella-default-gestures").then(mod => {
        oribella = mod.oribella;
      });
    });

    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sortable.element = mockElement;
      on = sandbox.stub(oribella, "on").returns(removeGestureFn);
      bindScroll = sandbox.stub(sortable, "bindScroll").returns(removeScrollFn);
      closest = sandbox.stub(sortable, "closest").returns(mockScroll);
    });

    afterEach(() => {
      sandbox.restore();
    });

    it("should add a oribella swipe listener", () => {
      sortable.activate();
      expect(on).to.have.been.calledWith({}, "swipe", sortable);
      expect(sortable.removeListener).to.equal(removeGestureFn);
    });

    it("should find closest scroll if a selector was bound", () => {
      sortable.scroll = "foo";
      sortable.activate();
      expect(closest).to.have.been.calledWith(mockElement, "foo");
    });

    it("should default scroll to injected element", () => {
      sortable.activate();
      expect(sortable.scroll).to.equal(mockElement);
    });

    it("should add a scroll listener", () => {
      sortable.activate();
      expect(bindScroll).to.have.been.calledWith(mockElement, sinon.match.func);
      expect(sortable.removeScroll).to.equal(removeScrollFn);
    });

  });

});
<commit_msg>test(sortable): add tests for `deactivate`<commit_after>import {Loader as loader} from "jspm";
let System = loader();

describe("Sortable", () => {
  let sandbox;
  let Sortable;
  let sortable;
  let templatingEngine;
  let MockElement = () => {};

  before(() => {
    return System.import("aurelia-pal").then(pal => {
      pal.initializePAL((platform, feature, dom) => {
        dom.Element = MockElement;
        dom.createMutationObserver = function() { return { observe(){} }; };
        dom.createElement = function() {
          return {
            firstChild: {
              firstElementChild: {}
            }
          };
        };
        dom.createTextNode = function() { return {}; };
      });
      return System.import("aurelia-templating").then(tmpl => {
        templatingEngine = tmpl.templatingEngine;
        templatingEngine.initialize();
        return System.import("./src/sortable").then(mod => {
          Sortable = mod.Sortable;
        });
      });
    });
  });

  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    sortable = templatingEngine.createModelForUnitTest(Sortable);
  });

  afterEach(() => {
    sandbox.restore();
  });

  describe( "Constructor", () => {

    it("should set element", () => {
      expect(sortable.element).to.be.an("object");
    });

    it("should set drag", () => {
      return System.import("./src/drag").then(mod => {
        expect(sortable.drag).to.be.an.instanceof(mod.Drag);
      });
    });

    it("should set autoScroll", () => {
      return System.import("./src/auto-scroll").then(mod => {
        expect(sortable.autoScroll).to.be.an.instanceof(mod.AutoScroll);
      });
    });

    it("should set selector", () => {
      expect(sortable.selector).to.equal("[sortable-item]");
    });

    it("should set fromIx", () => {
      expect(sortable.fromIx).to.equal(-1);
    });

    it("should set toIx", () => {
      expect(sortable.toIx).to.equal(-1);
    });

  });

  describe( "Defaults", () =>{

    it("should set scroll speed", () => {
      expect(sortable.scrollSpeed).to.equal(10);
    });

    it("should set scroll sensitivity", () => {
      expect(sortable.scrollSensitivity).to.equal(10);
    });

    it("should set items", () => {
      expect(sortable.items).to.have.length(0);
    });

    it("should set placeholder", () => {
      expect(sortable.placeholder).to.deep.equal({ placeholderClass: "placeholder", style: {} });
    });

    it("should set axis", () => {
      expect(sortable.axis).to.have.length(0);
    });

    it("should have a bounding rect", () => {
      expect(sortable.boundingRect).to.be.a("null");
    });

    it("should have a moved function", () => {
      expect(sortable.moved).to.be.a("function");
    });

    it("should set dragZIndex", () => {
      expect(sortable.dragZIndex).to.equal(1);
    });

    it("should set disallowedDragTagNames", () => {
      expect(sortable.disallowedDragTagNames).to.deep.equal(["INPUT", "SELECT", "TEXTAREA"]);
    });

    it("should have a allowDrag function", () => {
      expect(sortable.allowDrag).to.be.a("function");
    });

    it("should have a allowMove function", () => {
      expect(sortable.allowMove).to.be.a("function");
    });

  });

  describe("activate", () => {
    let oribella;
    let removeGestureFn = () => {};
    let removeScrollFn = () => {};
    let on;
    let bindScroll;
    let closest;
    let mockElement = {};
    let mockScroll = {};

    before(() => {
      return System.import("oribella-default-gestures").then(mod => {
        oribella = mod.oribella;
      });
    });

    beforeEach(() => {
      sortable.element = mockElement;
      on = sandbox.stub(oribella, "on").returns(removeGestureFn);
      bindScroll = sandbox.stub(sortable, "bindScroll").returns(removeScrollFn);
      closest = sandbox.stub(sortable, "closest").returns(mockScroll);
    });

    it("should add a oribella swipe listener", () => {
      sortable.activate();
      expect(on).to.have.been.calledWith({}, "swipe", sortable);
      expect(sortable.removeListener).to.equal(removeGestureFn);
    });

    it("should find closest scroll if a selector was bound", () => {
      sortable.scroll = "foo";
      sortable.activate();
      expect(closest).to.have.been.calledWith(mockElement, "foo");
    });

    it("should default scroll to injected element", () => {
      sortable.activate();
      expect(sortable.scroll).to.equal(mockElement);
    });

    it("should add a scroll listener", () => {
      sortable.activate();
      expect(bindScroll).to.have.been.calledWith(mockElement, sinon.match.func);
      expect(sortable.removeScroll).to.equal(removeScrollFn);
    });

  });

  describe("deactivate", () => {

    it("should remove oribella swipe listener", () => {
      let removeListener = sandbox.stub();
      sortable.removeListener = removeListener;
      sortable.deactivate();
      expect(removeListener).to.have.been.calledWithExactly();
    });

    it("should not throw if typeof removeListener isn't a function", () => {
      sortable.removeListener = null;
      expect(sortable.deactivate.bind(sortable)).not.to.throw();
    });

    it("should remove scroll listener", () => {
      let removeScroll = sandbox.stub();
      sortable.removeScroll = removeScroll;
      sortable.deactivate();
      expect(removeScroll).to.have.been.calledWithExactly();
    });

    it("should not throw if typeof removeScroll isn't a function", () => {
      sortable.removeScroll = null;
      expect(sortable.deactivate.bind(sortable)).not.to.throw();
    });

  });

});
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var rule = require('../rules/spell-checker'),
    RuleTester = require('eslint').RuleTester;

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

var ruleTester = new RuleTester({
    env: {
        'es6': true
    },

    parserOptions: {
      "ecmaVersion": 2018,
      "sourceType": "module",
        ecmaFeatures: {
            "modules": true
        }
    }
});

ruleTester.run('spellcheck/spell-checker', rule, {
    valid: [
        'var a = 1 // This is a comment',
        'var this2 = 1 // This shouldn\'t fail, not the first or the 2nd time',
        'var test12anything78variable = 1 // This shouldn\'t fail, not the first or \'the\' 3rd time',
        'var a = 2 /* This is a Block Comment */',
        'var a = 2 //Array',
        'var angular = thisIsATest(of_a_snake_case)',
        'var a = new RegExp(`\^Card\\sreader\\xAAnot\\uFFFFconnected\\sin\\s${ numberOfSeconds }s\\.`);',
        'var a = new RegExp(`\^Card\\sreader\\snot\\sconnected\\sin\\s${ numberOfSeconds }s\\.`);',
        'var a = function testingCamelCase(each){};',
        'var a = RegExp',
        'var a = "January"',
        'var a = \'Hello how are you this is a string\'',
        'var a = \'ArrayBuffer\'',
        'var a = \'foobar\'.substring(0,1)',
        'var a = JSON.stringify({})',
        'var a = Math.trunc(-0.1)',
        'import Foo from "component/Foo"',
        'import { Foo } from "component/Foo"',
        'export { Foo } from "component/Foo"',
        {
            code: 'var url = "http://examplus.com"',
            options:[{skipWords: ['url'], skipIfMatch:['http://[^\s]*']}]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{minLength: 4}]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{skipWordIfMatch: ['^.{1,3}$']}]
        }
    ],
    invalid: [
        {
            code: 'var a = 1 // tsih is a comment srting dict',
            options:[{skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var ajhasd = \'liasdfuhn\' // tsih is a comment srting dict',
            options:[{strings: false, identifiers: false, skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var a = \'liasdfuhn\' // tsih is a comment srting dict',
            options:[{comments: false, strings: true, skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: liasdfuhn on String'}]
        },
        {
            code: 'var a = 1 // tsih is a comment srting dict',
            options:[{skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var url = "http://examplus.com"',
            options:[{skipWords: ['url']}],
            errors: [
                { message: 'You have a misspelled word: http on String'},
                { message: 'You have a misspelled word: examplus on String'}]
        },
        {
            code: 'var a = 1 /* tsih is a comment srting Block */ ',
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var test12anthing78variable = 1 // This shuldn\'t fail, not the first or the 3rd time ',
            errors: [
                { message: 'You have a misspelled word: test12anthing78variable on Identifier'},
                { message: 'You have a misspelled word: shuldn\'t on Comment'}]
        },
        {
            code: 'var angular = tsihIsATest(of_a_snake_case_srting)',
            errors: [
                { message: 'You have a misspelled word: tsih on Identifier'},
                { message: 'You have a misspelled word: srting on Identifier'}]
        },
        {
            code: 'var el = "myElement"',
            options:[{minLength: 2}],
            errors: [
                { message: 'You have a misspelled word: el on Identifier'}
            ]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{skipWordIfMatch: ['^.{1,2}$']}],
            errors: [
                { message: 'You have a misspelled word: Orm on Identifier'}
            ]
        },
        {
            code: 'var a = \'Hello tsih is a srting\'',
            errors: [
                { message: 'You have a misspelled word: tsih on String'},
                { message: 'You have a misspelled word: srting on String'}]
        },
        {
            code: 'var a = 1 // colour cheque behaviour tsih',
            options:[{lang: 'en_GB', skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'}]
        },
        {
            code: 'var a = 1 // color is a comment behavior dict',
            options:[{lang: 'en_GB', skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: color on Comment'},
                { message: 'You have a misspelled word: behavior on Comment'}]
        }
    ]
});
<commit_msg>added unit test<commit_after>//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var rule = require('../rules/spell-checker'),
    RuleTester = require('eslint').RuleTester;

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

var ruleTester = new RuleTester({
    env: {
        'es6': true
    },

    parserOptions: {
      "ecmaVersion": 2018,
      "sourceType": "module",
        ecmaFeatures: {
            "modules": true
        }
    }
});

ruleTester.run('spellcheck/spell-checker', rule, {
    valid: [
        'var a = 1 // This is a comment',
        'var this2 = 1 // This shouldn\'t fail, not the first or the 2nd time',
        'var test12anything78variable = 1 // This shouldn\'t fail, not the first or \'the\' 3rd time',
        'var a = 2 /* This is a Block Comment */',
        'var a = 2 //Array',
        'var angular = thisIsATest(of_a_snake_case)',
        'var a = new RegExp(`\^Card\\sreader\\xAAnot\\uFFFFconnected\\sin\\s${ numberOfSeconds }s\\.`);',
        'var a = new RegExp(`\^Card\\sreader\\snot\\sconnected\\sin\\s${ numberOfSeconds }s\\.`);',
        'var a = function testingCamelCase(each){};',
        'var a = RegExp',
        'var a = "January"',
        'var a = \'Hello how are you this is a string\'',
        'var a = \'ArrayBuffer\'',
        'var a = \'foobar\'.substring(0,1)',
        'var a = JSON.stringify({})',
        'var a = Math.trunc(-0.1)',
        'import Foo from "component/Foo"',
        'import { Foo } from "component/Foo"',
        'export { Foo } from "component/Foo"',
        {
            code: 'var url = "http://examplus.com"',
            options:[{skipWords: ['url'], skipIfMatch:['http://[^\s]*']}]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{minLength: 4}]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{skipWordIfMatch: ['^.{1,3}$']}]
        },
        {
            code: 'var source = \'<div className="video-img">\'',
            options:[{skipIfMatch:['=".*"']}]
        },
    ],
    invalid: [
        {
            code: 'var a = 1 // tsih is a comment srting dict',
            options:[{skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var ajhasd = \'liasdfuhn\' // tsih is a comment srting dict',
            options:[{strings: false, identifiers: false, skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var a = \'liasdfuhn\' // tsih is a comment srting dict',
            options:[{comments: false, strings: true, skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: liasdfuhn on String'}]
        },
        {
            code: 'var a = 1 // tsih is a comment srting dict',
            options:[{skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var url = "http://examplus.com"',
            options:[{skipWords: ['url']}],
            errors: [
                { message: 'You have a misspelled word: http on String'},
                { message: 'You have a misspelled word: examplus on String'}]
        },
        {
            code: 'var a = 1 /* tsih is a comment srting Block */ ',
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'},
                { message: 'You have a misspelled word: srting on Comment'}]
        },
        {
            code: 'var test12anthing78variable = 1 // This shuldn\'t fail, not the first or the 3rd time ',
            errors: [
                { message: 'You have a misspelled word: test12anthing78variable on Identifier'},
                { message: 'You have a misspelled word: shuldn\'t on Comment'}]
        },
        {
            code: 'var angular = tsihIsATest(of_a_snake_case_srting)',
            errors: [
                { message: 'You have a misspelled word: tsih on Identifier'},
                { message: 'You have a misspelled word: srting on Identifier'}]
        },
        {
            code: 'var el = "myElement"',
            options:[{minLength: 2}],
            errors: [
                { message: 'You have a misspelled word: el on Identifier'}
            ]
        },
        {
            code: 'var myOrmFunctions = "myElement"',
            options:[{skipWordIfMatch: ['^.{1,2}$']}],
            errors: [
                { message: 'You have a misspelled word: Orm on Identifier'}
            ]
        },
        {
            code: 'var a = \'Hello tsih is a srting\'',
            errors: [
                { message: 'You have a misspelled word: tsih on String'},
                { message: 'You have a misspelled word: srting on String'}]
        },
        {
            code: 'var a = 1 // colour cheque behaviour tsih',
            options:[{lang: 'en_GB', skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: tsih on Comment'}]
        },
        {
            code: 'var a = 1 // color is a comment behavior dict',
            options:[{lang: 'en_GB', skipWords: ['dict']}],
            errors: [
                { message: 'You have a misspelled word: color on Comment'},
                { message: 'You have a misspelled word: behavior on Comment'}]
        }
    ]
});
<|endoftext|>


<commit_before>/*!
 *
 * Text Input Changes - Spare jQuery
 *
 * Copyright 2013 Franklin Davenport
 * Released under the MIT license
 *
 * Date: 2013-04-14
 */

(function($) {

	// Text Input Changes
	//////////////////////
	//
	// Attach to an input element to capture backspaces, deletions, and character insertions.
	// This is useful when the regular key events don't work properly (eg, Chrome on Android - 04/2013)
	// Listen for the "text-input-change" with a param like:
	// 	{backspaces: 0, deletions: 1, insertions: "abc"}
	//
	// Warning: This plugin will overwrite the text in the input box with "\\\\\\\\////////", When the input
	//          is focused, a timer will check the input's value against "\\\\\\\\////////" to detect changes.
	//
	// Example:
	//	$('input.capture-changes').textInputChanges()
	//  	.on('text-input-change', function(ev, changes) { ... });
	//
	// Call the flush method to trigger the "text-input-change" immediately
	// 	$(...).textInputChanges('flush')
	//
	$.fn.textInputChanges = (function() {
		var listenerOps = {
			timeoutPeriod: 300,
			timeout: 0
		};

		var inputOps = {
			charLeft: "\\",
			charRight: "/",
			charRepeat: 15,
			left: "",
			right: "",
			default: ""
		}

		var opToKeyCode = {
			"backspace": 8,
			"delete": 46
		}

		function repeatString(rs, count) {
			var s = "";
			for(var i = 0; i < count; i++) {
				s += rs;
			}
			return s;
		}

		inputOps.left = repeatString(inputOps.charLeft, inputOps.charRepeat);
		inputOps.right = repeatString(inputOps.charRight, inputOps.charRepeat);
		inputOps.default = inputOps.left + inputOps.right;

		// Listener Timing
		function listenerStart(ele$, data) {
			data.listenerRunning = true;
			inputReset(ele$, data);
			listenerRunSleep(ele$, data);
		}
		function listenerStop(ele$, data) {
			data.listenerRunning = false;
		}
		function listenerRunSleep(ele$, data) {
			if(data.listenerRunning) {
				try {
					listenerRun(ele$, data);
				} catch(e) {if(window.console && console.error) {console.error(e);} }

				clearTimeout(listenerOps.timeout);
				listenerOps.timeout = setTimeout(function(){
					listenerRunSleep(ele$, data)
				}, listenerOps.timeoutPeriod);
			}
		}
		// Listener Function
		function listenerRun(ele$, data) {
			var iVal = inputFlush(ele$);
			if(iVal != inputOps.default && iVal != null) {
				inputReset(ele$);
				var charMatch = iVal.match(/^(\\*)([^\\\/]*)(\/*)$/)

				var backspaces = inputOps.charRepeat - charMatch[1].length
				var deletions = inputOps.charRepeat - charMatch[3].length;
				var insertions = repeatString(inputOps.charLeft, -backspaces)
					+ charMatch[2]
					+ repeatString(inputOps.charRight, -deletions)

				ele$.trigger('text-input-change', {
					backspaces: Math.max(0, backspaces),
					insertions: insertions,
					deletions: Math.max(0, deletions)
				});
			}
		}

		// Input Handling
		function inputReset(ele$) {
			ele$.val(inputOps.default);
			ele$.selectRange(inputOps.charRepeat, inputOps.charRepeat);
		}

		function inputFlush(ele$) {
			var fVal = ele$.val();
			inputReset(ele$);
			return fVal;
		}

		var methods = {

			// Init
			init: function() {

				this.each(function() {
					var input$ = $(this);

					var data = input$.data('text-input-changes');
					if(data == null) {
						var data = {};
						input$.data('text-input-changes', data);
					}

					input$.on('focus', function() {
						listenerStart(input$, data);
					});
					input$.on('click', function() {
						 inputReset(input$);
					});
					input$.on('blur', function() {
						 listenerStop(input$, data);
					});

					return function(arg1) {
						if(arguments.length == 0) {
							return methods.init.apply(this);
						}
						if(arguments.length == 1) {
							if(typeof arg1 === "string") {
								return methods[arg1].apply(this);
							} else {
								return methods.init.apply(this, [arg1]);
							}
						}
					};
				});
				return this;

			},

			// Flush, Gets the changes and resets
			flush: function() {
				return inputFlush(this);
			}
		};

		return function() {
			if(arguments.length <= 1) {
				return methods.init.apply(this, arguments);
			}

		}

	})();
})(jQuery)

<commit_msg>+ add select-range plugin as required by text-input-changes + apply source formatting<commit_after>/*!
 * Text Input Changes - Spare jQuery
 * Select Range - Spare jQuery
 *
 * Copyright 2013 Franklin Davenport
 * Released under the MIT license
 *
 * Date: 2013-04-14
 */

( function( $ ) {

  // Text Input Changes
  //////////////////////
  //
  // Attach to an input element to capture backspaces, deletions, and character insertions.
  // This is useful when the regular key events don't work properly (eg, Chrome on Android - 04/2013)
  // Listen for the "text-input-change" with a param like:
  //   {backspaces: 0, deletions: 1, insertions: "abc"}
  //
  // Warning: This plugin will overwrite the text in the input box with "\\\\\\\\////////", When the input
  //          is focused, a timer will check the input's value against "\\\\\\\\////////" to detect changes.
  //
  // Example:
  //  $('input.capture-changes').textInputChanges()
  //    .on('text-input-change', function(ev, changes) { ... });
  //
  // Call the flush method to trigger the "text-input-change" immediately
  //   $(...).textInputChanges('flush')
  //
  $.fn.textInputChanges = function( method ) {
    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }
  };

  var listenerOps = {
    delay: 90
  };

  var inputOps = {
    charLeft: "\\",
    charRight: "/",
    charRepeat: 15,
    left: "",
    right: "",
    default: ""
  }

  var defaultOps = {
    listener: listenerOps,
    input: inputOps
  }

  function repeatString( rs, count ) {
    var s = "";
    for( var i = 0; i < count; i++ ) {
      s += rs;
    }
    return s;
  }

  inputOps.left = repeatString(inputOps.charLeft, inputOps.charRepeat);
  inputOps.right = repeatString(inputOps.charRight, inputOps.charRepeat);
  inputOps.default = inputOps.left + inputOps.right;

  function _d( ele$, val ) {
    if( arguments.length == 1 ) {
      return ele$.data( 'text-input-changes' )
    } else if( arguments.length == 2 ) {
      return ele$.data( 'text-input-changes', val );
    }
  }

  // Listener Timing
  function listenerStart( ele$ ) {
    _d( ele$ ).listenerRunning = true;
    inputReset( ele$ );
    listenerRunSleep( ele$ );
  }
  function listenerStop( ele$ ) {
    _d( ele$ ).listenerRunning = false;
  }
  function listenerRunSleep( ele$ ) {
    var data = _d( ele$ );
    if( data.listenerRunning ) {
      try {
        listenerRun( ele$ );
      } catch(e) { if( window.console && console.error) { console.error(e); } }

      clearTimeout( data.listener.timeout );
      data.listener.timeout = setTimeout( function() {
        listenerRunSleep( ele$ )
      }, data.listener.delay );
    }
  }

  // Listener Function
  function listenerRun( ele$ ) {
    var iVal = inputFlush( ele$ );
    if( iVal != inputOps.default && iVal != null ) {
      inputReset( ele$ );
      var charMatch = iVal.match( /^(\\*)([^\\\/]*)(\/*)$/ )

      var backspaces = inputOps.charRepeat - charMatch[1].length
      var deletions = inputOps.charRepeat - charMatch[3].length;
      var insertions = repeatString( inputOps.charLeft, -backspaces ) +
        charMatch[2] + repeatString(inputOps.charRight, -deletions);

      ele$.trigger('text-input-change', {
        backspaces: Math.max( 0, backspaces ),
        insertions: insertions,
        deletions: Math.max( 0, deletions )
      });
    }
  }

  // Input Handling
  function inputReset( ele$ ) {
    ele$.val( inputOps.default );
    ele$.selectRange( inputOps.charRepeat, inputOps.charRepeat );
  }

  function inputFlush( ele$ ) {
    var fVal = ele$.val();
    inputReset( ele$ );
    return fVal;
  }

  var methods = {

    // Init
    init: function( ops ) {
      this.each( function() {
        var input$ = $( this );

        // Update Data
        var data = $.extend( true, defaultOps, _d( input$ ), ops );
        _d( input$, data );

        // Bind Events
        input$.on( 'focus', function() {
          listenerStart( input$, data );
        });
        input$.on( 'click', function() {
           inputReset( input$ );
        });
        input$.on( 'blur', function() {
           listenerStop( input$, data );
        });
      });
      return this;
    },

    // Flush, triggers the change event and resets
    flush: function() {
      return inputFlush( this );
    }
  };

})(jQuery);

( function( $ ) {

  // Select Range
  ////////////////
  //
  // Selects a range of characters or moves the cursor
  // in a text input or textarea
  //
  $.fn.selectRange = function( start, end ) {
    return this.each( function() {
      if ( this.setSelectionRange ) {
        this.focus();
        this.setSelectionRange( start, end );
      } else if ( this.createTextRange ) {
        var range = this.createTextRange();
        range.collapse( true );
        range.moveEnd( 'character', end );
        range.moveStart( 'character', start );
        range.select();
      }
    });
  };

})(jQuery);

<|endoftext|>


<commit_before>var sandbox = require("sandboxed-module");
var async = require("async");

exports["api.remote.join: missing params"] = function(test){

	var flag = 1;
	var dbdocs = {};
	dbdocs["50187f71556efcbb25000002"] = {_id:"50187f71556efcbb25000002",uid:620793114, ctime:1350094951092, catalog:"dummy", test:"test", rcpts:[620793114]};

	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){

								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000002");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,{_id:620793114, name:"enric",wids:["50187f71556efcbb25000002"]});
								}
							},
							save:function(col_str,doc,ret_handler){

								//Not executed because constraint is not satisfied
								flag = 0;
								ret_handler();
							}
						 },
					"./server":{config:{app:{status:1},db:{default_catalog:"docs"}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	//uid missing
	var params = {miss_uid:620793114, wid:"50187f71556efcbb25000002"};
	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err, {code:-12, message: "uid parameter required"});

	});

	//wid missing
	params = {uid:620793114, miss_wid:"50187f71556efcbb25000002"};
	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err, {code:-12, message: "wid parameter required"});
		test.expect(7);
		test.done();
	});

}

exports["api.remote.join: valid params, default catalog, db async"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", rcpts:[{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"}], catalog:"docs"};

	var api = sandbox.require("../lib/api",{
		requires:{"./db":{	//db mock module for join procedure

		}}
	});
	var dbusers = {620793114:{name:"enric", push_id:"gcm-114", push_type:"gcm", wids:[]}, 620793117:{name:"foo", push_id:"gcm-117", push_type:"gcm", wids:["50187f71556efcbb25000001"]}};
	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){
								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,dbusers["" + id_str]);
								}

							},
							save:function(col_str,doc,ret_handler){

								if(col_str == "docs"){
									test.equal(col_str,"docs");
									test.deepEqual(doc.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm"}]);

									//save doc to db...returns with _id:12345
									setTimeout(function(){//100ms delay saving document

										ret_handler(null,doc);
									},100);
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									test.deepEqual(doc.wids,["50187f71556efcbb25000001"])
									ret_handler(null);
								}
							}
						 },
				 "./api" : api,
				 "./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793114, wid:"50187f71556efcbb25000001"};//uid not in rcpts
	async.series(
		[function(next){

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.deepEqual(ctx.retval.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm"}]);
				test.equal(ctx.retval._id, undefined);
				test.equal(ctx.retval.wid, "50187f71556efcbb25000001");
				test.equal(ctx.retval.catalog, "docs");
				test.equal(ctx.retval.a,1);
				test.equal(ctx.retval.b,"test1234");
				next();

			});

		},function(next){
			params = {uid:620793117, wid:"50187f71556efcbb25000001"};//uid in rcpts

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.equal(ctx.retval,1);

				test.expect(25);
				test.done();
				next();

			});

		}]);

}

exports["api.remote.join: valid params, no rcpts, explicit catalog"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", catalog:"docs"};

	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){

								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,{_id:620793114, name:"enric",wids:["50187f71556efcbb25000001"]});
								}

							},
							save:function(col_str,doc,ret_handler){

								//Not executed because constraint joinable is not satisfied.
								flag = 0;
								ret_handler();
							}
						 },
					"./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793118, wid:"50187f71556efcbb25000001"};//uid not in rcpts

	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err,{code:-7, message:"No access permission: not joinable/unjoinable"});

		test.expect(5);
		test.done();

	});

}
<commit_msg>extended tests to include new ev_types parameters when joining a document.<commit_after>var sandbox = require("sandboxed-module");
var async = require("async");

exports["api.remote.join: missing params"] = function(test){

	var flag = 1;
	var dbdocs = {};
	dbdocs["50187f71556efcbb25000002"] = {_id:"50187f71556efcbb25000002",uid:620793114, ctime:1350094951092, catalog:"dummy", test:"test", rcpts:[620793114]};

	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){

								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000002");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,{_id:620793114, name:"enric",wids:["50187f71556efcbb25000002"]});
								}
							},
							save:function(col_str,doc,ret_handler){

								//Not executed because constraint is not satisfied
								flag = 0;
								ret_handler();
							}
						 },
					"./server":{config:{app:{status:1},db:{default_catalog:"docs"}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	//uid missing
	var params = {miss_uid:620793114, wid:"50187f71556efcbb25000002"};
	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err, {code:-12, message: "uid parameter required"});

	});

	//wid missing
	params = {uid:620793114, miss_wid:"50187f71556efcbb25000002"};
	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err, {code:-12, message: "wid parameter required"});
		test.expect(7);
		test.done();
	});

}

exports["api.remote.join: valid params, default catalog, no ev_types"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", rcpts:[{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"}], catalog:"docs"};

	var api = sandbox.require("../lib/api",{
		requires:{"./db":{	//db mock module for join procedure

		}}
	});
	var dbusers = {620793114:{name:"enric", push_id:"gcm-114", push_type:"gcm", wids:[]}, 620793117:{name:"foo", push_id:"gcm-117", push_type:"gcm", wids:["50187f71556efcbb25000001"]}};
	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){
								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,dbusers["" + id_str]);
								}

							},
							save:function(col_str,doc,ret_handler){

								if(col_str == "docs"){
									test.equal(col_str,"docs");
									test.deepEqual(doc.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm"}]);

									//save doc to db...returns with _id:12345
									setTimeout(function(){//100ms delay saving document

										ret_handler(null,doc);
									},100);
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									test.deepEqual(doc.wids,["50187f71556efcbb25000001"])
									ret_handler(null);
								}
							}
						 },
				 "./api" : api,
				 "./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793114, wid:"50187f71556efcbb25000001"};//uid not in rcpts
	async.series(
		[function(next){

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.deepEqual(ctx.retval.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm"}]);
				test.equal(ctx.retval._id, undefined);
				test.equal(ctx.retval.wid, "50187f71556efcbb25000001");
				test.equal(ctx.retval.catalog, "docs");
				test.equal(ctx.retval.a,1);
				test.equal(ctx.retval.b,"test1234");
				next();

			});

		},function(next){
			params = {uid:620793117, wid:"50187f71556efcbb25000001"};//uid in rcpts

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.equal(ctx.retval,1);

				test.expect(21);
				test.done();
				next();

			});

		}]);

}

exports["api.remote.join: valid params, default catalog, ev_types"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", rcpts:[{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"}], catalog:"docs"};

	var api = sandbox.require("../lib/api",{
		requires:{"./db":{	//db mock module for join procedure

		}}
	});
	var dbusers = {620793114:{name:"enric", push_id:"gcm-114", push_type:"gcm", wids:[]}, 620793117:{name:"foo", push_id:"gcm-117", push_type:"gcm", wids:["50187f71556efcbb25000001"]}};
	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){
								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,dbusers["" + id_str]);
								}

							},
							save:function(col_str,doc,ret_handler){

								if(col_str == "docs"){
									test.equal(col_str,"docs");
									test.deepEqual(doc.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm",ev_types:["ev_api_set","ev_api_create"]}]);

									//save doc to db...returns with _id:12345
									setTimeout(function(){//100ms delay saving document

										ret_handler(null,doc);
									},100);
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									test.deepEqual(doc.wids,["50187f71556efcbb25000001"])
									ret_handler(null);
								}
							}
						 },
				 "./api" : api,
				 "./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793114, wid:"50187f71556efcbb25000001", ev_types:["ev_api_set","ev_api_create"]};//uid not in rcpts
	async.series(
		[function(next){

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.deepEqual(ctx.retval.rcpts, [{push_id:"gcm-115", push_type:"gcm"},{push_id:"gcm-117", push_type:"gcm"},{push_id:"gcm-114",push_type:"gcm",ev_types:["ev_api_set","ev_api_create"]}]);
				test.equal(ctx.retval._id, undefined);
				test.equal(ctx.retval.wid, "50187f71556efcbb25000001");
				test.equal(ctx.retval.catalog, "docs");
				test.equal(ctx.retval.a,1);
				test.equal(ctx.retval.b,"test1234");
				next();

			});

		},function(next){
			params = {uid:620793117, wid:"50187f71556efcbb25000001"};//uid in rcpts

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.equal(ctx.retval,1);

				test.expect(21);
				test.done();
				next();

			});

		}]);

}

exports["api.remote.join: valid params, default catalog, already joined, ev_types"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", rcpts:[{push_id:"gcm-115", push_type:"gcm",ev_types:["ev_api_pop"]},{push_id:"gcm-117", push_type:"gcm"}], catalog:"docs"};

	var api = sandbox.require("../lib/api",{
		requires:{"./db":{	//db mock module for join procedure

		}}
	});
	var dbusers = {620793115:{name:"loser", push_id:"gcm-115", push_type:"gcm", wids:["50187f71556efcbb25000001"]},620793114:{name:"enric", push_id:"gcm-114", push_type:"gcm", wids:[]}, 620793117:{name:"foo", push_id:"gcm-117", push_type:"gcm", wids:["50187f71556efcbb25000001"]}};
	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){
								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");

									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,dbusers["" + id_str]);
								}

							},
							save:function(col_str,doc,ret_handler){

								if(col_str == "docs"){
									test.equal(col_str,"docs");
									test.deepEqual(doc.rcpts, [{push_id:"gcm-115", push_type:"gcm",ev_types:["ev_api_set","ev_api_create"]},{push_id:"gcm-117", push_type:"gcm"}]);

									//save doc to db...returns with _id:12345
									setTimeout(function(){//100ms delay saving document

										ret_handler(null,doc);
									},100);
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									test.deepEqual(doc.wids,["50187f71556efcbb25000001"])
									ret_handler(null);
								}
							}
						 },
				 "./api" : api,
				 "./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793115, wid:"50187f71556efcbb25000001", ev_types:["ev_api_set","ev_api_create"]};//uid not in rcpts
	async.series(
		[function(next){

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.equal(ctx.retval, 1);

				next();

			});

		},function(next){
			params = {uid:620793117, wid:"50187f71556efcbb25000001"};//uid in rcpts

			sb.execute("join", params, function(err,ctx){

				test.ok(flag);
				test.equal(err,null);
				test.equal(ctx.retval,1);

				test.expect(16);
				test.done();
				next();

			});

		}]);

}

exports["api.remote.join: valid params, no rcpts, explicit catalog"] = function(test){

	var dbdocs = {};//documents at db
		dbdocs["50187f71556efcbb25000001"] = {_id:"50187f71556efcbb25000001", uid:620793115, a:1, b:"test1234", catalog:"docs"};

	var flag = 1;
	var sb = sandbox.require("../lib/sandbox",{
		requires:{"./db":{
							select: function(col_str, id_str, ret_handler){

								if( col_str == "docs"){

									test.equal(col_str,"docs");
									test.equal(id_str,"50187f71556efcbb25000001");
									ret_handler(null,dbdocs[id_str]);//return doc
								}else if(col_str == "users"){

									test.equal(col_str,"users");
									ret_handler(null,{_id:620793114, name:"enric",wids:["50187f71556efcbb25000001"]});
								}

							},
							save:function(col_str,doc,ret_handler){

								//Not executed because constraint joinable is not satisfied.
								flag = 0;
								ret_handler();
							}
						 },
					"./server":{config:{app:{status:1},db:{default_catalog:"docs", system_catalogs:["timers","events"]}},api:{config:{procedures:{join:1}}}}
		}
	});
	sb.init();
	sb.add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"timers")
	  .add_constraint_post("join","not_catalog",sb.constraints.not_catalog,"events")
	  .add_constraint_post("join","is_joinable",sb.constraints.is_joinable)
	  .add_constraint_post("join","param_wid",sb.constraints.is_required("wid"))
	  .add_constraint_post("join","param_uid",sb.constraints.is_required("uid"));

	var params = {uid:620793118, wid:"50187f71556efcbb25000001"};//uid not in rcpts

	sb.execute("join", params, function(err,result){

		test.ok(flag);
		test.deepEqual(err,{code:-7, message:"No access permission: not joinable/unjoinable"});

		test.expect(5);
		test.done();

	});

}
<|endoftext|>


<commit_before>/* global describe, it, before, expect */

var Test = require('../lib/test');

describe('test helper that prepares app', function() {

  describe('with helper', function() {
    function helper() {
      return 'Help me, ' + this.someone();
    }

    before(function(done) {
      var test = new Test(helper, 'test', 'show');
      test.app(function(app) {
        app.helper('someone', function() { return 'Dave'; });
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Help me, Dave');
    });
  });

  describe('with dynamic helper', function() {
    function helper() {
      return 'Help me, ' + this.someone();
    }

    before(function(done) {
      var test = new Test(helper, 'test', 'show');
      test.app(function(app) {
        app.dynamicHelper('someone', function(req, res) {
          return function() { return req.query.name; }
        });
      }).req(function(req) {
        req.query = {};
        req.query.name = 'Bob';
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Help me, Bob');
    });
  });

});
<commit_msg>More test cases for Test#app.<commit_after>/* global describe, it, before, expect */

var Test = require('../lib/test');

describe('test that prepares app', function() {

  describe('with helper', function() {
    function helper() {
      return 'Help me, ' + this.someone();
    }

    before(function(done) {
      var test = new Test(helper, 'test', 'show');
      test.app(function(app) {
        app.helper('someone', function() { return 'Dave'; });
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Help me, Dave');
    });
  });

  describe('with dynamic helper', function() {
    function helper() {
      return 'Help me, ' + this.someone();
    }

    before(function(done) {
      var test = new Test(helper, 'test', 'show');
      test.app(function(app) {
        app.dynamicHelper('someone', function(req, res) {
          return function() { return req.query.name; }
        });
      }).req(function(req) {
        req.query = {};
        req.query.name = 'Bob';
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Help me, Bob');
    });
  });

  describe('with route', function() {
    function dynamicHelper(req, res) {
      return function() {
        var app = req._locomotive.app;
        return 'Redirecting to ' + app._routeTo('foo', 'index').path();
      }
    }

    before(function(done) {
      var test = new Test(dynamicHelper, 'test', 'case', true);
      test.app(function(app) {
        app.route('/foo', 'foo', 'index');
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Redirecting to /foo');
    });
  });

  describe('with route with placeholder', function() {
    function dynamicHelper(req, res) {
      return function() {
        var app = req._locomotive.app;
        return 'Redirecting to ' + app._routeTo('foo', 'show').path({ id: 123 });
      }
    }

    before(function(done) {
      var test = new Test(dynamicHelper, 'test', 'case', true);
      test.app(function(app) {
        app.route('/foo/:id', 'foo', 'show');
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Redirecting to /foo/123');
    });
  });

  describe('with route with placeholder and optional format', function() {
    function dynamicHelper(req, res) {
      return function() {
        var app = req._locomotive.app;
        return 'Redirecting to ' + app._routeTo('foo', 'show').path({ id: 123, format: 'json' });
      }
    }

    before(function(done) {
      var test = new Test(dynamicHelper, 'test', 'case', true);
      test.app(function(app) {
        app.route('/foo/:id.:format?', 'foo', 'show');
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Redirecting to /foo/123.json');
    });
  });

  describe('with route with placeholder and optional format that is not specified', function() {
    function dynamicHelper(req, res) {
      return function() {
        var app = req._locomotive.app;
        return 'Redirecting to ' + app._routeTo('foo', 'show').path({ id: 123 });
      }
    }

    before(function(done) {
      var test = new Test(dynamicHelper, 'test', 'case', true);
      test.app(function(app) {
        app.route('/foo/:id.:format?', 'foo', 'show');
      }).create(function(err, h) {
        if (err) { return done(err); }
        help = h;
        done();
      });
    });

    it('should create helper', function() {
      expect(help).to.be.a('function');
      expect(help()).to.equal('Redirecting to /foo/123');
    });
  });

});
<|endoftext|>


<commit_before>var nj = require('../src/base'),
  utils = require('../src/utils/utils'),
  compiler = require('../src/compiler/compile'),
  compile = compiler.compile,
  _ = require('lodash'),
  React = require('react'),
  ReactDOM = require('react-dom'),
  ReactDOMServer = require('react-dom/server');

describe('test speed', function () {
  var tmpl = nj`
  <{div} id={num '_100'}>
    <#each {arr}>

        test_{../num}
        <#each {../list2}>

            <#params>
              <$if {../#:five}>
                <#p {'name'}>five

              </$if>
            </#params>
            span{no}
            {no}

        </#each>

      <#if {#:five(1):test}>

      <#else />

      </#if>
    </#each>
  </{div}>
  `;

  beforeAll(function () {
    nj.setComponentEngine('react', React, ReactDOM);

    nj.registerFilter('five', function (obj) {
      if (obj % 5 == 0) {
        return true;
      }
    });

    nj.registerFilter('test', function (obj) {
      return obj;
    });
  });

  xit('test render to string', function () {
    var data = {
      arr: _.times(5, function (n) {
        return n;
      }),
      num: Date.now(),
      list2: [1, 2, 3],
      onClick: 'onClick',
      params: {
        'data-a': 1,
        'data-b': 2
      },
      styles: "color:blue"
    };

    var tmplFn = compile(tmpl, 'tmpl1'),
        html = tmplFn(data);

    //console.log(JSON.stringify(nj.templates['tmpl1']));
    console.log(html);
    expect(html).toBeTruthy();
  });

  it('test render to component', function () {
    var start;

    var TestComponent1 = React.createClass({
      getInitialState: function () {
        start = Date.now();

        return {
          num: 100
        };
      },
      onClick: function () {
        start = Date.now();
        this.setState({ num: Date.now() }, function() {
          console.log('total:' + (Date.now() - start));
        });
      },
      render: function () {
        var list2 = [{ no: 1 }, { no: 2 }, { no: 3 }];

        var start = Date.now();
        var ret = React.createElement('div', { id: this.state.num + '_100' }, this.props.arr.map(function (o, i) {
          return [
              React.createElement('span', { className: 'test_' + i, style: { color: 'blue' }, onClick: this.onClick },
                'test_' + this.state.num,
                list2.map(function(p, j) {
                  return [React.createElement('div', i % 5 == 0 ? { name: 'five' } : null,
                    React.createElement('span', null, 'span' + p.no),
                    React.createElement('i', null, p.no)
                  )];
                })
              ),
              i % 5 == 0 ? React.createElement('br') : React.createElement('img')
          ];
        }.bind(this)));

        //var params = ['div', null];
        //this.props.arr.forEach(function (o, i) {
        //  params.push(React.createElement('span', { className: 'test_' + i }, 'test_' + i));
        //});
        //ret = React.createElement.apply(React, params);

        console.log('render:' + (Date.now() - start));
        return ret;
      }
    });

    var TestComponent = React.createClass({
      getInitialState: function () {
        start = Date.now();

        return {
          num: 100
        };
      },
      template: nj.compileComponent(tmpl, 'tmpl1'),
      onClick: function () {
        start = Date.now();
        this.setState({ num: Date.now() }, function () {
          console.log('total:' + (Date.now() - start));
        });
      },
      render: function () {
        var params = {
          arr: this.props.arr,
          num: this.state.num,
          list2: [{ no: 1 }, { no: 2 }, { no: 3 }],
          onClick: this.onClick,
          params: {
            'data-a': 1,
            'data-b': 2
          },
          styles: {
            color: 'blue'
          },
          div: 'div'
        };

        var ret = this.template(params);
        console.log('render:' + (Date.now() - start));
        return ret;
      }
    });

    var html = ReactDOMServer.renderToStaticMarkup(React.createElement(TestComponent, {
      arr: _.times(5, function (n) {
        return n;
      }),
      a: 1,
      list: [{ no: 1, b: 1 }, { no: 2, b: 0 }, { no: 3, b: 1 }]
    }));

    //console.log(JSON.stringify(nj.templates['tmpl1']));
    console.log(html);
    expect(html).toBeTruthy();
  });
});<commit_msg>Update spec<commit_after>var nj = require('../src/base'),
  utils = require('../src/utils/utils'),
  compiler = require('../src/compiler/compile'),
  compile = compiler.compile,
  _ = require('lodash'),
  React = require('react'),
  ReactDOM = require('react-dom'),
  ReactDOMServer = require('react-dom/server');

describe('test speed', function () {
  var tmpl = nj`
  <{div} id="{num '_100'}">
    <#each {arr}>

        test_{../num}
        <#each {../list2}>

            <#params>
              <$if {../#:five}>
                <#p {'name'}>five</#p>
              </$if>
            </#params>
            span{no}
            {no}

        </#each>

      <#if {#:five(1):test}>

      <#else />

      </#if>
    </#each>
  </{div}>
  `;

  beforeAll(function () {
    nj.setComponentEngine('react', React, ReactDOM);

    nj.registerFilter('five', function (obj) {
      if (obj % 5 == 0) {
        return true;
      }
    });

    nj.registerFilter('test', function (obj) {
      return obj;
    });
  });

  xit('test render to string', function () {
    var data = {
      arr: _.times(5, function (n) {
        return n;
      }),
      num: Date.now(),
      list2: [1, 2, 3],
      onClick: 'onClick',
      params: {
        'data-a': 1,
        'data-b': 2
      },
      styles: "color:blue"
    };

    var tmplFn = compile(tmpl, 'tmpl1'),
        html = tmplFn(data);

    //console.log(JSON.stringify(nj.templates['tmpl1']));
    console.log(html);
    expect(html).toBeTruthy();
  });

  it('test render to component', function () {
    var start;

    var TestComponent1 = React.createClass({
      getInitialState: function () {
        start = Date.now();

        return {
          num: 100
        };
      },
      onClick: function () {
        start = Date.now();
        this.setState({ num: Date.now() }, function() {
          console.log('total:' + (Date.now() - start));
        });
      },
      render: function () {
        var list2 = [{ no: 1 }, { no: 2 }, { no: 3 }];

        var start = Date.now();
        var ret = React.createElement('div', { id: this.state.num + '_100' }, this.props.arr.map(function (o, i) {
          return [
              React.createElement('span', { className: 'test_' + i, style: { color: 'blue' }, onClick: this.onClick },
                'test_' + this.state.num,
                list2.map(function(p, j) {
                  return [React.createElement('div', i % 5 == 0 ? { name: 'five' } : null,
                    React.createElement('span', null, 'span' + p.no),
                    React.createElement('i', null, p.no)
                  )];
                })
              ),
              i % 5 == 0 ? React.createElement('br') : React.createElement('img')
          ];
        }.bind(this)));

        //var params = ['div', null];
        //this.props.arr.forEach(function (o, i) {
        //  params.push(React.createElement('span', { className: 'test_' + i }, 'test_' + i));
        //});
        //ret = React.createElement.apply(React, params);

        console.log('render:' + (Date.now() - start));
        return ret;
      }
    });

    var TestComponent = React.createClass({
      getInitialState: function () {
        start = Date.now();

        return {
          num: 100
        };
      },
      template: nj.compileComponent(tmpl, 'tmpl1'),
      onClick: function () {
        start = Date.now();
        this.setState({ num: Date.now() }, function () {
          console.log('total:' + (Date.now() - start));
        });
      },
      render: function () {
        var params = {
          arr: this.props.arr,
          num: this.state.num,
          list2: [{ no: 1 }, { no: 2 }, { no: 3 }],
          onClick: this.onClick,
          params: {
            'data-a': 1,
            'data-b': 2
          },
          styles: {
            color: 'blue'
          },
          div: 'div'
        };

        var ret = this.template(params);
        console.log('render:' + (Date.now() - start));
        return ret;
      }
    });

    var html = ReactDOMServer.renderToStaticMarkup(React.createElement(TestComponent, {
      arr: _.times(500, function (n) {
        return n;
      }),
      a: 1,
      list: [{ no: 1, b: 1 }, { no: 2, b: 0 }, { no: 3, b: 1 }]
    }));

    //console.log(JSON.stringify(nj.templates['tmpl1']));
    //console.log(html);
    expect(html).toBeTruthy();
  });
});<|endoftext|>


<commit_before>import cc from 'conventional-changelog'
import config from 'conventional-changelog-vue-material'
import ora from 'ora'
import { green } from 'chalk'
import concat from 'concat'
import { createWriteStream } from 'fs'
import packageJson from '../package.json'

const { version } = packageJson
const releaseNotesFile = './RELEASE_NOTES.MD'
const changelogFile = './CHANGELOG.md'
const releaseNotes = createWriteStream(releaseNotesFile)
const spinner = ora({
  text: 'Generating changelog...',
  color: 'green'
})

spinner.start()

config.then(data => {
  const changelogConfig = {
    config: data,
    pkg: {
      transform (pkg) {
        pkg.version = `v${version}`
        return pkg
      }
    }
  }

  cc(changelogConfig).pipe(releaseNotes).on('close', () => {
    concat([releaseNotesFile, changelogFile], changelogFile)

    spinner.succeed(green('Changelog released!'))
  })
})
<commit_msg>style: fix lint issues<commit_after>import cc from 'conventional-changelog'
import config from 'conventional-changelog-vue-material'
import ora from 'ora'
import { green } from 'chalk'
import concat from 'concat'
import { createWriteStream } from 'fs'
import packageJson from '../package.json'

const { version } = packageJson
const releaseNotesFile = './RELEASE_NOTES.MD'
const changelogFile = './CHANGELOG.md'
const releaseNotes = createWriteStream(releaseNotesFile)
const spinner = ora({
  text: 'Generating changelog...',
  color: 'green'
})

spinner.start()

config.then(data => {
  const changelogConfig = {
    config: data,
    pkg: {
      transform (pkg) {
        pkg.version = `v${version}`
        return pkg
      }
    }
  }

  cc(changelogConfig).pipe(releaseNotes).on('close', () => {
    concat([releaseNotesFile, changelogFile], changelogFile)

  spinner.succeed(green('Changelog released!'))
  })
})
<|endoftext|>


<commit_before>/*global $*/
$(function() {
	$.getJSON('colors.json', function( data ) {
		var css = '/*! Colors.css 1.9.0 | MIT License | https://github.com/eustasy/colors.css */\n'
		//console.log(data)
		$.each( data, function( group, list ) {
			//console.log(group + ': ' + list)
			css += '/* $$ ' + group + ' */\n'
			css += '/* $ Backgrounds */\n'
			if ( group == 'Baseline' ) {
				group = ''
			} else {
				group = group.replace(/\s+/g, '').toLowerCase() + '-'
			}
			$.each( list, function( key, val ) {
				//console.log(key + ': ' + val)
				css += '.background-' + group + key.replace(/\s+/g, '-').toLowerCase() + ' { background: ' + val.toLowerCase() + '; }\n'
			})
			css += '/* $ Colors */\n'
			$.each( list, function( key, val ) {
				//console.log(key + ': ' + val)
				css += '.color-' + group + key.replace(/\s+/g, '-').toLowerCase() + ' { color: ' + val.toLowerCase() + '; }\n'
			})
			css += '/* $ Fills */\n'
			$.each( list, function( key, val ) {
				//console.log(key + ': ' + val)
				css += '.fill-' + group + key.replace(/\s+/g, '-').toLowerCase() + ' { fill: ' + val.toLowerCase() + '; }\n'
			})
		})
		$('#js-target-css').val(css)
	})
})
<commit_msg>deduplicate code<commit_after>/*global $*/
$(function() {
	$.getJSON('colors.json', function( data ) {
		var css = '/*! Colors.css 1.9.0 | MIT License | https://github.com/eustasy/colors.css */\n'
		//console.log(data)
		$.each( data, function( group, list ) {
			//console.log(group + ': ' + list)
			css += '/* $$ ' + group + ' */\n'
			css += '/* $ Backgrounds */\n'
			if ( group == 'Baseline' ) {
				group = ''
			} else {
				group = group.replace(/\s+/g, '').toLowerCase() + '-'
			}
			var typeIndex
			var types = ['background', 'color', 'fill']
			for (typeIndex = 0; typeIndex < types.length; ++typeIndex) {
				css += '/* $ ' + types[typeIndex].charAt(0).toUpperCase() + types[typeIndex].slice(1); + 's */\n'
				$.each( list, function( key, val ) {
					//console.log(key + ': ' + val)
					css += '.' + types[typeIndex] + '-' + group + key.replace(/\s+/g, '-').toLowerCase() + ' { background: ' + val.toLowerCase() + '; }\n'
				})
			}
		})
		$('#js-target-css').val(css)
	})
})
<|endoftext|>