<commit_before>
module.exports = readJson
readJson.processJson = processJson
readJson.unParsePeople = unParsePeople
readJson.parsePeople = parsePeople

var fs = require("./graceful-fs")
  , semver = require("semver")
  , path = require("path")
  , log = require("./log")
  , npm = require("../../npm")
  , cache = {}
  , timers = {}
  , loadPackageDefaults = require("./load-package-defaults")

function readJson (jsonFile, opts, cb) {
  if (typeof cb !== "function") cb = opts, opts = {}
  if (cache.hasOwnProperty(jsonFile)) {
    log.verbose(jsonFile, "from cache")
    return cb(null, cache[jsonFile])
  }
  opts.file = jsonFile
  if (!opts.tag) {
    var parsedPath = jsonFile.indexOf(npm.dir) === 0 && jsonFile.match(
      /\/([^\/]+)\/([^\/]+)\/package\/package\.json$/)
    if (parsedPath && semver.valid(parsedPath[2])) {
      // this is a package.json in some installed package.
      // infer the opts.tag so that linked packages behave right.
      opts.tag = parsedPath[2]
    }
  }

  fs.readFile( path.join(path.dirname(jsonFile), "wscript")
             , function (er, data) {
    if (er) opts.wscript = false
    else opts.wscript = data.toString().match(/(^|\n)def build\b/)
                      && data.toString().match(/(^|\n)def configure\b/)
    fs.readFile(jsonFile, processJson(opts, function (er, data) {
      if (er) return cb(er)
      var doLoad = !(jsonFile.indexOf(npm.cache) === 0 &&
                     path.basename(path.dirname(jsonFile)) !== "package")
      if (!doLoad) return cb(er, data)
      loadPackageDefaults(data, path.dirname(jsonFile), cb)
    }))
  })
}
function processJson (opts, cb) {
  if (typeof cb !== "function") cb = opts, opts = {}
  if (typeof cb !== "function") {
    var thing = cb, cb = null
    return P(null, thing)
  } else return P

  function P (er, thing) {
    if (er) {
      if (cb) return cb(er, thing)
      throw er
    }
    if (typeof thing === "object" && !Buffer.isBuffer(thing)) {
      return processObject(opts, cb)(er, thing)
    } else {
      return processJsonString(opts, cb)(er, thing)
    }
  }
}
function processJsonString (opts, cb) { return function (er, jsonString) {
  jsonString += ""
  if (er) return cb(er, jsonString)
  var json
  try {
    json = JSON.parse(jsonString)
  } catch (ex) {
    if (opts.file && opts.file.indexOf(npm.dir) === 0) {
      try {
        json = require("vm").runInNewContext("(\n"+jsonString+"\n)")
        log.error(ex, "parse error "+opts.file)
      } catch (ex2) {
        return jsonParseFail(ex, cb)
      }
    } else {
      return jsonParseFail(ex, cb)
    }
  }
  return processObject(opts, cb)(er, json)
}}

function jsonParseFail (ex, cb) {
  var e = new Error(
    "Failed to parse json\n"+ex.message)
  e.errno = npm.EJSONPARSE
  if (cb) return cb(e)
  throw e
}

function processObject (opts, cb) { return function (er, json) {

  // slashes would be a security risk.
  // anything else will just fail harmlessly.
  if (!json.name) {
    var e = new Error("No 'name' field found in package.json")
    if (cb) return cb(e)
    throw e
  }
  json.name = json.name.trim()
  if (json.name.charAt(0) === "." || json.name.match(/[\/@\s\+%:]/)) {
    var msg = "Invalid name: "
            + JSON.stringify(json.name)
            + " may not start with '.' or contain %/@+: or whitespace"
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }
  if (json.name.toLowerCase() === "node_modules") {
    var msg = "Invalid package name: node_modules"
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }
  if (json.name.toLowerCase() === "favicon.ico") {
    var msg = "Sorry, favicon.ico is a picture, not a package."
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }

  if (json.repostories) {
    var msg = "'repositories' (plural) No longer supported.\n"
            + "Please pick one, and put it in the 'repository' field."
      , e = new Error(msg)
    // uncomment once this is no longer an issue.
    // if (cb) return cb(e)
    // throw e
    log.error(msg, "incorrect json")
    json.repostory = json.repositories[0]
    delete json.repositories
  }

  if (json.repository) {
    if (typeof json.repository === "string") {
      json.repository = { type : "git"
                        , url : json.repository }
    }
    var repo = json.repository.url || ""
    repo = repo.replace(/^(https?|git):\/\/[^\@]+\@github.com/
                       ,'$1://github.com')
    if (json.repository.type === "git"
        && ( repo.match(/^https?:\/\/github.com/)
          || repo.match(/github.com\/[^\/]+\/[^\/]+\/?$/)
             && !repo.match(/\.git$/)
        )) {
      repo = repo.replace(/^https?:\/\/github.com/, 'git://github.com')
      if (!repo.match(/\.git$/)) {
        repo = repo.replace(/\/?$/, '.git')
      }
    }
    if (repo.match(/github\.com\/[^\/]+\/[^\/]+\/?$/)
        && repo.match(/\.git\.git$/)) {
      log.warn(repo, "Probably broken git url")
    }
    json.repository.url = repo
  }

  var tag = opts.tag
  if (tag) json.version = tag//+"-"+json.version

  if (json.modules) {
    if (typeof json.modules !== "object") {
      var e = new Error("Invalid modules object")
      if (cb) return cb(e)
      throw e
    }
    Object.keys(json.modules).forEach(function (mod) {
      if (typeof json.modules[mod] !== "string") {
        var e = new Error("Invalid module "+mod+", not a string: "
                         +JSON.stringify(json.modules[mod]))
        if (cb) return cb(e)
        throw e
      }
    })
  }

  if (opts.wscript) {
    var scripts = json.scripts = json.scripts || {}
    if (!scripts.install && !scripts.preinstall) {
      // don't fail if it was unexpected, just try.
      scripts.preinstall = "node-waf clean || true; node-waf configure build"
    }
  }

  if (!(semver.valid(json.version))) {
    var e = new Error("Invalid version: "+json.version+"\n"
                     +"Must be X.Y.Z, with an optional trailing tag.\n"
                     +"See the section on 'version' in `npm help json`")
    if (cb) return cb(e)
    throw e
  }
  json.version = semver.clean(json.version)

  if (json.bin && typeof json.bin === "string") {
    var b = {}
    b[ path.basename( json.bin ) ] = json.bin
    json.bin = b
  }

  if (json["dev-dependencies"] && !json.devDependencies) {
    json.devDependencies = json["dev-dependencies"]
    delete json["dev-dependencies"]
  }
  ;["dependencies", "devDependencies"].forEach(function (d) {
    if (!json[d]) return
    json[d] = depObjectify(json[d])
  })

  json._id = json.name+"@"+json.version
  json = testEngine(json)
  json = parsePeople(unParsePeople(json))
  if ( json.bugs ) json.bugs = parsePerson(unParsePerson(json.bugs))
  json._npmVersion = npm.version
  json._nodeVersion = process.version
  if (opts.file) {
    log.verbose(opts.file, "caching")
    cache[opts.file] = json
    // arbitrary
    var keys = Object.keys(cache)
      , l = keys.length
    if (l > 10000) for (var i = 0; i < l - 5000; i ++) {
      delete cache[keys[i]]
    }
  }
  if (cb) cb(null,json)
  return json
}}
function depObjectify (deps) {
  if (!Array.isArray(deps)) return deps
  var o = {}
  deps.forEach(function (d) {
    d = d.trim().split(/(:?[@\s><=])/)
    o[d.shift()] = d.join("").trim().replace(/^@/, "")
  })
  return o
}
function testEngine (json) {
  // if engines is empty, then assume that node is allowed.
  log.silly(json, "testEngine")
  if ( !json.engines
      || Array.isArray(json.engines)
        && !json.engines.length
      || typeof json.engines === "object"
        && !Object.keys(json.engines).length
      ) {
    json.engines = { "node" : "*" }
  }
  if (typeof json.engines === "string") {
    if (semver.validRange(json.engines) !== null) {
      json.engines = { "node" : json.engines }
    } else json.engines = [ json.engines ]
  }

  var nodeVer = npm.config.get("node-version")
    , ok = false
  if (nodeVer) nodeVer = nodeVer.replace(/\+$/, '')
  if (Array.isArray(json.engines)) {
    // Packages/1.0 commonjs style, with an array.
    // hack it to just hang a "node" member with the version range,
    // then do the npm-style check below.
    for (var i = 0, l = json.engines.length; i < l; i ++) {
      var e = json.engines[i].trim()
      if (e.substr(0, 4) === "node") {
        json.engines.node = e.substr(4)
      } else if (e.substr(0, 3) === "npm") {
        json.engines.npm = e.substr(3)
      }
    }
  }
  if (json.engines.node === "") json.engines.node = "*"
  if (json.engines.node && null === semver.validRange(json.engines.node)) {
    log.warn( json.engines.node
            , "Invalid range in engines.node.  Please see `npm help json`" )
  }

  if (nodeVer) {
    json._engineSupported = semver.satisfies( nodeVer
                                            , json.engines.node || "null" )
  }
  if (json.engines.hasOwnProperty("npm") && json._engineSupported) {
    json._engineSupported = semver.satisfies(npm.version, json.engines.npm)
  }
  return json
}

