<commit_before>import auth from '@/services/api/auth'
import authUser from '@/services/api/authUser'
import router from '@/router'
import { createMetaModule, withMeta, metaStatuses } from '@/store/helpers'
import { objectDiff } from '@/services/utils'
import push from '@/store/modules/auth/push'

function initialState () {
  return {
    user: null,
    redirectTo: null,
    joinGroupAfterLogin: null,
    acceptInviteAfterLogin: null,
    muteConversationAfterLogin: [],
    failedEmailDeliveries: [],
    maybeLoggedOut: false,
  }
}

export default {
  namespaced: true,
  modules: { meta: createMetaModule(), push },
  state: initialState(),
  getters: {
    isLoggedIn: state => !!state.user,
    user: state => state.user,
    userId: state => state.user && state.user.id,
    currentGroupId: state => state.user && state.user.currentGroup,
    failedEmailDeliveries: state => state.failedEmailDeliveries,
    redirectTo: state => state.redirectTo,
    hasJoinGroupAfterLogin: state => Boolean(state.joinGroupAfterLogin),
    ...metaStatuses(['login', 'logout', 'save', 'changePassword', 'changeEmail']),
  },
  actions: {
    clearLoginStatus: ({ dispatch }) => dispatch('meta/clear', ['login']),
    ...withMeta({
      async login ({ state, commit, getters, dispatch, rootGetters }, data) {
        const user = await auth.login(data)
        dispatch('update', user)
        dispatch('afterLoggedIn')

        state.muteConversationAfterLogin.forEach(conversationId => {
          try {
            dispatch('conversations/maybeToggleEmailNotifications', {
              conversationId,
              value: false,
            }, { root: true })
          }
          catch (error) {}
          commit('clearMuteConversationAfterLogin')
        })

        if (state.acceptInviteAfterLogin) {
          await dispatch('invitations/accept', state.acceptInviteAfterLogin, { root: true })
        }
        else if (state.joinGroupAfterLogin) {
          const groupId = state.joinGroupAfterLogin
          const group = () => rootGetters['groups/get'](groupId)
          if (group().isMember) {
            // go to group if already a member
            router.push({ name: 'group', params: { groupId } })
          }
          else {
            await dispatch('groups/join', groupId, { root: true })
            if (group().joinStatus.hasValidationErrors) {
              // go back to goup preview if error occured
              // it should show the error status on group preview, thanks to persistent state!
              router.push({ name: 'groupPreview', params: { groupPreviewId: groupId } })
            }
          }
        }
        else if (getters.redirectTo) {
          router.push(getters.redirectTo)
        }
        else {
          router.push('/')
        }
        commit('clearAcceptInviteAfterLogin')
        commit('clearJoinGroupAfterLogin')
        commit('clearRedirectTo')
      },

      async logout ({ dispatch }) {
        await dispatch('push/disable')
        await dispatch('fcm/disable', null, { root: true })
        await auth.logout()

        dispatch('update', null)
        dispatch('toasts/show', {
          message: 'USERDATA.LOGOUT_SUCCESS',
        }, { root: true })

        dispatch('conversations/clear', null, { root: true })
        dispatch('currentThread/clear', null, { root: true })
        router.push({ name: 'groupsGallery' })
      },

      async changePassword ({ dispatch }, { oldPassword, newPassword, done }) {
        await auth.changePassword({ oldPassword, newPassword })
        done()
        dispatch('toasts/show', {
          message: 'PASSWORD.CHANGE.SUCCESS',
        }, { root: true })
      },

      async changeEmail ({ dispatch, getters }, { newEmail, password, done }) {
        await auth.changeEmail({ newEmail, password })
        done()
        dispatch('users/refresh', { userId: getters.userId }, { root: true })
        dispatch('refresh')
      },
    }),

    async getFailedEmailDeliveries ({ commit }) {
      commit('setFailedEmailDeliveries', await authUser.getFailedEmailDeliveries())
    },

    ...withMeta({
      async save ({ dispatch }, data) {
        try {
          await dispatch('backgroundSave', data)
          dispatch('toasts/show', {
            message: 'NOTIFICATIONS.CHANGES_SAVED',
            config: {
              timeout: 2000,
              icon: 'thumb_up',
            },
          }, { root: true })
        }
        catch (error) {
          dispatch('toasts/show', {
            message: 'NOTIFICATIONS.CHANGES_ERROR',
            config: {
              timeout: 2000,
              icon: 'warning',
            },
          }, { root: true })
        }
      },
    }, {
      // ignore ID to have simple saveStatus
      findId: () => undefined,
    }),

    maybeBackgroundSave ({ dispatch, state }, data) {
      const diff = objectDiff(state.user, { ...state.user, ...data })
      if (Object.keys(diff).length === 0) return
      return dispatch('backgroundSave', diff)
    },

    async backgroundSave ({ dispatch }, data) {
      const savedUser = await authUser.save(data)
      dispatch('update', savedUser)
      dispatch('users/update', savedUser, { root: true })
      return savedUser
    },

    setRedirectTo ({ commit }, redirectTo) {
      commit('setRedirectTo', { redirectTo })
    },

    setJoinGroupAfterLogin ({ commit }, groupId) {
      commit('setJoinGroupAfterLogin', groupId)
    },

    setAcceptInviteAfterLogin ({ commit }, token) {
      commit('setAcceptInviteAfterLogin', { token })
    },

    setMuteConversationAfterLogin ({ commit }, conversationId) {
      commit('appendMuteConversationAfterLogin', { conversationId })
    },

    afterLoggedIn ({ state, dispatch }) {
      const { user } = state
      dispatch('i18n/setLocale', user.language || 'en', { root: true })
    },

    update ({ commit }, user) {
      commit('setUser', user)
    },

    async refresh ({ commit, dispatch, getters }) {
      const wasLoggedIn = getters.isLoggedIn
      let user = null
      try {
        user = await authUser.get()
      }
      catch (error) {}
      dispatch('update', user)
      commit('setMaybeLoggedOut', false)

      if (user) {
        dispatch('afterLoggedIn')
      }
      else if (wasLoggedIn && !getters.logoutStatus.pending) {
        dispatch('logout')
      }
    },

    clearSettingsStatus ({ commit, dispatch }) {
      dispatch('meta/clear', ['changeEmail'])
      dispatch('meta/clear', ['changePassword'])
      dispatch('meta/clear', ['save'])
      dispatch('users/clearResendVerificationCode', null, { root: true })
    },
  },
  mutations: {
    setUser (state, user) {
      state.user = user
    },

    // Redirect
    setRedirectTo (state, { redirectTo }) {
      state.redirectTo = redirectTo
    },
    clearRedirectTo (state) {
      state.redirectTo = null
    },

    // Group to join after login
    setJoinGroupAfterLogin (state, groupId) {
      state.joinGroupAfterLogin = groupId
    },
    clearJoinGroupAfterLogin (state) {
      state.joinGroupAfterLogin = null
    },

    // Invite token to accept after login
    setAcceptInviteAfterLogin (state, { token }) {
      state.acceptInviteAfterLogin = token
    },
    clearAcceptInviteAfterLogin (state) {
      state.acceptInviteAfterLogin = null
    },

    // Mute conversation after login
    appendMuteConversationAfterLogin (state, { conversationId }) {
      state.muteConversationAfterLogin.push(conversationId)
    },
    clearMuteConversationAfterLogin (state) {
      state.muteConversationAfterLogin = []
    },

    setFailedEmailDeliveries (state, events) {
      state.failedEmailDeliveries = events
    },

    setMaybeLoggedOut (state, value) {
      if (state.user) {
        state.maybeLoggedOut = value
      }
      else {
        state.maybeLoggedOut = false
      }
    },
  },
}

export function plugin (store) {
  store.watch(state => state.auth.maybeLoggedOut, async (maybeLoggedOut) => {
    if (maybeLoggedOut) {
      await store.dispatch('auth/refresh')
    }
  })
}
<commit_msg>prevent duplicate logout toasts<commit_after>import auth from '@/services/api/auth'
import authUser from '@/services/api/authUser'
import router from '@/router'
import { createMetaModule, withMeta, metaStatuses } from '@/store/helpers'
import { objectDiff } from '@/services/utils'
import push from '@/store/modules/auth/push'
import { throttle } from 'quasar'

function initialState () {
  return {
    user: null,
    redirectTo: null,
    joinGroupAfterLogin: null,
    acceptInviteAfterLogin: null,
    muteConversationAfterLogin: [],
    failedEmailDeliveries: [],
    maybeLoggedOut: false,
  }
}

const showLogoutToast = throttle((dispatch) => {
  dispatch('toasts/show', {
    message: 'USERDATA.LOGOUT_SUCCESS',
    config: {
      timeout: 5000,
    },
  }, { root: true })
}, 5000)

