<commit_before>/* globals assert */

const temp = require('temp').track()
const season = require('season')
const dedent = require('dedent')
const electron = require('electron')
const fs = require('fs-plus')
const path = require('path')
const AtomApplication = require('../../src/main-process/atom-application')
const parseCommandLine = require('../../src/main-process/parse-command-line')
const {emitterEventPromise} = require('../async-spec-helpers')

describe('AtomApplication', function () {
  this.timeout(60 * 1000)
  let scenario

  beforeEach(async function () {
    scenario = await LaunchScenario.create()
  })

  afterEach(async function () {
    await scenario.destroy()
  })

  describe('command-line interface behavior', function () {
    describe('with no open windows', function () {
      it('opens a file', async function () {
        await scenario.launch(parseCommandLine(['a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory', async function () {
        await scenario.launch(parseCommandLine(['a']))
        await scenario.assert('[a _]')
      })

      it('opens a file with --add', async function () {
        await scenario.launch(parseCommandLine(['--add', 'a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory with --add', async function () {
        await scenario.launch(parseCommandLine(['--add', 'a']))
        await scenario.assert('[a _]')
      })

      it('opens a file with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a']))
        await scenario.assert('[a _]')
      })

      it('opens a directory with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a']))
      })
    })
  })
})

let channelIdCounter = 0

class LaunchScenario {
  static async create () {
    const scenario = new this()
    await scenario.init()
    return scenario
  }

  constructor () {
    this.applications = new Set()
    this.windows = new Set()
    this.root = null
    this.atomHome = null
    this.projectRootPool = new Map()
    this.filePathPool = new Map()

    this.originalAtomHome = process.env.ATOM_HOME
  }

  async init () {
    if (this.root !== null) {
      return this.root
    }

    await this.clearElectronSession()

    this.root = await new Promise((resolve, reject) => {
      temp.mkdir('launch-', (err, rootPath) => {
        if (err) { reject(err) } else { resolve(rootPath) }
      })
    })

    this.atomHome = path.join(this.root, '.atom')
    process.env.ATOM_HOME = this.atomHome
    await new Promise((resolve, reject) => {
      season.writeFile(path.join(this.atomHome, 'config.cson'), {
        '*': {
          welcome: { showOnStartup: false },
          core: { telemetryConsent: 'no', automaticallyUpdate: false }
        }
      }, err => {
        if (err) { reject(err) } else { resolve() }
      })
    })

    await new Promise((resolve, reject) => {
      // Symlinking the compile cache into the temporary home dir makes the windows load much faster
      fs.symlink(
        path.join(this.originalAtomHome, 'compile-cache'),
        path.join(this.atomHome, 'compile-cache'),
        'junction',
        err => {
          if (err) { reject(err) } else { resolve() }
        }
      )
    })

    await Promise.all(
      ['a', 'b'].map(dirPath => new Promise((resolve, reject) => {
        const fullDirPath = path.join(this.root, dirPath)
        fs.makeTree(fullDirPath, err => {
          if (err) {
            reject(err)
          } else {
            this.projectRootPool.set(dirPath, fullDirPath)
            resolve()
          }
        })
      }))
    )

    await Promise.all(
      ['a/1.md', 'b/2.md'].map(filePath => new Promise((resolve, reject) => {
        const fullFilePath = path.join(this.root, filePath)
        fs.writeFile(fullFilePath, `file: ${filePath}\n`, {encoding: 'utf8'}, err => {
          if (err) {
            reject(err)
          } else {
            this.filePathPool.set(filePath, fullFilePath)
            resolve()
          }
        })
      }))
    )
  }

  async preconditions (source) {
    const app = this.addApplication()
    const windowPromises = []
    for (const windowSpec of this.parseWindowSpecs(source)) {
      const fullRootPaths = windowSpec.roots.map(rootPath => this.projectRootPool.get(rootPath))
      const fullEditorPaths = windowSpec.editors.map(filePath => this.filePathPool.get(filePath))

      windowPromises.push((async (theApp, foldersToOpen, pathsToOpen) => {
        const window = await theApp.openPaths({ newWindow: true, foldersToOpen, pathsToOpen })
        await emitterEventPromise(window, 'window:locations-opened')
        return window
      })(app, fullRootPaths, fullEditorPaths))

      windowPromises.push(app.openPaths({
        newWindow: true,
        foldersToOpen: fullRootPaths,
        pathsToOpen: fullEditorPaths
      }))
    }
    for (const window of await Promise.all(windowPromises)) {
      this.windows.add(window)
    }
  }

