<commit_before>'use strict'

const App = require('./platform')
const common = require('./common')
const debug = require('debug')('electron-packager')
const fs = require('fs-extra')
const path = require('path')
const plist = require('plist')
const { notarize } = require('electron-notarize')
const { signAsync } = require('electron-osx-sign')

class MacApp extends App {
  constructor (opts, templatePath) {
    super(opts, templatePath)

    this.appName = opts.name
  }

  get appCategoryType () {
    return this.opts.appCategoryType
  }

  get appCopyright () {
    return this.opts.appCopyright
  }

  get appVersion () {
    return this.opts.appVersion
  }

  get buildVersion () {
    return this.opts.buildVersion
  }

  get enableDarkMode () {
    return this.opts.darwinDarkModeSupport
  }

  get usageDescription () {
    return this.opts.usageDescription
  }

  get protocols () {
    return this.opts.protocols.map((protocol) => {
      return {
        CFBundleURLName: protocol.name,
        CFBundleURLSchemes: [].concat(protocol.schemes)
      }
    })
  }

  get dotAppName () {
    return `${common.sanitizeAppName(this.appName)}.app`
  }

  get defaultBundleName () {
    return `com.electron.${common.sanitizeAppName(this.appName).toLowerCase()}`
  }

  get bundleName () {
    return filterCFBundleIdentifier(this.opts.appBundleId || this.defaultBundleName)
  }

  get originalResourcesDir () {
    return path.join(this.contentsPath, 'Resources')
  }

  get resourcesDir () {
    return path.join(this.dotAppName, 'Contents', 'Resources')
  }

  get electronBinaryDir () {
    return path.join(this.contentsPath, 'MacOS')
  }

  get originalElectronName () {
    return 'Electron'
  }

  get newElectronName () {
    return this.appPlist.CFBundleExecutable
  }

  get renamedAppPath () {
    return path.join(this.stagingPath, this.dotAppName)
  }

  get electronAppPath () {
    return path.join(this.stagingPath, `${this.originalElectronName}.app`)
  }

  get contentsPath () {
    return path.join(this.electronAppPath, 'Contents')
  }

  get frameworksPath () {
    return path.join(this.contentsPath, 'Frameworks')
  }

  get loginItemsPath () {
    return path.join(this.contentsPath, 'Library', 'LoginItems')
  }

  get loginHelperPath () {
    return path.join(this.loginItemsPath, 'Electron Login Helper.app')
  }

  updatePlist (base, displayName, identifier, name) {
    return Object.assign(base, {
      CFBundleDisplayName: displayName,
      CFBundleExecutable: common.sanitizeAppName(displayName),
      CFBundleIdentifier: identifier,
      CFBundleName: common.sanitizeAppName(name)
    })
  }

  updateHelperPlist (base, suffix, identifierIgnoresSuffix) {
    let helperSuffix, identifier, name
    if (suffix) {
      helperSuffix = `Helper ${suffix}`
      if (identifierIgnoresSuffix) {
        identifier = this.helperBundleIdentifier
      } else {
        identifier = `${this.helperBundleIdentifier}.${suffix}`
      }
      name = `${this.appName} ${helperSuffix}`
    } else {
      helperSuffix = 'Helper'
      identifier = this.helperBundleIdentifier
      name = this.appName
    }
    return this.updatePlist(base, `${this.appName} ${helperSuffix}`, identifier, name)
  }

  async extendAppPlist (propsOrFilename) {
    if (!propsOrFilename) {
      return Promise.resolve()
    }

    if (typeof propsOrFilename === 'string') {
      const plist = await this.loadPlist(propsOrFilename)
      return Object.assign(this.appPlist, plist)
    } else {
      return Object.assign(this.appPlist, propsOrFilename)
    }
  }

  async loadPlist (filename, propName) {
    const loadedPlist = plist.parse((await fs.readFile(filename)).toString())
    if (propName) {
      this[propName] = loadedPlist
    }
    return loadedPlist
  }

  ehPlistFilename (helper) {
    return this.helperPlistFilename(path.join(this.frameworksPath, helper))
  }

  helperPlistFilename (helperApp) {
    return path.join(helperApp, 'Contents', 'Info.plist')
  }

  async determinePlistFilesToUpdate () {
    const appPlistFilename = path.join(this.contentsPath, 'Info.plist')

    const plists = [
      [appPlistFilename, 'appPlist'],
      [this.ehPlistFilename('Electron Helper.app'), 'helperPlist']
    ]

    const possiblePlists = [
      [this.ehPlistFilename('Electron Helper (Renderer).app'), 'helperRendererPlist'],
      [this.ehPlistFilename('Electron Helper (Plugin).app'), 'helperPluginPlist'],
      [this.ehPlistFilename('Electron Helper (GPU).app'), 'helperGPUPlist'],
      [this.ehPlistFilename('Electron Helper EH.app'), 'helperEHPlist'],
      [this.ehPlistFilename('Electron Helper NP.app'), 'helperNPPlist'],
      [this.helperPlistFilename(this.loginHelperPath), 'loginHelperPlist']
    ]

    const optional = await Promise.all(possiblePlists.map(async item =>
      (await fs.pathExists(item[0])) ? item : null))
    return plists.concat(optional.filter(item => item))
  }

  async updatePlistFiles () {
    const appBundleIdentifier = this.bundleName
    this.helperBundleIdentifier = filterCFBundleIdentifier(this.opts.helperBundleId || `${appBundleIdentifier}.helper`)

    const plists = await this.determinePlistFilesToUpdate()
    await Promise.all(plists.map(plistArgs => this.loadPlist(...plistArgs)))
    await this.extendAppPlist(this.opts.extendInfo)
    this.appPlist = this.updatePlist(this.appPlist, this.executableName, appBundleIdentifier, this.appName)
    this.helperPlist = this.updateHelperPlist(this.helperPlist)
    const updateIfExists = [
      ['helperRendererPlist', '(Renderer)', true],
      ['helperPluginPlist', '(Plugin)', true],
      ['helperGPUPlist', '(GPU)', true],
      ['helperEHPlist', 'EH'],
      ['helperNPPlist', 'NP']
    ]
    for (const [plistKey, ...suffixArgs] of updateIfExists) {
      if (!this[plistKey]) continue
      this[plistKey] = this.updateHelperPlist(this[plistKey], ...suffixArgs)
    }

    if (this.loginHelperPlist) {
      const loginHelperName = common.sanitizeAppName(`${this.appName} Login Helper`)
      this.loginHelperPlist.CFBundleExecutable = loginHelperName
      this.loginHelperPlist.CFBundleIdentifier = `${appBundleIdentifier}.loginhelper`
      this.loginHelperPlist.CFBundleName = loginHelperName
    }

    if (this.appVersion) {
      this.appPlist.CFBundleShortVersionString = this.appPlist.CFBundleVersion = '' + this.appVersion
    }

    if (this.buildVersion) {
      this.appPlist.CFBundleVersion = '' + this.buildVersion
    }

    if (this.opts.protocols && this.opts.protocols.length) {
      this.appPlist.CFBundleURLTypes = this.protocols
    }

    if (this.appCategoryType) {
      this.appPlist.LSApplicationCategoryType = this.appCategoryType
    }

    if (this.appCopyright) {
      this.appPlist.NSHumanReadableCopyright = this.appCopyright
    }

    if (this.enableDarkMode) {
      this.appPlist.NSRequiresAquaSystemAppearance = false
    }

    if (this.usageDescription) {
      for (const [type, description] of Object.entries(this.usageDescription)) {
        this.appPlist[`NS${type}UsageDescription`] = description
      }
    }

    await Promise.all(plists.map(([filename, varName]) =>
      fs.writeFile(filename, plist.build(this[varName]))))
  }

  async moveHelpers () {
    const helpers = [' Helper', ' Helper EH', ' Helper NP', ' Helper (Renderer)', ' Helper (Plugin)', ' Helper (GPU)']
    await Promise.all(helpers.map(suffix => this.moveHelper(this.frameworksPath, suffix)))
    if (await fs.pathExists(this.loginItemsPath)) {
      await this.moveHelper(this.loginItemsPath, ' Login Helper')
    }
  }

  async moveHelper (helperDirectory, suffix) {
    const originalBasename = `Electron${suffix}`

    if (await fs.pathExists(path.join(helperDirectory, `${originalBasename}.app`))) {
      return this.renameHelperAndExecutable(
        helperDirectory,
        originalBasename,
        `${common.sanitizeAppName(this.appName)}${suffix}`
      )
    } else {
      return Promise.resolve()
    }
  }

  async renameHelperAndExecutable (helperDirectory, originalBasename, newBasename) {
    const originalAppname = `${originalBasename}.app`
    const executableBasePath = path.join(helperDirectory, originalAppname, 'Contents', 'MacOS')
    await this.relativeRename(executableBasePath, originalBasename, newBasename)
    await this.relativeRename(helperDirectory, originalAppname, `${newBasename}.app`)
  }

  async copyIcon () {
    if (!this.opts.icon) {
      return Promise.resolve()
    }

    let icon

    try {
      icon = await this.normalizeIconExtension('.icns')
    } catch {
      // Ignore error if icon doesn't exist, in case it's only available for other OSes
      /* istanbul ignore next */
      return Promise.resolve()
    }
    if (icon) {
      debug(`Copying icon "${icon}" to app's Resources as "${this.appPlist.CFBundleIconFile}"`)
      await fs.copy(icon, path.join(this.originalResourcesDir, this.appPlist.CFBundleIconFile))
    }
  }

  async renameAppAndHelpers () {
    await this.moveHelpers()
    await fs.rename(this.electronAppPath, this.renamedAppPath)
  }

  async signAppIfSpecified () {
    const osxSignOpt = this.opts.osxSign
    const platform = this.opts.platform
    const version = this.opts.electronVersion

    if ((platform === 'all' || platform === 'mas') &&
        osxSignOpt === undefined) {
      common.warning('signing is required for mas builds. Provide the osx-sign option, ' +
                     'or manually sign the app later.')
    }

    if (osxSignOpt) {
      const signOpts = createSignOpts(osxSignOpt, platform, this.renamedAppPath, version, this.opts.osxNotarize, this.opts.quiet)
      debug(`Running electron-osx-sign with the options ${JSON.stringify(signOpts)}`)
      try {
        await signAsync(signOpts)
      } catch (err) {
        // Although not signed successfully, the application is packed.
        common.warning(`Code sign failed; please retry manually. ${err}`)
      }
    }
  }

  async notarizeAppIfSpecified () {
    const osxNotarizeOpt = this.opts.osxNotarize

    /* istanbul ignore if */
    if (osxNotarizeOpt) {
      const notarizeOpts = createNotarizeOpts(
        osxNotarizeOpt,
        this.bundleName,
        this.renamedAppPath,
        this.opts.quiet
      )
      if (notarizeOpts) {
        return notarize(notarizeOpts)
      }
    }
  }