function unParsePeople (json) { return parsePeople(json, true) }
function parsePeople (json, un) {
  var fn = un ? unParsePerson : parsePerson
  if (json.author) json.author = fn(json.author)
  ;["maintainers", "contributors"].forEach(function (set) {
    if (Array.isArray(json[set])) json[set] = json[set].map(fn)
  })
  return json
}
function unParsePerson (person) {
  if (typeof person === "string") return person
  var name = person.name || ""
    , u = person.url || person.web
    , url = u ? (" ("+u+")") : ""
    , e = person.email || person.mail
    , email = e ? (" <"+e+">") : ""
  return name+email+url
}
function parsePerson (person) {
  if (typeof person !== "string") return person
  var name = person.match(/^([^\(<]+)/)
    , url = person.match(/\(([^\)]+)\)/)
    , email = person.match(/<([^>]+)>/)
    , obj = {}
  if (name && name[0].trim()) obj.name = name[0].trim()
  if (email) obj.email = email[1]
  if (url) obj.url = url[1]
  return obj
}
<commit_msg>Log the error nicer<commit_after>
module.exports = readJson
readJson.processJson = processJson
readJson.unParsePeople = unParsePeople
readJson.parsePeople = parsePeople

var fs = require("./graceful-fs")
  , semver = require("semver")
  , path = require("path")
  , log = require("./log")
  , npm = require("../../npm")
  , cache = {}
  , timers = {}
  , loadPackageDefaults = require("./load-package-defaults")

function readJson (jsonFile, opts, cb) {
  if (typeof cb !== "function") cb = opts, opts = {}
  if (cache.hasOwnProperty(jsonFile)) {
    log.verbose(jsonFile, "from cache")
    return cb(null, cache[jsonFile])
  }
  opts.file = jsonFile
  if (!opts.tag) {
    var parsedPath = jsonFile.indexOf(npm.dir) === 0 && jsonFile.match(
      /\/([^\/]+)\/([^\/]+)\/package\/package\.json$/)
    if (parsedPath && semver.valid(parsedPath[2])) {
      // this is a package.json in some installed package.
      // infer the opts.tag so that linked packages behave right.
      opts.tag = parsedPath[2]
    }
  }

  fs.readFile( path.join(path.dirname(jsonFile), "wscript")
             , function (er, data) {
    if (er) opts.wscript = false
    else opts.wscript = data.toString().match(/(^|\n)def build\b/)
                      && data.toString().match(/(^|\n)def configure\b/)
    fs.readFile(jsonFile, processJson(opts, function (er, data) {
      if (er) return cb(er)
      var doLoad = !(jsonFile.indexOf(npm.cache) === 0 &&
                     path.basename(path.dirname(jsonFile)) !== "package")
      if (!doLoad) return cb(er, data)
      loadPackageDefaults(data, path.dirname(jsonFile), cb)
    }))
  })
}
function processJson (opts, cb) {
  if (typeof cb !== "function") cb = opts, opts = {}
  if (typeof cb !== "function") {
    var thing = cb, cb = null
    return P(null, thing)
  } else return P

  function P (er, thing) {
    if (er) {
      if (cb) return cb(er, thing)
      throw er
    }
    if (typeof thing === "object" && !Buffer.isBuffer(thing)) {
      return processObject(opts, cb)(er, thing)
    } else {
      return processJsonString(opts, cb)(er, thing)
    }
  }
}
function processJsonString (opts, cb) { return function (er, jsonString) {
  jsonString += ""
  if (er) return cb(er, jsonString)
  var json
  try {
    json = JSON.parse(jsonString)
  } catch (ex) {
    if (opts.file && opts.file.indexOf(npm.dir) === 0) {
      try {
        json = require("vm").runInNewContext("(\n"+jsonString+"\n)")
        log.error(opts.file, "Error parsing json")
        log.error(ex, "parse error ")
      } catch (ex2) {
        return jsonParseFail(ex, cb)
      }
    } else {
      return jsonParseFail(ex, cb)
    }
  }
  return processObject(opts, cb)(er, json)
}}

function jsonParseFail (ex, cb) {
  var e = new Error(
    "Failed to parse json\n"+ex.message)
  e.errno = npm.EJSONPARSE
  if (cb) return cb(e)
  throw e
}

function processObject (opts, cb) { return function (er, json) {

  // slashes would be a security risk.
  // anything else will just fail harmlessly.
  if (!json.name) {
    var e = new Error("No 'name' field found in package.json")
    if (cb) return cb(e)
    throw e
  }
  json.name = json.name.trim()
  if (json.name.charAt(0) === "." || json.name.match(/[\/@\s\+%:]/)) {
    var msg = "Invalid name: "
            + JSON.stringify(json.name)
            + " may not start with '.' or contain %/@+: or whitespace"
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }
  if (json.name.toLowerCase() === "node_modules") {
    var msg = "Invalid package name: node_modules"
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }
  if (json.name.toLowerCase() === "favicon.ico") {
    var msg = "Sorry, favicon.ico is a picture, not a package."
      , e = new Error(msg)
    if (cb) return cb(e)
    throw e
  }

  if (json.repostories) {
    var msg = "'repositories' (plural) No longer supported.\n"
            + "Please pick one, and put it in the 'repository' field."
      , e = new Error(msg)
    // uncomment once this is no longer an issue.
    // if (cb) return cb(e)
    // throw e
    log.error(msg, "incorrect json")
    json.repostory = json.repositories[0]
    delete json.repositories
  }

  if (json.repository) {
    if (typeof json.repository === "string") {
      json.repository = { type : "git"
                        , url : json.repository }
    }
    var repo = json.repository.url || ""
    repo = repo.replace(/^(https?|git):\/\/[^\@]+\@github.com/
                       ,'$1://github.com')
    if (json.repository.type === "git"
        && ( repo.match(/^https?:\/\/github.com/)
          || repo.match(/github.com\/[^\/]+\/[^\/]+\/?$/)
             && !repo.match(/\.git$/)
        )) {
      repo = repo.replace(/^https?:\/\/github.com/, 'git://github.com')
      if (!repo.match(/\.git$/)) {
        repo = repo.replace(/\/?$/, '.git')
      }
    }
    if (repo.match(/github\.com\/[^\/]+\/[^\/]+\/?$/)
        && repo.match(/\.git\.git$/)) {
      log.warn(repo, "Probably broken git url")
    }
    json.repository.url = repo
  }

  var tag = opts.tag
  if (tag) json.version = tag//+"-"+json.version

  if (json.modules) {
    if (typeof json.modules !== "object") {
      var e = new Error("Invalid modules object")
      if (cb) return cb(e)
      throw e
    }
    Object.keys(json.modules).forEach(function (mod) {
      if (typeof json.modules[mod] !== "string") {
        var e = new Error("Invalid module "+mod+", not a string: "
                         +JSON.stringify(json.modules[mod]))
        if (cb) return cb(e)
        throw e
      }
    })
  }

  if (opts.wscript) {
    var scripts = json.scripts = json.scripts || {}
    if (!scripts.install && !scripts.preinstall) {
      // don't fail if it was unexpected, just try.
      scripts.preinstall = "node-waf clean || true; node-waf configure build"
    }
  }

  if (!(semver.valid(json.version))) {
    var e = new Error("Invalid version: "+json.version+"\n"
                     +"Must be X.Y.Z, with an optional trailing tag.\n"
                     +"See the section on 'version' in `npm help json`")
    if (cb) return cb(e)
    throw e
  }
  json.version = semver.clean(json.version)

  if (json.bin && typeof json.bin === "string") {
    var b = {}
    b[ path.basename( json.bin ) ] = json.bin
    json.bin = b
  }

  if (json["dev-dependencies"] && !json.devDependencies) {
    json.devDependencies = json["dev-dependencies"]
    delete json["dev-dependencies"]
  }
  ;["dependencies", "devDependencies"].forEach(function (d) {
    if (!json[d]) return
    json[d] = depObjectify(json[d])
  })

  json._id = json.name+"@"+json.version
  json = testEngine(json)
  json = parsePeople(unParsePeople(json))
  if ( json.bugs ) json.bugs = parsePerson(unParsePerson(json.bugs))
  json._npmVersion = npm.version
  json._nodeVersion = process.version
  if (opts.file) {
    log.verbose(opts.file, "caching")
    cache[opts.file] = json
    // arbitrary
    var keys = Object.keys(cache)
      , l = keys.length
    if (l > 10000) for (var i = 0; i < l - 5000; i ++) {
      delete cache[keys[i]]
    }
  }
  if (cb) cb(null,json)
  return json
}}
function depObjectify (deps) {
  if (!Array.isArray(deps)) return deps
  var o = {}
  deps.forEach(function (d) {
    d = d.trim().split(/(:?[@\s><=])/)
    o[d.shift()] = d.join("").trim().replace(/^@/, "")
  })
  return o
}
function testEngine (json) {
  // if engines is empty, then assume that node is allowed.
  log.silly(json, "testEngine")
  if ( !json.engines
      || Array.isArray(json.engines)
        && !json.engines.length
      || typeof json.engines === "object"
        && !Object.keys(json.engines).length
      ) {
    json.engines = { "node" : "*" }
  }
  if (typeof json.engines === "string") {
    if (semver.validRange(json.engines) !== null) {
      json.engines = { "node" : json.engines }
    } else json.engines = [ json.engines ]
  }

  var nodeVer = npm.config.get("node-version")
    , ok = false
  if (nodeVer) nodeVer = nodeVer.replace(/\+$/, '')
  if (Array.isArray(json.engines)) {
    // Packages/1.0 commonjs style, with an array.
    // hack it to just hang a "node" member with the version range,
    // then do the npm-style check below.
    for (var i = 0, l = json.engines.length; i < l; i ++) {
      var e = json.engines[i].trim()
      if (e.substr(0, 4) === "node") {
        json.engines.node = e.substr(4)
      } else if (e.substr(0, 3) === "npm") {
        json.engines.npm = e.substr(3)
      }
    }
  }
  if (json.engines.node === "") json.engines.node = "*"
  if (json.engines.node && null === semver.validRange(json.engines.node)) {
    log.warn( json.engines.node
            , "Invalid range in engines.node.  Please see `npm help json`" )
  }

  if (nodeVer) {
    json._engineSupported = semver.satisfies( nodeVer
                                            , json.engines.node || "null" )
  }
  if (json.engines.hasOwnProperty("npm") && json._engineSupported) {
    json._engineSupported = semver.satisfies(npm.version, json.engines.npm)
  }
  return json
}

