<commit_before>"use strict";

var _ = require("underscore");
var CurateBaseCollection = require("./CurateBaseCollection.js");

var ArticleCollection = CurateBaseCollection.extend({
  name: "ArticleCollection",
  model: require("../models/ArticleModel.js"),
  initialize: function() {
    this.total = 0;
    this.loading = false;
  },
  search: function(options) {
    var url = "https://www.curatescience.org/articles?q=" + options.query;
    if (!_.isUndefined(options.from)) {
      url = url + "&from=" + options.from;
    }
    var _this = this;
    var t0 = _.now();
    this.loading = true;
    var res = this.sync("read", this, {url: url})
    res.then(function(res) {
      var t1 = _.now();
      _this.loading = false;
      _this.total = res.total;
      _this.from = res.from;
      _this.reset(res.documents);
      ga('send', 'timing', 'SearchResults', 'Fetch', t1-t0, "/articles?q="+options.query+"&from="+res.from);
  });

    return res;
  }
});

module.exports = ArticleCollection;
<commit_msg>ArticleCollection: fix indentation<commit_after>"use strict";

var _ = require("underscore");
var CurateBaseCollection = require("./CurateBaseCollection.js");

var ArticleCollection = CurateBaseCollection.extend({
  name: "ArticleCollection",
  model: require("../models/ArticleModel.js"),
  initialize: function() {
    this.total = 0;
    this.loading = false;
  },
  search: function(options) {
    var url = "https://www.curatescience.org/articles?q=" + options.query;
    if (!_.isUndefined(options.from)) {
      url = url + "&from=" + options.from;
    }
    var _this = this;
    var t0 = _.now();
    this.loading = true;
    var res = this.sync("read", this, {url: url})
    res.then(function(res) {
      var t1 = _.now();
      _this.loading = false;
      _this.total = res.total;
      _this.from = res.from;
      _this.reset(res.documents);
      ga('send', 'timing', 'SearchResults', 'Fetch', t1-t0, "/articles?q="+options.query+"&from="+res.from);
    });

    return res;
  }
});

module.exports = ArticleCollection;
<|endoftext|>


<commit_before>'use strict';
import { _ } from 'meteor/underscore';
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { alertDialog } from '../layout/alertDialog';
import { shouldStopSubscribe } from '../utils/idle';

let lastQueryInstantMessageTime = Date.now() - 60000;
const rInstantMessageList = new ReactiveVar([]);
const rDontInterrupt = new ReactiveVar(false);
Meteor.setInterval(queryInstantMessage, 5000);
function queryInstantMessage() {
  if (rDontInterrupt.get()) {
    return false;
  }
  if (shouldStopSubscribe()) {
    return false;
  }
  Meteor.call('queryInstantMessage', lastQueryInstantMessageTime, (error, result) => {
    if (! error) {
      lastQueryInstantMessageTime = result.lastTime || (Date.now() - 60000);
      const oldMessageList = rInstantMessageList.get();
      const oldMessageIdList = _.pluck(oldMessageList, '_id');
      const listResult = _.chain(result.list)
        .sortBy('createdAt')
        .reverse()
        .map((message) => {
          message.createdAt = new Date(message.createdAt);

          return message;
        })
        .reject((message) => {
          return _.contains(oldMessageIdList, message._id);
        })
        .value();

      rInstantMessageList.set(listResult.concat(oldMessageList));
    }
  });
}
Template.instantMessage.helpers({
  isDontInterruptButtonClass() {
    return rDontInterrupt.get() ? 'btn btn-sm btn-warning float-right mr-1' : 'btn btn-sm btn-outline-warning float-right mr-1';
  }
});
Template.instantMessage.events({
  'click [data-action="clearMessage"]'(event) {
    event.preventDefault();
    rInstantMessageList.set([]);
  },
  'click [data-action="dontInterrupt"]'(event) {
    event.preventDefault();
    rDontInterrupt.set(! rDontInterrupt.get());
  }
});

Template.instantMessageChatForm.onRendered(function() {
  this.$message = this.$('[name="message"]');
});
Template.instantMessageChatForm.events({
  submit(event, templateInstance) {
    event.preventDefault();
    const message = templateInstance.$message.val();
    if (message.length > 255) {
      alertDialog.alert('輸入訊息過長！');
    }
    else if (message.length) {
      Meteor.customCall('instantMessageChat', message, () => {
        templateInstance.$message.val('');
      });
    }
  }
});

//不能篩掉、永遠顯示的紀錄類別
const alwaysDisplayLogTypeList = [
  '發薪紀錄',
  '舉報違規',
  '禁止舉報',
  '禁止下單',
  '禁止聊天',
  '禁止廣告',
  '課以罰款',
  '沒收股份',
  '禁任經理',
  '解除舉報',
  '解除下單',
  '解除聊天',
  '解除廣告',
  '退還罰款',
  '解除禁任',
  '查封關停',
  '解除查封',
  '產品下架',
  '撤銷廣告'
];
//篩選器可以選擇的紀錄類別
const messageTypeGroupHash = {
  '聊天發言': [
    '聊天發言'
  ],
  '交易相關': [
    '交易紀錄',
    '購買下單',
    '販賣下單',
    '取消下單',
    '公司釋股'
  ],
  '新創相關': [
    '創立公司',
    '參與投資',
    '創立失敗',
    '創立成功'
  ],
  '競選相關': [
    '參選紀錄',
    '就任經理',
    '辭職紀錄',
    '撤職紀錄',
    '支持紀錄'
  ],
  '經理管理': [
    '經理管理'
  ],
  '推薦產品': [
    '推薦產品'
  ]
};
const defaultFilterValue = _.chain(messageTypeGroupHash)
  .flatten()
  .values()
  .value()
  .concat(alwaysDisplayLogTypeList);
const rFilterTypeList = new ReactiveVar(defaultFilterValue);
Template.instantMessageFilterButton.helpers({
  btnClass() {
    const btnType = this.type;
    const messageTypeList = messageTypeGroupHash[btnType] || [btnType];
    if (_.contains(rFilterTypeList.get(), messageTypeList[0])) {
      return 'btn btn-sm btn-primary';
    }
    else {
      return 'btn btn-sm btn-outline-primary';
    }
  },
  btnText() {
    return this.type;
  }
});
Template.instantMessageFilterButton.events({
  'click'(event, templateInstance) {
    event.preventDefault();
    const btnType = templateInstance.data.type;
    const messageTypeList = messageTypeGroupHash[btnType] || [btnType];
    const previousFilterTypeList = rFilterTypeList.get();
    if (_.intersection(previousFilterTypeList, messageTypeList).length > 0) {
      rFilterTypeList.set(_.difference(previousFilterTypeList, messageTypeList));
    }
    else {
      rFilterTypeList.set(_.union(previousFilterTypeList, messageTypeList));
    }
  }
});

const rFilterUserId = new ReactiveVar([]);
const rFilterCompanyId = new ReactiveVar([]);
Template.instantMessageFilterById.helpers({
  filterUserId() {
    return rFilterUserId.get();
  },
  filterCompanyId() {
    return rFilterCompanyId.get();
  }
});
Template.instantMessageFilterById.events({
  'click [data-action="filterUserId"]'(event) {
    event.preventDefault();
    alertDialog.dialog({
      type: 'prompt',
      title: '篩選使用者',
      message: `

請輸入使用者識別碼：

使用者識別碼可以在帳號資訊頁面的網址列中取得。

http://acgn-stock.com/accountInfo/識別碼

      `,
      defaultValue: '',
      callback: function(userId) {
        if (userId) {
          const newFilterUserId = _.union(rFilterUserId.get(), userId);
          rFilterUserId.set(newFilterUserId);
          const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
          rFilterTypeList.set(newFilterTypeList);
        }
      }
    });
  },
  'click [data-action="filterCompanyId"]'(event) {
    event.preventDefault();
    alertDialog.dialog({
      type: 'prompt',
      title: '篩選公司',
      message: `

請輸入公司識別碼：

使用者識別碼可以在公司細節頁面的網址列中取得。

http://acgn-stock.com/company/識別碼

      `,
      defaultValue: '',
      callback: function(companyId) {
        if (companyId) {
          const newFilterCompanyId = _.union(rFilterCompanyId.get(), companyId);
          rFilterCompanyId.set(newFilterCompanyId);
          const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
          rFilterTypeList.set(newFilterTypeList);
        }
      }
    });
  },
  'click [data-action="filterFavorite"]'(event) {
    event.preventDefault();
    const user = Meteor.user();
    if (user) {
      console.log(user.favorite);
      const newFilterCompanyId = _.union(rFilterCompanyId.get(), user.favorite);
      rFilterCompanyId.set(newFilterCompanyId);
      const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
      rFilterTypeList.set(newFilterTypeList);
    }
  }
});

Template.instantMessageFilterByUserId.events({
  'click [data-action="remove"]'(event, templateInstance) {
    const newFilterUserId = _.without(rFilterUserId.get(), templateInstance.data);
    rFilterUserId.set(newFilterUserId);
  }
});
Template.instantMessageFilterByCompanyId.events({
  'click [data-action="remove"]'(event, templateInstance) {
    const newFilterCompanyId = _.without(rFilterCompanyId.get(), templateInstance.data);
    rFilterCompanyId.set(newFilterCompanyId);
  }
});

Template.instantMessageList.helpers({
  logList() {
    const user = Meteor.user();
    const userId = user ? user._id : '';
    const filterTypeList = rFilterTypeList.get();
    const displayLogList = _.filter(rInstantMessageList.get(), (logData) => {
      //發布給所有使用者的紀錄一定要顯示
      if (logData.userId === '!all') {
        return true;
      }
      //登入使用者自身有關的紀錄一定要顯示
      if (userId && logData.userId && _.contains(logData.userId, userId)) {
        return true;
      }
      //如果有點擊「只看指定使用者或公司」篩選按鈕
      if (_.contains(filterTypeList, '只看指定使用者或公司')) {
        const filterUserId = rFilterUserId.get();
        const filterCompanyId = rFilterCompanyId.get();

        //只顯示按鈕篩選器有啟動的訊息且有相符使用者識別碼或公司識別碼的紀錄
        return _.contains(filterTypeList, logData.logType) && (
          (logData.userId && _.intersection(filterUserId, logData.userId).length > 0) ||
          logData.companyId && _.contains(filterCompanyId, logData.companyId)
        );
      }

      //只顯示按鈕篩選器有啟動的紀錄
      return _.contains(filterTypeList, logData.logType);
    });

    return displayLogList;
  }
});
<commit_msg>eslint<commit_after>'use strict';
import { _ } from 'meteor/underscore';
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { alertDialog } from '../layout/alertDialog';
import { shouldStopSubscribe } from '../utils/idle';