  async create () {
    await this.initialize()
    await this.updatePlistFiles()
    await this.copyIcon()
    await this.renameElectron()
    await this.renameAppAndHelpers()
    await this.copyExtraResources()
    await this.signAppIfSpecified()
    await this.notarizeAppIfSpecified()
    return this.move()
  }
}

/**
 * Remove special characters and allow only alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.)
 * Apple documentation:
 * https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
 */
function filterCFBundleIdentifier (identifier) {
  return identifier.replace(/ /g, '-').replace(/[^a-zA-Z0-9.-]/g, '')
}

function createSignOpts (properties, platform, app, version, notarize, quiet) {
  // use default sign opts if osx-sign is true, otherwise clone osx-sign object
  const signOpts = properties === true ? { identity: null } : { ...properties }

  // osx-sign options are handed off to sign module, but
  // with a few additions from the main options
  // user may think they can pass platform, app, or version, but they will be ignored
  common.subOptionWarning(signOpts, 'osx-sign', 'platform', platform, quiet)
  common.subOptionWarning(signOpts, 'osx-sign', 'app', app, quiet)
  common.subOptionWarning(signOpts, 'osx-sign', 'version', version, quiet)

  if (signOpts.binaries) {
    common.warning('osx-sign.binaries is not an allowed sub-option. Not passing to electron-osx-sign.')
    delete signOpts.binaries
  }

  // Take argument osx-sign as signing identity:
  // if opts.osxSign is true (bool), fallback to identity=null for
  // autodiscovery. Otherwise, provide signing certificate info.
  if (signOpts.identity === true) {
    signOpts.identity = null
  }

  if (notarize && !signOpts.hardenedRuntime) {
    common.warning('notarization is enabled but hardenedRuntime was not enabled in the signing ' +
      'options. It has been enabled for you but you should enable it in your config.')
    signOpts.hardenedRuntime = true
  }

  return signOpts
}

function createNotarizeOpts (properties, appBundleId, appPath, quiet) {
  const notarizeOpts = properties
  let notarize = true

  if (!notarizeOpts.appleId) {
    common.warning('The appleId sub-property is required when using notarization, notarize will not run')
    notarize = false
  }

  if (!notarizeOpts.appleIdPassword) {
    common.warning('The appleIdPassword sub-property is required when using notarization, notarize will not run')
    notarize = false
  }

  if (notarize) {
    // osxNotarize options are handed off to the electron-notarize module, but with a few
    // additions from the main options. The user may think they can pass bundle ID or appPath,
    // but they will be ignored.
    common.subOptionWarning(notarizeOpts, 'osxNotarize', 'appBundleId', appBundleId, quiet)
    common.subOptionWarning(notarizeOpts, 'osxNotarize', 'appPath', appPath, quiet)

    return notarizeOpts
  }
}

module.exports = {
  App: MacApp,
  createNotarizeOpts: createNotarizeOpts,
  createSignOpts: createSignOpts,
  filterCFBundleIdentifier: filterCFBundleIdentifier
}
<commit_msg>fix(mac): check for osxNotarize.hardened-runtime in addition to hardenedRuntime<commit_after>'use strict'

const App = require('./platform')
const common = require('./common')
const debug = require('debug')('electron-packager')
const fs = require('fs-extra')
const path = require('path')
const plist = require('plist')
const { notarize } = require('electron-notarize')
const { signAsync } = require('electron-osx-sign')

class MacApp extends App {
  constructor (opts, templatePath) {
    super(opts, templatePath)

    this.appName = opts.name
  }

  get appCategoryType () {
    return this.opts.appCategoryType
  }

  get appCopyright () {
    return this.opts.appCopyright
  }

  get appVersion () {
    return this.opts.appVersion
  }

  get buildVersion () {
    return this.opts.buildVersion
  }

  get enableDarkMode () {
    return this.opts.darwinDarkModeSupport
  }

  get usageDescription () {
    return this.opts.usageDescription
  }

  get protocols () {
    return this.opts.protocols.map((protocol) => {
      return {
        CFBundleURLName: protocol.name,
        CFBundleURLSchemes: [].concat(protocol.schemes)
      }
    })
  }

  get dotAppName () {
    return `${common.sanitizeAppName(this.appName)}.app`
  }

  get defaultBundleName () {
    return `com.electron.${common.sanitizeAppName(this.appName).toLowerCase()}`
  }

  get bundleName () {
    return filterCFBundleIdentifier(this.opts.appBundleId || this.defaultBundleName)
  }

  get originalResourcesDir () {
    return path.join(this.contentsPath, 'Resources')
  }

  get resourcesDir () {
    return path.join(this.dotAppName, 'Contents', 'Resources')
  }

  get electronBinaryDir () {
    return path.join(this.contentsPath, 'MacOS')
  }

  get originalElectronName () {
    return 'Electron'
  }

  get newElectronName () {
    return this.appPlist.CFBundleExecutable
  }

  get renamedAppPath () {
    return path.join(this.stagingPath, this.dotAppName)
  }

  get electronAppPath () {
    return path.join(this.stagingPath, `${this.originalElectronName}.app`)
  }

  get contentsPath () {
    return path.join(this.electronAppPath, 'Contents')
  }

  get frameworksPath () {
    return path.join(this.contentsPath, 'Frameworks')
  }

  get loginItemsPath () {
    return path.join(this.contentsPath, 'Library', 'LoginItems')
  }

  get loginHelperPath () {
    return path.join(this.loginItemsPath, 'Electron Login Helper.app')
  }

  updatePlist (base, displayName, identifier, name) {
    return Object.assign(base, {
      CFBundleDisplayName: displayName,
      CFBundleExecutable: common.sanitizeAppName(displayName),
      CFBundleIdentifier: identifier,
      CFBundleName: common.sanitizeAppName(name)
    })
  }

  updateHelperPlist (base, suffix, identifierIgnoresSuffix) {
    let helperSuffix, identifier, name
    if (suffix) {
      helperSuffix = `Helper ${suffix}`
      if (identifierIgnoresSuffix) {
        identifier = this.helperBundleIdentifier
      } else {
        identifier = `${this.helperBundleIdentifier}.${suffix}`
      }
      name = `${this.appName} ${helperSuffix}`
    } else {
      helperSuffix = 'Helper'
      identifier = this.helperBundleIdentifier
      name = this.appName
    }
    return this.updatePlist(base, `${this.appName} ${helperSuffix}`, identifier, name)
  }

  async extendAppPlist (propsOrFilename) {
    if (!propsOrFilename) {
      return Promise.resolve()
    }

    if (typeof propsOrFilename === 'string') {
      const plist = await this.loadPlist(propsOrFilename)
      return Object.assign(this.appPlist, plist)
    } else {
      return Object.assign(this.appPlist, propsOrFilename)
    }
  }

  async loadPlist (filename, propName) {
    const loadedPlist = plist.parse((await fs.readFile(filename)).toString())
    if (propName) {
      this[propName] = loadedPlist
    }
    return loadedPlist
  }

  ehPlistFilename (helper) {
    return this.helperPlistFilename(path.join(this.frameworksPath, helper))
  }

  helperPlistFilename (helperApp) {
    return path.join(helperApp, 'Contents', 'Info.plist')
  }

  async determinePlistFilesToUpdate () {
    const appPlistFilename = path.join(this.contentsPath, 'Info.plist')

    const plists = [
      [appPlistFilename, 'appPlist'],
      [this.ehPlistFilename('Electron Helper.app'), 'helperPlist']
    ]

    const possiblePlists = [
      [this.ehPlistFilename('Electron Helper (Renderer).app'), 'helperRendererPlist'],
      [this.ehPlistFilename('Electron Helper (Plugin).app'), 'helperPluginPlist'],
      [this.ehPlistFilename('Electron Helper (GPU).app'), 'helperGPUPlist'],
      [this.ehPlistFilename('Electron Helper EH.app'), 'helperEHPlist'],
      [this.ehPlistFilename('Electron Helper NP.app'), 'helperNPPlist'],
      [this.helperPlistFilename(this.loginHelperPath), 'loginHelperPlist']
    ]

    const optional = await Promise.all(possiblePlists.map(async item =>
      (await fs.pathExists(item[0])) ? item : null))
    return plists.concat(optional.filter(item => item))
  }

  async updatePlistFiles () {
    const appBundleIdentifier = this.bundleName
    this.helperBundleIdentifier = filterCFBundleIdentifier(this.opts.helperBundleId || `${appBundleIdentifier}.helper`)

    const plists = await this.determinePlistFilesToUpdate()
    await Promise.all(plists.map(plistArgs => this.loadPlist(...plistArgs)))
    await this.extendAppPlist(this.opts.extendInfo)
    this.appPlist = this.updatePlist(this.appPlist, this.executableName, appBundleIdentifier, this.appName)
    this.helperPlist = this.updateHelperPlist(this.helperPlist)
    const updateIfExists = [
      ['helperRendererPlist', '(Renderer)', true],
      ['helperPluginPlist', '(Plugin)', true],
      ['helperGPUPlist', '(GPU)', true],
      ['helperEHPlist', 'EH'],
      ['helperNPPlist', 'NP']
    ]
    for (const [plistKey, ...suffixArgs] of updateIfExists) {
      if (!this[plistKey]) continue
      this[plistKey] = this.updateHelperPlist(this[plistKey], ...suffixArgs)
    }

    if (this.loginHelperPlist) {
      const loginHelperName = common.sanitizeAppName(`${this.appName} Login Helper`)
      this.loginHelperPlist.CFBundleExecutable = loginHelperName
      this.loginHelperPlist.CFBundleIdentifier = `${appBundleIdentifier}.loginhelper`
      this.loginHelperPlist.CFBundleName = loginHelperName
    }

    if (this.appVersion) {
      this.appPlist.CFBundleShortVersionString = this.appPlist.CFBundleVersion = '' + this.appVersion
    }

    if (this.buildVersion) {
      this.appPlist.CFBundleVersion = '' + this.buildVersion
    }

    if (this.opts.protocols && this.opts.protocols.length) {
      this.appPlist.CFBundleURLTypes = this.protocols
    }

    if (this.appCategoryType) {
      this.appPlist.LSApplicationCategoryType = this.appCategoryType
    }

    if (this.appCopyright) {
      this.appPlist.NSHumanReadableCopyright = this.appCopyright
    }

    if (this.enableDarkMode) {
      this.appPlist.NSRequiresAquaSystemAppearance = false
    }

    if (this.usageDescription) {
      for (const [type, description] of Object.entries(this.usageDescription)) {
        this.appPlist[`NS${type}UsageDescription`] = description
      }
    }

    await Promise.all(plists.map(([filename, varName]) =>
      fs.writeFile(filename, plist.build(this[varName]))))
  }