function unParsePeople (json) { return parsePeople(json, true) }
function parsePeople (json, un) {
  var fn = un ? unParsePerson : parsePerson
  if (json.author) json.author = fn(json.author)
  ;["maintainers", "contributors"].forEach(function (set) {
    if (Array.isArray(json[set])) json[set] = json[set].map(fn)
  })
  return json
}
function unParsePerson (person) {
  if (typeof person === "string") return person
  var name = person.name || ""
    , u = person.url || person.web
    , url = u ? (" ("+u+")") : ""
    , e = person.email || person.mail
    , email = e ? (" <"+e+">") : ""
  return name+email+url
}
function parsePerson (person) {
  if (typeof person !== "string") return person
  var name = person.match(/^([^\(<]+)/)
    , url = person.match(/\(([^\)]+)\)/)
    , email = person.match(/<([^>]+)>/)
    , obj = {}
  if (name && name[0].trim()) obj.name = name[0].trim()
  if (email) obj.email = email[1]
  if (url) obj.url = url[1]
  return obj
}
<|endoftext|>


<commit_before>import React from 'react';

import Portal from './portal';

/**
 * `PaneItem` adds its child to the current Atom pane when rendered.
 * When the pane is closed, the component's `onDidCloseItem` is called.
 * You should use this callback to set state so that the `PaneItem` is no
 * longer rendered; you will get an error in your console if you forget.
 *
 * You may pass a `getItem` function that takes an object with `portal` and
 * `subtree` properties. `getItem` should return an item to be added to the
 * Panel. `portal` is an instance of th Portal component, and `subtree` is the
 * rendered subtree component built from the `children` prop. The default
 * implementation simply returns the Portal instance, which contains a
 * `getElement` method (to be compatible with Atom's view system).
 *
 * Unmounting the component when the item is open will close the item.
 */
export default class PaneItem extends React.Component {
  static propTypes = {
    workspace: React.PropTypes.object.isRequired,
    children: React.PropTypes.element.isRequired,
    getItem: React.PropTypes.func,
    onDidCloseItem: React.PropTypes.func,
  }

  static defaultProps = {
    getItem: ({portal, subtree}) => portal.getView(),
    onDidCloseItem: paneItem => {},
  }

  componentDidMount() {
    this.setupPaneItem();
  }

  componentWillReceiveProps() {
    if (this.didCloseItem) {
      // eslint-disable-next-line no-console
      console.error('Unexpected update in `PaneItem`: the contained item has been closed');
    }
  }

  render() {
    return <Portal ref={c => { this.portal = c; }}>{this.props.children}</Portal>;
  }

  setupPaneItem() {
    if (this.paneItem) { return; }

    const itemToAdd = this.props.getItem({portal: this.portal, subtree: this.portal.getRenderedSubtree()});
    this.paneItem = this.props.workspace.getActivePane().addItem(itemToAdd);
    this.subscriptions = this.props.workspace.onDidDestroyPaneItem(({item}) => {
      if (item === this.paneItem) {
        this.didCloseItem = true;
        this.props.onDidCloseItem(this.paneItem);
      }
    });
  }

  getPaneItem() {
    return this.paneItem;
  }

  componentWillUnmount() {
    this.subscriptions && this.subscriptions.dispose();
    if (this.paneItem && !this.didCloseItem) {
      this.paneItem.destroy && this.paneItem.destroy();
      this.props.workspace.getActivePane().destroyItem(this.paneItem);
    }
  }

  activate() {
    setTimeout(() => {
      if (!this.paneItem) { return; }

      const pane = this.props.workspace.paneForItem(this.paneItem);
      if (pane) {
        pane.activateItem(this.paneItem);
      } else {
        throw new Error('Cannot find pane for item in `PaneItem#activate`');
      }
    });
  }
}
<commit_msg>Use either item.destroy() or activePane.destroyItem()<commit_after>import React from 'react';

import Portal from './portal';

/**
 * `PaneItem` adds its child to the current Atom pane when rendered.
 * When the pane is closed, the component's `onDidCloseItem` is called.
 * You should use this callback to set state so that the `PaneItem` is no
 * longer rendered; you will get an error in your console if you forget.
 *
 * You may pass a `getItem` function that takes an object with `portal` and
 * `subtree` properties. `getItem` should return an item to be added to the
 * Panel. `portal` is an instance of th Portal component, and `subtree` is the
 * rendered subtree component built from the `children` prop. The default
 * implementation simply returns the Portal instance, which contains a
 * `getElement` method (to be compatible with Atom's view system).
 *
 * Unmounting the component when the item is open will close the item.
 */
export default class PaneItem extends React.Component {
  static propTypes = {
    workspace: React.PropTypes.object.isRequired,
    children: React.PropTypes.element.isRequired,
    getItem: React.PropTypes.func,
    onDidCloseItem: React.PropTypes.func,
  }

  static defaultProps = {
    getItem: ({portal, subtree}) => portal.getView(),
    onDidCloseItem: paneItem => {},
  }

  componentDidMount() {
    this.setupPaneItem();
  }

  componentWillReceiveProps() {
    if (this.didCloseItem) {
      // eslint-disable-next-line no-console
      console.error('Unexpected update in `PaneItem`: the contained item has been closed');
    }
  }

  render() {
    return <Portal ref={c => { this.portal = c; }}>{this.props.children}</Portal>;
  }

  setupPaneItem() {
    if (this.paneItem) { return; }

    const itemToAdd = this.props.getItem({portal: this.portal, subtree: this.portal.getRenderedSubtree()});
    this.paneItem = this.props.workspace.getActivePane().addItem(itemToAdd);
    this.subscriptions = this.props.workspace.onDidDestroyPaneItem(({item}) => {
      if (item === this.paneItem) {
        this.didCloseItem = true;
        this.props.onDidCloseItem(this.paneItem);
      }
    });
  }

  getPaneItem() {
    return this.paneItem;
  }

  componentWillUnmount() {
    this.subscriptions && this.subscriptions.dispose();
    if (this.paneItem && !this.didCloseItem) {
      if (this.paneItem.destroy) {
        this.paneItem.destroy && this.paneItem.destroy();
      } else {
        const activePane = this.props.workspace.getActivePane();
        if (activePane) {
          activePane.destroyItem(this.paneItem);
        }
      }
    }
  }

  activate() {
    setTimeout(() => {
      if (!this.paneItem) { return; }

      const pane = this.props.workspace.paneForItem(this.paneItem);
      if (pane) {
        pane.activateItem(this.paneItem);
      } else {
        throw new Error('Cannot find pane for item in `PaneItem#activate`');
      }
    });
  }
}
<|endoftext|>


<commit_before>/*
Wrapper for PhantomJS and YUITest
*/

/*jslint browser: true */
/*global phantom */

/*
TODO --
onError: Handle JS errors and throw a YUITest error
Timeout: Specify a timeout (override too) to kill a test
*/
var waitTimer,
    waitCounter = 0,
    testTimer,
    file = phantom.args[0],
    timeout = parseInt(phantom.args[1], 10),
    timer,
    exited = false,
    debug = false,
    log = function(a, b) {
        b = (typeof b === 'undefined') ? '' : b;
        if (debug) {
            console.log(a, b);
        }
    };

var injectGetYUITest = function() {
    window.TestResults = null;
    window.getYUITest = function() {
        return window.YUITest;
    };

    window.getYUITestResults = function() {
        if (window.TestResults) {
            return window.TestResults;
        }
        var YUITest = window.getYUITest(), json, cover;
        if (YUITest) {
            json = YUITest.Runner.getResults(YUITest.Format.JSON);
            cover = YUITest.Runner.getCoverage();

            if (json && cover) {
                json = JSON.parse(json);
                json.coverage = cover;
                json = JSON.stringify(json);

            }
            if (json && window.__coverage__) {
                json = JSON.parse(json);
                json.coverageType = 'istanbul';
                json.coverage = window.__coverage__;
                json = JSON.stringify(json);
            }
            return json;
        }
    };

};
var startTest = function(page, cb) {
    log('Checking for YUITest');
    testTimer = setInterval(function() {
        //console.log('Checking..');
        var status = page.evaluate(function() {
            var t = window.getYUITest(),
                i, name;
            if (t) {
                for (i in t) {
                    name = i.replace('Test', '');
                    t[name] = t[i];
                }
            }
            return (t ? true : false);
        });
        log('Tester: ', status);
        if (status) {
            clearInterval(testTimer);
            cb(status);
        }
    }, 50);
};

var throwError = function(msg, trace) {
    var json = {
        passed: 0,
        failed: 1,
        total: 1,
        ignored: 0,
        name: file,
        error: msg
    };
    if (trace) {
        trace.forEach(function(item) {
            json.error += '\n' + item.file +  ':' + item.line;
        });
    }
    if (!exited) {
        console.log(JSON.stringify(json));
    }
    exited = true;
    phantom.exit(1);
};

var waitForResults = function(page, cb) {

    waitTimer = setInterval(function() {
        waitCounter++;
        log('Waiting on Results', waitCounter);
        var status = page.evaluate(function() {
            return window.getYUITestResults();
        });
        if (status) {
            clearInterval(waitTimer);
            log('Found Results');
            cb(status);
            return;
        }

    }, 150);

};