let lastQueryInstantMessageTime = Date.now() - 60000;
const rInstantMessageList = new ReactiveVar([]);
const rDontInterrupt = new ReactiveVar(false);
Meteor.setInterval(queryInstantMessage, 5000);
function queryInstantMessage() {
  if (rDontInterrupt.get()) {
    return false;
  }
  if (shouldStopSubscribe()) {
    return false;
  }
  Meteor.call('queryInstantMessage', lastQueryInstantMessageTime, (error, result) => {
    if (! error) {
      lastQueryInstantMessageTime = result.lastTime || (Date.now() - 60000);
      const oldMessageList = rInstantMessageList.get();
      const oldMessageIdList = _.pluck(oldMessageList, '_id');
      const listResult = _.chain(result.list)
        .sortBy('createdAt')
        .reverse()
        .map((message) => {
          message.createdAt = new Date(message.createdAt);

          return message;
        })
        .reject((message) => {
          return _.contains(oldMessageIdList, message._id);
        })
        .value();

      rInstantMessageList.set(listResult.concat(oldMessageList));
    }
  });
}
Template.instantMessage.helpers({
  isDontInterruptButtonClass() {
    return rDontInterrupt.get() ? 'btn btn-sm btn-warning float-right mr-1' : 'btn btn-sm btn-outline-warning float-right mr-1';
  }
});
Template.instantMessage.events({
  'click [data-action="clearMessage"]'(event) {
    event.preventDefault();
    rInstantMessageList.set([]);
  },
  'click [data-action="dontInterrupt"]'(event) {
    event.preventDefault();
    rDontInterrupt.set(! rDontInterrupt.get());
  }
});

Template.instantMessageChatForm.onRendered(function() {
  this.$message = this.$('[name="message"]');
});
Template.instantMessageChatForm.events({
  submit(event, templateInstance) {
    event.preventDefault();
    const message = templateInstance.$message.val();
    if (message.length > 255) {
      alertDialog.alert('輸入訊息過長！');
    }
    else if (message.length) {
      Meteor.customCall('instantMessageChat', message, () => {
        templateInstance.$message.val('');
      });
    }
  }
});

//不能篩掉、永遠顯示的紀錄類別
const alwaysDisplayLogTypeList = [
  '發薪紀錄',
  '舉報違規',
  '禁止舉報',
  '禁止下單',
  '禁止聊天',
  '禁止廣告',
  '課以罰款',
  '沒收股份',
  '禁任經理',
  '解除舉報',
  '解除下單',
  '解除聊天',
  '解除廣告',
  '退還罰款',
  '解除禁任',
  '查封關停',
  '解除查封',
  '產品下架',
  '撤銷廣告'
];
//篩選器可以選擇的紀錄類別
const messageTypeGroupHash = {
  '聊天發言': [
    '聊天發言'
  ],
  '交易相關': [
    '交易紀錄',
    '購買下單',
    '販賣下單',
    '取消下單',
    '公司釋股'
  ],
  '新創相關': [
    '創立公司',
    '參與投資',
    '創立失敗',
    '創立成功'
  ],
  '競選相關': [
    '參選紀錄',
    '就任經理',
    '辭職紀錄',
    '撤職紀錄',
    '支持紀錄'
  ],
  '經理管理': [
    '經理管理'
  ],
  '推薦產品': [
    '推薦產品'
  ]
};
const defaultFilterValue = _.chain(messageTypeGroupHash)
  .flatten()
  .values()
  .value()
  .concat(alwaysDisplayLogTypeList);
const rFilterTypeList = new ReactiveVar(defaultFilterValue);
Template.instantMessageFilterButton.helpers({
  btnClass() {
    const btnType = this.type;
    const messageTypeList = messageTypeGroupHash[btnType] || [btnType];
    if (_.contains(rFilterTypeList.get(), messageTypeList[0])) {
      return 'btn btn-sm btn-primary';
    }
    else {
      return 'btn btn-sm btn-outline-primary';
    }
  },
  btnText() {
    return this.type;
  }
});
Template.instantMessageFilterButton.events({
  'click'(event, templateInstance) {
    event.preventDefault();
    const btnType = templateInstance.data.type;
    const messageTypeList = messageTypeGroupHash[btnType] || [btnType];
    const previousFilterTypeList = rFilterTypeList.get();
    if (_.intersection(previousFilterTypeList, messageTypeList).length > 0) {
      rFilterTypeList.set(_.difference(previousFilterTypeList, messageTypeList));
    }
    else {
      rFilterTypeList.set(_.union(previousFilterTypeList, messageTypeList));
    }
  }
});

const rFilterUserId = new ReactiveVar([]);
const rFilterCompanyId = new ReactiveVar([]);
Template.instantMessageFilterById.helpers({
  filterUserId() {
    return rFilterUserId.get();
  },
  filterCompanyId() {
    return rFilterCompanyId.get();
  }
});
Template.instantMessageFilterById.events({
  'click [data-action="filterUserId"]'(event) {
    event.preventDefault();
    alertDialog.dialog({
      type: 'prompt',
      title: '篩選使用者',
      message: `

請輸入使用者識別碼：

使用者識別碼可以在帳號資訊頁面的網址列中取得。

http://acgn-stock.com/accountInfo/識別碼

      `,
      defaultValue: '',
      callback: function(userId) {
        if (userId) {
          const newFilterUserId = _.union(rFilterUserId.get(), userId);
          rFilterUserId.set(newFilterUserId);
          const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
          rFilterTypeList.set(newFilterTypeList);
        }
      }
    });
  },
  'click [data-action="filterCompanyId"]'(event) {
    event.preventDefault();
    alertDialog.dialog({
      type: 'prompt',
      title: '篩選公司',
      message: `

請輸入公司識別碼：

使用者識別碼可以在公司細節頁面的網址列中取得。

http://acgn-stock.com/company/識別碼

      `,
      defaultValue: '',
      callback: function(companyId) {
        if (companyId) {
          const newFilterCompanyId = _.union(rFilterCompanyId.get(), companyId);
          rFilterCompanyId.set(newFilterCompanyId);
          const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
          rFilterTypeList.set(newFilterTypeList);
        }
      }
    });
  },
  'click [data-action="filterFavorite"]'(event) {
    event.preventDefault();
    const user = Meteor.user();
    if (user) {
      const newFilterCompanyId = _.union(rFilterCompanyId.get(), user.favorite);
      rFilterCompanyId.set(newFilterCompanyId);
      const newFilterTypeList = _.union(rFilterTypeList.get(), ['只看指定使用者或公司']);
      rFilterTypeList.set(newFilterTypeList);
    }
  }
});

Template.instantMessageFilterByUserId.events({
  'click [data-action="remove"]'(event, templateInstance) {
    const newFilterUserId = _.without(rFilterUserId.get(), templateInstance.data);
    rFilterUserId.set(newFilterUserId);
  }
});
Template.instantMessageFilterByCompanyId.events({
  'click [data-action="remove"]'(event, templateInstance) {
    const newFilterCompanyId = _.without(rFilterCompanyId.get(), templateInstance.data);
    rFilterCompanyId.set(newFilterCompanyId);
  }
});

Template.instantMessageList.helpers({
  logList() {
    const user = Meteor.user();
    const userId = user ? user._id : '';
    const filterTypeList = rFilterTypeList.get();
    const displayLogList = _.filter(rInstantMessageList.get(), (logData) => {
      //發布給所有使用者的紀錄一定要顯示
      if (logData.userId === '!all') {
        return true;
      }
      //登入使用者自身有關的紀錄一定要顯示
      if (userId && logData.userId && _.contains(logData.userId, userId)) {
        return true;
      }
      //如果有點擊「只看指定使用者或公司」篩選按鈕
      if (_.contains(filterTypeList, '只看指定使用者或公司')) {
        const filterUserId = rFilterUserId.get();
        const filterCompanyId = rFilterCompanyId.get();

        //只顯示按鈕篩選器有啟動的訊息且有相符使用者識別碼或公司識別碼的紀錄
        return _.contains(filterTypeList, logData.logType) && (
          (logData.userId && _.intersection(filterUserId, logData.userId).length > 0) ||
          logData.companyId && _.contains(filterCompanyId, logData.companyId)
        );
      }

      //只顯示按鈕篩選器有啟動的紀錄
      return _.contains(filterTypeList, logData.logType);
    });

    return displayLogList;
  }
});
<|endoftext|>


<commit_before>import { resolve } from 'path'
import { expect } from 'chai'
import {
  DEPENDENCIES_KEY,
  BEFORE_KEY,
  OPTIONAL_BEFORE_KEY,
  AFTER_KEY,
  OPTIONAL_AFTER_KEY,
  ANYTIME_KEY
} from '../src/configKeys'
import expandConfig from '../src/expandConfig'
import buildRequiredTaskList from '../src/buildRequiredTaskList'
import buildTaskDependencyGraph from '../src/buildTaskDependencyGraph'

describe('buildTaskDependencyGraph.js', function () {
  let tasks
  beforeEach(function () {
    const testConfigPath = resolve(__dirname, 'test.topolo.config.js')
    delete require.cache[require.resolve(testConfigPath)]
    tasks = expandConfig(require(testConfigPath))
  })

  it(`hoists all ${BEFORE_KEY}/${AFTER_KEY}/${OPTIONAL_BEFORE_KEY}/${OPTIONAL_AFTER_KEY} dependencies to the "${DEPENDENCIES_KEY}" key`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['beforeAndAfter1'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    expect(Object.keys(taskDepGraph)).to.have.length(3)
    expect(taskDepGraph)
      .to.have.property('justCommandTask')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('beforeAndAfter1')
    expect(taskDepGraph)
      .to.have.property('beforeAndAfter1')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('stringTask')
  })
  it(`doesn\'t hoist ${ANYTIME_KEY} dependencies anywhere`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['anytimeDependencies'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    expect(Object.keys(taskDepGraph)).to.have.length(2)
    expect(taskDepGraph)
      .to.have.property('anytimeDependencies')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
    expect(taskDepGraph)
      .to.have.property('stringTask')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
  })
  it(`hoists dependencies with params correctly`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['paramDependencies', 'justSyncFunctionTest'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    // console.log(taskDepGraph)
    expect(Object.keys(taskDepGraph)).to.have.length(4)
    expect(taskDepGraph)
      .to.have.property('paramDependencies')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('justSyncFunctionTest:param1')
    expect(taskDepGraph)
      .to.have.property('justSyncFunctionTest:param2')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('paramDependencies')
    expect(taskDepGraph)
      .to.have.property('justSyncFunctionTest')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
  })
})
<commit_msg>add another test to get close to 100% coverage<commit_after>import { resolve } from 'path'
import { expect } from 'chai'
import {
  DEPENDENCIES_KEY,
  BEFORE_KEY,
  OPTIONAL_BEFORE_KEY,
  AFTER_KEY,
  OPTIONAL_AFTER_KEY,
  ANYTIME_KEY
} from '../src/configKeys'
import expandConfig from '../src/expandConfig'
import buildRequiredTaskList from '../src/buildRequiredTaskList'
import buildTaskDependencyGraph from '../src/buildTaskDependencyGraph'