  async moveHelpers () {
    const helpers = [' Helper', ' Helper EH', ' Helper NP', ' Helper (Renderer)', ' Helper (Plugin)', ' Helper (GPU)']
    await Promise.all(helpers.map(suffix => this.moveHelper(this.frameworksPath, suffix)))
    if (await fs.pathExists(this.loginItemsPath)) {
      await this.moveHelper(this.loginItemsPath, ' Login Helper')
    }
  }

  async moveHelper (helperDirectory, suffix) {
    const originalBasename = `Electron${suffix}`

    if (await fs.pathExists(path.join(helperDirectory, `${originalBasename}.app`))) {
      return this.renameHelperAndExecutable(
        helperDirectory,
        originalBasename,
        `${common.sanitizeAppName(this.appName)}${suffix}`
      )
    } else {
      return Promise.resolve()
    }
  }

  async renameHelperAndExecutable (helperDirectory, originalBasename, newBasename) {
    const originalAppname = `${originalBasename}.app`
    const executableBasePath = path.join(helperDirectory, originalAppname, 'Contents', 'MacOS')
    await this.relativeRename(executableBasePath, originalBasename, newBasename)
    await this.relativeRename(helperDirectory, originalAppname, `${newBasename}.app`)
  }

  async copyIcon () {
    if (!this.opts.icon) {
      return Promise.resolve()
    }

    let icon

    try {
      icon = await this.normalizeIconExtension('.icns')
    } catch {
      // Ignore error if icon doesn't exist, in case it's only available for other OSes
      /* istanbul ignore next */
      return Promise.resolve()
    }
    if (icon) {
      debug(`Copying icon "${icon}" to app's Resources as "${this.appPlist.CFBundleIconFile}"`)
      await fs.copy(icon, path.join(this.originalResourcesDir, this.appPlist.CFBundleIconFile))
    }
  }

  async renameAppAndHelpers () {
    await this.moveHelpers()
    await fs.rename(this.electronAppPath, this.renamedAppPath)
  }

  async signAppIfSpecified () {
    const osxSignOpt = this.opts.osxSign
    const platform = this.opts.platform
    const version = this.opts.electronVersion

    if ((platform === 'all' || platform === 'mas') &&
        osxSignOpt === undefined) {
      common.warning('signing is required for mas builds. Provide the osx-sign option, ' +
                     'or manually sign the app later.')
    }

    if (osxSignOpt) {
      const signOpts = createSignOpts(osxSignOpt, platform, this.renamedAppPath, version, this.opts.osxNotarize, this.opts.quiet)
      debug(`Running electron-osx-sign with the options ${JSON.stringify(signOpts)}`)
      try {
        await signAsync(signOpts)
      } catch (err) {
        // Although not signed successfully, the application is packed.
        common.warning(`Code sign failed; please retry manually. ${err}`)
      }
    }
  }

  async notarizeAppIfSpecified () {
    const osxNotarizeOpt = this.opts.osxNotarize

    /* istanbul ignore if */
    if (osxNotarizeOpt) {
      const notarizeOpts = createNotarizeOpts(
        osxNotarizeOpt,
        this.bundleName,
        this.renamedAppPath,
        this.opts.quiet
      )
      if (notarizeOpts) {
        return notarize(notarizeOpts)
      }
    }
  }

  async create () {
    await this.initialize()
    await this.updatePlistFiles()
    await this.copyIcon()
    await this.renameElectron()
    await this.renameAppAndHelpers()
    await this.copyExtraResources()
    await this.signAppIfSpecified()
    await this.notarizeAppIfSpecified()
    return this.move()
  }
}

/**
 * Remove special characters and allow only alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.)
 * Apple documentation:
 * https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070
 */
function filterCFBundleIdentifier (identifier) {
  return identifier.replace(/ /g, '-').replace(/[^a-zA-Z0-9.-]/g, '')
}

function createSignOpts (properties, platform, app, version, notarize, quiet) {
  // use default sign opts if osx-sign is true, otherwise clone osx-sign object
  const signOpts = properties === true ? { identity: null } : { ...properties }

  // osx-sign options are handed off to sign module, but
  // with a few additions from the main options
  // user may think they can pass platform, app, or version, but they will be ignored
  common.subOptionWarning(signOpts, 'osx-sign', 'platform', platform, quiet)
  common.subOptionWarning(signOpts, 'osx-sign', 'app', app, quiet)
  common.subOptionWarning(signOpts, 'osx-sign', 'version', version, quiet)

  if (signOpts.binaries) {
    common.warning('osx-sign.binaries is not an allowed sub-option. Not passing to electron-osx-sign.')
    delete signOpts.binaries
  }

  // Take argument osx-sign as signing identity:
  // if opts.osxSign is true (bool), fallback to identity=null for
  // autodiscovery. Otherwise, provide signing certificate info.
  if (signOpts.identity === true) {
    signOpts.identity = null
  }

  if (notarize && !signOpts.hardenedRuntime && !signOpts['hardened-runtime']) {
    common.warning('notarization is enabled but hardenedRuntime was not enabled in the signing ' +
      'options. It has been enabled for you but you should enable it in your config.')
    signOpts.hardenedRuntime = true
  }

  return signOpts
}

function createNotarizeOpts (properties, appBundleId, appPath, quiet) {
  const notarizeOpts = properties
  let notarize = true

  if (!notarizeOpts.appleId) {
    common.warning('The appleId sub-property is required when using notarization, notarize will not run')
    notarize = false
  }

  if (!notarizeOpts.appleIdPassword) {
    common.warning('The appleIdPassword sub-property is required when using notarization, notarize will not run')
    notarize = false
  }

  if (notarize) {
    // osxNotarize options are handed off to the electron-notarize module, but with a few
    // additions from the main options. The user may think they can pass bundle ID or appPath,
    // but they will be ignored.
    common.subOptionWarning(notarizeOpts, 'osxNotarize', 'appBundleId', appBundleId, quiet)
    common.subOptionWarning(notarizeOpts, 'osxNotarize', 'appPath', appPath, quiet)

    return notarizeOpts
  }
}

module.exports = {
  App: MacApp,
  createNotarizeOpts: createNotarizeOpts,
  createSignOpts: createSignOpts,
  filterCFBundleIdentifier: filterCFBundleIdentifier
}
<|endoftext|>


<commit_before>var ok = require('assert').ok,
    slice = [].slice

function detach (cartridge) {
    var magazine = cartridge._magazine, cache = magazine._cache
    magazine.heft -= cartridge.heft
    cache.heft -= cartridge.heft
    delete cache._cache[cartridge._compoundKey]
    magazine.count--
    cache.count--
    unlink(cartridge)
}

function unlink (cartridge, prefix) {
    if (!prefix) {
        unlink(cartridge, 'cache')
        unlink(cartridge, 'magazine')
    } else {
        var prev = '_' + prefix + 'Previous'
        var next = '_' + prefix + 'Next'
        cartridge[prev][next] = cartridge[next]
        cartridge[next][prev] = cartridge[prev]
    }
}

function link (cartridge, previous, prefix) {
    var prev = '_' + prefix + 'Previous'
    var next = '_' + prefix + 'Next'
    cartridge[next] = previous[next]
    cartridge[prev] = previous
    cartridge[next][prev] = cartridge
    previous[next] = cartridge
}

function Cache (options) {
    options = options || {}

    this._clock = options.clock || function () {
        return Date.now()
    }

    var head = {}
    head._cachePrevious = head._cacheNext = head

    this._cache = {}
    this._head = head
    this._nextKey = 0

    this.count = 0
    this.holds = 0
    this.heft = 0
}

Cache.prototype.createMagazine = function () {
    var key = ':' + (++this._nextKey) + ':'
    return new Magazine(this, key)
}

Cache.prototype.purge = function () {
    return purge.call(this, '_cachePrevious', slice.call(arguments))
}

Cache.prototype.expire = function (expired) {
    expire(this, expired)
}

function Magazine (cache, key) {
    var head = {}
    head._magazinePrevious = head._magazineNext = head

    this._cache = cache
    this._key = key
    this._head = head

    this.count = 0
    this.holds = 0
    this.heft = 0
}

Magazine.prototype.hold = function (key, defaultValue) {
    var compoundKey = this._key + key
    var cartridge = this._cache._cache[compoundKey]
    if (!cartridge) {
        if (typeof defaultValue == 'function') {
            defaultValue = defaultValue()
        }
        cartridge = this._cache._cache[compoundKey] =
            new Cartridge(this, key, defaultValue, compoundKey)
        this.count++
        this._cache.count++
    } else {
        unlink(cartridge)
    }
    link(cartridge, this._cache._head, 'cache')
    link(cartridge, this._head, 'magazine')
    cartridge.holds++
    this.holds++
    this._cache.holds++
    cartridge.when = this._cache._clock()
    return cartridge
}

// todo: dubious, you should track your own holds.
Magazine.prototype.get = function (key) {
    var compoundKey = this._key + key
    var cartridge = this._cache._cache[compoundKey]
    if (!cartridge || !cartridge.holds) {
        throw new Error('attempt to get a cartridge not held')
    }
    return cartridge
}

function expire (collection, expired) {
    var purge = collection.purge()
    while (purge.cartridge && purge.cartridge.when <= expired) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()
}

// todo: legacy, do not document, use expire or iterator interface.
function purge (next, vargs) {
    var downTo, condition, gather, stop, head, iterator, cache, magazine
    if (vargs.length == 0) {
        return new Purge(this, next)
    }
    downTo = vargs.shift()
    if (typeof vargs[0] == 'function') {
        condition = vargs.shift()
    }
    if (Array.isArray(vargs[0])) {
        gather = vargs.shift()
    }
    condition || (condition = function () { return true })
    stop = downTo
    head = this._head
    iterator = head
    if (typeof downTo == 'number') {
        downTo = Math.max(downTo, -1)
        stop = function () { return this.heft <= downTo }.bind(this)
    }
    while (iterator[next] !== head && !stop(iterator[next])) {
        var cartridge = iterator[next]
        if (!cartridge.holds && condition(cartridge)) {
            magazine = cartridge._magazine, cache = magazine._cache
            if (gather) {
                gather.push(cartridge.value)
            }
            detach(cartridge)
        } else {
            iterator = cartridge
        }
    }
}

Magazine.prototype.purge = function () {
    return purge.call(this, '_magazinePrevious', slice.call(arguments))
}

Magazine.prototype.expire = function (expired) {
    expire(this, expired)
}

function Cartridge (magazine, key, value, compoundKey) {
    this.key = key
    this.value = value

    this._magazine = magazine
    this._compoundKey = compoundKey

    this.heft = 0
    this.holds = 0
}

Cartridge.prototype.adjustHeft = function (heft) {
    this.heft += heft
    this._magazine.heft += heft
    this._magazine._cache.heft += heft
    return this
}

Cartridge.prototype.release = function () {
    if (!this.holds) {
        throw new Error('attempt to release a cartridge not held')
    }
    if (--this.holds == 0) {
        this._magazine.holds--
        this._magazine._cache.holds--
    }
}

