<commit_before>'use strict'

const rimraf = require('rimraf')
const assign = require('object-assign')
const expect = require('chai').expect
const mkdirp = require('mkdirp')
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const execSync = require('child_process').execSync
const fsExtra = require('fs-extra')
const exec = require('child_process').exec

const cleanScopeAndRequire = require('../support/cleanScopeAndRequire')

RegExp.escape = function(s) {
  return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
}

describe('integration', function(){
  this.timeout(20000)
  beforeEach(cleanScopeAndRequire)

  const tmpDir = path.resolve(__dirname, '../../tmp')
  const outputBaseDir = path.resolve(tmpDir, 'output')
  const cacheDir = path.join(outputBaseDir, 'cache')
  const fixturesDir = path.resolve(__dirname, '../fixtures')
  const currentDirectoryExp = new RegExp(RegExp.escape(process.cwd()))
  function aFixture(file) { return path.join(fixturesDir, file) }

  const dependencyMain = aFixture('dependency.rb')
  const dependencyBackup = aFixture('dependency.rb.backup')
  const opalLoader = path.resolve(__dirname, '../../')
  const outputDir = path.resolve(outputBaseDir, 'loader')
  const globalConfig = {
    output: {
      path: outputDir,
      filename: '[id].loader.js'
    },
    module: {
      loaders: [{ test: /\.rb$/, loader: opalLoader }]
    }
  }

  function useTweakedCompiler() {
    process.env.OPAL_COMPILER_PATH = path.resolve(__dirname, '../support/tweakedOpalCompiler.js')
  }

  function getOpalCompilerFilename() {
    return require('../../lib/getOpalCompilerFilename')()
  }

  function assertBasic(config, done) {
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      let errors = stats.compilation.errors
      if (errors.length > 0) {
        console.dir(errors[0].stack)
      }
      expect(errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\n')

          return done()
        })
      })
    })
  }

  beforeEach(function(done) {
    fsExtra.mkdirp('./tmp', done)
  })

  function runCode(otherArgs) {
    const args = otherArgs || ''
    const command = `phantomjs ${path.resolve(__dirname, '../support/runPhantom.js')} ${args} ${path.resolve(outputDir, '0.loader.js')} 2>&1 || true`
    //console.log(`Running command: ${command}`)
    return execSync(command).toString()
  }

  // the source-map-support plugin that load_source_maps.js loads makes it easy to test this on node
  function runSourceMapDependentCode() {
    const sourceMapFinder = aFixture('load_source_maps.js')
    const command = `node -r ${sourceMapFinder} ${path.join(outputDir, '0.loader.js')} 2>&1 || true`
    //console.log(`Running command: ${command}`)
    return execSync(command).toString()
  }

  beforeEach(function (done) {
    fsExtra.copySync(dependencyMain, dependencyBackup, {clobber: true})
    rimraf(outputBaseDir, function(err) {
      if (err) { return done(err) }
      mkdirp(outputDir, done)
    })
  })

  afterEach(function (done) {
    // cleanup
    fsExtra.copy(dependencyBackup, dependencyMain, {clobber: true}, done)
  })

  it('loads basic files', function (done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_basic.js')
    })
    assertBasic(config, done)
  })

  // not an end to end test, but since it's a bit slower, put here instead of unit test
  it('matches our bundler test version', function(done) {
    this.timeout(5000) // time for shell execute

    const opalVersion = Opal.get('RUBY_ENGINE_VERSION')

    exec('opal -e "puts RUBY_ENGINE_VERSION"', function(err, stdout) {
      if (err) { done(err) }
      expect(stdout.trim()).to.eq(opalVersion)
      return done()
    })
  })

  it('loads requires', function (done){
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep.js')
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\nwe made it\n\n')

          return done()
        })
      })
    })
  })

  it('loads requires with node conventions', function (done){
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep_node.js')
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\nwe made it\n\n')

          return done()
        })
      })
    })
  })

  it('works with stubs', function (done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep.js'),
      opal: {
        stubs: ['dependency']
      }
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.not.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('we made it\n\n')

          return done()
        })
      })
    })
  })

  it('allows stubbing Opal requires so they can be provided outside webpack', function(done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_basic.js'),
      opal: {
        externalOpal: true
      }
    })
    webpack(config, (err) => {
      if (err) { return done(err) }
      expect(runCode(getOpalCompilerFilename())).to.eq('123\n\n')

      return done()
    })
  })

  it('allows using a statically provided Opal distro', function(done) {
    useTweakedCompiler()

    const config = assign({}, globalConfig, {
      entry: aFixture('entry_static_opal.js')
    })

    webpack(config, (err) => {
      if (err) { return done(err) }
      expect(runCode().trim()).to.eq('0.10.0.beta2.webpacktest')

      return done()
    })
  })

  it('allows using bundler for compilation/dependencies', function (done) {
    if (execSync('opal -v').toString().trim().indexOf('0.10') != -1) {
      // some issues with 0.10 and opal-browser
      this.skip()<commit_msg>add an MRI require integration test<commit_after>'use strict'

const rimraf = require('rimraf')
const assign = require('object-assign')
const expect = require('chai').expect
const mkdirp = require('mkdirp')
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const execSync = require('child_process').execSync
const fsExtra = require('fs-extra')
const exec = require('child_process').exec

const cleanScopeAndRequire = require('../support/cleanScopeAndRequire')

RegExp.escape = function(s) {
  return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
}

describe('integration', function(){
  this.timeout(20000)
  beforeEach(cleanScopeAndRequire)

  const tmpDir = path.resolve(__dirname, '../../tmp')
  const outputBaseDir = path.resolve(tmpDir, 'output')
  const cacheDir = path.join(outputBaseDir, 'cache')
  const fixturesDir = path.resolve(__dirname, '../fixtures')
  const currentDirectoryExp = new RegExp(RegExp.escape(process.cwd()))
  function aFixture(file) { return path.join(fixturesDir, file) }

  const dependencyMain = aFixture('dependency.rb')
  const dependencyBackup = aFixture('dependency.rb.backup')
  const opalLoader = path.resolve(__dirname, '../../')
  const outputDir = path.resolve(outputBaseDir, 'loader')
  const globalConfig = {
    output: {
      path: outputDir,
      filename: '[id].loader.js'
    },
    module: {
      loaders: [{ test: /\.rb$/, loader: opalLoader }]
    }
  }

  function useTweakedCompiler() {
    process.env.OPAL_COMPILER_PATH = path.resolve(__dirname, '../support/tweakedOpalCompiler.js')
  }

  function getOpalCompilerFilename() {
    return require('../../lib/getOpalCompilerFilename')()
  }

  function assertBasic(config, done) {
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      let errors = stats.compilation.errors
      if (errors.length > 0) {
        console.dir(errors[0].stack)
      }
      expect(errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\n')

          return done()
        })
      })
    })
  }

  beforeEach(function(done) {
    fsExtra.mkdirp('./tmp', done)
  })

  function runCode(otherArgs) {
    const args = otherArgs || ''
    const command = `phantomjs ${path.resolve(__dirname, '../support/runPhantom.js')} ${args} ${path.resolve(outputDir, '0.loader.js')} 2>&1 || true`
    //console.log(`Running command: ${command}`)
    return execSync(command).toString()
  }

  // the source-map-support plugin that load_source_maps.js loads makes it easy to test this on node
  function runSourceMapDependentCode() {
    const sourceMapFinder = aFixture('load_source_maps.js')
    const command = `node -r ${sourceMapFinder} ${path.join(outputDir, '0.loader.js')} 2>&1 || true`
    //console.log(`Running command: ${command}`)
    return execSync(command).toString()
  }

  beforeEach(function (done) {
    fsExtra.copySync(dependencyMain, dependencyBackup, {clobber: true})
    rimraf(outputBaseDir, function(err) {
      if (err) { return done(err) }
      mkdirp(outputDir, done)
    })
  })

  afterEach(function (done) {
    // cleanup
    fsExtra.copy(dependencyBackup, dependencyMain, {clobber: true}, done)
  })

  it('loads basic files', function (done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_basic.js')
    })
    assertBasic(config, done)
  })

  // not an end to end test, but since it's a bit slower, put here instead of unit test
  it('matches our bundler test version', function(done) {
    this.timeout(5000) // time for shell execute

    const opalVersion = Opal.get('RUBY_ENGINE_VERSION')

    exec('opal -e "puts RUBY_ENGINE_VERSION"', function(err, stdout) {
      if (err) { done(err) }
      expect(stdout.trim()).to.eq(opalVersion)
      return done()
    })
  })

  it('loads requires', function (done){
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep.js')
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\nwe made it\n\n')

          return done()
        })
      })
    })
  })

  it('loads requires with node conventions', function (done){
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep_node.js')
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('123\n\nwe made it\n\n')

          return done()
        })
      })
    })
  })

  it('works with stubs', function (done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_another_dep.js'),
      opal: {
        stubs: ['dependency']
      }
    })
    webpack(config, (err, stats) => {
      expect(err).to.be.null
      expect(stats.compilation.errors).to.be.empty

      fs.readdir(outputDir, (err, files) => {
        expect(err).to.be.null
        expect(files).to.have.length(1)
        fs.readFile(path.resolve(outputDir, files[0]), (err, data) => {
          var subject = data.toString()

          expect(err).to.be.null
          expect(subject).to.not.include('Opal.cdecl($scope, \'HELLO\', 123)')
          expect(subject).to.include('Opal.cdecl($scope, \'INSIDE\', 789)')
          expect(subject).to.not.match(currentDirectoryExp)
          expect(runCode()).to.eq('we made it\n\n')

          return done()
        })
      })
    })
  })

  it('allows stubbing Opal requires so they can be provided outside webpack', function(done) {
    const config = assign({}, globalConfig, {
      entry: aFixture('entry_basic.js'),
      opal: {
        externalOpal: true
      }
    })
    webpack(config, (err) => {
      if (err) { return done(err) }
      expect(runCode(getOpalCompilerFilename())).to.eq('123\n\n')

      return done()
    })
  })

  it('specific MRI require', function(done) {
    if (execSync('opal -v').toString().trim().indexOf('0.10') != -1) {
      // some issues with 0.10 and opal-browser
      this.skip()
    }

    process.env.OPAL_MRI_REQUIRES = 'opal-browser'

    const config = assign({}, globalConfig, {
      entry: aFixture('entry_bundler_opal.js')
    })

    webpack(config, (err) => {
      if (err) { return done(err) }
      expect(runCode().trim()).to.eq('0.2.0')

      return done()
    })
  })

  it('allows using a statically provided Opal distro', function(done) {
    useTweakedCompiler()

    const config = assign({}, globalConfig, {
      entry: aFixture('entry_static_opal.js')
    })

    webpack(config, (err) => {
      if (err) { return done(err) }
      expect(runCode().trim()).to.eq('0.10.0.beta2.webpacktest')

      return done()
    })
  })

  it('allows using bundler for compilation/dependencies', function (done) {
    if (execSync('opal -v').toString().trim().indexOf('0.10') != -1) {
      // some issues with 0.10 and opal-browser
      this.skip()
{'fraction_non_alphanumeric': 0.16616785135303655, 'fraction_numerical': 0.00935278713056491, 'mean_word_length': 2.9292013718765313, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 38, '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': '3287640', 'n_tokens_mistral': 5376, 'n_tokens_neox': 5140, 'n_words': 980}