describe('buildTaskDependencyGraph.js', function () {
  let tasks
  beforeEach(function () {
    const testConfigPath = resolve(__dirname, 'test.topolo.config.js')
    delete require.cache[require.resolve(testConfigPath)]
    tasks = expandConfig(require(testConfigPath))
  })

  it(`hoists all ${BEFORE_KEY}/${AFTER_KEY} dependencies to the "${DEPENDENCIES_KEY}" key`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['beforeAndAfter1'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    expect(Object.keys(taskDepGraph)).to.have.length(3)
    expect(taskDepGraph)
      .to.have.property('justCommandTask')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('beforeAndAfter1')
    expect(taskDepGraph)
      .to.have.property('beforeAndAfter1')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('stringTask')
  })
  it(`hoists all ${OPTIONAL_BEFORE_KEY}/${OPTIONAL_AFTER_KEY} dependencies to the "${DEPENDENCIES_KEY}" key if they are required`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['optDependencies1', 'stringTask', 'justCommandTask'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    expect(Object.keys(taskDepGraph)).to.have.length(3)
    expect(taskDepGraph)
      .to.have.property('justCommandTask')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('optDependencies1')
    expect(taskDepGraph)
      .to.have.property('optDependencies1')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('stringTask')
  })
  it(`doesn\'t hoist ${ANYTIME_KEY} dependencies anywhere`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['anytimeDependencies'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    expect(Object.keys(taskDepGraph)).to.have.length(2)
    expect(taskDepGraph)
      .to.have.property('anytimeDependencies')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
    expect(taskDepGraph)
      .to.have.property('stringTask')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
  })
  it(`hoists dependencies with params correctly`, function () {
    const taskNameSet = buildRequiredTaskList(tasks, ['paramDependencies', 'justSyncFunctionTest'])
    const taskDepGraph = buildTaskDependencyGraph(tasks, taskNameSet)
    // console.log(taskDepGraph)
    expect(Object.keys(taskDepGraph)).to.have.length(4)
    expect(taskDepGraph)
      .to.have.property('paramDependencies')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('justSyncFunctionTest:param1')
    expect(taskDepGraph)
      .to.have.property('justSyncFunctionTest:param2')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.property('0')
      .that.equals('paramDependencies')
    expect(taskDepGraph)
      .to.have.property('justSyncFunctionTest')
      .that.has.property(DEPENDENCIES_KEY)
      .that.has.length(0)
  })
})
<|endoftext|>


<commit_before>import { module } from 'substance-test'
import {
 DefaultDOMElement, Configurator
} from 'substance'

// TODO: export all trafos via index.es.js, and import {..} from '../../index.es.js'
import ImportEntities from '../../src/converter/r2t/ImportEntities'
import { EntitiesPackage } from '../../src/entities'
import readFixture from '../fixture/readFixture'

const test = module('Import Entities')
const fixture = readFixture('element-citation.xml')

test("Import journal citation", function(t) {
  let dom = DefaultDOMElement.parseXML(fixture)
  let entityDb = _emptyEntityDb()
  let api = _createAPI(entityDb)
  let converter = new ImportEntities()

  converter.import(dom, api)

  // TODO: how can we turn the original id into a uuid, what to do
  // with the old id?, and how to find the record after its id has changed?
  let r1 = entityDb.get('r1')

  t.equal(r1.authors.length, 2)
  t.equal(r1.editors.length, 1)
  t.equal(r1.year, '2009')
  t.equal(r1.articleTitle, 'Journal article title')
  t.equal(r1.source, 'Journal article source')
  t.equal(r1.volume, '29')
  t.equal(r1.fpage, '6436')
  t.equal(r1.lpage, '6448')
  t.equal(r1.pageRange, '6436-6448')
  t.equal(r1.elocationId, 'ELOCID')
  t.equal(r1.doi, '10.1523/JNEUROSCI.5479-08.2009')

  t.end()
})

test("Extract persons from element citation", function(t) {
  let dom = DefaultDOMElement.parseXML(fixture)
  let entityDb = _emptyEntityDb()
  let api = _createAPI(entityDb)
  let converter = new ImportEntities()

  converter.import(dom, api)

  const r1 = entityDb.get('r1')
  const authors = r1.authors
  t.equal(authors.length, 2)
  const author1 = entityDb.get(authors[0])
  t.equal(author1.surname, 'Doe')
  t.equal(author1.givenNames, 'John')
  t.isNil(author1.prefix)
  t.isNil(author1.suffix)

  const author2 = entityDb.get(authors[1])
  t.equal(author2.surname, 'Doe')
  t.equal(author2.givenNames, 'Jane')
  t.equal(author2.prefix, 'Dr')
  t.equal(author2.suffix, 'Jr')

  t.end()
})

function _emptyEntityDb() {
  // creating an in-memory model of the EntityDB
  // which will be used to create records from JATS
  let entitiesConf = new Configurator()
  entitiesConf.import(EntitiesPackage)
  return entitiesConf.createDocument()
}

// By storing the errors we can later check for an error count in failing
// tests.
function _createAPI(entityDB) {
  let errors = []
  return {
    entityDB,
    error: function(data) {
      errors.push(data)
    }
  }
}
<commit_msg>Book citation import test.<commit_after>import { module } from 'substance-test'
import {
 DefaultDOMElement, Configurator
} from 'substance'

// TODO: export all trafos via index.es.js, and import {..} from '../../index.es.js'
import ImportEntities from '../../src/converter/r2t/ImportEntities'
import { EntitiesPackage } from '../../src/entities'
import readFixture from '../fixture/readFixture'

const test = module('Import Entities')
const fixture = readFixture('element-citation.xml')

test("Import journal citation", function(t) {
  let dom = DefaultDOMElement.parseXML(fixture)
  let entityDb = _emptyEntityDb()
  let api = _createAPI(entityDb)
  let converter = new ImportEntities()

  converter.import(dom, api)

  // TODO: how can we turn the original id into a uuid, what to do
  // with the old id?, and how to find the record after its id has changed?
  let r1 = entityDb.get('r1')

  t.equal(r1.authors.length, 2)
  t.equal(r1.editors.length, 1)
  t.equal(r1.year, '2009')
  t.equal(r1.articleTitle, 'Journal article title')
  t.equal(r1.source, 'Journal article source')
  t.equal(r1.volume, '29')
  t.equal(r1.fpage, '6436')
  t.equal(r1.lpage, '6448')
  t.equal(r1.pageRange, '6436-6448')
  t.equal(r1.elocationId, 'ELOCID')
  t.equal(r1.doi, '10.1523/JNEUROSCI.5479-08.2009')

  t.end()
})

test("Import book citation", function(t) {
  let dom = DefaultDOMElement.parseXML(fixture)
  let entityDb = _emptyEntityDb()
  let api = _createAPI(entityDb)
  let converter = new ImportEntities()

  converter.import(dom, api)
  let r2 = entityDb.get('r2')

  t.equal(r2.authors.length, 1)
  t.equal(r2.editors.length, 1)
  t.equal(r2.chapterTitle, 'Tobacco use')
  t.equal(r2.source, 'Clinical methods: the history, physical, and laboratory examinations')
  t.equal(r2.publisherLoc, 'Stoneham (MA)')
  t.equal(r2.publisherName, 'Butterworth Publishers')
  t.equal(r2.year, '1990')
  t.equal(r2.month, '10')
  t.equal(r2.day, '5')
  t.equal(r2.fpage, '214')
  t.equal(r2.lpage, '216')
  t.equal(r2.pageRange, '214-216')
  t.equal(r2.elocationId, 'ELOCID')

  t.end()
})

test("Extract persons from element citation", function(t) {
  let dom = DefaultDOMElement.parseXML(fixture)
  let entityDb = _emptyEntityDb()
  let api = _createAPI(entityDb)
  let converter = new ImportEntities()

  converter.import(dom, api)

  const r1 = entityDb.get('r1')
  const authors = r1.authors
  t.equal(authors.length, 2)
  const author1 = entityDb.get(authors[0])
  t.equal(author1.surname, 'Doe')
  t.equal(author1.givenNames, 'John')
  t.isNil(author1.prefix)
  t.isNil(author1.suffix)

  const author2 = entityDb.get(authors[1])
  t.equal(author2.surname, 'Doe')
  t.equal(author2.givenNames, 'Jane')
  t.equal(author2.prefix, 'Dr')
  t.equal(author2.suffix, 'Jr')

  t.end()
})

function _emptyEntityDb() {
  // creating an in-memory model of the EntityDB
  // which will be used to create records from JATS
  let entitiesConf = new Configurator()
  entitiesConf.import(EntitiesPackage)
  return entitiesConf.createDocument()
}