export default {
  namespaced: true,
  modules: { meta: createMetaModule(), push },
  state: initialState(),
  getters: {
    isLoggedIn: state => !!state.user,
    user: state => state.user,
    userId: state => state.user && state.user.id,
    currentGroupId: state => state.user && state.user.currentGroup,
    failedEmailDeliveries: state => state.failedEmailDeliveries,
    redirectTo: state => state.redirectTo,
    hasJoinGroupAfterLogin: state => Boolean(state.joinGroupAfterLogin),
    ...metaStatuses(['login', 'logout', 'save', 'changePassword', 'changeEmail']),
  },
  actions: {
    clearLoginStatus: ({ dispatch }) => dispatch('meta/clear', ['login']),
    ...withMeta({
      async login ({ state, commit, getters, dispatch, rootGetters }, data) {
        const user = await auth.login(data)
        dispatch('update', user)
        dispatch('afterLoggedIn')

        state.muteConversationAfterLogin.forEach(conversationId => {
          try {
            dispatch('conversations/maybeToggleEmailNotifications', {
              conversationId,
              value: false,
            }, { root: true })
          }
          catch (error) {}
          commit('clearMuteConversationAfterLogin')
        })

        if (state.acceptInviteAfterLogin) {
          await dispatch('invitations/accept', state.acceptInviteAfterLogin, { root: true })
        }
        else if (state.joinGroupAfterLogin) {
          const groupId = state.joinGroupAfterLogin
          const group = () => rootGetters['groups/get'](groupId)
          if (group().isMember) {
            // go to group if already a member
            router.push({ name: 'group', params: { groupId } })
          }
          else {
            await dispatch('groups/join', groupId, { root: true })
            if (group().joinStatus.hasValidationErrors) {
              // go back to goup preview if error occured
              // it should show the error status on group preview, thanks to persistent state!
              router.push({ name: 'groupPreview', params: { groupPreviewId: groupId } })
            }
          }
        }
        else if (getters.redirectTo) {
          router.push(getters.redirectTo)
        }
        else {
          router.push('/')
        }
        commit('clearAcceptInviteAfterLogin')
        commit('clearJoinGroupAfterLogin')
        commit('clearRedirectTo')
      },

      async logout ({ dispatch }) {
        await dispatch('push/disable')
        await dispatch('fcm/disable', null, { root: true })
        await auth.logout()

        dispatch('update', null)
        showLogoutToast(dispatch)

        dispatch('conversations/clear', null, { root: true })
        dispatch('currentThread/clear', null, { root: true })
        router.push({ name: 'groupsGallery' })
      },

      async changePassword ({ dispatch }, { oldPassword, newPassword, done }) {
        await auth.changePassword({ oldPassword, newPassword })
        done()
        dispatch('toasts/show', {
          message: 'PASSWORD.CHANGE.SUCCESS',
        }, { root: true })
      },

      async changeEmail ({ dispatch, getters }, { newEmail, password, done }) {
        await auth.changeEmail({ newEmail, password })
        done()
        dispatch('users/refresh', { userId: getters.userId }, { root: true })
        dispatch('refresh')
      },
    }),

    async getFailedEmailDeliveries ({ commit }) {
      commit('setFailedEmailDeliveries', await authUser.getFailedEmailDeliveries())
    },

    ...withMeta({
      async save ({ dispatch }, data) {
        try {
          await dispatch('backgroundSave', data)
          dispatch('toasts/show', {
            message: 'NOTIFICATIONS.CHANGES_SAVED',
            config: {
              timeout: 2000,
              icon: 'thumb_up',
            },
          }, { root: true })
        }
        catch (error) {
          dispatch('toasts/show', {
            message: 'NOTIFICATIONS.CHANGES_ERROR',
            config: {
              timeout: 2000,
              icon: 'warning',
            },
          }, { root: true })
        }
      },
    }, {
      // ignore ID to have simple saveStatus
      findId: () => undefined,
    }),

    maybeBackgroundSave ({ dispatch, state }, data) {
      const diff = objectDiff(state.user, { ...state.user, ...data })
      if (Object.keys(diff).length === 0) return
      return dispatch('backgroundSave', diff)
    },

    async backgroundSave ({ dispatch }, data) {
      const savedUser = await authUser.save(data)
      dispatch('update', savedUser)
      dispatch('users/update', savedUser, { root: true })
      return savedUser
    },

    setRedirectTo ({ commit }, redirectTo) {
      commit('setRedirectTo', { redirectTo })
    },

    setJoinGroupAfterLogin ({ commit }, groupId) {
      commit('setJoinGroupAfterLogin', groupId)
    },

    setAcceptInviteAfterLogin ({ commit }, token) {
      commit('setAcceptInviteAfterLogin', { token })
    },

    setMuteConversationAfterLogin ({ commit }, conversationId) {
      commit('appendMuteConversationAfterLogin', { conversationId })
    },

    afterLoggedIn ({ state, dispatch }) {
      const { user } = state
      dispatch('i18n/setLocale', user.language || 'en', { root: true })
    },

    update ({ commit }, user) {
      commit('setUser', user)
    },

    async refresh ({ commit, dispatch, getters }) {
      const wasLoggedIn = getters.isLoggedIn
      let user = null
      try {
        user = await authUser.get()
      }
      catch (error) {}
      dispatch('update', user)
      commit('setMaybeLoggedOut', false)

      if (user) {
        dispatch('afterLoggedIn')
      }
      else if (wasLoggedIn && !getters.logoutStatus.pending) {
        dispatch('logout')
      }
    },

    clearSettingsStatus ({ commit, dispatch }) {
      dispatch('meta/clear', ['changeEmail'])
      dispatch('meta/clear', ['changePassword'])
      dispatch('meta/clear', ['save'])
      dispatch('users/clearResendVerificationCode', null, { root: true })
    },
  },
  mutations: {
    setUser (state, user) {
      state.user = user
    },

    // Redirect
    setRedirectTo (state, { redirectTo }) {
      state.redirectTo = redirectTo
    },
    clearRedirectTo (state) {
      state.redirectTo = null
    },

    // Group to join after login
    setJoinGroupAfterLogin (state, groupId) {
      state.joinGroupAfterLogin = groupId
    },
    clearJoinGroupAfterLogin (state) {
      state.joinGroupAfterLogin = null
    },

    // Invite token to accept after login
    setAcceptInviteAfterLogin (state, { token }) {
      state.acceptInviteAfterLogin = token
    },
    clearAcceptInviteAfterLogin (state) {
      state.acceptInviteAfterLogin = null
    },

    // Mute conversation after login
    appendMuteConversationAfterLogin (state, { conversationId }) {
      state.muteConversationAfterLogin.push(conversationId)
    },
    clearMuteConversationAfterLogin (state) {
      state.muteConversationAfterLogin = []
    },

    setFailedEmailDeliveries (state, events) {
      state.failedEmailDeliveries = events
    },

    setMaybeLoggedOut (state, value) {
      if (state.user) {
        state.maybeLoggedOut = value
      }
      else {
        state.maybeLoggedOut = false
      }
    },
  },
}

export function plugin (store) {
  store.watch(state => state.auth.maybeLoggedOut, async (maybeLoggedOut) => {
    if (maybeLoggedOut) {
      await store.dispatch('auth/refresh')
    }
  })
}
<|endoftext|>


<commit_before>/* global XMLHttpRequest, expect */

function loadBinaryResource (url) {
  const req = new XMLHttpRequest()
  req.open('GET', url, false)
   // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  req.overrideMimeType('text\/plain; charset=x-user-defined')
  req.send(null)
  if (req.status !== 200) {
    throw new Error('Unable to load file')
  }
  return req.responseText
}

function sendReference (filename, data) {
  const req = new XMLHttpRequest()
  req.open('POST', `http://localhost:9090/${filename}`, true)
  req.onload = e => {
    console.log(e)
  }
  req.send(data)
}

const resetCreationDate = input =>
  input.replace(
    /\/CreationDate \(D:(.*?)\)/,
    '/CreationDate (D:19871210000000+00\'00\'\)'
  )

/**
 * Find a better way to set this
 * @type {Boolean}
 */
window.comparePdf = (actual, expectedFile, suite) => {
  let pdf
  try {
    pdf = loadBinaryResource(`/base/tests/${suite}/reference/${expectedFile}`)
  } catch (error) {
    sendReference(`/tests/${suite}/reference/${expectedFile}`, resetCreationDate(actual))
    pdf = actual
  }
  const expected = resetCreationDate(pdf).trim()
  actual = resetCreationDate(actual.trim())

  expect(actual).toEqual(expected)
}
<commit_msg>Update compare.js<commit_after>/* global XMLHttpRequest, expect */

function loadBinaryResource (url) {
  const req = new XMLHttpRequest()
  req.open('GET', url, false)
   // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  req.overrideMimeType('text\/plain; charset=x-user-defined')
  req.send(null)
  if (req.status !== 200) {
    throw new Error('Unable to load file')
  }
  return req.responseText
}

function sendReference (filename, data) {
  const req = new XMLHttpRequest()
  req.open('POST', `http://localhost:9090/${filename}`, true)
  req.onload = e => {
    //console.log(e)
  }
  req.send(data)
}

const resetCreationDate = input =>
  input.replace(
    /\/CreationDate \(D:(.*?)\)/,
    '/CreationDate (D:19871210000000+00\'00\'\)'
  )

/**
 * Find a better way to set this
 * @type {Boolean}
 */
window.comparePdf = (actual, expectedFile, suite) => {
  let pdf
  try {
    pdf = loadBinaryResource(`/base/tests/${suite}/reference/${expectedFile}`)
  } catch (error) {
    sendReference(`/tests/${suite}/reference/${expectedFile}`, resetCreationDate(actual))
    pdf = actual
  }
  const expected = resetCreationDate(pdf).trim()
  actual = resetCreationDate(actual.trim())

  expect(actual).toEqual(expected)
}
<|endoftext|>