var executeTest = function(file, cb) {
    log('executing tests in ', file);
    var page = require('webpage').create(),
        opened = false;

    page.settings.javascriptEnabled = true;
    page.settings.localToRemoteUrlAccessEnabled = true;
    page.settings.loadImages = true;
    page.settings.loadPlugins = true;
    page.viewportSize = {
      width: 1024,
      height: 768
    };

    page.onConsoleMessage = function() {
        //console.log('[console.log]', msg);
    };
    page.onAlert = function() {
        //console.log('[window.alert]', msg);
    };
    page.onError = function(msg, trace) {
        throwError(msg, trace);
    };

    if (!opened) {
        log('Opening File', file, opened);
        page.open(file, function(status) {
            log('Opened File', file);
            if (opened) {
                return;
            }
            if (status === 'fail') {
                throwError('Phantom failed to load this page');
            }
            log('Status: ', status);
            log('Injecting getYUITest');
            page.evaluate(injectGetYUITest);

            startTest(page, function() {
                log('YUITest Found..');
                waitForResults(page, function(results) {
                    log('YUITest Results Returned');
                    cb(page, results);
                });
            });
            opened = true;
        });
    }
};

if (!phantom.args.length) {
    console.log('Please provide some test files to execute');
    phantom.exit(1);
}

if (isNaN(timeout)) {
    timeout = 60; //Default to one minute before failing the test
}
timer = setTimeout(function() {
    throwError('Script Timeout');
}, (timeout * 1000));

executeTest(file, function(page, results) {
    if (!exited) {
        console.log(results);
    }
    exited = true;
    phantom.exit();
});
<commit_msg>Added some more debugging lines<commit_after>/*
Wrapper for PhantomJS and YUITest
*/

/*jslint browser: true */
/*global phantom */

/*
TODO --
onError: Handle JS errors and throw a YUITest error
Timeout: Specify a timeout (override too) to kill a test
*/
var waitTimer,
    waitCounter = 0,
    testTimer,
    file = phantom.args[0],
    timeout = parseInt(phantom.args[1], 10),
    timer,
    exited = false,
    debug = false,
    log = function(a, b) {
        b = (typeof b === 'undefined') ? '' : b;
        if (debug) {
            console.log(a, b);
        }
    };

var injectGetYUITest = function() {
    window.TestResults = null;
    window.getYUITest = function() {
        return window.YUITest;
    };

    window.getYUITestResults = function() {
        if (window.TestResults) {
            return window.TestResults;
        }
        var YUITest = window.getYUITest(), json, cover;
        if (YUITest) {
            json = YUITest.Runner.getResults(YUITest.Format.JSON);
            cover = YUITest.Runner.getCoverage();

            if (json && cover) {
                json = JSON.parse(json);
                json.coverage = cover;
                json = JSON.stringify(json);

            }
            if (json && window.__coverage__) {
                json = JSON.parse(json);
                json.coverageType = 'istanbul';
                json.coverage = window.__coverage__;
                json = JSON.stringify(json);
            }
            return json;
        }
    };

};
var startTest = function(page, cb) {
    log('Checking for YUITest');
    testTimer = setInterval(function() {
        //console.log('Checking..');
        var status = page.evaluate(function() {
            var t = window.getYUITest(),
                i, name;
            if (t) {
                for (i in t) {
                    name = i.replace('Test', '');
                    t[name] = t[i];
                }
            }
            return (t ? true : false);
        });
        log('Tester: ', status);
        if (status) {
            clearInterval(testTimer);
            cb(status);
        }
    }, 50);
};

var throwError = function(msg, trace) {
    log('throwError executed');
    var json = {
        passed: 0,
        failed: 1,
        total: 1,
        ignored: 0,
        name: file,
        error: msg
    };
    if (trace) {
        trace.forEach(function(item) {
            json.error += '\n' + item.file +  ':' + item.line;
        });
    }
    if (!exited) {
        console.log(JSON.stringify(json));
    }
    exited = true;
    phantom.exit(1);
};

var waitForResults = function(page, cb) {

    waitTimer = setInterval(function() {
        waitCounter++;
        log('Waiting on Results', waitCounter);
        var status = page.evaluate(function() {
            return window.getYUITestResults();
        });
        if (status) {
            clearInterval(waitTimer);
            log('Found Results');
            cb(status);
            return;
        } else {
            log('NO RESULTS');
        }

    }, 150);

};

var executeTest = function(file, cb) {
    log('executing tests in ', file);
    var page = require('webpage').create(),
        opened = false;

    page.settings.javascriptEnabled = true;
    page.settings.localToRemoteUrlAccessEnabled = true;
    page.settings.loadImages = true;
    page.settings.loadPlugins = true;
    page.viewportSize = {
      width: 1024,
      height: 768
    };

    if (debug) {
        page.onConsoleMessage = function(msg) {
            console.log('[console.log]', msg);
        };
    }
    page.onAlert = function() {
        //console.log('[window.alert]', msg);
    };
    page.onError = function(msg, trace) {
        throwError(msg, trace);
    };

    if (!opened) {
        log('Opening File', file, opened);
        page.open(file, function(status) {
            log('Opened File', file);
            if (opened) {
                return;
            }
            if (status === 'fail') {
                throwError('Phantom failed to load this page');
            }
            log('Status: ', status);
            log('Injecting getYUITest');
            page.evaluate(injectGetYUITest);

            startTest(page, function() {
                log('YUITest Found..');
                waitForResults(page, function(results) {
                    log('YUITest Results Returned');
                    cb(page, results);
                });
            });
            opened = true;
        });
    }
};

if (!phantom.args.length) {
    console.log('Please provide some test files to execute');
    phantom.exit(1);
}

if (isNaN(timeout)) {
    timeout = 60; //Default to one minute before failing the test
}
timer = setTimeout(function() {
    throwError('Script Timeout');
}, (timeout * 1000));

executeTest(file, function(page, results) {
    log('executeTest callback fired');
    if (!exited) {
        console.log(results);
    }
    exited = true;
    phantom.exit();
});
<|endoftext|>


<commit_before>'use strict';

const path = require("path");
const fs = require("fs");
const spawn = require("child_process").spawn;
const exec = require("child_process").exec;

const installerConfig = require(path.normalize(process.env.PWD + "/../etc/config.js"));

const SOAJS_RMS = {
	'gateway': "soajs.controller",
	'urac': 'soajs.urac',
	'oauth': 'soajs.oauth',
	'dashboard': 'soajs.dashboard',
	'ui': 'soajs.dashboard.ui'
};