// By storing the errors we can later check for an error count in failing
// tests.
function _createAPI(entityDB) {
  let errors = []
  return {
    entityDB,
    error: function(data) {
      errors.push(data)
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

describe('Service: apiMock', function () {

	// load the service's module
	beforeEach(module('apiMock'));

	// Hack (?) to get the provider so we can call .config()
	var apiMockProvider;
	beforeEach(module(function(_apiMockProvider_){
		apiMockProvider = _apiMockProvider_;
	}));

	// instantiate services
	var httpInterceptor;
	var apiMock;
	var $location;
	var $http;
	var $httpBackend;
	var $log;
	var $rootScope;

	var defaultApiPath;
	var defaultMockPath;
	var defaultExpectMethod;
	var defaultExpectPath;
	var defaultRequest;

	beforeEach(inject(function (_httpInterceptor_, _apiMock_, _$location_, _$http_, _$httpBackend_, _$log_, _$rootScope_) {
		httpInterceptor = _httpInterceptor_;
		apiMock = _apiMock_;
		$location = _$location_;
		$http = _$http_;
		$httpBackend = _$httpBackend_;
		$log = _$log_;
		$rootScope = _$rootScope_;

		defaultApiPath = '/api/pokemon';
		defaultMockPath = '/mock_data/pokemon.get.json';
		defaultExpectPath = defaultMockPath;
		defaultExpectMethod = 'GET';
		defaultRequest = {
			url: defaultApiPath,
			method: defaultExpectMethod
		};
	}));

	afterEach(function () {
		$httpBackend.verifyNoOutstandingExpectation(); // loops and $httpBackend.expect() doesn't seem to play nice
		$httpBackend.verifyNoOutstandingRequest();
	});

/* This doesn't behave as when in the browser?
		it('should detect apimock param after hash', function () {
			$location.url('/#/view/?apimock=true');
			expect(apiMock.isMocking()).to.be.true;
		}); */

/* Need to test with html5Mode turned on, but how?
	it('should detect apimock param after hash', inject(function($locationProvider) {
		$locationProvider.html5Mode(true);
		$location.url('/#/view/?apimock=true');
		expect(apiMock.isMocking()).to.be.true;
	})); */

	// TODO: Add test for $http config overrides.
	describe('httpInterceptor', function () {

		function expectMockEnabled() {
		}

		function expectMockDisabled() {
			defaultExpectPath = defaultApiPath;
		}

		function expectHttpFailure(done, fail) {
			$httpBackend.expect(defaultExpectMethod, defaultExpectPath).respond(404);

			$http(defaultRequest)
				.success(function () {
					assertFail(); // Todo: How to fail the test if this happens?
					fail && fail();
				})
				.error(function (data, status) {
					done && done(data, status);
				});

			$rootScope.$digest();
			$httpBackend.flush();
		}

		function expectHttpSuccess(done, fail) {
			$httpBackend.expect(defaultExpectMethod, defaultExpectPath).respond({});

			$http(defaultRequest)
				.success(function () {
					done && done();
				})
				.error(function () {
					assertFail();
					fail && fail();
				});

			$rootScope.$digest();
			$httpBackend.flush();
		}

		function assertFail() {
			expect(true).to.be.false; // Todo: How to fail properly? There should be a method for that.
		}

		describe('flag detection', function () {

			it('should detect parameter regardless of case on "apiMock". (http://server/?aPiMoCk=true)', function () {
				var value = true;

				// Define a valid query string.
				var keys = [
					'apimock',
					'apiMock',
					'APIMOCK',
					'ApImOcK',
					'ApiMock'
				];

				angular.forEach(keys, function(key) {
					// Set location with the query string.
					$location.search(key, value);

					// Test connection.
					expectMockEnabled();
					expectHttpSuccess();

					// Remove param tested from the location.
					$location.search(key, null);
				});
			});

			it('should detect in search queries', function () {
				$location.url('/page?apiMock=true');

				expectMockEnabled();
				expectHttpSuccess();
			});

			it('should be disabled and do regular call if no flag is present', function () {
				expectMockDisabled();
				expectHttpSuccess();
			});

			it('should accept only global flag set', function () {
				$location.search('apiMock', true);

				expectMockEnabled();
				expectHttpSuccess();
			});

			it('should accept only local flag set', function () {
				defaultRequest.apiMock = true;

				expectMockEnabled();
				expectHttpSuccess();
			});

			it('should accept local flag overriding global flag', function () {
				$location.search('apiMock', false);
				defaultRequest.apiMock = true;

				expectMockEnabled();
				expectHttpSuccess();
			});

			it('should work as usual if no flag is set', function () {
				expectMockDisabled();
				expectHttpFailure();
			});
		});

		describe('command auto', function () {

			beforeEach(function () {
				// Set global flag to auto
				$location.search('apiMock', 'auto');
			});

			afterEach(function () {
				// Remove global flag
				$location.search('apiMock', null);
			});

			it('should automatically mock when request fails', function () {
				// Do a call, and expect it to recover from fail.
				$httpBackend.expect('GET', defaultApiPath).respond(404);

				expectHttpSuccess(function() {
					expect(apiMock._countFallbacks()).to.equal(0);
				});
			});

			it('cant automatically mock request on failure if the URL is an invalid API url', function () {
				// Don't include override, but use an URL that doesn't pass the isApiPath test.
				defaultExpectPath = '/something/people/pokemon';
				defaultRequest.url = defaultExpectPath;

				// Do a call, and expect it to fail.
				expectHttpFailure();
			});
		});

		describe('command HTTP status', function () {

			beforeEach(function () {
				// Set global flag to HTTP status
				$location.search('apiMock', 404);
			});

			it('should return status', function () {
				var options = [
					200,
					404,
					500
				];

				angular.forEach(options, function (option) {
					defaultRequest.apiMock = option;

					// Cannot use $http.expect() because HTTP status doesn't do a request
					$http(defaultRequest)
						.success(assertFail)
						.error(function(data, status) {
							expect(apiMock._countFallbacks()).to.equal(0);
							expect(status).to.equal(option);
						});

					$rootScope.$digest();
				});
			});

			it('should have basic header data in $http request status override', function () {
				// Cannot use $http.expect() because HTTP status doesn't do a request
				$http(defaultRequest)
					.success(assertFail)
					.error(function(data, status, headers) {
						expect(apiMock._countFallbacks()).to.equal(0);
						expect(headers).to.exist;
						expect(headers['Content-Type']).to.equal('text/html; charset=utf-8');
						expect(headers.Server).to.equal('Angular ApiMock');
					});

				$rootScope.$digest();
			});
		});

		describe('command mock', function () {

			beforeEach(function () {
				// Set global flag to mock
				$location.search('apiMock', true);
			});

			it('should ignore query objects in request URL (path has /?)', function () {
				defaultRequest.url = '/api/pokemon/?name=Pikachu';

				expectHttpSuccess();
			});

			it('should ignore query objects in request URL (path has only ?)', function () {
				defaultRequest.url = '/api/pokemon?name=Pikachu';

				expectHttpSuccess();
			});

			it('should mock calls with valid API path', function () {
				expectHttpSuccess();
			});

			it('should not mock calls with invalid API path (no /api/ in path)', function () {
				defaultExpectPath = '/something/pikachu';
				defaultRequest.url = defaultExpectPath;

				expectHttpFailure();
			});

			it('should not mock calls with wrong API path (/api/ is not the beginning of path)', function () {
				defaultExpectPath = '/wrong/api/pikachu';
				defaultRequest.url = defaultExpectPath;

				expectHttpFailure();
			});

			it('should correctly reroute for all HTTP verbs', function () {
				var verbs = [
					'GET',
					'POST',
					'DELETE',
					'PUT'
				];

				angular.forEach(verbs, function (verb) {
					defaultExpectPath = '/mock_data/pokemon.'+verb.toLowerCase()+'.json';
					defaultRequest.method = verb;

					expectHttpSuccess();
				});
			});

		});

		describe('command off', function () {

			it('should explicitly behave as usual with falsy values', function () {
				// Define falsy values.
				var values = [
					false,
					'',
					0,
					NaN,
					undefined,
					null
				];

				angular.forEach(values, function (value) {
					defaultRequest.apiMock = value;
					expectMockDisabled();

					expectHttpFailure();
				});

			});

		});

		describe('disable option', function () {

			beforeEach(function() {
				apiMockProvider.config({disable: true});
			});

			afterEach(function() {
				apiMockProvider.config({disable: false});
			});

			it('should override command mock', function () {
				var key = 'apimock';
				$location.search(key, true);

				// Test connection.
				expectMockDisabled();
				expectHttpFailure();

				// Remove param tested from the location.
				$location.search(key, null);
			});

			it('should override command auto', function () {
				var key = 'apimock';
				$location.search(key, 'auto');

				// Test connection.
				expectMockDisabled();
				expectHttpFailure();

				// Remove param tested from the location.
				$location.search(key, null);
			});

		});

		describe('$log.info', function () {

			it('should log when command is true', function () {
				$location.search('apiMock', true);

				expectHttpSuccess(function () {
					expect($log.info.logs[0][0]).to.equal('apiMock: rerouting ' + defaultApiPath + ' to ' + defaultMockPath);
				});
			});

			it('should log when command is auto', function () {
				$location.search('apiMock', 'auto');

				$httpBackend.expect(defaultRequest.method, defaultApiPath).respond(404);
				expectHttpSuccess(function () {
					expect($log.info.logs[0][0]).to.equal('apiMock: recovering from failure at ' + defaultApiPath);
				});
			});

			it('should log when command is a HTTP status', function () {
				$location.search('apiMock', 404);

				// Don't do $httpBackend.expect() because the command doesn't do a real request.
				$http(defaultRequest)
					.error(function () {
						expect($log.info.logs[0][0]).to.equal('apiMock: mocking HTTP status to 404');
					})
					.success(assertFail);

				$rootScope.$digest();
			});

		});

	});
});
<commit_msg>refactor(tests): group tests<commit_after>'use strict';

describe('Service: apiMock', function () {

	// load the service's module
	beforeEach(module('apiMock'));

	// Hack (?) to get the provider so we can call .config()
	var apiMockProvider;
	beforeEach(module(function(_apiMockProvider_){
		apiMockProvider = _apiMockProvider_;
	}));

	// instantiate services
	var httpInterceptor;
	var apiMock;
	var $location;
	var $http;
	var $httpBackend;
	var $log;
	var $rootScope;

	var defaultApiPath;
	var defaultMockPath;
	var defaultExpectMethod;
	var defaultExpectPath;
	var defaultRequest;

	beforeEach(inject(function (_httpInterceptor_, _apiMock_, _$location_, _$http_, _$httpBackend_, _$log_, _$rootScope_) {
		httpInterceptor = _httpInterceptor_;
		apiMock = _apiMock_;
		$location = _$location_;
		$http = _$http_;
		$httpBackend = _$httpBackend_;
		$log = _$log_;
		$rootScope = _$rootScope_;

		defaultApiPath = '/api/pokemon';
		defaultMockPath = '/mock_data/pokemon.get.json';
		defaultExpectPath = defaultMockPath;
		defaultExpectMethod = 'GET';
		defaultRequest = {
			url: defaultApiPath,
			method: defaultExpectMethod
		};
	}));

	afterEach(function () {
		$httpBackend.verifyNoOutstandingExpectation(); // loops and $httpBackend.expect() doesn't seem to play nice
		$httpBackend.verifyNoOutstandingRequest();
	});

/* This doesn't behave as when in the browser?
		it('should detect apimock param after hash', function () {
			$location.url('/#/view/?apimock=true');
			expect(apiMock.isMocking()).to.be.true;
		}); */

/* Need to test with html5Mode turned on, but how?
	it('should detect apimock param after hash', inject(function($locationProvider) {
		$locationProvider.html5Mode(true);
		$location.url('/#/view/?apimock=true');
		expect(apiMock.isMocking()).to.be.true;
	})); */

	// TODO: Add test for $http config overrides.
	describe('httpInterceptor', function () {

		function expectMockEnabled() {
		}

		function expectMockDisabled() {
			defaultExpectPath = defaultApiPath;
		}

		function expectHttpFailure(done, fail) {
			$httpBackend.expect(defaultExpectMethod, defaultExpectPath).respond(404);

			$http(defaultRequest)
				.success(function () {
					assertFail(); // Todo: How to fail the test if this happens?
					fail && fail();
				})
				.error(function (data, status) {
					done && done(data, status);
				});

			$rootScope.$digest();
			$httpBackend.flush();
		}

		function expectHttpSuccess(done, fail) {
			$httpBackend.expect(defaultExpectMethod, defaultExpectPath).respond({});

			$http(defaultRequest)
				.success(function () {
					done && done();
				})
				.error(function () {
					assertFail();
					fail && fail();
				});

			$rootScope.$digest();
			$httpBackend.flush();
		}

		function assertFail() {
			expect(true).to.be.false; // Todo: How to fail properly? There should be a method for that.
		}

		describe('URL flag', function () {

			describe('detection', function () {

				it('should detect parameter regardless of case on "apiMock". (http://server/?aPiMoCk=true)', function () {
					var value = true;

					// Define a valid query string.
					var keys = [
						'apimock',
						'apiMock',
						'APIMOCK',
						'ApImOcK',
						'ApiMock'
					];

					angular.forEach(keys, function(key) {
						// Set location with the query string.
						$location.search(key, value);

						// Test connection.
						expectMockEnabled();
						expectHttpSuccess();

						// Remove param tested from the location.
						$location.search(key, null);
					});
				});

				it('should detect in search queries', function () {
					$location.url('/page?apiMock=true');

					expectMockEnabled();
					expectHttpSuccess();
				});

				it('should be disabled and do regular call if no flag is present', function () {
					expectMockDisabled();
					expectHttpSuccess();
				});

				it('should accept only global flag set', function () {
					$location.search('apiMock', true);

					expectMockEnabled();
					expectHttpSuccess();
				});

				it('should accept only local flag set', function () {
					defaultRequest.apiMock = true;

					expectMockEnabled();
					expectHttpSuccess();
				});

				it('should accept local flag overriding global flag', function () {
					$location.search('apiMock', false);
					defaultRequest.apiMock = true;

					expectMockEnabled();
					expectHttpSuccess();
				});

				it('should work as usual if no flag is set', function () {
					expectMockDisabled();
					expectHttpFailure();
				});
			});

			describe('command', function () {

				describe('auto', function () {
					beforeEach(function () {
						// Set global flag to auto
						$location.search('apiMock', 'auto');
					});

					afterEach(function () {
						// Remove global flag
						$location.search('apiMock', null);
					});

					it('should automatically mock when request fails', function () {
						// Do a call, and expect it to recover from fail.
						$httpBackend.expect('GET', defaultApiPath).respond(404);

						expectHttpSuccess(function() {
							expect(apiMock._countFallbacks()).to.equal(0);
						});
					});

					it('can\'t automatically mock request on failure if the URL is an invalid API url', function () {
						// Don't include override, but use an URL that doesn't pass the isApiPath test.
						defaultExpectPath = '/something/people/pokemon';
						defaultRequest.url = defaultExpectPath;

						// Do a call, and expect it to fail.
						expectHttpFailure();
					});
				});

				describe('HTTP status', function () {

					beforeEach(function () {
						// Set global flag to HTTP status
						$location.search('apiMock', 404);
					});

					it('should return status', function () {
						var options = [
							200,
							404,
							500
						];

						angular.forEach(options, function (option) {
							defaultRequest.apiMock = option;

							// Cannot use $http.expect() because HTTP status doesn't do a request
							$http(defaultRequest)
								.success(assertFail)
								.error(function(data, status) {
									expect(apiMock._countFallbacks()).to.equal(0);
									expect(status).to.equal(option);
								});

							$rootScope.$digest();
						});
					});

					it('should have basic header data in $http request status override', function () {
						// Cannot use $http.expect() because HTTP status doesn't do a request
						$http(defaultRequest)
							.success(assertFail)
							.error(function(data, status, headers) {
								expect(apiMock._countFallbacks()).to.equal(0);
								expect(headers).to.exist;
								expect(headers['Content-Type']).to.equal('text/html; charset=utf-8');
								expect(headers.Server).to.equal('Angular ApiMock');
							});

						$rootScope.$digest();
					});
				});

				describe('mock', function () {

					beforeEach(function () {
						// Set global flag to mock
						$location.search('apiMock', true);
					});

					it('should ignore query objects in request URL (path has /?)', function () {
						defaultRequest.url = '/api/pokemon/?name=Pikachu';

						expectHttpSuccess();
					});

					it('should ignore query objects in request URL (path has only ?)', function () {
						defaultRequest.url = '/api/pokemon?name=Pikachu';

						expectHttpSuccess();
					});

					it('should mock calls with valid API path', function () {
						expectHttpSuccess();
					});

					it('should not mock calls with invalid API path (no /api/ in path)', function () {
						defaultExpectPath = '/something/pikachu';
						defaultRequest.url = defaultExpectPath;

						expectHttpFailure();
					});

					it('should not mock calls with wrong API path (/api/ is not the beginning of path)', function () {
						defaultExpectPath = '/wrong/api/pikachu';
						defaultRequest.url = defaultExpectPath;

						expectHttpFailure();
					});

					it('should correctly reroute for all HTTP verbs', function () {
						var verbs = [
							'GET',
							'POST',
							'DELETE',
							'PUT'
						];

						angular.forEach(verbs, function (verb) {
							defaultExpectPath = '/mock_data/pokemon.'+verb.toLowerCase()+'.json';
							defaultRequest.method = verb;

							expectHttpSuccess();
						});
					});

				});

				describe('off', function () {

					it('should explicitly behave as usual with falsy values', function () {
						// Define falsy values.
						var values = [
							false,
							'',
							0,
							NaN,
							undefined,
							null
						];

						angular.forEach(values, function (value) {
							defaultRequest.apiMock = value;
							expectMockDisabled();

							expectHttpFailure();
						});

					});

				});
			});

		});

		describe('module config', function () {
			describe('disable option', function () {

				beforeEach(function() {
					apiMockProvider.config({disable: true});
				});

				afterEach(function() {
					apiMockProvider.config({disable: false});
				});

				it('should override command mock', function () {
					var key = 'apimock';
					$location.search(key, true);

					// Test connection.
					expectMockDisabled();
					expectHttpFailure();

					// Remove param tested from the location.
					$location.search(key, null);
				});

				it('should override command auto', function () {
					var key = 'apimock';
					$location.search(key, 'auto');

					// Test connection.
					expectMockDisabled();
					expectHttpFailure();

					// Remove param tested from the location.
					$location.search(key, null);
				});

			});
		});

		describe('logging', function () {

			it('should log when command is true', function () {
				$location.search('apiMock', true);

				expectHttpSuccess(function () {
					expect($log.info.logs[0][0]).to.equal('apiMock: rerouting ' + defaultApiPath + ' to ' + defaultMockPath);
				});
			});

			it('should log when command is auto', function () {
				$location.search('apiMock', 'auto');

				$httpBackend.expect(defaultRequest.method, defaultApiPath).respond(404);
				expectHttpSuccess(function () {
					expect($log.info.logs[0][0]).to.equal('apiMock: recovering from failure at ' + defaultApiPath);
				});
			});

			it('should log when command is a HTTP status', function () {
				$location.search('apiMock', 404);

				// Don't do $httpBackend.expect() because the command doesn't do a real request.
				$http(defaultRequest)
					.error(function () {
						expect($log.info.logs[0][0]).to.equal('apiMock: mocking HTTP status to 404');
					})
					.success(assertFail);

				$rootScope.$digest();
			});

		});

	});
});
<|endoftext|>


<commit_before>describe("deviceManager", function() {
    var sandbox = null;
    var device = null;
    var gl = null;

    beforeEach(function () {
        sandbox = sinon.sandbox.create();
        device = wd.DeviceManager.getInstance();
        sandbox.stub(device, "gl", testTool.buildFakeGl(sandbox));
        gl = device.gl;
    });
    afterEach(function () {
        testTool.clearInstance();
        sandbox.restore();
    });

    describe("clear", function(){
        it("clear color passed from options", function(){
            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.clearColor).toCalledWith(1, 1, 1, 1);
        });
        it("enable all color and alpha write to ensure the clear buffer will not be affected by it", function(){
            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.colorMask).toCalledWith(true, true, true, true);
        });
        it("clear buffer", function(){
            sandbox.stub(gl, "COLOR_BUFFER_BIT", 1);
            sandbox.stub(gl, "DEPTH_BUFFER_BIT", 10);

            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.clear).toCalledWith(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        });
    });

    describe("setScreen", function(){
        function insertDom() {
            $("html").append($("<canvas id='event-test'></canvas>"));
        }

        function removeDom() {
            $("#event-test").remove();
        }

        beforeEach(function(){
            insertDom();
            sandbox.stub(window, "innerWidth", 100);
            sandbox.stub(window, "innerHeight", 200);

            sandbox.stub(device, "createGL");
            sandbox.stub(wd.GPUDetector.getInstance(), "detect");

            device.view = wd.ViewWebGL.create($("#event-test").get(0));
            device.gl = testTool.buildFakeGl(sandbox);

        });
        afterEach(function(){
            removeDom();
        });

        it("support full screen", function(){
            wd.Main.setConfig({
                screenSize:wd.ScreenSize.FULL,
                canvasId: "#event-test"
            }).init();

            expect(device.view.x).toEqual(0);
            expect(device.view.y).toEqual(0);
            expect(device.view.width).toEqual(100);
            expect(device.view.height).toEqual(200);
            expect(device.gl.viewport).toCalledWith(0, 0, 100, 200);
        });
        it("support custom screen size and position", function(){
            wd.Main.setConfig({
                screenSize:{width:50, x:10},
                canvasId: "#event-test"
            }).init();

            expect(device.view.x).toEqual(10);
            expect(device.view.y).toEqual(0);
            expect(device.view.width).toEqual(50);
            expect(device.view.height).toEqual(200);
            expect(device.gl.viewport).toCalledWith(0, 0, 50, 200);
        });
    });
});
<commit_msg>continue try ci<commit_after>describe("deviceManager", function() {
    var sandbox = null;
    var device = null;
    var gl = null;

    beforeEach(function () {
        sandbox = sinon.sandbox.create();
        device = wd.DeviceManager.getInstance();
        sandbox.stub(device, "gl", testTool.buildFakeGl(sandbox));
        gl = device.gl;
    });
    afterEach(function () {
        testTool.clearInstance();
        sandbox.restore();
    });

    describe("clear", function(){
        it("clear color passed from options", function(){
            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.clearColor).toCalledWith(1, 1, 1, 1);
        });
        it("enable all color and alpha write to ensure the clear buffer will not be affected by it", function(){
            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.colorMask).toCalledWith(true, true, true, true);
        });
        it("clear buffer", function(){
            sandbox.stub(gl, "COLOR_BUFFER_BIT", 1);
            sandbox.stub(gl, "DEPTH_BUFFER_BIT", 10);

            device.clear({
                color:wd.Color.create("#ffffff")
            });

            expect(gl.clear).toCalledWith(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        });
    });

    describe("setScreen", function(){
        function insertDom() {
            $("html").append($("<canvas id='event-test'></canvas>"));
        }

        function removeDom() {
            $("#event-test").remove();
        }

        beforeEach(function(){
            insertDom();
            //sandbox.stub(window, "innerWidth", 100);
            //sandbox.stub(window, "innerHeight", 200);

            sandbox.stub(device, "createGL");
            sandbox.stub(wd.GPUDetector.getInstance(), "detect");

            device.view = wd.ViewWebGL.create($("#event-test").get(0));
            device.gl = testTool.buildFakeGl(sandbox);

        });
        afterEach(function(){
            removeDom();
        });

        it("support full screen", function(){
            var view = device.view;

            wd.Main.setConfig({
                screenSize:wd.ScreenSize.FULL,
                canvasId: "#event-test"
            }).init();

            expect(view.x).toEqual(0);
            expect(view.y).toEqual(0);
            expect(view.width > 0).toBeTruthy();
            expect(view.height > 0).toBeTruthy();
            expect(device.gl.viewport).toCalledWith(view.x, view.y, view.width, view.height);
        });
        it("support custom screen size and position", function(){
            var view = device.view;

            wd.Main.setConfig({
                screenSize:{width:50, x:10},
                canvasId: "#event-test"
            }).init();

            expect(view.x).toEqual(10);
            expect(view.y).toEqual(0);
            expect(view.width).toEqual(50);
            expect(view.height > 0).toBeTruthy();
            expect(device.gl.viewport).toCalledWith(0, 0, view.width, view.height);
            expect($("#event-test").css("left")).toEqual("10px");
            expect($("#event-test").css("top")).toEqual("0px");
        });
    });
});
<|endoftext|>