<commit_before>
//When page loadded, read data and URL state, if any
$( document ).ready(load_data());

function page_main(){
  update_stats();
  load_data_state(default_function="full_list");
}

function full_list(){
  //Add listing and stats
  updateURLParameters("full_list");
  empty_dashboard();
  add_goals();
  add_targets();
  add_indicators();
}

function update_stats(){
 //make stats
 stats.goals=sdgs.goals.goals.length;
 stats.targets = sdgs.targets.targets.length;
 stats.indicators = sdgs.indicators.indicators.length;
 stats.goal_targets = array_num(sdgs.goals.goals.length,0);
 stats.goal_indicators = array_num(sdgs.goals.goals.length,0);
 for (var i in sdgs.indicators.indicators){ stats.goal_indicators[sdgs.indicators.indicators[i].goal-1]++; }
 for (var j in sdgs.targets.targets){ stats.goal_targets[sdgs.targets.targets[j].goal-1]++; }
 // Add left bar with numbers.
 document.getElementById("goals-num").innerHTML = stats.goals+" Goals";
 document.getElementById("targets-num").innerHTML = stats.targets+" Targets";
 document.getElementById("indicators-num").innerHTML = stats.indicators+" Indicators";
}

function vizs(){
  empty_dashboard();
  updateURLParameters("vizs");
  $('#Visualizations').addClass("btn-primary");
  document.getElementById("dashboard-title").innerHTML = "SDGs Visualized";
  add_stack_plot();
  add_leads_pie();
}

function add_stack_plot(){
 // Add plot stack viz on id "barplot".
 var data = {
    labels: d3.range(1, stats.goals+1).map(function(i){return "Goal "+i;}),
    labels_tooltip: sdgs.goals.goals.map(function (key) { return key.short;}),
    datasets: [
        {
            label: "Targets",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: stats.goal_targets
        },
        {
            label: "Potential Indicators",
            fillColor: "rgba(151,187,205,0.5)",
            strokeColor: "rgba(151,187,205,0.8)",
            highlightFill: "rgba(151,187,205,0.75)",
            highlightStroke: "rgba(151,187,205,1)",
            data: stats.goal_indicators
        }
    ]
 };
 var options = {
    barStrokeWidth : 2
 };
 var anchor=document.getElementById("dashboard-content");
 var wrapper = document.createElement("div");
 var title = document.createElement("h3");
 title.innerHTML = "Indicator candidates and Targets per Goal";
 var canvas = document.createElement("canvas");
 canvas.setAttribute("id", "barplot");
 canvas.setAttribute("class", "barplot");
 anchor.appendChild(wrapper).appendChild(title);
 anchor.appendChild(wrapper).appendChild(canvas);
 var ctx= canvas.getContext("2d");
 Chart.defaults.global.multiTooltipTemplate = "<%= value %> <%= datasetLabel %> ";
 var myBarChart = new Chart(ctx).Bar(data, options);
}

function count_match_leads(dictionary,regex){
 //Given a dictionary, return the sum of the values whose
 //keys match the string
 var count = 0;
 for (var key in dictionary){
   regex.test(key)? count+=dictionary[key]: null;
 }
 return count;
}

function add_leads_pie(){
 // Add leads pie. Leads normalized by indicator

 //count leads
 var leads = {total:0};
 for (var j in sdgs.indicators.indicators){
  var ileads = sdgs.indicators.indicators[j].leads.split(",");
   for (var jj in ileads){
    var lead=ileads[jj].trim().replace('""',"");
    leads[lead] ? leads[lead]++ : leads[lead]=1;
    leads["total"]++;
   }
  }
 var data = [
    {
        value: count_match_leads(leads,/UN/),
        color:"#F7464A",
        highlight: "#FF5A5E",
        label: "UN bodies"
    },
    {
        value: count_match_leads(leads,/WB|World Bank/),
        color: "#46BFBD",
        highlight: "#5AD3D1",
        label: "World Bank Group"
    },
    {
        value: count_match_leads(leads,/OECD/),
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "OECD"
    },
    {
        value: leads["total"]-
               count_match_leads(leads,/OECD|WB|UN|World Bank/)
               -leads[""],
        color: "#FF245C",
        highlight: "#FF245A",
        label: "Others"
    },
    {
        value: leads[""],
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "Unclear"
    }
];
 var options = [];
 var anchor=document.getElementById("dashboard-content");
 var wrapper = document.createElement("div");
 var title = document.createElement("h3");
 title.innerHTML = "Leads per Indicator";
 var canvas = document.createElement("canvas");
 canvas.setAttribute("id", "leadpie");
 canvas.setAttribute("class", "pie");
 anchor.appendChild(wrapper).appendChild(title);
 anchor.appendChild(wrapper).appendChild(canvas);
 var ctx= canvas.getContext("2d");
 var myPieChart = new Chart(ctx).Pie(data,options);
}

function empty_dashboard(){
  document.getElementById("dashboard-title").innerHTML = "";
  document.getElementById("dashboard-content").innerHTML = "";
  $('li.active').removeClass("active");
  $('#Visualizations').removeClass("btn-primary");
}

function list_goals(){
  updateURLParameters("list_goals");
  empty_dashboard();
  $('#goals').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Goals";
  var sdgList = document.getElementById("dashboard-content");
  var goals=sdgs.goals.goals;
  for (var i in goals){
    var goal= goals[i];
    append('li',sdgList,"goal-"+goal.goal,"",goal.goal+": "+goal.title+".");
  }
}

function list_indicators(){
  updateURLParameters("list_indicators");
  empty_dashboard();
  $('#indicators').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Indicators Candidates";
  var sdgList = document.getElementById("dashboard-content");
  var indicators=sdgs.indicators.indicators;
  for (var i in indicators){
    var indicator= indicators[i];
    append('li',sdgList,"goal-"+indicator.indicator,"indicator",indicator.indicator+": "+indicator.indicator+".");
  }
}

function list_targets(){
  updateURLParameters("list_targets");
  empty_dashboard();
  $('#targets').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Targets";
  var sdgList = document.getElementById("dashboard-content");
  var targets=sdgs.targets.targets;
  for (var i in targets){
    var target= targets[i];
    append('li',sdgList,"goal-"+target.target,"",target.id+": "+target.title+".");
  }
}

function add_goals(){
  $('#load-all').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Goals";
  var sdgList = document.getElementById("dashboard-content");
  var goals=sdgs.goals.goals;
  for (var i in goals){
    var goal= goals[i];
    append('li',sdgList,"goal-"+goal.goal,"h2",goal.goal+": "+goal.title+".");
  }
}

function add_targets(){
  var targets=sdgs.targets.targets;
  for (var i in targets){
    var target=targets[i];
    var goalLi = document.getElementById("goal-"+target.goal);
    var targetId="goal-"+target.goal+"-targets";
    if ( document.getElementById(targetId) === null) {
      var nestedOl = document.createElement("ul");
      nestedOl.setAttribute("id", targetId);
      goalLi.appendChild(nestedOl);
    }
    var goalLiUl = document.getElementById(targetId);
    append('li',goalLiUl,"target-"+target.id,"target",target.id+": "+target.title);
  }
}

function add_indicators(){
  var indicators=sdgs.indicators.indicators;
  for (var i in indicators){
    var indicator=indicators[i];
    var goalLi = document.getElementById("goal-"+indicator.goal);
    var indicatorsId="goal-"+indicator.goal+"-indicators";
    if (document.getElementById(indicatorsId) === null) {
      var responsiveTable = document.createElement("div");
      responsiveTable.setAttribute("class","table-responsive");
      var nestedTable = document.createElement("table");
      nestedTable.setAttribute("class","table table-striped table-bordered");
      var header = nestedTable.createTHead();
      var rowObject = header.insertRow(0);
      var columns=["Candidate Indicator","Category","Leads","Available"];
      for (var ii in columns ){
          var th = document.createElement('th');
          th.innerHTML = columns[ii];
          rowObject.appendChild(th);
      }
      var body = nestedTable.createTBody();
      body.setAttribute("id", indicatorsId);
      body.setAttribute("class", "indicator");
      goalLi.appendChild(responsiveTable).appendChild(nestedTable);
     }else{
      append_row(indicatorsId,[indicator.indicator,indicator.category,indicator.leads,indicator.available]);
    }
  }
}
<commit_msg>Update list.js<commit_after>
//When page loadded, read data and URL state, if any
$( document ).ready(load_data());

function page_main(){
  update_stats();
  load_data_state(default_function="full_list");
}

function full_list(){
  //Add listing and stats
  empty_dashboard();
  add_goals();
  add_targets();
  add_indicators();
  updateURLParameters("full_list");
}

function update_stats(){
 //make stats
 stats.goals=sdgs.goals.goals.length;
 stats.targets = sdgs.targets.targets.length;
 stats.indicators = sdgs.indicators.indicators.length;
 stats.goal_targets = array_num(sdgs.goals.goals.length,0);
 stats.goal_indicators = array_num(sdgs.goals.goals.length,0);
 for (var i in sdgs.indicators.indicators){ stats.goal_indicators[sdgs.indicators.indicators[i].goal-1]++; }
 for (var j in sdgs.targets.targets){ stats.goal_targets[sdgs.targets.targets[j].goal-1]++; }
 // Add left bar with numbers.
 document.getElementById("goals-num").innerHTML = stats.goals+" Goals";
 document.getElementById("targets-num").innerHTML = stats.targets+" Targets";
 document.getElementById("indicators-num").innerHTML = stats.indicators+" Indicators";
}