  async launch (options) {
    const app = options.app || this.addApplication()
    if (options.pathsToOpen) {
      options.pathsToOpen = options.pathsToOpen.map(shortPath => {
        const fullRoot = this.projectRootPool.get(shortPath)
        if (fullRoot) { return fullRoot }
        const fullEditor = this.filePathPool.get(shortPath)
        if (fullEditor) { return fullEditor }
        throw new Error(`Unexpected short path: ${shortPath}`)
      })
    }

    const windows = await app.launch(options)
    const openedPromises = []
    for (const window of windows) {
      this.windows.add(window)
      openedPromises.push(emitterEventPromise(window, 'window:locations-opened'))<commit_msg>Don't open all precondition windows twice (oops)<commit_after>/* globals assert */

const temp = require('temp').track()
const season = require('season')
const dedent = require('dedent')
const electron = require('electron')
const fs = require('fs-plus')
const path = require('path')
const AtomApplication = require('../../src/main-process/atom-application')
const parseCommandLine = require('../../src/main-process/parse-command-line')
const {emitterEventPromise} = require('../async-spec-helpers')

describe('AtomApplication', function () {
  this.timeout(60 * 1000)
  let scenario

  beforeEach(async function () {
    scenario = await LaunchScenario.create()
  })

  afterEach(async function () {
    await scenario.destroy()
  })

  describe('command-line interface behavior', function () {
    describe('with no open windows', function () {
      it('opens a file', async function () {
        await scenario.launch(parseCommandLine(['a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory', async function () {
        await scenario.launch(parseCommandLine(['a']))
        await scenario.assert('[a _]')
      })

      it('opens a file with --add', async function () {
        await scenario.launch(parseCommandLine(['--add', 'a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory with --add', async function () {
        await scenario.launch(parseCommandLine(['--add', 'a']))
        await scenario.assert('[a _]')
      })

      it('opens a file with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a/1.md']))
        await scenario.assert('[_ 1.md]')
      })

      it('opens a directory with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a']))
        await scenario.assert('[a _]')
      })

      it('opens a directory with --new-window', async function () {
        await scenario.launch(parseCommandLine(['--new-window', 'a']))
      })
    })
  })
})

let channelIdCounter = 0

class LaunchScenario {
  static async create () {
    const scenario = new this()
    await scenario.init()
    return scenario
  }

  constructor () {
    this.applications = new Set()
    this.windows = new Set()
    this.root = null
    this.atomHome = null
    this.projectRootPool = new Map()
    this.filePathPool = new Map()

    this.originalAtomHome = process.env.ATOM_HOME
  }

  async init () {
    if (this.root !== null) {
      return this.root
    }

    await this.clearElectronSession()

    this.root = await new Promise((resolve, reject) => {
      temp.mkdir('launch-', (err, rootPath) => {
        if (err) { reject(err) } else { resolve(rootPath) }
      })
    })

    this.atomHome = path.join(this.root, '.atom')
    process.env.ATOM_HOME = this.atomHome
    await new Promise((resolve, reject) => {
      season.writeFile(path.join(this.atomHome, 'config.cson'), {
        '*': {
          welcome: { showOnStartup: false },
          core: { telemetryConsent: 'no', automaticallyUpdate: false }
        }
      }, err => {
        if (err) { reject(err) } else { resolve() }
      })
    })

    await new Promise((resolve, reject) => {
      // Symlinking the compile cache into the temporary home dir makes the windows load much faster
      fs.symlink(
        path.join(this.originalAtomHome, 'compile-cache'),
        path.join(this.atomHome, 'compile-cache'),
        'junction',
        err => {
          if (err) { reject(err) } else { resolve() }
        }
      )
    })

    await Promise.all(
      ['a', 'b'].map(dirPath => new Promise((resolve, reject) => {
        const fullDirPath = path.join(this.root, dirPath)
        fs.makeTree(fullDirPath, err => {
          if (err) {
            reject(err)
          } else {
            this.projectRootPool.set(dirPath, fullDirPath)
            resolve()
          }
        })
      }))
    )

    await Promise.all(
      ['a/1.md', 'b/2.md'].map(filePath => new Promise((resolve, reject) => {
        const fullFilePath = path.join(this.root, filePath)
        fs.writeFile(fullFilePath, `file: ${filePath}\n`, {encoding: 'utf8'}, err => {
          if (err) {
            reject(err)
          } else {
            this.filePathPool.set(filePath, fullFilePath)
            resolve()
          }
        })
      }))
    )
  }

  async preconditions (source) {
    const app = this.addApplication()
    const windowPromises = []
    for (const windowSpec of this.parseWindowSpecs(source)) {
      const fullRootPaths = windowSpec.roots.map(rootPath => this.projectRootPool.get(rootPath))
      const fullEditorPaths = windowSpec.editors.map(filePath => this.filePathPool.get(filePath))

      windowPromises.push((async (theApp, foldersToOpen, pathsToOpen) => {
        const window = await theApp.openPaths({ newWindow: true, foldersToOpen, pathsToOpen })
        await emitterEventPromise(window, 'window:locations-opened')
        return window
      })(app, fullRootPaths, fullEditorPaths))
    }
    for (const window of await Promise.all(windowPromises)) {
      this.windows.add(window)
    }
  }

  async launch (options) {
    const app = options.app || this.addApplication()
    if (options.pathsToOpen) {
      options.pathsToOpen = options.pathsToOpen.map(shortPath => {
        const fullRoot = this.projectRootPool.get(shortPath)
        if (fullRoot) { return fullRoot }
        const fullEditor = this.filePathPool.get(shortPath)
        if (fullEditor) { return fullEditor }
        throw new Error(`Unexpected short path: ${shortPath}`)
      })
    }

    const windows = await app.launch(options)
    const openedPromises = []
    for (const window of windows) {
      this.windows.add(window)
      openedPromises.push(emitterEventPromise(window, 'window:locations-opened'))
{'fraction_non_alphanumeric': 0.14432815665091156, 'fraction_numerical': 0.0027008777852802163, 'mean_word_length': 2.5993317132442284, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5928205', 'n_tokens_mistral': 3538, 'n_tokens_neox': 3459, 'n_words': 778}