<commit_before>const root = require('root-path')
require(root('test/setup'))
var factories = require(root('test/setup/factories'))

const destroyAllPushNotifications = () => {
  return PushNotification.fetchAll()
  .then(pns => pns.map(pn => pn.destroy()))
}

const relations = [
  'activity',
  'activity.post',
  'activity.post.user',
  'activity.post.communities',
  'activity.comment',
  'activity.comment.user',
  'activity.comment.post',
  'activity.comment.post.communities',
  'activity.community',
  'activity.reader',
  'activity.actor'
]

describe('Notification', function () {
  var post, comment, activity, community, reader, actor, device

  before(() => {
    return factories.user({name: 'Joe'}).save()
    .then(u => actor = u)
    .then(() => factories.post({name: 'My Post', user_id: actor.id, description: 'The body of the post'}).save())
    .then(p => post = p)
    .then(() => new Comment({text: 'hi', user_id: actor.id, post_id: post.id}).save())
    .then(c => comment = c)
    .then(() => factories.community({name: 'My Community'}).save())
    .then(c => community = c)
    .then(() => community.posts().attach(post))
    .then(() => factories.user({email: 'readersemail@hylo.com'}).save())
    .then(u => reader = u)
    .then(() => new Device({
      user_id: reader.id,
      token: 'eieio',
      version: 20,
      enabled: true
    }).save())
    .then(d => device = d)
    .then(() => new Activity({
      post_id: post.id
    }).save())
    .then(a => activity = a)
  })

  beforeEach(() => destroyAllPushNotifications())

  describe('.send', () => {
    it('sends a push for a new post', () => {
      return new Activity({
        post_id: post.id,
        meta: {reasons: [`newPost: ${community.id}`]},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe posted "My Post" in My Community')
      })
    })

    it('sends a push for a mention in a post', () => {
      return new Activity({
        post_id: post.id,
        meta: {reasons: ['mention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe mentioned you in "My Post"')
      })
    })

    it('sends a push for a comment', () => {
      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['newComment']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe commented on "My Post"')
      })
    })

    it('sends a push for a mention in a comment', () => {
      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['commentMention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe mentioned you in a comment on "My Post"')
      })
    })

    it('sends an email for a mention in a post', () => {
      var originalMethod = Email.sendPostMentionNotification

      Email.sendPostMentionNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          post_user_name: 'Joe',
          post_description: 'The body of the post',
          post_title: 'My Post'
        })
      })

      return new Activity({
        post_id: post.id,
        meta: {reasons: ['mention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendPostMentionNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendPostMentionNotification = originalMethod
      })
    })

    it('sends an email for a comment', () => {
      var originalMethod = Email.sendNewCommentNotification

      Email.sendNewCommentNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          commenter_name: 'Joe',
          post_title: 'My Post'
        })
      })

      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['newComment']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendNewCommentNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendNewCommentNotification = originalMethod
      })
    })

    it('sends an email for a mention in a comment', () => {
      var originalMethod = Email.sendNewCommentNotification

      Email.sendNewCommentNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com',
          version: 'mention'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          commenter_name: 'Joe',
          post_title: 'My Post'
        })
      })

      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['commentMention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendNewCommentNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendNewCommentNotification = originalMethod
      })
    })
  })

  describe('#findUnsent', () => {
    it('returns the unsent', () => {
      return Promise.join(
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.Email,
          sent_at: (new Date()).toISOString()
        }).save(),
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.Push
        }).save(),
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.InApp
        }).save())
      .then(() => Notification.findUnsent())
      .then(notifications => {
        expect(notifications.length).to.equal(1)
        var notification = notifications.first()
        expect(notification.get('medium')).to.equal(Notification.MEDIUM.Push)
      })
    })
  })
})
<commit_msg>update test<commit_after>const root = require('root-path')
require(root('test/setup'))
var factories = require(root('test/setup/factories'))