function vizs(){
  empty_dashboard();
  updateURLParameters("vizs");
  $('#Visualizations').addClass("btn-primary");
  document.getElementById("dashboard-title").innerHTML = "SDGs Visualized";
  add_stack_plot();
  add_leads_pie();
}

function add_stack_plot(){
 // Add plot stack viz on id "barplot".
 var data = {
    labels: d3.range(1, stats.goals+1).map(function(i){return "Goal "+i;}),
    labels_tooltip: sdgs.goals.goals.map(function (key) { return key.short;}),
    datasets: [
        {
            label: "Targets",
            fillColor: "rgba(220,220,220,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(220,220,220,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: stats.goal_targets
        },
        {
            label: "Potential Indicators",
            fillColor: "rgba(151,187,205,0.5)",
            strokeColor: "rgba(151,187,205,0.8)",
            highlightFill: "rgba(151,187,205,0.75)",
            highlightStroke: "rgba(151,187,205,1)",
            data: stats.goal_indicators
        }
    ]
 };
 var options = {
    barStrokeWidth : 2
 };
 var anchor=document.getElementById("dashboard-content");
 var wrapper = document.createElement("div");
 var title = document.createElement("h3");
 title.innerHTML = "Indicator candidates and Targets per Goal";
 var canvas = document.createElement("canvas");
 canvas.setAttribute("id", "barplot");
 canvas.setAttribute("class", "barplot");
 anchor.appendChild(wrapper).appendChild(title);
 anchor.appendChild(wrapper).appendChild(canvas);
 var ctx= canvas.getContext("2d");
 Chart.defaults.global.multiTooltipTemplate = "<%= value %> <%= datasetLabel %> ";
 var myBarChart = new Chart(ctx).Bar(data, options);
}

function count_match_leads(dictionary,regex){
 //Given a dictionary, return the sum of the values whose
 //keys match the string
 var count = 0;
 for (var key in dictionary){
   regex.test(key)? count+=dictionary[key]: null;
 }
 return count;
}

function add_leads_pie(){
 // Add leads pie. Leads normalized by indicator

 //count leads
 var leads = {total:0};
 for (var j in sdgs.indicators.indicators){
  var ileads = sdgs.indicators.indicators[j].leads.split(",");
   for (var jj in ileads){
    var lead=ileads[jj].trim().replace('""',"");
    leads[lead] ? leads[lead]++ : leads[lead]=1;
    leads["total"]++;
   }
  }
 var data = [
    {
        value: count_match_leads(leads,/UN/),
        color:"#F7464A",
        highlight: "#FF5A5E",
        label: "UN bodies"
    },
    {
        value: count_match_leads(leads,/WB|World Bank/),
        color: "#46BFBD",
        highlight: "#5AD3D1",
        label: "World Bank Group"
    },
    {
        value: count_match_leads(leads,/OECD/),
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "OECD"
    },
    {
        value: leads["total"]-
               count_match_leads(leads,/OECD|WB|UN|World Bank/)
               -leads[""],
        color: "#FF245C",
        highlight: "#FF245A",
        label: "Others"
    },
    {
        value: leads[""],
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "Unclear"
    }
];
 var options = [];
 var anchor=document.getElementById("dashboard-content");
 var wrapper = document.createElement("div");
 var title = document.createElement("h3");
 title.innerHTML = "Leads per Indicator";
 var canvas = document.createElement("canvas");
 canvas.setAttribute("id", "leadpie");
 canvas.setAttribute("class", "pie");
 anchor.appendChild(wrapper).appendChild(title);
 anchor.appendChild(wrapper).appendChild(canvas);
 var ctx= canvas.getContext("2d");
 var myPieChart = new Chart(ctx).Pie(data,options);
}

function empty_dashboard(){
  document.getElementById("dashboard-title").innerHTML = "";
  document.getElementById("dashboard-content").innerHTML = "";
  $('li.active').removeClass("active");
  $('#Visualizations').removeClass("btn-primary");
}

function list_goals(){
  updateURLParameters("list_goals");
  empty_dashboard();
  $('#goals').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Goals";
  var sdgList = document.getElementById("dashboard-content");
  var goals=sdgs.goals.goals;
  for (var i in goals){
    var goal= goals[i];
    append('li',sdgList,"goal-"+goal.goal,"",goal.goal+": "+goal.title+".");
  }
}

function list_indicators(){
  updateURLParameters("list_indicators");
  empty_dashboard();
  $('#indicators').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Indicators Candidates";
  var sdgList = document.getElementById("dashboard-content");
  var indicators=sdgs.indicators.indicators;
  for (var i in indicators){
    var indicator= indicators[i];
    append('li',sdgList,"goal-"+indicator.indicator,"indicator",indicator.indicator+": "+indicator.indicator+".");
  }
}

function list_targets(){
  updateURLParameters("list_targets");
  empty_dashboard();
  $('#targets').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Targets";
  var sdgList = document.getElementById("dashboard-content");
  var targets=sdgs.targets.targets;
  for (var i in targets){
    var target= targets[i];
    append('li',sdgList,"goal-"+target.target,"",target.id+": "+target.title+".");
  }
}

function add_goals(){
  $('#load-all').addClass("active");
  document.getElementById("dashboard-title").innerHTML = "SDG Goals";
  var sdgList = document.getElementById("dashboard-content");
  var goals=sdgs.goals.goals;
  for (var i in goals){
    var goal= goals[i];
    append('li',sdgList,"goal-"+goal.goal,"h2",goal.goal+": "+goal.title+".");
  }
}

function add_targets(){
  var targets=sdgs.targets.targets;
  for (var i in targets){
    var target=targets[i];
    var goalLi = document.getElementById("goal-"+target.goal);
    var targetId="goal-"+target.goal+"-targets";
    if ( document.getElementById(targetId) === null) {
      var nestedOl = document.createElement("ul");
      nestedOl.setAttribute("id", targetId);
      goalLi.appendChild(nestedOl);
    }
    var goalLiUl = document.getElementById(targetId);
    append('li',goalLiUl,"target-"+target.id,"target",target.id+": "+target.title);
  }
}