Cartridge.prototype.remove = function () {
    if (this.holds != 1) {
        throw new Error('attempt to remove cartridge held by others')
    }
    detach(this)
}

function Purge (object, next) {
    this._object = object
    this._next = next
    this.cartridge = this._object._head
    this.next()
}

Purge.prototype.next = function () {
    do {
        this.cartridge = this.cartridge[this._next] === this._object._head
                       ? null : this.cartridge[this._next]
    } while (this.cartridge && this.cartridge.holds)
    if (this.cartridge) {
        this.cartridge.holds = 1
    }
}

Purge.prototype.release = function () {
    if (this.cartridge) {
        this.cartridge.release()
    }
}

module.exports = Cache
<commit_msg>Remove `Magazine.get()`.<commit_after>var ok = require('assert').ok,
    slice = [].slice

function detach (cartridge) {
    var magazine = cartridge._magazine, cache = magazine._cache
    magazine.heft -= cartridge.heft
    cache.heft -= cartridge.heft
    delete cache._cache[cartridge._compoundKey]
    magazine.count--
    cache.count--
    unlink(cartridge)
}

function unlink (cartridge, prefix) {
    if (!prefix) {
        unlink(cartridge, 'cache')
        unlink(cartridge, 'magazine')
    } else {
        var prev = '_' + prefix + 'Previous'
        var next = '_' + prefix + 'Next'
        cartridge[prev][next] = cartridge[next]
        cartridge[next][prev] = cartridge[prev]
    }
}

function link (cartridge, previous, prefix) {
    var prev = '_' + prefix + 'Previous'
    var next = '_' + prefix + 'Next'
    cartridge[next] = previous[next]
    cartridge[prev] = previous
    cartridge[next][prev] = cartridge
    previous[next] = cartridge
}

function Cache (options) {
    options = options || {}

    this._clock = options.clock || function () {
        return Date.now()
    }

    var head = {}
    head._cachePrevious = head._cacheNext = head

    this._cache = {}
    this._head = head
    this._nextKey = 0

    this.count = 0
    this.holds = 0
    this.heft = 0
}

Cache.prototype.createMagazine = function () {
    var key = ':' + (++this._nextKey) + ':'
    return new Magazine(this, key)
}

Cache.prototype.purge = function () {
    return purge.call(this, '_cachePrevious', slice.call(arguments))
}

Cache.prototype.expire = function (expired) {
    expire(this, expired)
}

function Magazine (cache, key) {
    var head = {}
    head._magazinePrevious = head._magazineNext = head

    this._cache = cache
    this._key = key
    this._head = head

    this.count = 0
    this.holds = 0
    this.heft = 0
}

Magazine.prototype.hold = function (key, defaultValue) {
    var compoundKey = this._key + key
    var cartridge = this._cache._cache[compoundKey]
    if (!cartridge) {
        if (typeof defaultValue == 'function') {
            defaultValue = defaultValue()
        }
        cartridge = this._cache._cache[compoundKey] =
            new Cartridge(this, key, defaultValue, compoundKey)
        this.count++
        this._cache.count++
    } else {
        unlink(cartridge)
    }
    link(cartridge, this._cache._head, 'cache')
    link(cartridge, this._head, 'magazine')
    cartridge.holds++
    this.holds++
    this._cache.holds++
    cartridge.when = this._cache._clock()
    return cartridge
}

function expire (collection, expired) {
    var purge = collection.purge()
    while (purge.cartridge && purge.cartridge.when <= expired) {
        purge.cartridge.remove()
        purge.next()
    }
    purge.release()
}

// todo: legacy, do not document, use expire or iterator interface.
function purge (next, vargs) {
    var downTo, condition, gather, stop, head, iterator, cache, magazine
    if (vargs.length == 0) {
        return new Purge(this, next)
    }
    downTo = vargs.shift()
    if (typeof vargs[0] == 'function') {
        condition = vargs.shift()
    }
    if (Array.isArray(vargs[0])) {
        gather = vargs.shift()
    }
    condition || (condition = function () { return true })
    stop = downTo
    head = this._head
    iterator = head
    if (typeof downTo == 'number') {
        downTo = Math.max(downTo, -1)
        stop = function () { return this.heft <= downTo }.bind(this)
    }
    while (iterator[next] !== head && !stop(iterator[next])) {
        var cartridge = iterator[next]
        if (!cartridge.holds && condition(cartridge)) {
            magazine = cartridge._magazine, cache = magazine._cache
            if (gather) {
                gather.push(cartridge.value)
            }
            detach(cartridge)
        } else {
            iterator = cartridge
        }
    }
}

Magazine.prototype.purge = function () {
    return purge.call(this, '_magazinePrevious', slice.call(arguments))
}

Magazine.prototype.expire = function (expired) {
    expire(this, expired)
}

function Cartridge (magazine, key, value, compoundKey) {
    this.key = key
    this.value = value

    this._magazine = magazine
    this._compoundKey = compoundKey

    this.heft = 0
    this.holds = 0
}

Cartridge.prototype.adjustHeft = function (heft) {
    this.heft += heft
    this._magazine.heft += heft
    this._magazine._cache.heft += heft
    return this
}

Cartridge.prototype.release = function () {
    if (!this.holds) {
        throw new Error('attempt to release a cartridge not held')
    }
    if (--this.holds == 0) {
        this._magazine.holds--
        this._magazine._cache.holds--
    }
}

Cartridge.prototype.remove = function () {
    if (this.holds != 1) {
        throw new Error('attempt to remove cartridge held by others')
    }
    detach(this)
}

function Purge (object, next) {
    this._object = object
    this._next = next
    this.cartridge = this._object._head
    this.next()
}

Purge.prototype.next = function () {
    do {
        this.cartridge = this.cartridge[this._next] === this._object._head
                       ? null : this.cartridge[this._next]
    } while (this.cartridge && this.cartridge.holds)
    if (this.cartridge) {
        this.cartridge.holds = 1
    }
}

Purge.prototype.release = function () {
    if (this.cartridge) {
        this.cartridge.release()
    }
}

module.exports = Cache
<|endoftext|>


<commit_before>var http = require('http');
var fs = require('fs');

var Server = function()
{
	console.log('Server has started !');
}