const destroyAllPushNotifications = () => {
  return PushNotification.fetchAll()
  .then(pns => pns.map(pn => pn.destroy()))
}

const relations = [
  'activity',
  'activity.post',
  'activity.post.user',
  'activity.post.communities',
  'activity.comment',
  'activity.comment.user',
  'activity.comment.post',
  'activity.comment.post.communities',
  'activity.community',
  'activity.reader',
  'activity.actor'
]

describe('Notification', function () {
  var post, comment, activity, community, reader, actor, device

  before(() => {
    return factories.user({name: 'Joe'}).save()
    .then(u => actor = u)
    .then(() => factories.post({name: 'My Post', user_id: actor.id, description: 'The body of the post'}).save())
    .then(p => post = p)
    .then(() => new Comment({text: 'hi', user_id: actor.id, post_id: post.id}).save())
    .then(c => comment = c)
    .then(() => factories.community({name: 'My Community'}).save())
    .then(c => community = c)
    .then(() => community.posts().attach(post))
    .then(() => factories.user({email: 'readersemail@hylo.com'}).save())
    .then(u => reader = u)
    .then(() => new Device({
      user_id: reader.id,
      token: 'eieio',
      version: 20,
      enabled: true
    }).save())
    .then(d => device = d)
    .then(() => new Activity({
      post_id: post.id
    }).save())
    .then(a => activity = a)
  })

  beforeEach(() => destroyAllPushNotifications())

  describe('.send', () => {
    it('sends a push for a new post', () => {
      return new Activity({
        post_id: post.id,
        meta: {reasons: [`newPost: ${community.id}`]},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe posted "My Post" in My Community')
      })
    })

    it('sends a push for a mention in a post', () => {
      return new Activity({
        post_id: post.id,
        meta: {reasons: ['mention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe mentioned you in "My Post"')
      })
    })

    it('sends a push for a comment', () => {
      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['newComment']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe commented on "My Post"')
      })
    })

    it('sends a push for a mention in a comment', () => {
      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['commentMention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Push
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => PushNotification.where({device_token: device.get('token')}).fetchAll())
      .then(pns => {
        expect(pns).to.exist
        expect(pns.length).to.equal(1)
        var pn = pns.first()
        expect(pn.get('alert')).to.equal('Joe mentioned you in a comment on "My Post"')
      })
    })

    it('sends an email for a mention in a post', () => {
      var originalMethod = Email.sendPostMentionNotification

      Email.sendPostMentionNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          post_user_name: 'Joe',
          post_description: 'The body of the post',
          post_title: 'My Post'
        })
      })

      return new Activity({
        post_id: post.id,
        meta: {reasons: ['mention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendPostMentionNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendPostMentionNotification = originalMethod
      })
    })

    it('sends an email for a comment', () => {
      var originalMethod = Email.sendNewCommentNotification

      Email.sendNewCommentNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          commenter_name: 'Joe',
          post_title: 'My Post'
        })
      })

      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['newComment']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendNewCommentNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendNewCommentNotification = originalMethod
      })
    })

    it('sends an email for a mention in a comment', () => {
      var originalMethod = Email.sendNewCommentNotification

      Email.sendNewCommentNotification = spy(opts => {
        expect(opts).to.contain({
          email: 'readersemail@hylo.com',
          version: 'mention'
        })

        expect(opts.sender).to.contain({
          name: 'Joe (via Hylo)'
        })

        expect(opts.data).to.contain({
          community_name: 'My Community',
          commenter_name: 'Joe',
          post_title: 'My Post'
        })
      })

      return new Activity({
        comment_id: comment.id,
        meta: {reasons: ['commentMention']},
        reader_id: reader.id,
        actor_id: actor.id
      }).save()
      .then(activity => new Notification({
        activity_id: activity.id,
        medium: Notification.MEDIUM.Email
      }).save())
      .then(notification => notification.load(relations))
      .then(notification => notification.send())
      .then(() => {
        expect(Email.sendNewCommentNotification).to.have.been.called()
      })
      .then(() => {
        Email.sendNewCommentNotification = originalMethod
      })
    })
  })

  describe('#findUnsent', () => {
    it('returns the unsent', () => {
      return Promise.join(
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.Email,
          sent_at: (new Date()).toISOString()
        }).save(),
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.Push
        }).save(),
        new Notification({
          activity_id: activity.id,
          medium: Notification.MEDIUM.InApp
        }).save())
      .then(() => Notification.findUnsent())
      .then(notifications => {
        expect(notifications.length).to.equal(2)
        expect(notifications.models[0].get('medium')).to.equal(Notification.MEDIUM.Push)
        expect(notifications.models[1].get('medium')).to.equal(Notification.MEDIUM.InApp)
      })
    })
  })
})
<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');