function add_indicators(){
  var indicators=sdgs.indicators.indicators;
  for (var i in indicators){
    var indicator=indicators[i];
    var goalLi = document.getElementById("goal-"+indicator.goal);
    var indicatorsId="goal-"+indicator.goal+"-indicators";
    if (document.getElementById(indicatorsId) === null) {
      var responsiveTable = document.createElement("div");
      responsiveTable.setAttribute("class","table-responsive");
      var nestedTable = document.createElement("table");
      nestedTable.setAttribute("class","table table-striped table-bordered");
      var header = nestedTable.createTHead();
      var rowObject = header.insertRow(0);
      var columns=["Candidate Indicator","Category","Leads","Available"];
      for (var ii in columns ){
          var th = document.createElement('th');
          th.innerHTML = columns[ii];
          rowObject.appendChild(th);
      }
      var body = nestedTable.createTBody();
      body.setAttribute("id", indicatorsId);
      body.setAttribute("class", "indicator");
      goalLi.appendChild(responsiveTable).appendChild(nestedTable);
     }else{
      append_row(indicatorsId,[indicator.indicator,indicator.category,indicator.leads,indicator.available]);
    }
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Tom Steele, Jason Doyle
// See the file license.txt for copying permission
var async = require('async');
var dns = require('dns');
var tls = require('tls');
var https = require('https');
var http = require('http');
var url = require('url');

//
// dictionary based lookup
//
exports.dictionary = function(domain, names, concurrency, callback) {
  var results = [];
  var q = async.queue(function (lookup, queueCallback) {
    lookup = lookup + '.' + domain;
    dns.resolve4(lookup, function (err, addresses) {
      if (err) {
       queueCallback();
      }
      else {
        results.push( { ip: addresses[0],
                        name:  lookup,
                        src: 'dictionary'
                       }
                     );
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(names);
};

//
// reverse ip lookup
//
exports.reverse = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    dns.reverse(host, function (err, domains) {
      if (err) {
        queueCallback();
      }
      else {
        domains.forEach(function(domain) {
          results.push( { ip: host,
                          name: domain,
                          src: 'reverse'
                         });
        });
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// grabs hostnames from ssl certificates
//
exports.cert = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    options = {
      host: host,
      port: 443,
      rejectUnauthorized: false
    };
    var cleartextStream = tls.connect(options, function () {
      var cert = cleartextStream.getPeerCertificate();
      var cn = cert['subject']['CN'];
      if (typeof cn == 'string' && cn.match(/[a-z]+/i)) {
        results.push( { ip: host,
                        name: cn,
                        src: 'cert'
                      });
      }
      if (cert['subjectaltname']) {
        var sns = cert['subjectaltname'].split(',');
        sns.forEach(function(sn) {
          sn = sn.substr(sn.indexOf(':') + 1);
          results.push( { ip: host,
                          name: sn,
                          src: 'cert'
                        });
        });
      }
     queueCallback();
    });
    cleartextStream.on('error', queueCallback);
    cleartextStream.on('data', queueCallback);
    cleartextStream.on('end', queueCallback);
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// query bing for vhosts using api
//
exports.bingApi = function(hosts, concurrency, options, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    bingQuery(0);

    function bingQuery(offset) {
      var message = '';
      var count = 50;
      var params = '?Query=%27ip:' + host + '%27' +
                   '&$top=' + count +
                   '&$skip=' + offset +
                   '&Adult=%27Off%27&$format=json';
      options.path = options.path.replace(/\?.*/, params);
      var req = https.request(options, function(res) {
        res.on('data', function(chunk) {
          message += chunk;
        });

        res.on('end', function() {
          var urls = JSON.parse(message).d.results;
          urls.forEach(function(element) {
              results.push({ ip: host,
                             name: url.parse(element.Url)['hostname'],
                             src: 'bing-api'
                           });
          });
          if (urls.length == count) {
            bingQuery(offset += count);
          }
          else {
            queueCallback();
          }
        });
      });
      req.end();
      req.on('error', function() {
        queueCallback();
      });
    }
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// query bing for vhosts without api key
//
exports.bing = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    var offset = 0;
    var message = '';
    var params = '?q=ip:' + host +
                 '&first=' + offset;
    var options = { hostname: 'www.bing.com',
                    path: '/search' + params };
    var req = http.request(options, function(res) {
      res.on('data', function(chunk) {
        message += chunk;
      });

      res.on('end', function() {
        var urls = message.match(/\">.*?<\/cite>/gm);
        if (urls) {
          urls.forEach(function(u) {
            u = u.match(/cite>(.*?)</i);
            if (u) {
              if (u[1].search('//')) {
                u[1] = 'http://'.concat(u[1]); // make url.parse happy
              }
              results.push({ ip: host,
                             name: url.parse(u[1])['hostname'],
                             src: 'bing'
                           });
            }
          });
        }
        queueCallback();
      });
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// grab name records from robtex.com one c-network at a time
//
exports.robtex = function(hosts, concurrency, callback) {
  var cNetworks = []; // unique C-networks
  for (var i = 0; i < hosts.length; i++) {
    var dup = false;
    var cnet = hosts[i].split(".", 3).join(".");
    for (var c = 0; c < cNetworks.length; c++) {
      if (cnet == cNetworks[c]) {
        dup = true;
        break;
      }
    }
    if (dup) {
      break;
    }
    cNetworks.push(cnet);
  }
  var results = [];
  var q = async.queue(function (cnet, queueCallback) {
    var message = '';
    var options = {
      hostname: 'cnet.robtex.com',
      path: '/' + cnet + '.html'
    };
    var req = http.request(options, function(res) {
      var prevIp = '';
      res.on('data', function(chunk) {
        message += chunk;
      });
      res.on('end', function() {
        var htmlRows = message.match(/
[\w\W]*?<\/tr>/mg);
        if (htmlRows) {
          htmlRows.forEach(function(row) {
            var ipMatch = row.match(/ip\.robtex\.com\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\./);
            if (ipMatch) {
              var ipaddr = ipMatch[1];
              hosts.forEach(function(h) {
                if (ipaddr === h) {
                  var hn = row.match(/>([a-z0-9-\.]{2,}[a-z])<\/a>/i);
                  if (hn) {
                    results.push({ip: ipaddr, name: hn[1], src: 'robtex'});
                  }
                }
              });
              prevIp = ipaddr;
            } else {
              var dnsMatch = row.match(/<a href="\/dns\/([a-z0-9-\.]{2,}[a-z]).html"/i);
              if (dnsMatch) {
                var hn = dnsMatch[1];
                hosts.forEach(function(h) {
                  if (prevIp === h) {
                    if (hn) {
                      results.push({ip: prevIp, name: hn, src: 'robtex'});
                    }
                  }
                });
              }
            }
          });
        }
        queueCallback();
      });
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });
  }, concurrency);
  q.drain = function () { callback(results) };
  q.push(cNetworks);
};

//
// parse http and https response headers
//
exports.headers = function(hosts, concurrency, callback) {
  var tasks = [];
  var results = [];

  function doRequest(host, proto, queueCallback) {
    if (proto === 'http') {
      var req = http.request({'host': host}, reqCallback);
    }
    else if (proto === 'https') {
      var options = {'host': host, rejectUnauthorized: false}
      var req = https.request(options, reqCallback);
    }
    req.setTimeout(2000, function() {
      queueCallback();
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });

    function reqCallback(res) {
      res.on('end', function() {
        if (res.headers.location) {
          var lName = url.parse(res.headers.location)['hostname'];
          if (lName && lName.match(/[a-z]+/i)) {
            results.push( { ip: host,
                            name: lName,
                            src: proto + '-location'
                          });
          }
        }
        if (res.headers['set-cookie']) {
          var cookies = res.headers['set-cookie'];
          cookies.forEach(function(c) {
            var cName = '';
            if (c.match(/BIGipServerPool/i)) {
              cName = c.substring(16).match(/[a-z][a-z\-]*\.[\.\-a-z]*/i);
            }
            else if (c.match(/BIGipServer/i)) {
              cName = c.substring(11).match(/[a-z][a-z\-]*\.[\.\-a-z]*/i);
            }
            if (cName) {
              results.push( { ip: host,
                              name: cName[0],
                              src: proto + '-BIGip'
                            });
            }
          });
        }
        queueCallback();
      });
    }
  }

  hosts.forEach(function(host) {
    tasks.push(function(taskCallback) {
      doRequest(host, 'https', function() {
        taskCallback(results);
      });
    });
    tasks.push(function(taskCallback) {
      doRequest(host, 'http', function(results) {
        taskCallback();
      });
    });
  });
  //TODO use parallelLimit() to include concurrency
  async.parallel(tasks, function(results) {
    callback(results);
  });
}

//
// Only return results that pass FCrDNS
//
exports.fcrdns = function(results, concurrency, callback) {
  var cleanResults = [];
  var q = async.queue(function (record, queueCallback) {
    dns.resolve4(record.name, function (err, addresses) {
      if (err) {
        queueCallback();
      }
      else {
        addresses.forEach(function(addr) {
          cleanResults.push( { ip: addr,
                               name: record.name,
                               src: record.src
                             });
        });
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function () { callback(cleanResults) };
  q.push(results);
};
<commit_msg>adding timeout for ssl cert<commit_after>// Copyright (c) 2012 Tom Steele, Jason Doyle
// See the file license.txt for copying permission
var async = require('async');
var dns = require('dns');
var tls = require('tls');
var https = require('https');
var http = require('http');
var url = require('url');

//
// dictionary based lookup
//
exports.dictionary = function(domain, names, concurrency, callback) {
  var results = [];
  var q = async.queue(function (lookup, queueCallback) {
    lookup = lookup + '.' + domain;
    dns.resolve4(lookup, function (err, addresses) {
      if (err) {
       queueCallback();
      }
      else {
        results.push( { ip: addresses[0],
                        name:  lookup,
                        src: 'dictionary'
                       }
                     );
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(names);
};

//
// reverse ip lookup
//
exports.reverse = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    dns.reverse(host, function (err, domains) {
      if (err) {
        queueCallback();
      }
      else {
        domains.forEach(function(domain) {
          results.push( { ip: host,
                          name: domain,
                          src: 'reverse'
                         });
        });
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// grabs hostnames from ssl certificates
//
exports.cert = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    options = {
      host: host,
      port: 443,
      rejectUnauthorized: false
    };
    var cleartextStream = tls.connect(options, function () {
      var cert = cleartextStream.getPeerCertificate();
      var cn = cert['subject']['CN'];
      if (typeof cn == 'string' && cn.match(/[a-z]+/i)) {
        results.push( { ip: host,
                        name: cn,
                        src: 'cert'
                      });
      }
      if (cert['subjectaltname']) {
        var sns = cert['subjectaltname'].split(',');
        sns.forEach(function(sn) {
          sn = sn.substr(sn.indexOf(':') + 1);
          results.push( { ip: host,
                          name: sn,
                          src: 'cert'
                        });
        });
      }
     queueCallback();
    });
    cleartextStream.setTimeout(2000, function() { queueCallback(); });
    cleartextStream.on('error', queueCallback);
    cleartextStream.on('data', queueCallback);
    cleartextStream.on('end', queueCallback);
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// query bing for vhosts using api
//
exports.bingApi = function(hosts, concurrency, options, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    bingQuery(0);

    function bingQuery(offset) {
      var message = '';
      var count = 50;
      var params = '?Query=%27ip:' + host + '%27' +
                   '&$top=' + count +
                   '&$skip=' + offset +
                   '&Adult=%27Off%27&$format=json';
      options.path = options.path.replace(/\?.*/, params);
      var req = https.request(options, function(res) {
        res.on('data', function(chunk) {
          message += chunk;
        });

        res.on('end', function() {
          var urls = JSON.parse(message).d.results;
          urls.forEach(function(element) {
              results.push({ ip: host,
                             name: url.parse(element.Url)['hostname'],
                             src: 'bing-api'
                           });
          });
          if (urls.length == count) {
            bingQuery(offset += count);
          }
          else {
            queueCallback();
          }
        });
      });
      req.end();
      req.on('error', function() {
        queueCallback();
      });
    }
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// query bing for vhosts without api key
//
exports.bing = function(hosts, concurrency, callback) {
  var results = [];
  var q = async.queue(function (host, queueCallback) {
    var offset = 0;
    var message = '';
    var params = '?q=ip:' + host +
                 '&first=' + offset;
    var options = { hostname: 'www.bing.com',
                    path: '/search' + params };
    var req = http.request(options, function(res) {
      res.on('data', function(chunk) {
        message += chunk;
      });

      res.on('end', function() {
        var urls = message.match(/\">.*?<\/cite>/gm);
        if (urls) {
          urls.forEach(function(u) {
            u = u.match(/cite>(.*?)</i);
            if (u) {
              if (u[1].search('//')) {
                u[1] = 'http://'.concat(u[1]); // make url.parse happy
              }
              results.push({ ip: host,
                             name: url.parse(u[1])['hostname'],
                             src: 'bing'
                           });
            }
          });
        }
        queueCallback();
      });
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });
  }, concurrency);
  q.drain = function() { callback(results) };
  q.push(hosts);
};

//
// grab name records from robtex.com one c-network at a time
//
exports.robtex = function(hosts, concurrency, callback) {
  var cNetworks = []; // unique C-networks
  for (var i = 0; i < hosts.length; i++) {
    var dup = false;
    var cnet = hosts[i].split(".", 3).join(".");
    for (var c = 0; c < cNetworks.length; c++) {
      if (cnet == cNetworks[c]) {
        dup = true;
        break;
      }
    }
    if (dup) {
      break;
    }
    cNetworks.push(cnet);
  }
  var results = [];
  var q = async.queue(function (cnet, queueCallback) {
    var message = '';
    var options = {
      hostname: 'cnet.robtex.com',
      path: '/' + cnet + '.html'
    };
    var req = http.request(options, function(res) {
      var prevIp = '';
      res.on('data', function(chunk) {
        message += chunk;
      });
      res.on('end', function() {
        var htmlRows = message.match(/
[\w\W]*?<\/tr>/mg);
        if (htmlRows) {
          htmlRows.forEach(function(row) {
            var ipMatch = row.match(/ip\.robtex\.com\/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\./);
            if (ipMatch) {
              var ipaddr = ipMatch[1];
              hosts.forEach(function(h) {
                if (ipaddr === h) {
                  var hn = row.match(/>([a-z0-9-\.]{2,}[a-z])<\/a>/i);
                  if (hn) {
                    results.push({ip: ipaddr, name: hn[1], src: 'robtex'});
                  }
                }
              });
              prevIp = ipaddr;
            } else {
              var dnsMatch = row.match(/<a href="\/dns\/([a-z0-9-\.]{2,}[a-z]).html"/i);
              if (dnsMatch) {
                var hn = dnsMatch[1];
                hosts.forEach(function(h) {
                  if (prevIp === h) {
                    if (hn) {
                      results.push({ip: prevIp, name: hn, src: 'robtex'});
                    }
                  }
                });
              }
            }
          });
        }
        queueCallback();
      });
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });
  }, concurrency);
  q.drain = function () { callback(results) };
  q.push(cNetworks);
};

//
// parse http and https response headers
//
exports.headers = function(hosts, concurrency, callback) {
  var tasks = [];
  var results = [];

  function doRequest(host, proto, queueCallback) {
    if (proto === 'http') {
      var req = http.request({'host': host}, reqCallback);
    }
    else if (proto === 'https') {
      var options = {'host': host, rejectUnauthorized: false}
      var req = https.request(options, reqCallback);
    }
    req.setTimeout(2000, function() {
      queueCallback();
    });
    req.end();
    req.on('error', function() {
      queueCallback();
    });

    function reqCallback(res) {
      res.on('end', function() {
        if (res.headers.location) {
          var lName = url.parse(res.headers.location)['hostname'];
          if (lName && lName.match(/[a-z]+/i)) {
            results.push( { ip: host,
                            name: lName,
                            src: proto + '-location'
                          });
          }
        }
        if (res.headers['set-cookie']) {
          var cookies = res.headers['set-cookie'];
          cookies.forEach(function(c) {
            var cName = '';
            if (c.match(/BIGipServerPool/i)) {
              cName = c.substring(16).match(/[a-z][a-z\-]*\.[\.\-a-z]*/i);
            }
            else if (c.match(/BIGipServer/i)) {
              cName = c.substring(11).match(/[a-z][a-z\-]*\.[\.\-a-z]*/i);
            }
            if (cName) {
              results.push( { ip: host,
                              name: cName[0],
                              src: proto + '-BIGip'
                            });
            }
          });
        }
        queueCallback();
      });
    }
  }

  hosts.forEach(function(host) {
    tasks.push(function(taskCallback) {
      doRequest(host, 'https', function() {
        taskCallback(results);
      });
    });
    tasks.push(function(taskCallback) {
      doRequest(host, 'http', function(results) {
        taskCallback();
      });
    });
  });
  //TODO use parallelLimit() to include concurrency
  async.parallel(tasks, function(results) {
    callback(results);
  });
}

//
// Only return results that pass FCrDNS
//
exports.fcrdns = function(results, concurrency, callback) {
  var cleanResults = [];
  var q = async.queue(function (record, queueCallback) {
    dns.resolve4(record.name, function (err, addresses) {
      if (err) {
        queueCallback();
      }
      else {
        addresses.forEach(function(addr) {
          cleanResults.push( { ip: addr,
                               name: record.name,
                               src: record.src
                             });
        });
        queueCallback();
      }
    });
  }, concurrency);
  q.drain = function () { callback(cleanResults) };
  q.push(results);
};
<|endoftext|>


<commit_before>import { expect, assert } from 'chai'
import { heightify } from '../src/heightify'

describe('Heightify', () => {
  describe('error messages', () => {
    it('should be ok if element is defined', () => {
      const heightifyWithDOMElement = heightify({
        element: 'div'
      })
      assert.isOk(heightifyWithDOMElement, 'OK' )
    })

    it('should throw if argument is not an object', () => {
      expect(() => {
        heightify('some options')
      }).to.throw('Expected \'some options\' to be an object.')
    })

    it('should throw when element is not defined', () => {
      expect(() => {
        heightify({})
      }).to.throw('Heightify requires a DOM node to match the height with.')
    })

    it('should throw when element is not a string', () => {
      expect(() => {
        heightify({element: ['div']})
      }).to.throw('\'div\' should be a type of string.')
    })
  })
})
<commit_msg>fixed test<commit_after>import { expect, assert } from 'chai'
import { heightify } from '../src/heightify'

describe('Heightify', () => {
  describe('error messages', () => {
    it('should be ok if element is defined', () => {
      const heightifyWithDOMElement = heightify({
        element: 'div'
      })
      assert.isOk(heightifyWithDOMElement, 'OK' )
    })

    it('should throw if argument is not an object', () => {
      expect(() => {
        heightify('some options')
      }).to.throw('Expected a plain object')
    })

    it('should throw when element is not defined', () => {
      expect(() => {
        heightify({})
      }).to.throw('Heightify requires a DOM node to match the height with.')
    })

    it('should throw when element is not a string', () => {
      expect(() => {
        heightify({element: ['div']})
      }).to.throw('\'div\' should be a type of string.')
    })
  })
})
<|endoftext|>


<commit_before>var exec = require('child_process').exec;

exports.checkSshPassExists = function(callback) {
  exec('sshpass -V', function(err, stdout, stderr) {
    if(err) {
      callback(false);
    } else {
      callback(true);
    }
  });
};

exports.printHelp = function() {
  console.error('\nUsage');
  console.error('-------------');
  console.error('mup <action> [--<parameter>]');
  console.error('');
  console.error('\nValid Actions (mandatory)');
  console.error('-------------');
  console.error('init                   - Initialize a Meteor Up project');
  console.error('setup                  - Setup the server');
  console.error('');
  console.error('deploy                 - Deploy app to server');
  console.error('reconfig               - Reconfigure the server and restart');
  console.error('');
  console.error('logs [-f --tail=all]   - Access logs');
  console.error('');
  console.error('start                  - Start your app instances');
  console.error('stop                   - Stop your app instances');
  console.error('restart                - Restart your app instances');
  console.error('\nAvailable Parameters (optional)');
  console.error('-------------');
  console.error('--config=mup-prod.json - Specify the deployment configuration');
  console.error('                         Default value: mup.json');
  console.error('--settings=file.json   - Specify the Meteor.settings file');
  console.error('                         Default value: settings.json');
};
<commit_msg>improve help screen<commit_after>var exec = require('child_process').exec;

exports.checkSshPassExists = function(callback) {
  exec('sshpass -V', function(err, stdout, stderr) {
    if(err) {
      callback(false);
    } else {
      callback(true);
    }
  });
};

exports.printHelp = function() {
  console.error('\nSyntax: mup <action> [--<parameter>]');
  console.error('');
  console.error('\nValid Actions (mandatory)');
  console.error('---------------------------');
  console.error('init                   - Initialize a Meteor Up project');
  console.error('setup                  - Setup the server');
  console.error('');
  console.error('deploy                 - Deploy app to server');
  console.error('reconfig               - Reconfigure the server and restart');
  console.error('');
  console.error('logs [-f --tail=all]   - Access logs');
  console.error('');
  console.error('start                  - Start your app instances');
  console.error('stop                   - Stop your app instances');
  console.error('restart                - Restart your app instances');
  console.error('\nAvailable Parameters (optional)');
  console.error('---------------------------------');
  console.error('--config=mup-prod.json - Specify the deployment configuration');
  console.error('                         Default value: mup.json');
  console.error('--settings=file.json   - Specify the Meteor.settings file');
  console.error('                         Default value: settings.json');
};
<|endoftext|>


<commit_before>'use babel';

/**
 * Copyright (C) 2016 Ivan Kravets. All rights reserved.
 *
 * This source file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

import fs from 'fs';
import path from 'path';
import ini from 'ini';
import {clone} from './utils';

export class PlatformIOBuildProvider {
  constructor(cwd) {
    this.cwd = cwd;
    this.platformioIniPath = path.join(this.cwd, 'platformio.ini');
    this.title = 'PlatformIO';
    this.targetNamePrefix = this.title + ': ';

    this.targetsBaseSettings = [
      {
        name: 'Build',
        args: ['run'],
        keymap: 'ctrl-alt-b',
      },
      {
        name: 'Clean',
        args: ['run', '--target', 'clean'],
        keymap: 'ctrl-alt-c',
      },
      {
        name: 'Upload',
        args: ['run', '--target', 'upload'],
        keymap: 'ctrl-alt-u',
      },
      {
        name: 'Upload using Programmer',
        args: ['run', '--target', 'program'],
      },
      {
        name: 'Upload SPIFFS image',
        args: ['run', '--target', 'uploadfs'],
      }
    ];
  }

  getNiceName() {
    return this.title;
  }

  isEligible() {
    return fs.statSyncNoException(this.platformioIniPath);
  }

  settings() {
    return new Promise((resolve, reject) => {
      fs.readFile(this.platformioIniPath, (err, data) => {
        if (err) reject(err);

        let envs = [];
        const envNamePrefix = 'env:';
        const configSections = Object.keys(ini.parse(data.toString()));
        for (let section of configSections) {
          if (section.indexOf(envNamePrefix) === 0) {
            envs.push(section.slice(envNamePrefix.length));
          }
        }

        let settings = this.prepareSettings(this.targetsBaseSettings);

        if (envs.length > 1) {
          let envsBaseSettings = this.targetsBaseSettings.slice(0, 3);
          for (let env of envs) {
            let envSettings = this.prepareSettings(envsBaseSettings).map((base) => {
              let item = clone(base);
              item.name += ` (env:${env})`;
              item.args.push('--environment');
              item.args.push(env);
              return item;
            });
            settings = settings.concat(envSettings);
          }
        }
        resolve(settings);
      });
    });
  }

  prepareSettings(baseSettings) {
    return baseSettings.map(base => {
      let item = clone(base);
      item.name = this.targetNamePrefix + item.name;
      item.exec = "platformio";
      item.sh = false;
      item.env = process.env;
      item.env.PLATFORMIO_FORCE_COLOR = "true";
      item.errorMatch = [
        "(?<file>src[\\/0-9a-zA-Z\\._\\\\]+):(?<line>\\d+):(?<col>\\d+)"
      ];
      return item;
    });
  }
}
<commit_msg>Do not register a keymap for env-specific build targets<commit_after>'use babel';

/**
 * Copyright (C) 2016 Ivan Kravets. All rights reserved.
 *
 * This source file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

import fs from 'fs';
import path from 'path';
import ini from 'ini';
import {clone} from './utils';

export class PlatformIOBuildProvider {
  constructor(cwd) {
    this.cwd = cwd;
    this.platformioIniPath = path.join(this.cwd, 'platformio.ini');
    this.title = 'PlatformIO';
    this.targetNamePrefix = this.title + ': ';

    this.targetsBaseSettings = [
      {
        name: 'Build',
        args: ['run'],
        keymap: 'ctrl-alt-b',
      },
      {
        name: 'Clean',
        args: ['run', '--target', 'clean'],
        keymap: 'ctrl-alt-c',
      },
      {
        name: 'Upload',
        args: ['run', '--target', 'upload'],
        keymap: 'ctrl-alt-u',
      },
      {
        name: 'Upload using Programmer',
        args: ['run', '--target', 'program'],
      },
      {
        name: 'Upload SPIFFS image',
        args: ['run', '--target', 'uploadfs'],
      }
    ];
  }

  getNiceName() {
    return this.title;
  }

  isEligible() {
    return fs.statSyncNoException(this.platformioIniPath);
  }

  settings() {
    return new Promise((resolve, reject) => {
      fs.readFile(this.platformioIniPath, (err, data) => {
        if (err) reject(err);

        let envs = [];
        const envNamePrefix = 'env:';
        const configSections = Object.keys(ini.parse(data.toString()));
        for (let section of configSections) {
          if (section.indexOf(envNamePrefix) === 0) {
            envs.push(section.slice(envNamePrefix.length));
          }
        }

        let settings = this.prepareSettings(this.targetsBaseSettings);

        if (envs.length > 1) {
          let envsBaseSettings = this.targetsBaseSettings.slice(0, 3);
          for (let env of envs) {
            let envSettings = this.prepareSettings(envsBaseSettings).map((base) => {
              let item = clone(base);
              item.name += ` (env:${env})`;
              item.args.push('--environment');
              item.args.push(env);
              delete item.keymap;
              return item;
            });
            settings = settings.concat(envSettings);
          }
        }
        resolve(settings);
      });
    });
  }

  prepareSettings(baseSettings) {
    return baseSettings.map(base => {
      let item = clone(base);
      item.name = this.targetNamePrefix + item.name;
      item.exec = "platformio";
      item.sh = false;
      item.env = process.env;
      item.env.PLATFORMIO_FORCE_COLOR = "true";
      item.errorMatch = [
        "(?<file>src[\\/0-9a-zA-Z\\._\\\\]+):(?<line>\\d+):(?<col>\\d+)"
      ];
      return item;
    });
  }
}
<|endoftext|>


<commit_before>'use strict';
var exec = require('child_process').exec;
var Promise = require('lie');

// I tried child-process-promise but it failed without errors and I just don't
// have time to fight with it right now.
module.exports.childProcessExecPromise = function(command, currentWorkingDirectory) {
  return new Promise(function (resolve, reject) {
    exec(command, { cwd: currentWorkingDirectory },
      function (error, stdout, stderr) {
        if (error) {
          error.stdout = stdout;
          error.stderr = stderr;

          reject(error);
          return;
        }
        // Log output even if command doesn't exit with an error,
        // because otherwise useful debugging information might get lost.
        if (stdout) { console.log(stdout); }
        if (stderr) { console.log(stderr); }
        resolve();
      });
  });
};
<commit_msg>debug CI<commit_after>'use strict';
var exec = require('child_process').exec;
var Promise = require('lie');

// I tried child-process-promise but it failed without errors and I just don't
// have time to fight with it right now.
module.exports.childProcessExecPromise = function(command, currentWorkingDirectory) {
  return new Promise(function (resolve, reject) {
    exec(command, { cwd: currentWorkingDirectory },
      function (error, stdout, stderr) {
        // TODO: remove the lines below. Only for CI debugging.
        if (stdout) { console.log(stdout); }
        if (stderr) { console.log(stderr); }

        if (error) {
          error.stdout = stdout;
          error.stderr = stderr;

          reject(error);
          return;
        }

        // Log output even if command doesn't exit with an error,
        // because otherwise useful debugging information might get lost.
        if (stdout) { console.log(stdout); }
        if (stderr) { console.log(stderr); }
        resolve();
      });
  });
};
<|endoftext|>


<commit_before>'use strict';

const arrayUtils = require('./array-utils');

class AsyncArray {
  constructor(array) {
    this._promise = Promise.resolve(array);
  }

  then(fn) {
    return this._promise.then(fn);
  }  // eslint-disable-line brace-style
  // (^ probably a bug in ESLint)

  catch(fn) {
    return this._promise.catch(fn);
  }

  map(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.map(array, fn, (err, result) => {
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      });
    });
    return this;
  }

  filter(fn) {
    this._update((array, resolve) => {
      arrayUtils.filter(array, fn, (result) => {
        resolve(result);
      });
    });
    return this;
  }

  reduce(fn, initial) {
    this._update((array, resolve, reject) => {
      arrayUtils.reduce(array, fn, (err, result) => {
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }, initial);
    });
    return this._promise;
  }

  each(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.each(array, fn, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
    return this._promise;
  }

  series(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.series(array, fn, (err) => {
        if (err) {
          reject(err);
        } else {
          resolve();
        }
      });
    });
    return this._promise;
  }

  find(fn) {
    this._update((array, resolve) => {
      arrayUtils.find((array, fn, (result) => {
        resolve(result);
      }));
    });
    return this._promise;
  }

  _update(fn) {
    this._promise = this._promise.then((array) => (
      new Promise((resolve, reject) => {
        fn(array, resolve, reject);
      })
    ));
  }
}

module.exports = AsyncArray;
<commit_msg>Resolver factory<commit_after>'use strict';

const arrayUtils = require('./array-utils');

const resolver = (resolve, reject) => (
  (err, result) => {
    if (err) reject(err);
    else resolve(result);
  }
);

class AsyncArray {

  constructor(array) {
    this._promise = Promise.resolve(array);
  }

  then(fn) {
    const promise = this._promise.then(fn);
    return promise;
  }

  catch(fn) {
    return this._promise.catch(fn);
  }

  map(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.map(array, fn, resolver(resolve, reject));
    });
    return this;
  }

  filter(fn) {
    this._update((array, resolve) => {
      arrayUtils.filter(array, fn, result => resolve(result));
    });
    return this;
  }

  reduce(fn, initial) {
    this._update((array, resolve, reject) => {
      arrayUtils.reduce(array, fn, resolver(resolve, reject), initial);
    });
    return this._promise;
  }

  each(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.each(array, fn, resolver(resolve, reject));
    });
    return this._promise;
  }

  series(fn) {
    this._update((array, resolve, reject) => {
      arrayUtils.series(array, fn, resolver(resolve, reject));
    });
    return this._promise;
  }

  find(fn) {
    this._update((array, resolve) => {
      arrayUtils.find(array, fn, result => resolve(result));
    });
    return this._promise;
  }

  _update(fn) {
    this._promise = this._promise.then((array) => (
      new Promise((resolve, reject) => fn(array, resolve, reject))
    ));
  }

}

module.exports = AsyncArray;
<|endoftext|>


<commit_before>var test = require('tap').test;
var validate = require('./');

test('good inline js', t => {
  var input = '<script>window.foo = \'bar\';</script>';
  var actual = validate(input);
  var expected = null;

  t.deepEqual(actual, expected);
  t.end();
});

test('bad inline js', t => {
  var input = '<script>window.foo = bar bas;</script>';
  var actual = validate(input);

  t.ok(actual instanceof Error);
  t.end();
});
<commit_msg>test is ES5<commit_after>var test = require('tap').test;
var validate = require('./');

test('good inline js', function (t) {
  var input = '<script>window.foo = \'bar\';</script>';
  var actual = validate(input);
  var expected = null;

  t.deepEqual(actual, expected);
  t.end();
});

test('bad inline js', function (t) {
  var input = '<script>window.foo = bar bas;</script>';
  var actual = validate(input);

  t.ok(actual instanceof Error);
  t.end();
});
<|endoftext|>


<commit_before>const { test, tearDown } = require('tap')
const nock = require('nock')
const proxyquire = require('proxyquire')

const dbs = require('../../lib/dbs')

test('open-issue', async t => {
  t.plan(29)
  const { repositories } = await dbs()

  await repositories.put({
    _id: '42',
    packages: {
      'package.json': {
        greenkeeper: {
          branchPrefix: 'prefix-',
          label: 'customlabel'
        }
      }
    }
  })

  const openIssue = proxyquire('../../lib/open-issue', {
    './create-branch': (
      { installationId, owner, repo, branch, newBranch, path, message, transform }
    ) => {
      t.ok(installationId, 'create-branch installationId')
      t.is(owner, 'finnp', 'create-branch owner')
      t.is(repo, 'testrepo', 'create-branch repo')
      t.is(branch, 'master', 'create-branch branch')
      t.is(newBranch, 'prefix-standard-pin-1.4.0', 'create-branch newBranch')
      t.is(path, 'package.json', 'create-branch path')
      t.ok(message, 'create-branch message')
      const change = transform(
        JSON.stringify({
          devDependencies: {
            standard: '~2.0.0'
          }
        })
      )
      t.is(
        change,
        JSON.stringify({
          devDependencies: {
            standard: '1.4.0'
          }
        }),
        'pinned standard to 1.4.0'
      )

      return { sha: 'deadbeef' }
    }
  })

  nock('https://api.github.com')
    .post('/installations/123/access_tokens')
    .reply(200, {
      token: 'secret'
    })
    .get('/rate_limit')
    .reply(200, {})
    .post('/repos/finnp/testrepo/issues', ({ title, body, labels }) => {
      t.ok(title, 'github issue has title')
      t.same(labels, ['customlabel'], 'github issue correct label')
      t.ok(body, 'github issue has body')
      return true
    })
    .reply(201, () => {
      t.pass('issue created')
      return {
        number: 10
      }
    })

  await openIssue({
    installationId: '123',
    repositoryId: '42',
    accountId: '1010',
    owner: 'finnp',
    repo: 'testrepo',
    version: '2.0.0',
    dependency: 'standard',
    dependencyType: 'devDependencies',
    oldVersionResolved: '1.4.0',
    base: 'master',
    head: 'greenkeeper-standard-2.0.0',
    dependencyLink: 'somelink',
    release: 'therelease',
    diffCommits: 'thecommits',
    statuses: []
  })

  const branch = await repositories.get('42:branch:deadbeef')
  t.is(branch.type, 'branch', 'branch type')
  t.is(branch.purpose, 'pin', 'branch purpose pin')
  t.is(branch.sha, 'deadbeef', 'branch sha')
  t.is(branch.head, 'prefix-standard-pin-1.4.0', 'branch head')
  t.is(branch.base, 'master', 'branch master')
  t.is(branch.dependency, 'standard', 'branch dependency')
  t.is(branch.dependencyType, 'devDependencies', 'branch dependencyType')
  t.is(branch.version, '1.4.0', 'branch version')
  t.is(branch.repositoryId, '42', 'branch repositoryId')
  t.is(branch.accountId, '1010', 'branch accountId')
  t.ok(branch.updatedAt, 'branch updatedAt')
  const issue = await repositories.get('42:issue:10')
  t.is(issue.type, 'issue', 'issue type')
  t.is(issue.version, '2.0.0', 'issue version')
  t.is(issue.number, 10, 'issue number')
  t.is(issue.dependency, 'standard', 'issue dependency')
  t.is(issue.state, 'open', 'issue state')
  t.is(issue.repositoryId, '42', 'issue repositoryId')
})

tearDown(async () => {
  const { repositories } = await dbs()

  await Promise.all([
    repositories.remove(await repositories.get('42')),
    repositories.remove(await repositories.get('42:branch:deadbeef')),
    repositories.remove(await repositories.get('42:issue:10'))
  ])
})
<commit_msg>test(open-issue): modify test to use correct api<commit_after>const { test, tearDown } = require('tap')
const nock = require('nock')
const proxyquire = require('proxyquire')

const dbs = require('../../lib/dbs')

test('open-issue', async t => {
  t.plan(29)
  const { repositories } = await dbs()

  await repositories.put({
    _id: '42',
    packages: {
      'package.json': {
        greenkeeper: {
          branchPrefix: 'prefix-',
          label: 'customlabel'
        }
      }
    }
  })

  const openIssue = proxyquire('../../lib/open-issue', {
    './create-branch': (
      { installationId, owner, repo, branch, newBranch, path, message, transform }
    ) => {
      t.ok(installationId, 'create-branch installationId')
      t.is(owner, 'finnp', 'create-branch owner')
      t.is(repo, 'testrepo', 'create-branch repo')
      t.is(branch, 'master', 'create-branch branch')
      t.is(newBranch, 'prefix-standard-pin-1.4.0', 'create-branch newBranch')
      t.is(path, 'package.json', 'create-branch path')
      t.ok(message, 'create-branch message')
      const change = transform(
        JSON.stringify({
          devDependencies: {
            standard: '~2.0.0'
          }
        })
      )
      t.is(
        change,
        JSON.stringify({
          devDependencies: {
            standard: '1.4.0'
          }
        }),
        'pinned standard to 1.4.0'
      )

      return 'deadbeef'
    }
  })

  nock('https://api.github.com')
    .post('/installations/123/access_tokens')
    .reply(200, {
      token: 'secret'
    })
    .get('/rate_limit')
    .reply(200, {})
    .post('/repos/finnp/testrepo/issues', ({ title, body, labels }) => {
      t.ok(title, 'github issue has title')
      t.same(labels, ['customlabel'], 'github issue correct label')
      t.ok(body, 'github issue has body')
      return true
    })
    .reply(201, () => {
      t.pass('issue created')
      return {
        number: 10
      }
    })

  await openIssue({
    installationId: '123',
    repositoryId: '42',
    accountId: '1010',
    owner: 'finnp',
    repo: 'testrepo',
    version: '2.0.0',
    dependency: 'standard',
    dependencyType: 'devDependencies',
    oldVersionResolved: '1.4.0',
    base: 'master',
    head: 'greenkeeper-standard-2.0.0',
    dependencyLink: 'somelink',
    release: 'therelease',
    diffCommits: 'thecommits',
    statuses: []
  })

  const branch = await repositories.get('42:branch:deadbeef')
  t.is(branch.type, 'branch', 'branch type')
  t.is(branch.purpose, 'pin', 'branch purpose pin')
  t.is(branch.sha, 'deadbeef', 'branch sha')
  t.is(branch.head, 'prefix-standard-pin-1.4.0', 'branch head')
  t.is(branch.base, 'master', 'branch master')
  t.is(branch.dependency, 'standard', 'branch dependency')
  t.is(branch.dependencyType, 'devDependencies', 'branch dependencyType')
  t.is(branch.version, '1.4.0', 'branch version')
  t.is(branch.repositoryId, '42', 'branch repositoryId')
  t.is(branch.accountId, '1010', 'branch accountId')
  t.ok(branch.updatedAt, 'branch updatedAt')
  const issue = await repositories.get('42:issue:10')
  t.is(issue.type, 'issue', 'issue type')
  t.is(issue.version, '2.0.0', 'issue version')
  t.is(issue.number, 10, 'issue number')
  t.is(issue.dependency, 'standard', 'issue dependency')
  t.is(issue.state, 'open', 'issue state')
  t.is(issue.repositoryId, '42', 'issue repositoryId')
})

tearDown(async () => {
  const { repositories } = await dbs()

  await Promise.all([
    repositories.remove(await repositories.get('42')),
    repositories.remove(await repositories.get('42:branch:deadbeef')),
    repositories.remove(await repositories.get('42:issue:10'))
  ])
})
<|endoftext|>