const serviceModule = {

	/**
	 * This command will calculate the needed env variables and
	 * start the requested service if supported in the requested environment
	 * @param args {Array}
	 * @param callback {Function}
	 */
	'start': (args, callback) => {
		if (args.length < 2) {
			return callback();
		}

		//check if service is supported
		let requestedService = args[0];
		let serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
		if(!SOAJS_RMS[requestedService]){
			serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
			return callback(`${serviceType} ${requestedService} is not supported!`);
		}

			//check for environment
		let requestedEnvironment = args[1];
		if(!requestedEnvironment.includes("--env")){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment.split("=");
		if(!requestedEnvironment[1] || requestedEnvironment[1] === ''){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment[1].toLowerCase();

		//check if service is installed and downloaded
		if(!installerConfig.workingDirectory || installerConfig.workingDirectory === ''){
			return callback(`${serviceType} ${requestedService} is not installed!`);
		}

		//check if service folder exists
		fs.stat(installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService], (error, stats) => {
			if(error || !stats){
				return callback(`${serviceType} ${requestedService} is not installed!`);
			}

			//set and ensure the log directory
			let logLoc;
			switch (process.env.PLATFORM){
				case 'Darwin':
					logLoc = "/usr/local/var/log/soajs/";
					break;
				case 'Linux':
				default:
					logLoc = "/var/log/soajs/";
					break;
			}

			//check log file
			fs.stat(logLoc, (error, stats) => {
				if(error){
					if(error.code === 'ENOENT' && !stats){
						//create log file
						fs.mkdir(logLoc, { 'recursive': true}, (error) => {
							if (error) {
								return callback(`Unable to create a Log File for ${serviceType} ${requestedService}!`);
							}

							if(requestedService === 'ui'){
								launchUI(logLoc);
							}
							else {
								launchService(logLoc);
							}
						});
					}
					else{
						return callback(`Unable to create a Log File for ${serviceType} ${requestedService}!`);
					}
				}
				else{
					if(requestedService === 'ui'){
						launchUI(logLoc);
					}
					else {
						launchService(logLoc);
					}
				}
			});
		});

		//function that sets the aggregated variables as environment variables and launches the service.
		function launchService(logLoc) {

			process.env.SOAJS_ENV = requestedEnvironment;
			process.env.SOAJS_SRVIP = '127.0.0.1';
			process.env.SOAJS_PROFILE = path.normalize(process.env.PWD + "/../data/soajs_profile.js" );

			//check for custom port
			if(args[2] && args[2].includes("--port")){
				let customServicePort = args[2].split("=");
				if(customServicePort[1] && customServicePort[1] !== ''){
					process.env.SOAJS_SRVPORT = customServicePort[1];
				}
			}

			let outLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-out.log`);
			let serviceOutLog = fs.openSync(outLog, "w");

			let errLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-err.log`);
			let serviceErrLog = fs.openSync(errLog, "w");

			let serviceInstance = spawn(process.env.NODE_BIN, [installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + `/index.js`, `--env=${requestedEnvironment}`], {
				"env": process.env,
				"stdio": ['ignore', serviceOutLog, serviceErrLog],
				"detached": true,
			});
			serviceInstance.unref();

			//generate out message for service
			let output = `Service ${requestedService} started ...\n`;
			output += "Logs:\n";
			output += `[ out ] -> ${outLog}\n`;
			output += `[ err ] -> ${errLog}\n`;
			return callback(null, output);
		}

		//function that starts the ui express app which contains the soajs console ui.
		function launchUI(logLoc) {
			let outLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-out.log`);
			let serviceOutLog = fs.openSync(outLog, "w");

			let errLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-err.log`);
			let serviceErrLog = fs.openSync(errLog, "w");

			let serviceInstance = spawn(process.env.NODE_BIN, [installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + "/app/index.js"], {
				"env": process.env,
				"stdio": ['ignore', serviceOutLog, serviceErrLog],
				"detached": true,
			});
			serviceInstance.unref();

			//require the ui config to learn the host and the port values
			let uiConfig = require(installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + "/app/config.js");

			//generate output message for ui
			let output = `SOAJS Console UI started ...\n`;
			output += `In your Browser, open: http://${uiConfig.host}:${uiConfig.port}/ \n`;
			return callback(null, output);
		}
	},

	/**
	 * This command will find the process id of the requested service in the requested environment and kill it
	 * @param args
	 * @param callback
	 * @returns {*}
	 */
	'stop': (args, callback) => {
		if (args.length < 2) {
			return callback();
		}

		//check if service is supported
		let requestedService = args[0];
		let serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
		if(!SOAJS_RMS[requestedService]){
			serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
			return callback(`${serviceType} ${requestedService} is not supported!`);
		}

		//check for environment
		let requestedEnvironment = args[1];
		if(!requestedEnvironment.includes("--env")){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment.split("=");
		if(!requestedEnvironment[1] || requestedEnvironment[1] === ''){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment[1].toLowerCase();

		//check if there is a running process for the requested
		exec(`ps aux | grep ${SOAJS_RMS[requestedService]}`, (error, cmdOutput) => {
			if(error || !cmdOutput){
				return callback();
			}

			//go through the returned output and find the process ID
			cmdOutput = cmdOutput.split("\n");
			if(Array.isArray(cmdOutput) && cmdOutput.length > 0){
				let PID;
				cmdOutput.forEach((oneCMDLine) => {

					if(requestedService === 'ui'){
						if(oneCMDLine.includes(SOAJS_RMS[requestedService])){
							let oneProcess = oneCMDLine.replace(/\s+/g, ' ').split(' ');
							PID = oneProcess[1];
						}
					}
					else{
						if(oneCMDLine.includes(SOAJS_RMS[requestedService]) && oneCMDLine.includes("--env=" + requestedEnvironment)){
							let oneProcess = oneCMDLine.replace(/\s+/g, ' ').split(' ');
							PID = oneProcess[1];
						}
					}
				});

				//if no PID return, nothing to do
				if(!PID){
					return callback();
				}

				//stop the running process
				exec(`kill -9 ${PID}`, (error) => {
					if(error){
						return callback(error);
					}
					else{
						return callback(null, `${serviceType} ${requestedService} Terminated ...`);
					}
				});
			}
			else {
				return callback();
			}
		});
	}
};

module.exports = serviceModule;<commit_msg>add check when stopping service to ignore command that contain grep.<commit_after>'use strict';

const path = require("path");
const fs = require("fs");
const spawn = require("child_process").spawn;
const exec = require("child_process").exec;

const installerConfig = require(path.normalize(process.env.PWD + "/../etc/config.js"));

const SOAJS_RMS = {
	'gateway': "soajs.controller",
	'urac': 'soajs.urac',
	'oauth': 'soajs.oauth',
	'dashboard': 'soajs.dashboard',
	'ui': 'soajs.dashboard.ui'
};

const serviceModule = {

	/**
	 * This command will calculate the needed env variables and
	 * start the requested service if supported in the requested environment
	 * @param args {Array}
	 * @param callback {Function}
	 */
	'start': (args, callback) => {
		if (args.length < 2) {
			return callback();
		}

		//check if service is supported
		let requestedService = args[0];
		let serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
		if(!SOAJS_RMS[requestedService]){
			serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
			return callback(`${serviceType} ${requestedService} is not supported!`);
		}

			//check for environment
		let requestedEnvironment = args[1];
		if(!requestedEnvironment.includes("--env")){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment.split("=");
		if(!requestedEnvironment[1] || requestedEnvironment[1] === ''){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment[1].toLowerCase();

		//check if service is installed and downloaded
		if(!installerConfig.workingDirectory || installerConfig.workingDirectory === ''){
			return callback(`${serviceType} ${requestedService} is not installed!`);
		}

		//check if service folder exists
		fs.stat(installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService], (error, stats) => {
			if(error || !stats){
				return callback(`${serviceType} ${requestedService} is not installed!`);
			}

			//set and ensure the log directory
			let logLoc;
			switch (process.env.PLATFORM){
				case 'Darwin':
					logLoc = "/usr/local/var/log/soajs/";
					break;
				case 'Linux':
				default:
					logLoc = "/var/log/soajs/";
					break;
			}

			//check log file
			fs.stat(logLoc, (error, stats) => {
				if(error){
					if(error.code === 'ENOENT' && !stats){
						//create log file
						fs.mkdir(logLoc, { 'recursive': true}, (error) => {
							if (error) {
								return callback(`Unable to create a Log File for ${serviceType} ${requestedService}!`);
							}

							if(requestedService === 'ui'){
								launchUI(logLoc);
							}
							else {
								launchService(logLoc);
							}
						});
					}
					else{
						return callback(`Unable to create a Log File for ${serviceType} ${requestedService}!`);
					}
				}
				else{
					if(requestedService === 'ui'){
						launchUI(logLoc);
					}
					else {
						launchService(logLoc);
					}
				}
			});
		});

		//function that sets the aggregated variables as environment variables and launches the service.
		function launchService(logLoc) {

			process.env.SOAJS_ENV = requestedEnvironment;
			process.env.SOAJS_SRVIP = '127.0.0.1';
			process.env.SOAJS_PROFILE = path.normalize(process.env.PWD + "/../data/soajs_profile.js" );

			//check for custom port
			if(args[2] && args[2].includes("--port")){
				let customServicePort = args[2].split("=");
				if(customServicePort[1] && customServicePort[1] !== ''){
					process.env.SOAJS_SRVPORT = customServicePort[1];
				}
			}

			let outLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-out.log`);
			let serviceOutLog = fs.openSync(outLog, "w");

			let errLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-err.log`);
			let serviceErrLog = fs.openSync(errLog, "w");

			let serviceInstance = spawn(process.env.NODE_BIN, [installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + `/index.js`, `--env=${requestedEnvironment}`], {
				"env": process.env,
				"stdio": ['ignore', serviceOutLog, serviceErrLog],
				"detached": true,
			});
			serviceInstance.unref();

			//generate out message for service
			let output = `Service ${requestedService} started ...\n`;
			output += "Logs:\n";
			output += `[ out ] -> ${outLog}\n`;
			output += `[ err ] -> ${errLog}\n`;
			return callback(null, output);
		}

		//function that starts the ui express app which contains the soajs console ui.
		function launchUI(logLoc) {
			let outLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-out.log`);
			let serviceOutLog = fs.openSync(outLog, "w");

			let errLog = path.normalize(logLoc + `/${requestedEnvironment}-${requestedService}-err.log`);
			let serviceErrLog = fs.openSync(errLog, "w");

			let serviceInstance = spawn(process.env.NODE_BIN, [installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + "/app/index.js"], {
				"env": process.env,
				"stdio": ['ignore', serviceOutLog, serviceErrLog],
				"detached": true,
			});
			serviceInstance.unref();

			//require the ui config to learn the host and the port values
			let uiConfig = require(installerConfig.workingDirectory + "/node_modules/" + SOAJS_RMS[requestedService] + "/app/config.js");

			//generate output message for ui
			let output = `SOAJS Console UI started ...\n`;
			output += `In your Browser, open: http://${uiConfig.host}:${uiConfig.port}/ \n`;
			return callback(null, output);
		}
	},

	/**
	 * This command will find the process id of the requested service in the requested environment and kill it
	 * @param args
	 * @param callback
	 * @returns {*}
	 */
	'stop': (args, callback) => {
		if (args.length < 2) {
			return callback();
		}

		//check if service is supported
		let requestedService = args[0];
		let serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
		if(!SOAJS_RMS[requestedService]){
			serviceType = (requestedService === 'ui') ? 'SOAJS Console' : 'Service';
			return callback(`${serviceType} ${requestedService} is not supported!`);
		}

		//check for environment
		let requestedEnvironment = args[1];
		if(!requestedEnvironment.includes("--env")){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment.split("=");
		if(!requestedEnvironment[1] || requestedEnvironment[1] === ''){
			return callback(`Specify the environment where you want ${requestedService} to be deployed!`);
		}
		requestedEnvironment = requestedEnvironment[1].toLowerCase();

		//check if there is a running process for the requested
		exec(`ps aux | grep ${SOAJS_RMS[requestedService]}`, (error, cmdOutput) => {
			if(error || !cmdOutput){
				return callback();
			}

			//go through the returned output and find the process ID
			cmdOutput = cmdOutput.split("\n");
			if(Array.isArray(cmdOutput) && cmdOutput.length > 0){
				let PID;
				cmdOutput.forEach((oneCMDLine) => {

					if(!oneCMDLine.includes("grep")){
						if(requestedService === 'ui'){
							if(oneCMDLine.includes(SOAJS_RMS[requestedService])){
								let oneProcess = oneCMDLine.replace(/\s+/g, ' ').split(' ');
								PID = oneProcess[1];
							}
						}
						else{
							if(oneCMDLine.includes(SOAJS_RMS[requestedService]) && oneCMDLine.includes("--env=" + requestedEnvironment)){
								let oneProcess = oneCMDLine.replace(/\s+/g, ' ').split(' ');
								PID = oneProcess[1];
							}
						}
					}
				});

				//if no PID return, nothing to do
				if(!PID){
					return callback();
				}

				//stop the running process
				exec(`kill -9 ${PID}`, (error) => {
					if(error){
						return callback(error);
					}
					else{
						return callback(null, `${serviceType} ${requestedService} Terminated ...`);
					}
				});
			}
			else {
				return callback();
			}
		});
	}
};

module.exports = serviceModule;<|endoftext|>


<commit_before>var readline = require('readline');
var google = require('googleapis');
var googleAuth = require('google-auth-library');
let colorService = require('./services/googleCalendarColorService')
let scraper = require('./services/scraper.js');
let MongoClient = require('mongodb').MongoClient;
let programmeCodeService = require('./services/programmeCodeService')
let clientSecret = JSON.parse(process.env.client_secret)
let url = process.env.dburl || "mongodb://localhost:27017/ieee-raspored";
module.exports.url = url
let SCOPES = ['https://www.googleapis.com/auth/calendar'];
module.exports.SCOPES = SCOPES

function loadSecrets() {

  authorize(clientSecret, updateCalendars);
}

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 *
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, callback) {
  var clientSecret = credentials.web.client_secret;
  var clientId = credentials.web.client_id;
  var redirectUrl = credentials.web.redirect_uris[0];
  var auth = new googleAuth();
  var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

  callback(oauth2Client)
}

function addEventsToCalendar(auth, events) {
  var calendar = google.calendar('v3');
  console.log('Adding events to a calendar');
  events.forEach((event) => {
    calendar.events.insert({
      auth: auth,
      calendarId: 'primary',
      resource: event,
    }, function (err, event) {
      if (err) {
        console.log('There was an error contacting the Calendar service: ' + err);
        return;
      }
      console.log('%s: Event created: %s', (new Date()).toISOString(), event.htmlLink);
    });

  });
}
module.exports.addEventsToCalendar = addEventsToCalendar

function updateCalendars(oauth2Client) {
  console.log('updating calendars ...')
  let programmeCodes = Object.values(programmeCodeService).filter(function (item, pos, self) {
    return self.indexOf(item) == pos;
  });

  programmeCodes.forEach(function (programmeCode) {
    numberOfYears = (programmeCode.length == 1 || programmeCode == programmeCodeService.komunikacije) ? 3 : 2;
    for (let i = 1; i <= numberOfYears; i++) {
      query =
        {
          "programme": programmeCode,
          "studentYear": String(i)
        }

      Promise.all([getStudentsFromDBAsync(query).catch(), scraper.scrapeEventsAsync(query.studentYear, query.programme)])
        .then((vals) => {
          let students = vals[0];
          let events = vals[1];

          students.forEach(student => {
            if (student.tokens === undefined) return;
            oauth2Client.credentials = student.tokens;
            oauth2Client.refreshAccessToken((err, tokens) => { });
            addEventsToCalendarWithExponentialBackoff(oauth2Client, events);
          })

        })
        .catch(err => console.error(err))
    }

  });
}
module.exports.updateCalendars = updateCalendars

function getStudentsFromDBAsync(query) {
  return new Promise((resolve, reject) => {
    MongoClient.connect(url,
      (err, db) => {
        if (err) reject(err);
        db.collection("students").find(query)
          .toArray((err, students) => {
            if (err) reject(err);
            return resolve(students);
            db.close();
          });
      });
  });
}

function addEventsToCalendarWithExponentialBackoff(auth, events) {
  var calendar = google.calendar('v3');
  console.log('Adding events to a calendar');
  events.forEach((event) => {
    calendar.events.insert({
      auth: auth,
      calendarId: 'primary',
      resource: event,
    }, (err, event) => {
      console.log('logging event obj before exponential backoff +'+ event)

      exponentialBackoff(err, event, calendar, auth) })
  })

}

function exponentialBackoff(err, event, calendar, auth, delay = 1) {
  console.log('logging event obj on begginign of exponential backoff +'+ event)
  if (err == null || err == undefined) {
    console.log('%s: Event created: %s', (new Date()).toISOString(), event.htmlLink);
    return;
  }
  console.error(err.code)
  if (err.code == 403 && delay < 25) {
    delay = delay + 1;
    console.log('retrying with delay:' + delay + ' ... ' + event)

    setTimeout(() => {
      calendar.events.insert({
        auth: auth,
        calendarId: 'primary',
        resource: event,
      }, (err, event) => {
        console.log('logging event obj inside exponential backoff set timeout +'+ event)

        exponentialBackoff(err, event, calendar, auth, delay) })
    }, 1000 * delay)
    return;
  }

  if (err) {
    if (err.code) {
      console.log('There was an error contacting the Calendar service with error code:  ' + err.code + ': ' + err);

    } else {
      console.log('There was an error contacting the Calendar service: ' + err);
    }
    return;
  }
}<commit_msg>null check<commit_after>var readline = require('readline');
var google = require('googleapis');
var googleAuth = require('google-auth-library');
let colorService = require('./services/googleCalendarColorService')
let scraper = require('./services/scraper.js');
let MongoClient = require('mongodb').MongoClient;
let programmeCodeService = require('./services/programmeCodeService')
let clientSecret = JSON.parse(process.env.client_secret)
let url = process.env.dburl || "mongodb://localhost:27017/ieee-raspored";
module.exports.url = url
let SCOPES = ['https://www.googleapis.com/auth/calendar'];
module.exports.SCOPES = SCOPES

function loadSecrets() {

  authorize(clientSecret, updateCalendars);
}

/**
 * Create an OAuth2 client with the given credentials, and then execute the
 * given callback function.
 *
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback to call with the authorized client.
 */
function authorize(credentials, callback) {
  var clientSecret = credentials.web.client_secret;
  var clientId = credentials.web.client_id;
  var redirectUrl = credentials.web.redirect_uris[0];
  var auth = new googleAuth();
  var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

  callback(oauth2Client)
}

function addEventsToCalendar(auth, events) {
  var calendar = google.calendar('v3');
  console.log('Adding events to a calendar');
  events.forEach((event) => {
    calendar.events.insert({
      auth: auth,
      calendarId: 'primary',
      resource: event,
    }, function (err, event) {
      if (err) {
        console.log('There was an error contacting the Calendar service: ' + err);
        return;
      }
      console.log('%s: Event created: %s', (new Date()).toISOString(), event.htmlLink);
    });

  });
}
module.exports.addEventsToCalendar = addEventsToCalendar

function updateCalendars(oauth2Client) {
  console.log('updating calendars ...')
  let programmeCodes = Object.values(programmeCodeService).filter(function (item, pos, self) {
    return self.indexOf(item) == pos;
  });

  programmeCodes.forEach(function (programmeCode) {
    numberOfYears = (programmeCode.length == 1 || programmeCode == programmeCodeService.komunikacije) ? 3 : 2;
    for (let i = 1; i <= numberOfYears; i++) {
      query =
        {
          "programme": programmeCode,
          "studentYear": String(i)
        }

      Promise.all([getStudentsFromDBAsync(query).catch(), scraper.scrapeEventsAsync(query.studentYear, query.programme)])
        .then((vals) => {
          let students = vals[0];
          let events = vals[1];

          students.forEach(student => {
            if (student.tokens === undefined) return;
            oauth2Client.credentials = student.tokens;
            oauth2Client.refreshAccessToken((err, tokens) => { });
            addEventsToCalendarWithExponentialBackoff(oauth2Client, events);
          })

        })
        .catch(err => console.error(err))
    }

  });
}
module.exports.updateCalendars = updateCalendars

function getStudentsFromDBAsync(query) {
  return new Promise((resolve, reject) => {
    MongoClient.connect(url,
      (err, db) => {
        if (err) reject(err);
        db.collection("students").find(query)
          .toArray((err, students) => {
            if (err) reject(err);
            return resolve(students);
            db.close();
          });
      });
  });
}

function addEventsToCalendarWithExponentialBackoff(auth, events) {
  var calendar = google.calendar('v3');
  console.log('Adding events to a calendar');
  events.forEach((event) => {
    if(event == null) {
      console.log('there seems to be an event equeal to null')
    }
    calendar.events.insert({
      auth: auth,
      calendarId: 'primary',
      resource: event,
    }, (err, event) => {
      console.log('logging event obj before exponential backoff +'+ event)

      exponentialBackoff(err, event, calendar, auth) })
  })

}

function exponentialBackoff(err, event, calendar, auth, delay = 1) {
  console.log('logging event obj on begginign of exponential backoff +'+ event)
  if (err == null || err == undefined) {
    console.log('%s: Event created: %s', (new Date()).toISOString(), event.htmlLink);
    return;
  }
  console.error(err.code)
  if (err.code == 403 && delay < 25) {
    delay = delay + 1;
    console.log('retrying with delay:' + delay + ' ... ' + event)

    setTimeout(() => {
      calendar.events.insert({
        auth: auth,
        calendarId: 'primary',
        resource: event,
      }, (err, event) => {
        console.log('logging event obj inside exponential backoff set timeout +'+ event)

        exponentialBackoff(err, event, calendar, auth, delay) })
    }, 1000 * delay)
    return;
  }

  if (err) {
    if (err.code) {
      console.log('There was an error contacting the Calendar service with error code:  ' + err.code + ': ' + err);

    } else {
      console.log('There was an error contacting the Calendar service: ' + err);
    }
    return;
  }
}<|endoftext|>


<commit_before>CT.log = function(msg, level) {
	if (CT.log._silent)
		return;
	for (var i = 0; i < CT.log.grep._ins.length; i++)
		if (msg.indexOf(CT.log.grep._ins[i]) == -1)
			return;
	for (var i = 0; i < CT.log.grep._outs.length; i++)
		if (msg.indexOf(CT.log.grep._outs[i]) != -1)
			return;
	var s = Date() + " ::";
	if (level) for (var i = 0; i < level; i++)
		s += "  ";
	console.log(s, msg);
};

CT.log.grep = function(ins, outs) {
	CT.log.grep._ins = ins || [];
	CT.log.grep._outs = outs || [];
};
CT.log.grep._ins = [];
CT.log.grep._outs = [];

CT.log.set = function(bool) {
	CT.log._silent = bool;
};
CT.log.getLogger = function(component) {
	var logger = function() {
		var str_arr = [];
		for (var i = 0; i < logger.arguments.length; i++) {
			var a = logger.arguments[i];
			str_arr.push((typeof(a) == "object") ? JSON.stringify(a) : a);
		}
		CT.log("[" + component + "] " + str_arr.join(" "));
	};
	return logger;
};<commit_msg>CT.log() stringifies objects as necessary<commit_after>CT.log = function(msg, level) {
	if (CT.log._silent)
		return;
	msg = CT.log._fix(msg);
	for (var i = 0; i < CT.log.grep._ins.length; i++)
		if (msg.indexOf(CT.log.grep._ins[i]) == -1)
			return;
	for (var i = 0; i < CT.log.grep._outs.length; i++)
		if (msg.indexOf(CT.log.grep._outs[i]) != -1)
			return;
	var s = Date() + " ::";
	if (level) for (var i = 0; i < level; i++)
		s += "  ";
	console.log(s, msg);
};

CT.log.grep = function(ins, outs) {
	CT.log.grep._ins = ins || [];
	CT.log.grep._outs = outs || [];
};
CT.log.grep._ins = [];
CT.log.grep._outs = [];

CT.log._fix = function(a) {
	return (typeof(a) == "object") ? JSON.stringify(a) : a;
}
CT.log.set = function(bool) {
	CT.log._silent = bool;
};
CT.log.getLogger = function(component) {
	var logger = function() {
		var str_arr = [];
		for (var i = 0; i < logger.arguments.length; i++)
			str_arr.push(CT.log._fix(logger.arguments[i]));
		CT.log("[" + component + "] " + str_arr.join(" "));
	};
	return logger;
};<|endoftext|>


<commit_before>import { module, skip } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { click, render, settled, triggerEvent } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import {
  popoverArrowClass,
  popoverPositionClass,
  test,
  versionDependent,
  visibilityClass,
} from '../../helpers/bootstrap';
import { assertPositioning, setupForPositioning } from '../../helpers/contextual-help';
import setupStylesheetSupport from '../../helpers/setup-stylesheet-support';
import setupNoDeprecations from '../../helpers/setup-no-deprecations';
import { gte } from 'ember-compatibility-helpers';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import sinon from 'sinon';

module('Integration | Component | bs-popover', function (hooks) {
  setupRenderingTest(hooks);
  setupStylesheetSupport(hooks);
  setupNoDeprecations(hooks);

  test('it has correct markup', async function (assert) {
    // Template block usage:
    await render(hbs`
      <BsPopover @id="popover-element" @fade={{true}} @title="dummy title" @visible={{true}} class="wide">
        template block text
      </BsPopover>
    `);

    assert.dom('.popover').exists({ count: 1 }, 'has popover class');
    assert.dom('.popover.wide').exists({ count: 1 }, 'it passes along class attribute');
    assert.dom('.popover').hasClass('fade', 'has fade class');
    assert.dom('.popover').hasClass(visibilityClass(), 'has visibility class');
    assert.equal(this.element.querySelector('.popover').getAttribute('role'), 'tooltip', 'has ARIA role');
    assert.dom(`.${popoverArrowClass()}`).exists({ count: 1 }, 'has arrow');
    assert.dom(versionDependent('.popover-header')).hasText('dummy title', 'shows title');
    assert.dom(versionDependent('.popover-body')).hasText('template block text', 'shows content');
  });

  skip('it supports different placements', async function (assert) {
    this.insertCSSRule('#wrapper { margin: 200px }');

    let placements = ['top', 'left', 'bottom', 'right'];
    this.set('placement', placements[0]);
    await render(hbs`

        <BsPopover::Element @id="popover-element" @placement={{this.placement}} @title="dummy title">
          template block text
        </BsPopover::Element>

    `);

    for (let placement of placements) {
      this.set('placement', placement);
      let placementClass = popoverPositionClass(placement);
      assert.dom('.popover').hasClass(placementClass, `has ${placementClass} class`);
    }
  });

  test('should place popover on top of element', async function (assert) {
    this.insertCSSRule('#wrapper p { margin-top: 200px }');

    await render(hbs`

          <button type="button" class="btn" id="target">
            Click me<BsPopover @placement="top" @title="very very very very very very very long popover" @fade={{false}}>very very very very very very very long popover</BsPopover>
          </button>

`);

    setupForPositioning();

    await click('#target');

    assertPositioning(assert, '.popover', 8);
  });

  test('should adjust popover arrow', async function (assert) {
    this.insertCSSRule('#wrapper p { margin-top: 200px }');
    this.insertCSSRule('#target { width: 100px; padding: 0; border: none; }');

    let expectedArrowPosition = 217;

    await render(hbs`

          <button type="button" id="target">
            Click me<BsPopover @placement="top" @autoPlacement={{true}} @viewportSelector="#wrapper" @title="very very very very very very very long popover" @fade={{false}}>very very very very very very very long popover</BsPopover>
          </button>

`);

    setupForPositioning('right');

    await click('#target');
    let arrowPosition = parseInt(
      this.element
        .querySelector(`.${popoverArrowClass()}`)
        .style.transform.match(/translate(?:3d)?\(([0-9]+)px.*\)/)[1],
      10
    );
    assert.ok(
      Math.abs(arrowPosition - expectedArrowPosition) <= 2,
      `Expected position: ${expectedArrowPosition}, actual: ${arrowPosition}`
    );

    // check again to prevent regression of https://github.com/kaliber5/ember-bootstrap/issues/361
    await click('#target');
    await click('#target');
    arrowPosition = parseInt(
      this.element
        .querySelector(`.${popoverArrowClass()}`)
        .style.transform.match(/translate(?:3d)?\(([0-9]+)px.*\)/)[1],
      10
    );
    assert.ok(
      Math.abs(arrowPosition - expectedArrowPosition) <= 2,
      `Expected position: ${expectedArrowPosition}, actual: ${arrowPosition}`
    );
  });

  test('it stays open when clicked when rendered in place', async function (assert) {
    await render(hbs`

        <BsPopover>

Content

        </BsPopover>

    `);

    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#content');
    assert.dom('.popover').exists('popover is still visible');
  });

  test('it yields close action', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(hbs`

        <BsPopover @visible={{true}} @onHide={{action this.hide}} @onHidden={{action this.hidden}} as |po|>

Hide

        </BsPopover>

    `);
    await click('#hide');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
    assert.dom('.popover').doesNotExist('popover is not visible');
  });

  test('click-initiated close action does not interfere with click-to-open', async function (assert) {
    await render(hbs`

        <BsPopover as |po|>

Hide

        </BsPopover>

    `);
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#hide');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('click-initiated close action does not interfere with click-to-open when wormholed', async function (assert) {
    await render(hbs`

        <BsPopover as |po|>
Hide
</BsPopover>

    `);
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#hide');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('non-click-initiated close action does not interfere with click-to-open', async function (assert) {
    await render(
      hbs`<div id="target"><BsPopover as |po|><input id="hide" onblur={{action po.close}}></BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await triggerEvent('#hide', 'blur');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('non-click-initiated close action does not interfere with click-to-open when wormholed', async function (assert) {
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div><div id="target"><BsPopover as |po|><input id="hide" onblur={{action po.close}}></BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await triggerEvent('#hide', 'blur');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('it passes along class attribute', async function (assert) {
    await render(hbs`<div id="target"><BsPopover @title="Dummy" @class="wide">test</BsPopover></div>`);
    await click('#target');
    assert.dom('.popover').hasClass('wide');
  });

  (gte('3.4.0') ? test : skip)('it passes all HTML attribute', async function (assert) {
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" class="wide" data-test role="foo">test</BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').hasClass('wide');
    assert.dom('.popover').hasAttribute('role', 'foo');
    assert.dom('.popover').hasAttribute('data-test');
  });

  test("Renders in wormhole's default destination if renderInPlace is not set", async function (assert) {
    this.set('show', false);
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div>{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} />{{/if}}`
    );
    this.set('show', true);
    await settled();

    assert.dom('#ember-bootstrap-wormhole .popover').exists({ count: 1 }, 'Popover exists in wormhole');
  });

  test('Renders in test container if renderInPlace is not set', async function (assert) {
    this.set('show', false);
    await render(hbs`{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} />{{/if}}`);
    this.set('show', true);
    await settled();

    assert.dom('.popover').exists({ count: 1 }, 'Popover exists.');
    assert.dom('#wrapper .popover').doesNotExist();
  });

  test('Renders in place (no wormhole) if renderInPlace is set', async function (assert) {
    this.set('show', false);
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div><div id="wrapper">{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} @renderInPlace={{true}} />{{/if}}</div>`
    );
    this.set('show', true);
    await settled();

    assert.dom('#wrapper .popover').exists({ count: 1 }, 'Popover exists in place.');
  });

  test('it calls onShow/onShown actions when showing popover by event [fade=false]', async function (assert) {
    let showAction = sinon.spy();
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    await click('#target');
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.calledOnce, 'shown action has been called');
  });

  test('it calls onShow/onShown actions when showing popover programmatically [fade=false]', async function (assert) {
    let showAction = sinon.spy();
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    this.set('visible', false);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @visible={{this.visible}} @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    this.set('visible', true);
    await settled();
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.calledOnce, 'shown action has been called');
  });

  test('it aborts showing if onShow action returns false', async function (assert) {
    let showAction = sinon.stub();
    showAction.returns(false);
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    await click('#target');
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.notCalled, 'show action has not been called');
    assert.dom('.popover').doesNotExist('popover is not visible');
  });

  test('it calls onHide/onHidden actions when hiding popover by event [fade=false]', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    await click('#target');
    await click('#target');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
  });

  test('it calls onHide/onHidden actions when hiding popover programmatically [fade=false]', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    this.set('visible', true);
    await render(
      hbs`<div id="target"><BsPopover @visible={{this.visible}} @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    this.set('visible', false);
    await settled();
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
  });

  test('it aborts hiding if onHide action returns false', async function (assert) {
    let hideAction = sinon.stub();
    hideAction.returns(false);
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    await click('#target');
    await click('#target');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.notCalled, 'hidden action has not been called');
    assert.dom('.popover').exists({ count: 1 }, 'popover is visible');
  });

  test('it passes accessibility checks', async function (assert) {
    await render(hbs`
      <button type="button">
        Test
        <BsPopover @title="dummy title" @visible={{true}}>
          template block text
        </BsPopover>
      </button>
    `);

    await a11yAudit();
    assert.ok(true, 'A11y audit passed');
  });
});
<commit_msg>remove test<commit_after>import { module, skip } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { click, render, settled, triggerEvent } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import {
  popoverArrowClass,
  popoverPositionClass,
  test,
  versionDependent,
  visibilityClass,
} from '../../helpers/bootstrap';
import { assertPositioning, setupForPositioning } from '../../helpers/contextual-help';
import setupStylesheetSupport from '../../helpers/setup-stylesheet-support';
import setupNoDeprecations from '../../helpers/setup-no-deprecations';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import sinon from 'sinon';

