require 'test_helper'
require 'es6_module_transpiler/tilt'
require 'execjs'

Scope = Struct.new('Scope', :root_path, :logical_path)

describe Tilt::ES6ModuleTranspilerTemplate do
  before do
    @source = <<-JS
import dep from 'dep';

var foo = function() {
  console.log('bar');
};

export default = foo;
JS
    @source.rstrip!
    @scope = Scope.new('', 'foo')
  end

  after do
    ES6ModuleTranspiler.compile_to = nil
    ES6ModuleTranspiler.prefix_patterns.clear
    ES6ModuleTranspiler.transform = nil
  end

  it 'transpiles es6 into amd by default' do
    expected = <<-JS
define("foo", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!

    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end

  it 'transpiles es6 into globals when set' do
    ES6ModuleTranspiler.compile_to = :globals

    expected = <<-JS
(function(__exports__, __dependency1__) {
  "use strict";
  var dep = __dependency1__;

  var foo = function() {
    console.log('bar');
  };

  __exports__.foo = foo;
})(window, window.dep);
JS
    expected.rstrip!

    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end

  it 'transpiles es6 into CommonJS when set' do
    ES6ModuleTranspiler.compile_to = :cjs

    expected = <<-JS
"use strict";
var dep = require("dep")["default"];

var foo = function() {
  console.log('bar');
};

exports["default"] = foo;
JS
    expected.rstrip!

    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end

  it 'transpiles with a prefixed name matching a pattern' do
    ES6ModuleTranspiler.add_prefix_pattern /app/, 'app'

    expected = <<-JS
define("app/controllers/foo", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!
    @scope = Scope.new('app', 'controllers/foo')
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected

    expected = <<-JS
define("foo", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!
    @scope = Scope.new('', 'foo')
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end

  it "can detect multiple prefix patterns" do
    ES6ModuleTranspiler.add_prefix_pattern /app/, 'app'
    ES6ModuleTranspiler.add_prefix_pattern /config/, 'config'

    expected = <<-JS
define("app/models/foo", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!
    @scope = Scope.new('/home/user/app', 'models/foo')
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected

    expected = <<-JS
define("config/foo", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!
    @scope = Scope.new('/home/users/config', 'foo')
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end

  it 'transpiles es6 into amd by default' do
    expected = <<-JS
define("FOO", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"];

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!

    ES6ModuleTranspiler.transform = lambda { |name| name.upcase }
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
  end
  
  it 'respects compiler_options' do
    expected = <<-JS
define("FOO", 
  ["dep","exports"],
  function(__dependency1__, __exports__) {
    "use strict";
    var dep = __dependency1__["default"] || __dependency1__;

    var foo = function() {
      console.log('bar');
    };

    __exports__["default"] = foo;
  });
JS
    expected.rstrip!
    
    ES6ModuleTranspiler.compiler_options[:compatFix] = true;
    ES6ModuleTranspiler.transform = lambda { |name| name.upcase }
    template = Tilt::ES6ModuleTranspilerTemplate.new { @source }
    template.render(@scope).must_equal expected
    ES6ModuleTranspiler.compiler_options[:compatFix] = false;
  end
end