Server.prototype.start = function(){

	http.createServer(function (req, res) {
	//check the request url
	console.log("Received request url: " + req.url);
	//check if the requet is a get
		if(req.method == 'GET')
		{
			fs.exists('./Image' + req.url, function (exists)
            {
				if (exists)
                  {
                      //read the json file
                        fs.readFile(req.url, function(error, data)
                        {
                            if (error)
                            {
                                //error notification to the user
								res.writeHead(500,{'content-type': 'text/html'});
								res.end('
File reading error
');
                            }
                              else
                              {
                                //write the data to the file
                                res.writeHead(200,{'content-type':'image/jpg'});
                                response.end(data);
                              }
                        }
                    }
		}

	}).listen(8080);
}

var myServer = new Server();
myServer.start();

<commit_msg>added error checking and completed assignment3<commit_after>//Created by Dhirendra Gupta at MindStix

//import required modules
var http = require('http');
var fs = require('fs');

//Sever class with constructor
var Server = function()
{
	console.log('Server has started !');
}

//The Sever.prototype property represents the Server prototype object.
//using Sever.prototype object create a start function as below
Server.prototype.start = function()
{

	http.createServer(function (req, res)
  {
	//check the request url
	console.log("Received request url: " + req.url);

  //check if the requet is a get
		if(req.method == 'GET')
		{
      //checking if reaquested image file exist or not
			fs.exists('./Image' + req.url, function (exists)
            {
				if (exists)
                  {
                      //read the image file
                        fs.readFile('./Image'+req.url, function(error, data)
                        {
                            if (error)
                            {
                                //display error to the user
								                res.writeHead(500,{'content-type': 'text/html'});
								                res.end('
File reading error
');
                            }
                              else
                              {
                                //display the data to the user
                                res.writeHead(200,{'content-type':'image/jpg'});
                                res.end(data);
                              }

                        });
                    }

                    else
                    {
                       //if requested image file does not exist display error to the user
                        res.writeHead(404, {'content-type':'text/html'});
                        res.end('
This Page Not found, Please check your URL
');
                    }
            });
    }

    else
    {
      //If the request is other than GET it will be traeted as Bad request
      res.writeHead(401,{'content-type':'text/html'});
      res.end('
This is a bad request
')
    }

	}).listen(8000, function(){
    console.log('Listening to port number 8000 !')
  });
}

//create a Server object and start it.
var myServer = new Server();
myServer.start();<|endoftext|>


<commit_before>var child_process = require('child_process')
var events = require('events')
var gtp = require('./index')

var Controller = function(exec, args) {
    var self = this
    events.EventEmitter.call(self)

    self._buffer = ''
    self.commands = []
    self.error = false
    self.process = child_process.execFile(exec, args)

    self.process.on('error', function() {
        self.error = true
    })

    self.process.on('exit', function(signal) {
        self.emit('quit', signal)
    })

    self.process.stdout.on('data', function(data) {
        self._buffer += (data + '').replace(/\r/g, '').replace(/#.*?\n/g, '').replace(/\t/g, ' ')

        var start = self._buffer.indexOf('\n\n')

        while (start != -1) {
            var response = gtp.parseResponse(self._buffer.substr(0, start))
            self._buffer = self._buffer.substr(start + 2)

            if (self.commands.length > 0) {
                self.emit('response-' + self.commands[0].internalId, response, self.commands[0])
                self.commands.splice(0, 1)
            }

            start = self._buffer.indexOf('\n\n')
        }
    })

    self.process.stderr.on('data', function(data) {})
}

require('util').inherits(Controller, events.EventEmitter)

Controller.prototype.sendCommand = function(command) {
    this.commands.push(command)

    try {
        this.process.stdin.write(command.toString() + '\n')
    } catch(e) {
        this.emit(
            'response-' + command.internalId,
            new gtp.Response(command.id, 'connection error', true, true),
            command
        )
        this.commands.splice(0, 1)
    }
}

module.exports = Controller
<commit_msg>Execute engines in their own working directory<commit_after>var child_process = require('child_process')
var path = require('path')
var events = require('events')
var gtp = require('./index')

var Controller = function(exec, args) {
    var self = this
    events.EventEmitter.call(self)

    self._buffer = ''
    self.commands = []
    self.error = false
    self.process = child_process.execFile(exec, args, {
        cwd: path.dirname(exec)
    })

    self.process.on('error', function() {
        self.error = true
    })

    self.process.on('exit', function(signal) {
        self.emit('quit', signal)
    })

    self.process.stdout.on('data', function(data) {
        self._buffer += (data + '').replace(/\r/g, '').replace(/#.*?\n/g, '').replace(/\t/g, ' ')

        var start = self._buffer.indexOf('\n\n')

        while (start != -1) {
            var response = gtp.parseResponse(self._buffer.substr(0, start))
            self._buffer = self._buffer.substr(start + 2)

            if (self.commands.length > 0) {
                self.emit('response-' + self.commands[0].internalId, response, self.commands[0])
                self.commands.splice(0, 1)
            }

            start = self._buffer.indexOf('\n\n')
        }
    })

    self.process.stderr.on('data', function(data) {})
}

require('util').inherits(Controller, events.EventEmitter)

Controller.prototype.sendCommand = function(command) {
    this.commands.push(command)

    try {
        this.process.stdin.write(command.toString() + '\n')
    } catch(e) {
        this.emit(
            'response-' + command.internalId,
            new gtp.Response(command.id, 'connection error', true, true),
            command
        )
        this.commands.splice(0, 1)
    }
}

module.exports = Controller
<|endoftext|>


<commit_before>import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {addLocaleData} from 'react-intl'
import {IntlProvider} from 'react-intl-redux'
import consoleLogger from '../consoleLogger'
import _union from 'lodash/union'
import _merge from 'lodash/merge'
import {ThemeProvider} from 'styled-components'

import de from 'react-intl/locale-data/de'
import en from 'react-intl/locale-data/en'
import fr from 'react-intl/locale-data/fr'
import it from 'react-intl/locale-data/it'

import {LoadMask} from 'tocco-ui'
import {ToccoTheme} from 'tocco-theme'

import intl from '../intl'
import errorLogging from '../errorLogging'

export const createApp = (name,
  content,
  store,
  {
    input = {},
    actions = undefined,
    publicPath = undefined,
    textResourceModules = [],
    customTheme = {}
  }) => {
  try {
    const theme = _merge({}, ToccoTheme, customTheme)

    if (publicPath) {
      setWebpacksPublicPath(publicPath)
    }

    if (actions) {
      dispatchActions(actions, store)
    }

    const initIntlPromise = setupIntl(input, store, name, textResourceModules)
    const component = getAppComponent(store, initIntlPromise, name, content, theme)

    return {
      renderComponent: () => component,
      store,
      methods: {
        setLocale: locale => intl.setLocale(store, textResourceModules, locale)
      }
    }
  } catch (error) {
    try {
      store.dispatch(errorLogging.logError('Error', 'Error creating react application: ', error))
    } catch (loggingError) {
      consoleLogger.logError('Error creating react application: ', error)
      consoleLogger.logError('Unable to log error: ', loggingError)
    }
  }
}

export const renderApp = (app, mountElementName = 'root') => {
  const mountElement = document.getElementById(mountElementName)
  let render = () => {
    ReactDOM.render(app, mountElement)
  }

  if (__DEV__ && module.hot) {
    const renderApp = render
    const renderError = error => {
      const RedBox = require('redbox-react')

      ReactDOM.render(<RedBox error={error}/>, mountElement)
    }
    render = () => {
      try {
        renderApp()
      } catch (error) {
        renderError(error)
      }
    }
  }
  render()
}

export const reloadApp = (app, mountElementName = 'root') => {
  const mountElement = document.getElementById(mountElementName)
  ReactDOM.unmountComponentAtNode(mountElement)
  renderApp(app, mountElementName)
}

export const registerAppInRegistry = (appName, initFunction) => {
  if (window.reactRegistry) {
    window.reactRegistry.register(appName, initFunction)
  }
}

const dispatchActions = (actions, store) => {
  actions.forEach(action => {
    store.dispatch(action)
  })
}

const setWebpacksPublicPath = publicPath => {
  /* eslint camelcase: 0 */
  __webpack_public_path__ = publicPath
}

const getAppComponent = (store, initIntlPromise, name, content, theme) => (
  <ThemeProvider theme={theme}>

      <Provider store={store}>
        <LoadMask promises={[initIntlPromise]}>
          <IntlProvider>
            <div className={`tocco-${name}`}>
              {content}

          </IntlProvider>
        </LoadMask>
      </Provider>

  </ThemeProvider>
)

const setupIntl = (input, store, module, textResourceModules) => {
  const modules = _union([module], textResourceModules)
  addLocaleData([...de, ...en, ...fr, ...it])
  const locale = input ? input.locale : null
  return intl.initIntl(store, modules, locale)
}
<commit_msg>style: provide theme<commit_after>import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import {addLocaleData} from 'react-intl'
import {IntlProvider} from 'react-intl-redux'
import consoleLogger from '../consoleLogger'
import _union from 'lodash/union'
import _merge from 'lodash/merge'
import {ThemeProvider} from 'styled-components'

import de from 'react-intl/locale-data/de'
import en from 'react-intl/locale-data/en'
import fr from 'react-intl/locale-data/fr'
import it from 'react-intl/locale-data/it'

import {LoadMask} from 'tocco-ui'
import {ToccoTheme} from 'tocco-theme'

import intl from '../intl'
import errorLogging from '../errorLogging'

export const createApp = (name,
  content,
  store,
  {
    input = {},
    actions = undefined,
    publicPath = undefined,
    textResourceModules = [],
    customTheme = {}
  }) => {
  try {
    const theme = _merge({}, ToccoTheme, customTheme)

    if (publicPath) {
      setWebpacksPublicPath(publicPath)
    }

    if (actions) {
      dispatchActions(actions, store)
    }

    const initIntlPromise = setupIntl(input, store, name, textResourceModules)
    const component = getAppComponent(store, initIntlPromise, name, content, theme)

    return {
      renderComponent: () => component,
      store,
      methods: {
        setLocale: locale => intl.setLocale(store, textResourceModules, locale)
      }
    }
  } catch (error) {
    try {
      store.dispatch(errorLogging.logError('Error', 'Error creating react application: ', error))
    } catch (loggingError) {
      consoleLogger.logError('Error creating react application: ', error)
      consoleLogger.logError('Unable to log error: ', loggingError)
    }
  }
}

export const renderApp = (app, mountElementName = 'root') => {
  const mountElement = document.getElementById(mountElementName)
  let render = () => {
    ReactDOM.render(app, mountElement)
  }

  if (__DEV__ && module.hot) {
    const renderApp = render
    const renderError = error => {
      const RedBox = require('redbox-react')

      ReactDOM.render(<RedBox error={error}/>, mountElement)
    }
    render = () => {
      try {
        renderApp()
      } catch (error) {
        renderError(error)
      }
    }
  }
  render()
}

export const reloadApp = (app, mountElementName = 'root') => {
  const mountElement = document.getElementById(mountElementName)
  ReactDOM.unmountComponentAtNode(mountElement)
  renderApp(app, mountElementName)
}

export const registerAppInRegistry = (appName, initFunction) => {
  if (window.reactRegistry) {
    window.reactRegistry.register(appName, initFunction)
  }
}

const dispatchActions = (actions, store) => {
  actions.forEach(action => {
    store.dispatch(action)
  })
}

const setWebpacksPublicPath = publicPath => {
  /* eslint camelcase: 0 */
  __webpack_public_path__ = publicPath
}

const getAppComponent = (store, initIntlPromise, name, content, theme) => (
  <ThemeProvider theme={theme}>

      <Provider store={store}>
        <LoadMask promises={[initIntlPromise]}>
          <IntlProvider>
            <div className={`tocco-${name}`}>
              {content}

          </IntlProvider>
        </LoadMask>
      </Provider>

  </ThemeProvider>
)

const setupIntl = (input, store, module, textResourceModules) => {
  const modules = _union([module], textResourceModules)
  addLocaleData([...de, ...en, ...fr, ...it])
  const locale = input ? input.locale : null
  return intl.initIntl(store, modules, locale)
}
<|endoftext|>


<commit_before>var Base = require('base-methods');
var toPath = require('./');

function App(options) {
  Base.call(this);
  this.options = options || {};
}
Base.extend(App);

App.prototype.option = function(key, value) {
  var path = toPath('options', key);
  if (arguments.length === 1) {
    return this.get(path, value);
  }
  this.set(path, value);
  return this;
};

var app = new App();
app.option('foo.bar', 'baz');

console.log(app);
//=> {options: { foo: { bar: 'baz' }}}

console.log(app.option('foo'));
//=> { bar: 'baz' }
<commit_msg>use `base` for example<commit_after>'use strict';

var Base = require('base');
var toPath = require('./');

function App(options) {
  Base.call(this);
  this.options = options || {};
}

Base.extend(App);

App.prototype.option = function(key, value) {
  var path = toPath('options', key);
  if (arguments.length === 1) {
    return this.get(path, value);
  }
  this.set(path, value);
  return this;
};

var app = new App();
app.option('foo.bar', 'baz');

console.log(app);
//=> {options: { foo: { bar: 'baz' }}}

console.log(app.option('foo'));
//=> { bar: 'baz' }
<|endoftext|>


<commit_before>/*! POSTCSS4 2015-08-02 4:18:26 PM EDT */
!function(){function a(a,b,c,d){"use strict";var e=window.document.createElement("link"),f=b||window.document.getElementsByTagName("script")[0],g=window.document.styleSheets;return e.rel="stylesheet",e.href=a,e.media="only x",d&&(e.onload=d),f.parentNode.insertBefore(e,f),e.onloadcssdefined=function(b){for(var c,d=0;d<g.length;d++)g[d].href&&g[d].href.indexOf(a)>-1&&(c=!0);c?b():setTimeout(function(){e.onloadcssdefined(b)})},e.onloadcssdefined(function(){e.media=c||"all"}),e}function b(a,b){a.onload=function(){a.onload=null,b&&b.call(a)},"isApplicationInstalled"in navigator&&"onloadcssdefined"in a&&a.onloadcssdefined(b)}!function(c){var d=function(e,f){"use strict";if(e&&3===e.length){var g=c.navigator,h=c.document,i=c.Image,j=!(!h.createElementNS||!h.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!h.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||c.opera&&-1===g.userAgent.indexOf("Chrome")||-1!==g.userAgent.indexOf("Series40")),k=new i;k.onerror=function(){d.method="png",d.href=e[2],a(e[2])},k.onload=function(){var c=1===k.width&&1===k.height,g=e[c&&j?0:c?1:2];c&&j?d.method="svg":c?d.method="datapng":d.method="png",d.href=g,b(a(g),f)},k.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",h.documentElement.className+=" grunticon"}};d.loadCSS=a,d.onloadCSS=b,c.grunticon=d}(this)}(),grunticon(["build/svg/icons.data.svg.css","build/svg/icons.data.png.css","build/svg/icons.fallback.css"],grunticon.svgLoadedCallback);for(i=1;i<=30;i++){var isModulus=i%3;isModulus?i%5===0?console.log(i+" Buzz"):i%15===0?console.log(i+" Fizz-Buzz"):console.log(i):console.log(i+" Fizz")}$(document).ready(function(){$(".img-container").slick({autoplay:!0,dots:!0,infinite:!1,edgeFriction:1})});<commit_msg>Just testing builds<commit_after>/*! POSTCSS4 2015-08-02 4:21:15 PM EDT */
!function(){function a(a,b,c,d){"use strict";var e=window.document.createElement("link"),f=b||window.document.getElementsByTagName("script")[0],g=window.document.styleSheets;return e.rel="stylesheet",e.href=a,e.media="only x",d&&(e.onload=d),f.parentNode.insertBefore(e,f),e.onloadcssdefined=function(b){for(var c,d=0;d<g.length;d++)g[d].href&&g[d].href.indexOf(a)>-1&&(c=!0);c?b():setTimeout(function(){e.onloadcssdefined(b)})},e.onloadcssdefined(function(){e.media=c||"all"}),e}function b(a,b){a.onload=function(){a.onload=null,b&&b.call(a)},"isApplicationInstalled"in navigator&&"onloadcssdefined"in a&&a.onloadcssdefined(b)}!function(c){var d=function(e,f){"use strict";if(e&&3===e.length){var g=c.navigator,h=c.document,i=c.Image,j=!(!h.createElementNS||!h.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!h.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||c.opera&&-1===g.userAgent.indexOf("Chrome")||-1!==g.userAgent.indexOf("Series40")),k=new i;k.onerror=function(){d.method="png",d.href=e[2],a(e[2])},k.onload=function(){var c=1===k.width&&1===k.height,g=e[c&&j?0:c?1:2];c&&j?d.method="svg":c?d.method="datapng":d.method="png",d.href=g,b(a(g),f)},k.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",h.documentElement.className+=" grunticon"}};d.loadCSS=a,d.onloadCSS=b,c.grunticon=d}(this)}(),grunticon(["build/svg/icons.data.svg.css","build/svg/icons.data.png.css","build/svg/icons.fallback.css"],grunticon.svgLoadedCallback);for(i=1;i<=30;i++){var isModulus=i%3;isModulus?i%5===0?console.log(i+" Buzz"):i%15===0?console.log(i+" Fizz-Buzz"):console.log(i):console.log(i+" Fizz")}$(document).ready(function(){$(".img-container").slick({autoplay:!0,dots:!0,infinite:!1,edgeFriction:1})});<|endoftext|>


<commit_before>/*
MagJS v0.20
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  'use strict';

  var hookins = {
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = [].concat(id2)[0]
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id)
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    mag.redraw(node, idInstance, 1);

    // LIFE CYCLE EVENT
    mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, props)
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  mag.redraw = function(node, idInstance, force) {
    if (!node || typeof idInstance == 'undefined') {
      throw Error('Mag.JS - Id or node invalid: ' + node, idInstance);
    }

    // verify idInstance
    if (!isValidId(node.id, idInstance)) {
      return
    }

    // clear existing configs ?
    // TODO: per idInstance / id ?
    // REMOVED: since the observer will be called and cache changed
    //
    if (force) mag.fill.configs.splice(0, mag.fill.configs.length)

    if (force) mag.mod.clear(idInstance)

    var fun = makeRedrawFun(node, idInstance, force)

    // check for existing frame id then clear it if exists
    fastdom.clear(mag.mod.getFrameId(idInstance))
      //ENQUEUE
    var fid = fastdom.write(fun);
    //save frame id with the instance
    mag.mod.setFrameId(idInstance, fid)
    // then if instance already has frame id create new discard old or just retain old
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }

  var makeClone = function(idInstance, node, mod, props) {
    var a = function(id, node, mod, props, index) {

      var cloner = node.cloneNode(1)
      cloner.id = node.id + (props.key ? '.' + props.key : '') + '.' + index;

      // if clone already exists return ?
      if (mag.utils.items.isItem(cloner.id)) {
        // return
      }

      var idInstance2 = mag.utils.getItemInstanceId(cloner.id)

      // get unqiue instance ID's module
      mag.mod.submodule(cloner.id, idInstance2, mod, props)

      observer(idInstance2, cloner.id)

      // DRAW
      mag.redraw(cloner, idInstance2, 1)

      return cloner
    }.bind({}, idInstance, node, mod, props)

    //BOUND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return idInstance
    }.bind({}, idInstance)
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids) {
      return [].concat(mag.mod.getState(ids))[0]
    }.bind({}, idInstance)

    return a
  }
  var nodeCache = []

  function getNode(id) {
    //cache nodes?
    if (nodeCache[id]) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {
    }
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id, change) {
      if (getNode(id)) {
        mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(nodeId)) {
        fastdom.clear(mag.mod.getFrameId(index))
        // remove from indexes
        mag.utils.items.removeItem(index)
        //mag.mod.remove(index)
        mag.mod.clear(index)
        //observer index
        mag.props.cached.splice(index, 1)
        //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.props.setup(idInstance, mag.debounce(callback))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      var props = mag.mod.getProps(idInstance)

      var data = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      mag.fill.run(node, state)
      // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node)

    }.bind({}, node1, idInstance1, force1)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  window.mag = mag

})(window.mag || {}, document);
<commit_msg>Update mag.js<commit_after>/*
MagJS v0.20
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  'use strict';

  var hookins = {
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = [].concat(id2)[0]
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id)
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    mag.redraw(node, idInstance, 1);

    // LIFE CYCLE EVENT
    mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, mag.utils.copy(props))
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  mag.redraw = function(node, idInstance, force) {
    if (!node || typeof idInstance == 'undefined') {
      throw Error('Mag.JS - Id or node invalid: ' + node, idInstance);
    }

    // verify idInstance
    if (!isValidId(node.id, idInstance)) {
      return
    }

    // clear existing configs ?
    // TODO: per idInstance / id ?
    // REMOVED: since the observer will be called and cache changed
    //
    if (force) mag.fill.configs.splice(0, mag.fill.configs.length)

    if (force) mag.mod.clear(idInstance)

    var fun = makeRedrawFun(node, idInstance, force)

    // check for existing frame id then clear it if exists
    fastdom.clear(mag.mod.getFrameId(idInstance))
      //ENQUEUE
    var fid = fastdom.write(fun);
    //save frame id with the instance
    mag.mod.setFrameId(idInstance, fid)
    // then if instance already has frame id create new discard old or just retain old
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }

  var makeClone = function(idInstance, node, mod, props) {

    var a = function(id, node, mod, props, index) {

      var cloner = node.cloneNode(1)
      cloner.id = node.id + (props.key ? '.' + props.key : '') + '.' + index;

      // if clone already exists return ?
      if (mag.utils.items.isItem(cloner.id)) {
        // return
      }

      var idInstance2 = mag.utils.getItemInstanceId(cloner.id)

      // get unqiue instance ID's module
      mag.mod.submodule(cloner.id, idInstance2, mod, props)

      observer(idInstance2, cloner.id)

      // DRAW
      mag.redraw(cloner, idInstance2, 1)

      return cloner
    }.bind({}, idInstance, node, mod, props)

    //BOUND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return idInstance
    }.bind({}, idInstance)
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids) {
      return [].concat(mag.mod.getState(ids))[0]
    }.bind({}, idInstance)
    a.getProps = function(ids) {
      return [].concat(mag.mod.getProps(ids))[0]
    }.bind({}, idInstance)

    return a
  }
  var nodeCache = []

  function getNode(id) {
    //cache nodes?
    if (nodeCache[id]) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {
    }
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id, change) {
      if (getNode(id)) {
        mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(nodeId)) {
        fastdom.clear(mag.mod.getFrameId(index))
        // remove from indexes
        mag.utils.items.removeItem(index)
        //mag.mod.remove(index)
        mag.mod.clear(index)
        //observer index
        mag.props.cached.splice(index, 1)
        //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.props.setup(idInstance, mag.debounce(callback))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      var props = mag.mod.getProps(idInstance)

      var data = mag.utils.merge(mag.utils.copy(props), mag.utils.copy(state))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      mag.fill.run(node, state)
      // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node)

    }.bind({}, node1, idInstance1, force1)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  window.mag = mag

})(window.mag || {}, document);
<|endoftext|>


<commit_before>/*
 jQuery Masked Input Plugin
 Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com)
 Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
 Version: 1.4.1
 */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b,c=navigator.userAgent,d=/iphone/i.test(c),e=/chrome/i.test(c),f=/android/i.test(c);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(c,g){var h,i,j,k,l,m,n,o;if(!c&&this.length>0){h=a(this[0]);var p=h.data(a.mask.dataName);return p?p():void 0}return g=a.extend({autoclear:a.mask.autoclear,placeholder:a.mask.placeholder,completed:null},g),i=a.mask.definitions,j=[],k=n=c.length,l=null,a.each(c.split(""),function(a,b){"?"==b?(n--,k=a):i[b]?(j.push(new RegExp(i[b])),null===l&&(l=j.length-1),k>a&&(m=j.length-1)):j.push(null)}),this.trigger("unmask").each(function(){function h(){if(g.completed){for(var a=l;m>=a;a++)if(j[a]&&C[a]===p(a))return;g.completed.call(B)}}function p(a){return g.placeholder.charAt(a<g.placeholder.length?a:0)}function q(a){for(;++a<n&&!j[a];);return a}function r(a){for(;--a>=0&&!j[a];);return a}function s(a,b){var c,d;if(!(0>a)){for(c=a,d=q(b);n>c;c++)if(j[c]){if(!(n>d&&j[c].test(C[d])))break;C[c]=C[d],C[d]=p(d),d=q(d)}z(),B.caret(Math.max(l,a))}}function t(a){var b,c,d,e;for(b=a,c=p(a);n>b;b++)if(j[b]){if(d=q(b),e=C[b],C[b]=c,!(n>d&&j[d].test(e)))break;c=e}}function u(){var a=B.val(),b=B.caret();if(o&&o.length&&o.length>a.length){for(A(!0);b.begin>0&&!j[b.begin-1];)b.begin--;if(0===b.begin)for(;b.begin<l&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}else{for(A(!0);b.begin<n&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}h()}function v(){A(),B.val()!=E&&B.change()}function w(a){if(!B.prop("readonly")){var b,c,e,f=a.which||a.keyCode;o=B.val(),8===f||46===f||d&&127===f?(b=B.caret(),c=b.begin,e=b.end,e-c===0&&(c=46!==f?r(c):e=q(c-1),e=46===f?q(e):e),y(c,e),s(c,e-1),a.preventDefault()):13===f?v.call(this,a):27===f&&(B.val(E),B.caret(0,A()),a.preventDefault())}}function x(b){if(!B.prop("readonly")){var c,d,e,g=b.which||b.keyCode,i=B.caret();if(!(b.ctrlKey||b.altKey||b.metaKey||32>g)&&g&&13!==g){if(i.end-i.begin!==0&&(y(i.begin,i.end),s(i.begin,i.end-1)),c=q(i.begin-1),n>c&&(d=String.fromCharCode(g),j[c].test(d))){if(t(c),C[c]=d,z(),e=q(c),f){var k=function(){a.proxy(a.fn.caret,B,e)()};setTimeout(k,0)}else B.caret(e);i.begin<=m&&h()}b.preventDefault()}}}function y(a,b){var c;for(c=a;b>c&&n>c;c++)j[c]&&(C[c]=p(c))}function z(){B.val(C.join(""))}function A(a){var b,c,d,e=B.val(),f=-1;for(b=0,d=0;n>b;b++)if(j[b]){for(C[b]=p(b);d++<e.length;)if(c=e.charAt(d-1),j[b].test(c)){C[b]=c,f=b;break}if(d>e.length){y(b+1,n);break}}else C[b]===e.charAt(d)&&d++,k>b&&(f=b);return a?z():k>f+1?g.autoclear||C.join("")===D?(B.val()&&B.val(""),y(0,n)):z():(z(),B.val(B.val().substring(0,f+1))),k?b:l}var B=a(this),C=a.map(c.split(""),function(a,b){return"?"!=a?i[a]?p(b):a:void 0}),D=C.join(""),E=B.val();B.data(a.mask.dataName,function(){return a.map(C,function(a,b){return j[b]&&a!=p(b)?a:null}).join("")}),B.one("unmask",function(){B.off(".mask").removeData(a.mask.dataName)}).on("focus.mask",function(){if(!B.prop("readonly")){clearTimeout(b);var a;E=B.val(),a=A(),b=setTimeout(function(){B.get(0)===document.activeElement&&(z(),a==c.replace("?","").length?B.caret(0,a):B.caret(a))},10)}}).on("blur.mask",v).on("keydown.mask",w).on("keypress.mask",x).on("input.mask paste.mask",function(){B.prop("readonly")||setTimeout(function(){var a=A(!0);B.caret(a),h()},0)}),e&&f&&B.off("input.mask").on("input.mask",u),A()})}})});

jQuery(document).ready(function() {

	// Functions
	function addMaskJs(attrName, attrValue, maskFormat) {
		attrValue = jQuery( "["+attrName+"~=" + attrValue + "]" );
		attrValue.each (
			function () {
				jQuery(this).attr("data-mask" , maskFormat);
			});}

	// Adiciona Máscaras com (Nome do atributo, valor do atributo, másscara)
	addMaskJs("title","Celular", "(99) 99999-999?9");
	addMaskJs("title","Telefone", "(99) 99999-999?9");
	addMaskJs("name","telephone", "(99) 99999-999?9");
	addMaskJs("name","billing_telephone", "(99) 99999-999?9");
	addMaskJs("name","billing_fax", "(99) 99999-999?9");
	addMaskJs("title","Cep", "99999-999");
	addMaskJs("title","CEP", "99999-999");
	addMaskJs("id","billing_zip", "99999-999");

	jQuery('input').each(function(index) {
		var me = jQuery(this);
		var dataMask = me.data('mask');
		if (dataMask) {
			me.mask(dataMask);
		}
	});
	jQuery('input[data-mask="(99) 99999-999?9"]')
		.focusout(function(){
			var me = jQuery(this);
			var dataMask = me.data('mask');
			var phone = me.val().replace(/\D/g, '');

			me.unmask();
			if(phone.length > 10){
				me.mask("(99) 99999-999?9");
			}else{
				me.mask("(99) 9999-9999?9");
			}
		})
		.trigger('focusout');
	jQuery('input[data-mask="(99)99999-999?9"]')
		.focusout(function(){
			var me = jQuery(this);
			var dataMask = me.data('mask');
			var phone = me.val().replace(/\D/g, '');

			me.unmask();
			if(phone.length > 10){
				me.mask("(99)99999-999?9");
			}else{
				me.mask("(99)9999-9999?9");
			}
		})
		.trigger('focusout');

});

<commit_msg>CPF/CNPJ<commit_after>/*
 jQuery Masked Input Plugin
 Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com)
 Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
 Version: 1.4.1
 */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b,c=navigator.userAgent,d=/iphone/i.test(c),e=/chrome/i.test(c),f=/android/i.test(c);a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},autoclear:!0,dataName:"rawMaskFn",placeholder:"_"},a.fn.extend({caret:function(a,b){var c;if(0!==this.length&&!this.is(":hidden"))return"number"==typeof a?(b="number"==typeof b?b:a,this.each(function(){this.setSelectionRange?this.setSelectionRange(a,b):this.createTextRange&&(c=this.createTextRange(),c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select())})):(this[0].setSelectionRange?(a=this[0].selectionStart,b=this[0].selectionEnd):document.selection&&document.selection.createRange&&(c=document.selection.createRange(),a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length),{begin:a,end:b})},unmask:function(){return this.trigger("unmask")},mask:function(c,g){var h,i,j,k,l,m,n,o;if(!c&&this.length>0){h=a(this[0]);var p=h.data(a.mask.dataName);return p?p():void 0}return g=a.extend({autoclear:a.mask.autoclear,placeholder:a.mask.placeholder,completed:null},g),i=a.mask.definitions,j=[],k=n=c.length,l=null,a.each(c.split(""),function(a,b){"?"==b?(n--,k=a):i[b]?(j.push(new RegExp(i[b])),null===l&&(l=j.length-1),k>a&&(m=j.length-1)):j.push(null)}),this.trigger("unmask").each(function(){function h(){if(g.completed){for(var a=l;m>=a;a++)if(j[a]&&C[a]===p(a))return;g.completed.call(B)}}function p(a){return g.placeholder.charAt(a<g.placeholder.length?a:0)}function q(a){for(;++a<n&&!j[a];);return a}function r(a){for(;--a>=0&&!j[a];);return a}function s(a,b){var c,d;if(!(0>a)){for(c=a,d=q(b);n>c;c++)if(j[c]){if(!(n>d&&j[c].test(C[d])))break;C[c]=C[d],C[d]=p(d),d=q(d)}z(),B.caret(Math.max(l,a))}}function t(a){var b,c,d,e;for(b=a,c=p(a);n>b;b++)if(j[b]){if(d=q(b),e=C[b],C[b]=c,!(n>d&&j[d].test(e)))break;c=e}}function u(){var a=B.val(),b=B.caret();if(o&&o.length&&o.length>a.length){for(A(!0);b.begin>0&&!j[b.begin-1];)b.begin--;if(0===b.begin)for(;b.begin<l&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}else{for(A(!0);b.begin<n&&!j[b.begin];)b.begin++;B.caret(b.begin,b.begin)}h()}function v(){A(),B.val()!=E&&B.change()}function w(a){if(!B.prop("readonly")){var b,c,e,f=a.which||a.keyCode;o=B.val(),8===f||46===f||d&&127===f?(b=B.caret(),c=b.begin,e=b.end,e-c===0&&(c=46!==f?r(c):e=q(c-1),e=46===f?q(e):e),y(c,e),s(c,e-1),a.preventDefault()):13===f?v.call(this,a):27===f&&(B.val(E),B.caret(0,A()),a.preventDefault())}}function x(b){if(!B.prop("readonly")){var c,d,e,g=b.which||b.keyCode,i=B.caret();if(!(b.ctrlKey||b.altKey||b.metaKey||32>g)&&g&&13!==g){if(i.end-i.begin!==0&&(y(i.begin,i.end),s(i.begin,i.end-1)),c=q(i.begin-1),n>c&&(d=String.fromCharCode(g),j[c].test(d))){if(t(c),C[c]=d,z(),e=q(c),f){var k=function(){a.proxy(a.fn.caret,B,e)()};setTimeout(k,0)}else B.caret(e);i.begin<=m&&h()}b.preventDefault()}}}function y(a,b){var c;for(c=a;b>c&&n>c;c++)j[c]&&(C[c]=p(c))}function z(){B.val(C.join(""))}function A(a){var b,c,d,e=B.val(),f=-1;for(b=0,d=0;n>b;b++)if(j[b]){for(C[b]=p(b);d++<e.length;)if(c=e.charAt(d-1),j[b].test(c)){C[b]=c,f=b;break}if(d>e.length){y(b+1,n);break}}else C[b]===e.charAt(d)&&d++,k>b&&(f=b);return a?z():k>f+1?g.autoclear||C.join("")===D?(B.val()&&B.val(""),y(0,n)):z():(z(),B.val(B.val().substring(0,f+1))),k?b:l}var B=a(this),C=a.map(c.split(""),function(a,b){return"?"!=a?i[a]?p(b):a:void 0}),D=C.join(""),E=B.val();B.data(a.mask.dataName,function(){return a.map(C,function(a,b){return j[b]&&a!=p(b)?a:null}).join("")}),B.one("unmask",function(){B.off(".mask").removeData(a.mask.dataName)}).on("focus.mask",function(){if(!B.prop("readonly")){clearTimeout(b);var a;E=B.val(),a=A(),b=setTimeout(function(){B.get(0)===document.activeElement&&(z(),a==c.replace("?","").length?B.caret(0,a):B.caret(a))},10)}}).on("blur.mask",v).on("keydown.mask",w).on("keypress.mask",x).on("input.mask paste.mask",function(){B.prop("readonly")||setTimeout(function(){var a=A(!0);B.caret(a),h()},0)}),e&&f&&B.off("input.mask").on("input.mask",u),A()})}})});

jQuery(document).ready(function() {

	// Functions
	function addMaskJs(attrName, attrValue, maskFormat) {
		attrValue = jQuery( "["+attrName+"~=" + attrValue + "]" );
		attrValue.each (
			function () {
				jQuery(this).attr("data-mask" , maskFormat);
			});}

	// Adiciona Máscaras com (Nome do atributo, valor do atributo, másscara)
	addMaskJs("title","Celular", "(99) 99999-999?9");
	addMaskJs("title","Telefone", "(99) 99999-999?9");
	addMaskJs("name","telephone", "(99) 99999-999?9");
	addMaskJs("name","billing_telephone", "(99) 99999-999?9");
	addMaskJs("name","billing_fax", "(99) 99999-999?9");
	addMaskJs("title","cpf", "99.999.999/9999-99");
	addMaskJs("title","Cep", "99999-999");
	addMaskJs("title","CEP", "99999-999");
	addMaskJs("id","billing_zip", "99999-999");

	jQuery('input').each(function(index) {
		var me = jQuery(this);
		var dataMask = me.data('mask');
		if (dataMask) {
			me.mask(dataMask);
		}
	});
	jQuery('input[data-mask="(99) 99999-999?9"]')
		.focusout(function(){
			          var mePhone = jQuery(this);
			          var dataMask = mePhone.data('mask');
			          var phone = mePhone.val().replace(/\D/g, '');
		              mePhone.unmask();
			          if(phone.length > 17){
				          mePhone.mask("(99) 99999-999?9");
			          }else{
				          mePhone.mask("(99) 9999-9999?9");
			          }
		          })
		.trigger('focusout');
	jQuery('input[data-mask="999.999.999-99"]')
		.focusout(function(){
			          var meCPF = jQuery(this);
			          var dataMask = meCPF.data('mask');
			          var cpf = meCPF.val().replace(/\D/g, '');

		                  meCPF.unmask();
			          if(cpf.length > 15){
				          meCPF.mask("999.999.999-99");
			          }else{
				          meCPF.mask("99.999.999/9999-99");
			          }
		          })
		.trigger('focusout');

});
<|endoftext|>


<commit_before>import React from 'react';
import { mount } from 'enzyme';
import toJson from 'enzyme-to-json';
import cases from 'jest-in-case';

import Async from '../Async';
import { OPTIONS } from './constants';
import { components } from '../components';
const { Option } = components;

test('defaults - snapshot', () => {
  const tree = mount(<Async />);
  expect(toJson(tree)).toMatchSnapshot();
});

/**
 * loadOptions with promise is not resolved and it renders loading options
 * confirmed by logging in component that loadOptions is resolved and options are available
 * but still loading options is rendered
 */
cases(
  'load option prop with defaultOptions true',
  ({ props, expectOptionLength }) => {
    const asyncSelectWrapper = mount(<Async menuIsOpen {...props} />);
    expect(asyncSelectWrapper.find(Option).length).toBe(expectOptionLength);
  },
  {
    'with callback  > should resolve options': {
      props: {
        defaultOptions: true,
        loadOptions: (inputValue, callBack) => callBack([OPTIONS[0]]),
      },
      expectOptionLength: 1,
    },
    'with promise  > should resolve options': {
      skip: true,
      props: {
        defaultOptions: true,
        loadOptions: () => Promise.resolve([OPTIONS[0]]),
      },
      expectOptionLength: 1,
    },
  }
);

/**
 * loadOptions with promise is not resolved and it renders loading options
 * confirmed by logging in component that loadOptions is resolved and options are available
 * but still loading options is rendered
 */
cases(
  'load options props with no default options',
  ({ props, expectloadOptionsLength }) => {
    let asyncSelectWrapper = mount(
      <Async className="react-select" classNamePrefix="react-select" {...props} />
    );
    let inputValueWrapper = asyncSelectWrapper.find(
      'div.react-select__input input'
    );
    asyncSelectWrapper.setProps({ inputValue: 'a' });
    inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } });
    expect(asyncSelectWrapper.find(Option).length).toBe(
      expectloadOptionsLength
    );
  },
  {
    'with callback > should resolve the options': {
      props: {
        loadOptions: (inputValue, callBack) => callBack(OPTIONS),
      },
      expectloadOptionsLength: 17,
    },
    'with promise > should resolve the options': {
      skip: true,
      props: {
        loadOptions: () => Promise.resolve(OPTIONS),
      },
      expectloadOptionsLength: 17,
    },
  }
);

/**
 * Need to update props to trigger on change in input
 * when updating props renders the component therefore options cache is lost thus loadOptions is called again
 */
test.skip('to not call loadOptions again for same value when cacheOptions is true', () => {
  let loadOptionsSpy = jest.fn();
  let asyncSelectWrapper = mount(
    <Async className="react-select" classNamePrefix="react-select" loadOptions={loadOptionsSpy} cacheOptions />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );

  asyncSelectWrapper.setProps({ inputValue: 'a' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(1);

  asyncSelectWrapper.setProps({ inputValue: 'b' });
  inputValueWrapper.simulate('change', {
    target: { value: 'b' },
    currentTarget: { value: 'b' },
  });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(2);

  asyncSelectWrapper.setProps({ inputValue: 'b' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'b' } });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(2);
});

test('to create new cache for each instance', () => {
  const asyncSelectWrapper = mount(<Async cacheOptions />);
  const instanceOne = asyncSelectWrapper.instance();

  const asyncSelectTwoWrapper = mount(<Async cacheOptions />);
  const instanceTwo = asyncSelectTwoWrapper.instance();

  expect(instanceOne.optionsCache).not.toBe(instanceTwo.optionsCache);
});

test('in case of callbacks display the most recently-requested loaded options (if results are returned out of order)', () => {
  let callbacks = [];
  const loadOptions = (inputValue, callback) => {
    callbacks.push(callback);
  };
  let asyncSelectWrapper = mount(
    <Async className="react-select" classNamePrefix="react-select" loadOptions={loadOptions} />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );
  asyncSelectWrapper.setProps({ inputValue: 'foo' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'foo' } });
  asyncSelectWrapper.setProps({ inputValue: 'bar' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'bar' } });
  expect(asyncSelectWrapper.find(Option).exists()).toBeFalsy();
  callbacks[1]([{ value: 'bar', label: 'bar' }]);
  callbacks[0]([{ value: 'foo', label: 'foo' }]);
  asyncSelectWrapper.update();
  expect(asyncSelectWrapper.find(Option).text()).toBe('bar');
});

/**
 * This throws a jsdom exception
 */
test.skip('in case of callbacks should handle an error by setting options to an empty array', () => {
  const loadOptions = (inputValue, callback) => {
    callback(new Error('error'));
  };
  let asyncSelectWrapper = mount(
    <Async
      className="react-select"
      classNamePrefix="react-select"
      loadOptions={loadOptions}
      options={OPTIONS}
    />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );
  asyncSelectWrapper.setProps({ inputValue: 'foo' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'foo' } });
  asyncSelectWrapper.update();
  expect(asyncSelectWrapper.find(Option).length).toBe(1);
});
<commit_msg>add test case<commit_after>import React from 'react';
import { mount } from 'enzyme';
import toJson from 'enzyme-to-json';
import cases from 'jest-in-case';

import Async from '../Async';
import { OPTIONS } from './constants';
import { components } from '../components';
const { Option } = components;

test('defaults - snapshot', () => {
  const tree = mount(<Async />);
  expect(toJson(tree)).toMatchSnapshot();
});

/**
 * loadOptions with promise is not resolved and it renders loading options
 * confirmed by logging in component that loadOptions is resolved and options are available
 * but still loading options is rendered
 */
cases(
  'load option prop with defaultOptions true',
  ({ props, expectOptionLength }) => {
    const asyncSelectWrapper = mount(<Async menuIsOpen {...props} />);
    expect(asyncSelectWrapper.find(Option).length).toBe(expectOptionLength);
  },
  {
    'with callback  > should resolve options': {
      props: {
        defaultOptions: true,
        loadOptions: (inputValue, callBack) => callBack([OPTIONS[0]]),
      },
      expectOptionLength: 1,
    },
    'with promise  > should resolve options': {
      skip: true,
      props: {
        defaultOptions: true,
        loadOptions: () => Promise.resolve([OPTIONS[0]]),
      },
      expectOptionLength: 1,
    },
  }
);

test('load options prop with defaultOptions true and inputValue prop', () => {
  const loadOptionsSpy = jest.fn((value) => value);
  const searchString = 'hello world';
  mount(<Async
      loadOptions={loadOptionsSpy}
      defaultOptions
      inputValue={searchString}
    />);
  expect(loadOptionsSpy).toHaveReturnedWith(searchString);
});

/**
 * loadOptions with promise is not resolved and it renders loading options
 * confirmed by logging in component that loadOptions is resolved and options are available
 * but still loading options is rendered
 */
cases(
  'load options props with no default options',
  ({ props, expectloadOptionsLength }) => {
    let asyncSelectWrapper = mount(
      <Async className="react-select" classNamePrefix="react-select" {...props} />
    );
    let inputValueWrapper = asyncSelectWrapper.find(
      'div.react-select__input input'
    );
    asyncSelectWrapper.setProps({ inputValue: 'a' });
    inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } });
    expect(asyncSelectWrapper.find(Option).length).toBe(
      expectloadOptionsLength
    );
  },
  {
    'with callback > should resolve the options': {
      props: {
        loadOptions: (inputValue, callBack) => callBack(OPTIONS),
      },
      expectloadOptionsLength: 17,
    },
    'with promise > should resolve the options': {
      skip: true,
      props: {
        loadOptions: () => Promise.resolve(OPTIONS),
      },
      expectloadOptionsLength: 17,
    },
  }
);

/**
 * Need to update props to trigger on change in input
 * when updating props renders the component therefore options cache is lost thus loadOptions is called again
 */
test.skip('to not call loadOptions again for same value when cacheOptions is true', () => {
  let loadOptionsSpy = jest.fn();
  let asyncSelectWrapper = mount(
    <Async className="react-select" classNamePrefix="react-select" loadOptions={loadOptionsSpy} cacheOptions />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );

  asyncSelectWrapper.setProps({ inputValue: 'a' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(1);

  asyncSelectWrapper.setProps({ inputValue: 'b' });
  inputValueWrapper.simulate('change', {
    target: { value: 'b' },
    currentTarget: { value: 'b' },
  });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(2);

  asyncSelectWrapper.setProps({ inputValue: 'b' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'b' } });
  expect(loadOptionsSpy).toHaveBeenCalledTimes(2);
});

test('to create new cache for each instance', () => {
  const asyncSelectWrapper = mount(<Async cacheOptions />);
  const instanceOne = asyncSelectWrapper.instance();

  const asyncSelectTwoWrapper = mount(<Async cacheOptions />);
  const instanceTwo = asyncSelectTwoWrapper.instance();

  expect(instanceOne.optionsCache).not.toBe(instanceTwo.optionsCache);
});

test('in case of callbacks display the most recently-requested loaded options (if results are returned out of order)', () => {
  let callbacks = [];
  const loadOptions = (inputValue, callback) => {
    callbacks.push(callback);
  };
  let asyncSelectWrapper = mount(
    <Async className="react-select" classNamePrefix="react-select" loadOptions={loadOptions} />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );
  asyncSelectWrapper.setProps({ inputValue: 'foo' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'foo' } });
  asyncSelectWrapper.setProps({ inputValue: 'bar' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'bar' } });
  expect(asyncSelectWrapper.find(Option).exists()).toBeFalsy();
  callbacks[1]([{ value: 'bar', label: 'bar' }]);
  callbacks[0]([{ value: 'foo', label: 'foo' }]);
  asyncSelectWrapper.update();
  expect(asyncSelectWrapper.find(Option).text()).toBe('bar');
});

/**
 * This throws a jsdom exception
 */
test.skip('in case of callbacks should handle an error by setting options to an empty array', () => {
  const loadOptions = (inputValue, callback) => {
    callback(new Error('error'));
  };
  let asyncSelectWrapper = mount(
    <Async
      className="react-select"
      classNamePrefix="react-select"
      loadOptions={loadOptions}
      options={OPTIONS}
    />
  );
  let inputValueWrapper = asyncSelectWrapper.find(
    'div.react-select__input input'
  );
  asyncSelectWrapper.setProps({ inputValue: 'foo' });
  inputValueWrapper.simulate('change', { currentTarget: { value: 'foo' } });
  asyncSelectWrapper.update();
  expect(asyncSelectWrapper.find(Option).length).toBe(1);
});
<|endoftext|>