module('Integration | Component | bs-popover', function (hooks) {
  setupRenderingTest(hooks);
  setupStylesheetSupport(hooks);
  setupNoDeprecations(hooks);

  test('it has correct markup', async function (assert) {
    // Template block usage:
    await render(hbs`
      <BsPopover @id="popover-element" @fade={{true}} @title="dummy title" @visible={{true}} class="wide">
        template block text
      </BsPopover>
    `);

    assert.dom('.popover').exists({ count: 1 }, 'has popover class');
    assert.dom('.popover.wide').exists({ count: 1 }, 'it passes along class attribute');
    assert.dom('.popover').hasClass('fade', 'has fade class');
    assert.dom('.popover').hasClass(visibilityClass(), 'has visibility class');
    assert.equal(this.element.querySelector('.popover').getAttribute('role'), 'tooltip', 'has ARIA role');
    assert.dom(`.${popoverArrowClass()}`).exists({ count: 1 }, 'has arrow');
    assert.dom(versionDependent('.popover-header')).hasText('dummy title', 'shows title');
    assert.dom(versionDependent('.popover-body')).hasText('template block text', 'shows content');
  });

  skip('it supports different placements', async function (assert) {
    this.insertCSSRule('#wrapper { margin: 200px }');

    let placements = ['top', 'left', 'bottom', 'right'];
    this.set('placement', placements[0]);
    await render(hbs`

        <BsPopover::Element @id="popover-element" @placement={{this.placement}} @title="dummy title">
          template block text
        </BsPopover::Element>

    `);

    for (let placement of placements) {
      this.set('placement', placement);
      let placementClass = popoverPositionClass(placement);
      assert.dom('.popover').hasClass(placementClass, `has ${placementClass} class`);
    }
  });

  test('should place popover on top of element', async function (assert) {
    this.insertCSSRule('#wrapper p { margin-top: 200px }');

    await render(hbs`

          <button type="button" class="btn" id="target">
            Click me<BsPopover @placement="top" @title="very very very very very very very long popover" @fade={{false}}>very very very very very very very long popover</BsPopover>
          </button>

`);

    setupForPositioning();

    await click('#target');

    assertPositioning(assert, '.popover', 8);
  });

  test('should adjust popover arrow', async function (assert) {
    this.insertCSSRule('#wrapper p { margin-top: 200px }');
    this.insertCSSRule('#target { width: 100px; padding: 0; border: none; }');

    let expectedArrowPosition = 217;

    await render(hbs`

          <button type="button" id="target">
            Click me<BsPopover @placement="top" @autoPlacement={{true}} @viewportSelector="#wrapper" @title="very very very very very very very long popover" @fade={{false}}>very very very very very very very long popover</BsPopover>
          </button>

`);

    setupForPositioning('right');

    await click('#target');
    let arrowPosition = parseInt(
      this.element
        .querySelector(`.${popoverArrowClass()}`)
        .style.transform.match(/translate(?:3d)?\(([0-9]+)px.*\)/)[1],
      10
    );
    assert.ok(
      Math.abs(arrowPosition - expectedArrowPosition) <= 2,
      `Expected position: ${expectedArrowPosition}, actual: ${arrowPosition}`
    );

    // check again to prevent regression of https://github.com/kaliber5/ember-bootstrap/issues/361
    await click('#target');
    await click('#target');
    arrowPosition = parseInt(
      this.element
        .querySelector(`.${popoverArrowClass()}`)
        .style.transform.match(/translate(?:3d)?\(([0-9]+)px.*\)/)[1],
      10
    );
    assert.ok(
      Math.abs(arrowPosition - expectedArrowPosition) <= 2,
      `Expected position: ${expectedArrowPosition}, actual: ${arrowPosition}`
    );
  });

  test('it stays open when clicked when rendered in place', async function (assert) {
    await render(hbs`

        <BsPopover>

Content

        </BsPopover>

    `);

    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#content');
    assert.dom('.popover').exists('popover is still visible');
  });

  test('it yields close action', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(hbs`

        <BsPopover @visible={{true}} @onHide={{action this.hide}} @onHidden={{action this.hidden}} as |po|>

Hide

        </BsPopover>

    `);
    await click('#hide');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
    assert.dom('.popover').doesNotExist('popover is not visible');
  });

  test('click-initiated close action does not interfere with click-to-open', async function (assert) {
    await render(hbs`

        <BsPopover as |po|>

Hide

        </BsPopover>

    `);
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#hide');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('click-initiated close action does not interfere with click-to-open when wormholed', async function (assert) {
    await render(hbs`

        <BsPopover as |po|>
Hide
</BsPopover>

    `);
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await click('#hide');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('non-click-initiated close action does not interfere with click-to-open', async function (assert) {
    await render(
      hbs`<div id="target"><BsPopover as |po|><input id="hide" onblur={{action po.close}}></BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await triggerEvent('#hide', 'blur');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('non-click-initiated close action does not interfere with click-to-open when wormholed', async function (assert) {
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div><div id="target"><BsPopover as |po|><input id="hide" onblur={{action po.close}}></BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').exists('popover is visible');
    await triggerEvent('#hide', 'blur');
    assert.dom('.popover').doesNotExist('popover is not visible');
    await click('#target');
    assert.dom('.popover').exists('popover visible again');
  });

  test('it passes all HTML attribute', async function (assert) {
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" class="wide" data-test role="foo">test</BsPopover></div>`
    );
    await click('#target');
    assert.dom('.popover').hasClass('wide');
    assert.dom('.popover').hasAttribute('role', 'foo');
    assert.dom('.popover').hasAttribute('data-test');
  });

  test("Renders in wormhole's default destination if renderInPlace is not set", async function (assert) {
    this.set('show', false);
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div>{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} />{{/if}}`
    );
    this.set('show', true);
    await settled();

    assert.dom('#ember-bootstrap-wormhole .popover').exists({ count: 1 }, 'Popover exists in wormhole');
  });

  test('Renders in test container if renderInPlace is not set', async function (assert) {
    this.set('show', false);
    await render(hbs`{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} />{{/if}}`);
    this.set('show', true);
    await settled();

    assert.dom('.popover').exists({ count: 1 }, 'Popover exists.');
    assert.dom('#wrapper .popover').doesNotExist();
  });

  test('Renders in place (no wormhole) if renderInPlace is set', async function (assert) {
    this.set('show', false);
    await render(
      hbs`<div id="ember-bootstrap-wormhole"></div><div id="wrapper">{{#if this.show}}<BsPopover @title="Simple popover" @visible={{true}} @fade={{false}} @renderInPlace={{true}} />{{/if}}</div>`
    );
    this.set('show', true);
    await settled();

    assert.dom('#wrapper .popover').exists({ count: 1 }, 'Popover exists in place.');
  });

  test('it calls onShow/onShown actions when showing popover by event [fade=false]', async function (assert) {
    let showAction = sinon.spy();
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    await click('#target');
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.calledOnce, 'shown action has been called');
  });

  test('it calls onShow/onShown actions when showing popover programmatically [fade=false]', async function (assert) {
    let showAction = sinon.spy();
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    this.set('visible', false);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @visible={{this.visible}} @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    this.set('visible', true);
    await settled();
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.calledOnce, 'shown action has been called');
  });

  test('it aborts showing if onShow action returns false', async function (assert) {
    let showAction = sinon.stub();
    showAction.returns(false);
    this.set('show', showAction);
    let shownAction = sinon.spy();
    this.set('shown', shownAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
    );
    await click('#target');
    assert.ok(showAction.calledOnce, 'show action has been called');
    assert.ok(shownAction.notCalled, 'show action has not been called');
    assert.dom('.popover').doesNotExist('popover is not visible');
  });

  test('it calls onHide/onHidden actions when hiding popover by event [fade=false]', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    await click('#target');
    await click('#target');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
  });

  test('it calls onHide/onHidden actions when hiding popover programmatically [fade=false]', async function (assert) {
    let hideAction = sinon.spy();
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    this.set('visible', true);
    await render(
      hbs`<div id="target"><BsPopover @visible={{this.visible}} @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    this.set('visible', false);
    await settled();
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.calledOnce, 'hidden action was called');
  });

  test('it aborts hiding if onHide action returns false', async function (assert) {
    let hideAction = sinon.stub();
    hideAction.returns(false);
    this.set('hide', hideAction);
    let hiddenAction = sinon.spy();
    this.set('hidden', hiddenAction);
    await render(
      hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
    );
    await click('#target');
    await click('#target');
    assert.ok(hideAction.calledOnce, 'hide action has been called');
    assert.ok(hiddenAction.notCalled, 'hidden action has not been called');
    assert.dom('.popover').exists({ count: 1 }, 'popover is visible');
  });

  test('it passes accessibility checks', async function (assert) {
    await render(hbs`
      <button type="button">
        Test
        <BsPopover @title="dummy title" @visible={{true}}>
          template block text
        </BsPopover>
      </button>
    `);

    await a11yAudit();
    assert.ok(true, 'A11y audit passed');
  });
});
<|endoftext|>