describe('streaming', function() {

	var testName = 'streaming test';
	before(function(cb) {
		User.createEach([

		// several of these exist
		{
			name: 'a',
			type: testName
		}, {
			name: 'b',
			type: testName
		}, {
			name: 'c',
			type: testName
		}], cb);
	});

	describe('stream()', function () {

		it('should return and terminate a valid Node.js stream', function (cb) {
			var stream = User.stream();
			stream.on('end', cb);
		});

		it('should grab the same set of data as findAll', function (cb) {
			var userstream = User.stream();
			var streamedData = '';

			userstream.on('data', function (data) {
				streamedData += data;
			});
			userstream.on('error', function (err) {
				throw new Error(err);
			});

			async.auto({
				streamReady: function (cb) {
					userstream.on('end', function (){
						cb(null, streamedData);
					});
				},

				findAllReady: function (cb) {
					User.findAll().done(function (err,users) {
						users = _.pluck(users, 'values');

						// Serialize to JSON so it will match the streamed output
						users = JSON.stringify(users);
						cb(err,users);
					});
				}
			}, function (err, results) {
				if (err) throw new Error(err);
				else if (!(results.streamReady && results.findAllReady)) throw new Error ('Invalid results sent.');

				// Check equality of findAll() and stream() result sets
				var equals = _.isEqual(results.findAllReady, results.streamReady);
				if (!equals) cb(new Error('JSON over stream does not equal JSON-stringified findAll() model values!'));
				else cb();
			});
		});

		// it('should work in a case insensitive fashion by default', function(cb) {
		// 	User.find({
		// 		name: 'theothertest',
		// 		type: testName
		// 	}, User.testExists(true, cb));
		// });

		// it('should work with findBy*()', function(cb) {
		// 	User.findByName('theothertest', User.testExists(true, cb));
		// });
	});

	// describe('findAll()', function () {

	// 	it('should work in a case insensitive fashion by default', function(cb) {
	// 		User.findAll({
	// 			name: 'thetest',
	// 			type: testName
	// 		},User.testCount(3, cb));
	// 	});

	// 	it('should work with findAllBy*()', function(cb) {
	// 		User.findAllByName('thetest', User.testCount(3, cb));
	// 	});
	// });

	// describe('special classified queries ', function () {

	// 	var testName = 'contains case sensitivity';
	// 	before(function(cb) {
	// 		User.createEach([

	// 			// several of these exist
	// 			{
	// 				name: 'tHeTest',
	// 				type: testName
	// 			}, {
	// 				name: 'thetest',
	// 				type: testName
	// 			}, {
	// 				name: 'THETEST',
	// 				type: testName
	// 			},

	// 			// only one of these exists
	// 			{
	// 				name: 'tHeOtherTest',
	// 				type: testName
	// 			},

	// 			{
	// 				name: 'OTHER THINGS 0',
	// 				type: testName
	// 			},

	// 			{
	// 				name: 'OTHER THINGS 1',
	// 				type: testName
	// 			},

	// 			{
	// 				name: 'AR)H$daxx',
	// 				type: testName
	// 			},

	// 			{
	// 				name: 'AR)H$daxxy',
	// 				type: testName
	// 			},

	// 			// ends with est
	// 			{
	// 				name: '0n3 m0r3 est',
	// 				type: testName
	// 			}
	// 		], cb);
	// 	});

	// 	it('contains should work in a case insensitive fashion by default', function(cb) {
	// 		User.findAll({
	// 			name: {
	// 				contains: 'hete'
	// 			},
	// 			type: testName
	// 		},User.testCount(3, cb));
	// 	});

	// 	it('startsWith should work in a case insensitive fashion by default', function(cb) {
	// 		User.findAll({
	// 			name: {
	// 				startsWith: 'the'
	// 			},
	// 			type: testName
	// 		},User.testCount(4, cb));
	// 	});

	// 	it('endsWith should work in a case insensitive fashion by default', function(cb) {
	// 		User.findAll({
	// 			name: {
	// 				endsWith: 'est'
	// 			},
	// 			type: testName
	// 		},User.testCount(5, cb));
	// 	});

	// 	it('like should work in a case insensitive fashion by default', function(cb) {
	// 		User.findAll({
	// 			name: {
	// 				like: '%hete%'
	// 			},
	// 			type: testName
	// 		},User.testCount(3, cb));
	// 	});

	// 	it('endsWith should actually enforce endswith', function(cb) {
	// 		User.findAll({
	// 			name: {
	// 				endsWith: 'AR)H$daxx'
	// 			},
	// 			type: testName
	// 		},User.testCount(1, cb));
	// 	});
	// });
});<commit_msg>Commented-out code cleanup<commit_after>var _ = require('underscore');
var async = require('async');

describe('streaming', function() {

	var testName = 'streaming test';
	before(function(cb) {
		User.createEach([

		// several of these exist
		{
			name: 'a',
			type: testName
		}, {
			name: 'b',
			type: testName
		}, {
			name: 'c',
			type: testName
		}], cb);
	});

	describe('stream()', function () {

		it('should return and terminate a valid Node.js stream', function (cb) {
			var stream = User.stream();
			stream.on('end', cb);
		});

		it('should grab the same set of data as findAll', function (cb) {
			var userstream = User.stream();
			var streamedData = '';

			userstream.on('data', function (data) {
				streamedData += data;
			});
			userstream.on('error', function (err) {
				throw new Error(err);
			});

			async.auto({
				streamReady: function (cb) {
					userstream.on('end', function (){
						cb(null, streamedData);
					});
				},

				findAllReady: function (cb) {
					User.findAll().done(function (err,users) {
						users = _.pluck(users, 'values');

						// Serialize to JSON so it will match the streamed output
						users = JSON.stringify(users);
						cb(err,users);
					});
				}
			}, function (err, results) {
				if (err) throw new Error(err);
				else if (!(results.streamReady && results.findAllReady)) throw new Error ('Invalid results sent.');

				// Check equality of findAll() and stream() result sets
				var equals = _.isEqual(results.findAllReady, results.streamReady);
				if (!equals) cb(new Error('JSON over stream does not equal JSON-stringified findAll() model values!'));
				else cb();
			});
		});

	});

	// TODO: test iterative transformations (like XML conversion)

});<|endoftext|>


<commit_before>// tutorial1.js
//
// This is a simple test script that does the following:
//  open a website
//  validate title
//

// required libraries
var webdriverio = require('webdriverio'),
  should = require('should');

// a test script block or suite
describe('Title Test for Web Driver IO - Tutorial Test Page Website', function() {

  // set timeout to 10 seconds
	this.timeout(10000);
  var driver = {};

  // hook to run before tests
  before( function (done) {
    // check for global browser (grunt + grunt-webdriver)
    if(typeof browser === "undefined") {
      // load the driver for browser
      driver = webdriverio.remote({ desiredCapabilities: {browserName: 'firefox'} });
      driver.init(done);
    } else {
      // grunt will load the browser driver
      driver = browser;
      done();
    }
  });

  // a test spec - "specification"
  it('should be load correct page and title', function () {
    // load page, then call function()
    return driver
      .url('http://www.tlkeith.com/WebDriverIOTutorialTest.html')
      // get title, then pass title to function()
      .getTitle().then( function (title) {
        // verify title
        (title).should.be.equal("Web Driver IO - Tutorial Test Page");
        // uncomment for console debug
        // console.log('Current Page Title: ' + title);
      });
  });

  // a "hook" to run after all tests in this block
	after(function(done) {
    if(typeof browser === "undefined") {
      driver.end(done);
    } else {
      done();
    }
  });
});<commit_msg>Minor update<commit_after>// tutorial1.js
//
// This is a simple test script that does the following tests:
//  open a website
//  validate title
//

// required libraries
var webdriverio = require('webdriverio'),
  should = require('should');

// a test script block or suite
describe('Title Test for Web Driver IO - Tutorial Test Page Website', function() {

  // set timeout to 10 seconds
	this.timeout(10000);
  var driver = {};

  // hook to run before tests
  before( function (done) {
    // check for global browser (grunt + grunt-webdriver)
    if(typeof browser === "undefined") {
      // load the driver for browser
      driver = webdriverio.remote({ desiredCapabilities: {browserName: 'firefox'} });
      driver.init(done);
    } else {
      // grunt will load the browser driver
      driver = browser;
      done();
    }
  });

  // a test spec - "specification"
  it('should be load correct page and title', function () {
    // load page, then call function()
    return driver
      .url('http://www.tlkeith.com/WebDriverIOTutorialTest.html')
      // get title, then pass title to function()
      .getTitle().then( function (title) {
        // verify title
        (title).should.be.equal("Web Driver IO - Tutorial Test Page");
        // uncomment for console debug
        // console.log('Current Page Title: ' + title);
      });
  });

  // a "hook" to run after all tests in this block
	after(function(done) {
    if(typeof browser === "undefined") {
      driver.end(done);
    } else {
      done();
    }
  });
});<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { DraftailEditor } from 'draftail';

import { IS_IE11, STRINGS } from '../../config/wagtailConfig';

import Icon from '../Icon/Icon';

import Link from './decorators/Link';
import Document from './decorators/Document';
import ImageBlock from './blocks/ImageBlock';
import EmbedBlock from './blocks/EmbedBlock';

import ModalWorkflowSource from './sources/ModalWorkflowSource';

import registry from './registry';

const wrapWagtailIcon = type => {
  if (type.icon) {
    return Object.assign(type, {
      icon: <Icon name={type.icon} />,
    });
  }

  return type;
};

export const initEditor = (fieldName, options = {}) => {
  const field = document.querySelector(`[name="${fieldName}"]`);
  const editorWrapper = document.createElement('div');
  field.parentNode.appendChild(editorWrapper);

  const serialiseInputValue = rawContentState => {
    // TODO Remove default {} when finishing https://github.com/springload/wagtaildraftail/issues/32.
    field.value = JSON.stringify(rawContentState || {});
  };

  let blockTypes;
  let inlineStyles;
  let entityTypes;

  if (options && options.blockTypes) {
    blockTypes = options.blockTypes.map(wrapWagtailIcon);
  }

  if (options && options.inlineStyles) {
    inlineStyles = options.inlineStyles.map(wrapWagtailIcon);
  }

  if (options && options.entityTypes) {
    entityTypes = options.entityTypes.map(wrapWagtailIcon).map(type =>
      Object.assign(type, {
        source: registry.getSource(type.source),
        strategy: registry.getStrategy(type.type) || null,
        decorator: registry.getDecorator(type.decorator),
        block: registry.getBlock(type.block),
      })
    );
  }

  const enableHorizontalRule = options && options.enableHorizontalRule ? {
    description: STRINGS.HORIZONTAL_LINE,
  } : false;

  const fieldValue = JSON.parse(field.value);
  // TODO Remove default null when finishing https://github.com/springload/wagtaildraftail/issues/32.
  const rawContentState =
    fieldValue && Object.keys(fieldValue).length === 0 ? null : fieldValue;

  const editor = (
    <DraftailEditor
      rawContentState={rawContentState}
      onSave={serialiseInputValue}
      placeholder={STRINGS.WRITE_HERE}
      spellCheck={true}
      enableLineBreak={{ description: STRINGS.LINE_BREAK }}
      showUndoControl={{ description: STRINGS.UNDO }}
      showRedoControl={{ description: STRINGS.REDO }}
      // If increasing above 4, we will need to add styles for the extra nesting levels.
      maxListNesting={4}
      // Draft.js + IE 11 presents some issues with pasting rich text. Disable rich paste there.
      stripPastedStyles={IS_IE11}
      {...options}
      blockTypes={blockTypes}
      inlineStyles={inlineStyles}
      entityTypes={entityTypes}
      enableHorizontalRule={enableHorizontalRule}
    />
  );

  const draftailEditor = ReactDOM.render(editor, editorWrapper);

  // Bind editor instance to its field so it can be accessed imperatively elsewhere.
  field.draftailEditor = draftailEditor;
};

registry.registerSources({
  ModalWorkflowSource,
});
registry.registerDecorators({
  Link,
  Document,
});
registry.registerBlocks({
  ImageBlock,
  EmbedBlock,
});

const draftail = Object.assign(
  {
    initEditor: initEditor,
    // Expose basic React methods for basic needs
    // TODO Expose React as global as part of Wagtail vendor file instead of doing this.
    // createClass: React.createClass,
    // createElement: React.createElement,
  },
  registry
);

export default draftail;
<commit_msg>Remove outdated TODOs in Draftail code<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { DraftailEditor } from 'draftail';

import { IS_IE11, STRINGS } from '../../config/wagtailConfig';

import Icon from '../Icon/Icon';

import Link from './decorators/Link';
import Document from './decorators/Document';
import ImageBlock from './blocks/ImageBlock';
import EmbedBlock from './blocks/EmbedBlock';

import ModalWorkflowSource from './sources/ModalWorkflowSource';

import registry from './registry';

const wrapWagtailIcon = type => {
  if (type.icon) {
    return Object.assign(type, {
      icon: <Icon name={type.icon} />,
    });
  }

  return type;
};

export const initEditor = (fieldName, options = {}) => {
  const field = document.querySelector(`[name="${fieldName}"]`);
  const editorWrapper = document.createElement('div');
  field.parentNode.appendChild(editorWrapper);

  const serialiseInputValue = rawContentState => {
    // TODO Remove default {} when finishing https://github.com/springload/wagtaildraftail/issues/32.
    field.value = JSON.stringify(rawContentState || {});
  };

  let blockTypes;
  let inlineStyles;
  let entityTypes;

  if (options && options.blockTypes) {
    blockTypes = options.blockTypes.map(wrapWagtailIcon);
  }

  if (options && options.inlineStyles) {
    inlineStyles = options.inlineStyles.map(wrapWagtailIcon);
  }

  if (options && options.entityTypes) {
    entityTypes = options.entityTypes.map(wrapWagtailIcon).map(type =>
      Object.assign(type, {
        source: registry.getSource(type.source),
        strategy: registry.getStrategy(type.type) || null,
        decorator: registry.getDecorator(type.decorator),
        block: registry.getBlock(type.block),
      })
    );
  }

  const enableHorizontalRule = options && options.enableHorizontalRule ? {
    description: STRINGS.HORIZONTAL_LINE,
  } : false;

  const fieldValue = JSON.parse(field.value);
  // TODO Remove default null when finishing https://github.com/springload/wagtaildraftail/issues/32.
  const rawContentState =
    fieldValue && Object.keys(fieldValue).length === 0 ? null : fieldValue;

  const editor = (
    <DraftailEditor
      rawContentState={rawContentState}
      onSave={serialiseInputValue}
      placeholder={STRINGS.WRITE_HERE}
      spellCheck={true}
      enableLineBreak={{ description: STRINGS.LINE_BREAK }}
      showUndoControl={{ description: STRINGS.UNDO }}
      showRedoControl={{ description: STRINGS.REDO }}
      // If increasing above 4, we will need to add styles for the extra nesting levels.
      maxListNesting={4}
      // Draft.js + IE 11 presents some issues with pasting rich text. Disable rich paste there.
      stripPastedStyles={IS_IE11}
      {...options}
      blockTypes={blockTypes}
      inlineStyles={inlineStyles}
      entityTypes={entityTypes}
      enableHorizontalRule={enableHorizontalRule}
    />
  );

  const draftailEditor = ReactDOM.render(editor, editorWrapper);

  // Bind editor instance to its field so it can be accessed imperatively elsewhere.
  field.draftailEditor = draftailEditor;
};

registry.registerSources({
  ModalWorkflowSource,
});
registry.registerDecorators({
  Link,
  Document,
});
registry.registerBlocks({
  ImageBlock,
  EmbedBlock,
});

const draftail = Object.assign(
  {
    initEditor,
  },
  registry
);

export default draftail;
<|endoftext|>


<commit_before>"use strict";
let _ = require("lodash");

module.exports = function howManyPhoto(judges) {
    const stat = _.countBy(judges, function (judge) {
        return !!judge['Фото'];
    });

    console.log(`${stat[true]} judges has photo and ${stat[false]} judges don't.`)

    return judges;
};
<commit_msg>Fix typo<commit_after>"use strict";
let _ = require("lodash");

module.exports = function howManyPhoto(judges) {
    const stat = _.countBy(judges, function (judge) {
        return !!judge['Фото'];
    });

    console.log(`${stat[true]} judges has photo and ${stat[false]} judges doesn't.`)

    return judges;
};
<|endoftext|>


<commit_before>//Need to find a way to have back-end emit the current
//list of available projects to here

//This is hardcoded

export default function (state = null, action) {
  switch(action.type) {
    case 'ALL_PROJECTS':
      console.log('Receiving the projects list:', action.payload);

      const newState = action.payload.map( (project) => {
        return {
          projectId: project.projectId,
          projectType: project.projectType,
          jobsLength: project.jobsLength,
          title: project.title
        }
      });

      return newState;

    default:
      return state;
  }

  return state;
}<commit_msg>Revised default projects state in projects reducer<commit_after>//Need to find a way to have back-end emit the current
//list of available projects to here

//This is hardcoded

export default function (state = {}, action) {
  switch(action.type) {
    case 'ALL_PROJECTS':
      console.log('Receiving the projects list:', action.payload);

      const newState = action.payload.map( (project) => {
        return {
          projectId: project.projectId,
          projectType: project.projectType,
          jobsLength: project.jobsLength,
          title: project.title
        }
      });

      return newState;

    default:
      return state;
  }

  return state;
}<|endoftext|>


<commit_before>dojo.provide("dojox.charting.action2d.MoveSlice");

dojo.require("dojox.charting.action2d.Base");
dojo.require("dojox.gfx.matrix");

dojo.require("dojox.lang.functional");
dojo.require("dojox.lang.functional.scan");
dojo.require("dojox.lang.functional.fold");

(function(){
	var DEFAULT_SCALE = 1.05,
		DEFAULT_SHIFT = 7,	// px
		m = dojox.gfx.matrix,
		gf = dojox.gfx.fx,
		df = dojox.lang.functional;

	dojo.declare("dojox.charting.action2d.MoveSlice", dojox.charting.action2d.Base, {
		// the data description block for the widget parser
		defaultParams: {
			duration: 400,	// duration of the action in ms
			easing:   dojo.fx.easing.backOut,	// easing for the action
			scale:    DEFAULT_SCALE,	// scale of magnification
			shift:    DEFAULT_SHIFT		// shift of the slice
		},
		optionalParams: {},	// no optional parameters

		constructor: function(chart, plot, kwArgs){
			// process optional named parameters
			if(!kwArgs){ kwArgs = {}; }
			this.scale = typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
			this.shift = typeof kwArgs.shift == "number" ? kwArgs.shift : DEFAULT_SHIFT;

			this.connect();
		},

		process: function(o){
			if(!o.shape || o.element != "slice" || !(o.type in this.overOutEvents)){ return; }

			if(!this.angles){
				// calculate the running total of slice angles
				if(typeof o.run.data[0] == "number"){
					this.angles = df.map(df.scanl(o.run.data, "+", 0),
						"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
				}else{
					this.angles = df.map(df.scanl(o.run.data, "a + b.y", 0),
						"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
				}
			}

			var index = o.index, anim, endScale, startOffset, endOffset,
				angle = (this.angles[index] + this.angles[index + 1]) / 2,
				rotateTo0  = m.rotateAt(-angle, o.cx, o.cy),
				rotateBack = m.rotateAt( angle, o.cx, o.cy);

			anim = this.anim[index];

			if(anim){
				anim.action.stop(true);
			}else{
				this.anim[index] = anim = {};
			}

			if(o.type == "onmouseover"){
				startOffset = 0;
				endOffset   = this.shift;
				endScale    = this.scale;
			}else{
				startOffset = this.shift;
				endOffset   = 0;
				endScale    = 1 / this.scale;
			}

			anim.action = dojox.gfx.fx.animateTransform({
				shape:    o.shape,
				duration: this.duration,
				easing:   this.easing,
				transform: [
					rotateBack,
					{name: "translate", start: [startOffset, 0], end: [endOffset, 0]},
					{name: "scaleAt",   start: [1, o.cx, o.cy],  end: [endScale, o.cx, o.cy]},
					rotateTo0
				]
			});

			if(o.type == "onmouseout"){
				dojo.connect(anim.action, "onEnd", this, function(){
					delete this.anim[index];
				});
			}
			anim.action.play();
		},

		reset: function(){
			delete this.angles;
		}
	});
})();<commit_msg>dojox.charting: fixing amusing typo, thx haysmark!, !strict, fixes #7883.<commit_after>dojo.provide("dojox.charting.action2d.MoveSlice");

dojo.require("dojox.charting.action2d.Base");
dojo.require("dojox.gfx.matrix");

dojo.require("dojox.lang.functional");
dojo.require("dojox.lang.functional.scan");
dojo.require("dojox.lang.functional.fold");

(function(){
	var DEFAULT_SCALE = 1.05,
		DEFAULT_SHIFT = 7,	// px
		m = dojox.gfx.matrix,
		gf = dojox.gfx.fx,
		df = dojox.lang.functional;

	dojo.declare("dojox.charting.action2d.MoveSlice", dojox.charting.action2d.Base, {
		// the data description block for the widget parser
		defaultParams: {
			duration: 400,	// duration of the action in ms
			easing:   dojo.fx.easing.backOut,	// easing for the action
			scale:    DEFAULT_SCALE,	// scale of magnification
			shift:    DEFAULT_SHIFT		// shift of the slice
		},
		optionalParams: {},	// no optional parameters

		constructor: function(chart, plot, kwArgs){
			// process optional named parameters
			if(!kwArgs){ kwArgs = {}; }
			this.scale = typeof kwArgs.scale == "number" ? kwArgs.scale : DEFAULT_SCALE;
			this.shift = typeof kwArgs.shift == "number" ? kwArgs.shift : DEFAULT_SHIFT;

			this.connect();
		},

		process: function(o){
			if(!o.shape || o.element != "slice" || !(o.type in this.overOutEvents)){ return; }

			if(!this.angles){
				// calculate the running total of slice angles
				if(typeof o.run.data[0] == "number"){
					this.angles = df.map(df.scanl(o.run.data, "+", 0),
						"* 2 * Math.PI / this", df.foldl(o.run.data, "+", 0));
				}else{
					this.angles = df.map(df.scanl(o.run.data, "a + b.y", 0),
						"* 2 * Math.PI / this", df.foldl(o.run.data, "a + b.y", 0));
				}
			}

			var index = o.index, anim, startScale, endScale, startOffset, endOffset,
				angle = (this.angles[index] + this.angles[index + 1]) / 2,
				rotateTo0  = m.rotateAt(-angle, o.cx, o.cy),
				rotateBack = m.rotateAt( angle, o.cx, o.cy);

			anim = this.anim[index];

			if(anim){
				anim.action.stop(true);
			}else{
				this.anim[index] = anim = {};
			}

			if(o.type == "onmouseover"){
				startOffset = 0;
				endOffset   = this.shift;
				startScale  = 1;
				endScale    = this.scale;
			}else{
				startOffset = this.shift;
				endOffset   = 0;
				startScale  = this.scale;
				endScale    = 1;
			}

			anim.action = dojox.gfx.fx.animateTransform({
				shape:    o.shape,
				duration: this.duration,
				easing:   this.easing,
				transform: [
					rotateBack,
					{name: "translate", start: [startOffset, 0], end: [endOffset, 0]},
					{name: "scaleAt",   start: [startScale, o.cx, o.cy],  end: [endScale, o.cx, o.cy]},
					rotateTo0
				]
			});

			if(o.type == "onmouseout"){
				dojo.connect(anim.action, "onEnd", this, function(){
					delete this.anim[index];
				});
			}
			anim.action.play();
		},

		reset: function(){
			delete this.angles;
		}
	});
})();<|endoftext|>