require 'spec_helper'
require 'integration/method_validator/spec_helper'

describe 'a good fit for DSLs', :shared => true do
  it 'is a good fit for DSLs' do
    @model.should be_valid_for_implementing_a_dsl
  end

  it 'is totally fine for DSLs' do
    @model.ensure_appropriate_for_dsls.should be(true)
  end
end

describe 'a poor candidate for DSLs', :shared => true do
  it 'is a poor candidate for DSLs' do
    @model.should_not be_valid_for_implementing_a_dsl
  end

  it 'is unappropriate for DSLs' do
    @model.ensure_appropriate_for_dsls.first.should be(false)
  end

  it 'has a (more or less) meaningful error message' do
    @model.errors.on(:ensure_appropriate_for_dsls).should == [ 'may not be so good for domain specific languages' ]
  end

  it 'has a violation type' do
    @model.errors[:ensure_appropriate_for_dsls].map(&:type).should == [:unsatisfied_condition]
  end
end


describe 'a good fit for game engine core', :shared => true do
  it 'is a good fit for game engine core' do
    @model.should be_valid_for_implementing_a_game_engine_core
  end

  it 'is appropriate for system programming' do
    @model.ensure_appropriate_for_system_programming.should be(true)
  end
end

describe 'a poor candidate for game engine core', :shared => true do
  it 'is a poor candidate for game engine core' do
    @model.should_not be_valid_for_implementing_a_game_engine_core
  end
end



describe 'a good fit for kernel hacking', :shared => true do
  it 'is a good fit for kernel hacking' do
    @model.should be_valid_for_hacking_on_the_kernel
  end

  it 'is appropriate for system programming' do
    @model.ensure_appropriate_for_system_programming.should be(true)
  end
end


describe 'a poor candidate for kernel hacking', :shared => true do
  it 'is not a good fit for kernel hacking' do
    @model.should_not be_valid_for_hacking_on_the_kernel
  end
end

#
# Note that ProgrammingLanguage is not a DM resource,
# it is a plain old Ruby object (PORO), or simply put,
# just a 'regular' Ruby class with a bunch of accessors.
#
# And yes, assumptions below are full of bullshit and
# author is a moron, and your favourite programming
# language is good for EVARYTHIN'!
#
#Please see spec_helper.rb next to this file
#

describe 'C' do
  before :all do
    @model = ::DataMapper::Validations::Fixtures::ProgrammingLanguage.new(:name                                     => 'C',
                                                                       :allows_system_calls                      => true,
                                                                       :allows_manual_memory_management          => true,
                                                                       :approved_by_linus                        => true,
                                                                       :compiler_excels_at_utilizing_cpu_cache   => true,
                                                                       :is_very_high_level                       => false,
                                                                       :does_not_require_explicit_return_keyword => false,
                                                                       :allows_operator_overload                 => false,
                                                                       :allows_optional_parentheses              => false
                                                                       )
  end

  it_should_behave_like 'a good fit for kernel hacking'

  it_should_behave_like 'a good fit for game engine core'

  it_should_behave_like 'a poor candidate for DSLs'
end



describe 'C++' do
  before :all do
    @model = ::DataMapper::Validations::Fixtures::ProgrammingLanguage.new(:name                                     => 'C++',
                                                                       :allows_system_calls                      => true,
                                                                       :allows_manual_memory_management          => true,
                                                                       :approved_by_linus                        => false,
                                                                       :compiler_excels_at_utilizing_cpu_cache   => true,
                                                                       :is_very_high_level                       => false,
                                                                       :does_not_require_explicit_return_keyword => false,
                                                                       :allows_operator_overload                 => true,
                                                                       :allows_optional_parentheses              => false
                                                                       )
  end

  it_should_behave_like 'a poor candidate for kernel hacking'

  it_should_behave_like 'a good fit for game engine core'

  it_should_behave_like 'a poor candidate for DSLs'

  it 'is not approved by Linus' do
    @model.valid?(:hacking_on_the_kernel)
    @model.errors.on(:ensure_approved_by_linus_himself).should_not be_empty
    @model.errors[:ensure_approved_by_linus_himself].map(&:type).should == [:unapproved_by_linus]
  end
end


describe 'Ruby' do
  before :all do
    @model = ::DataMapper::Validations::Fixtures::ProgrammingLanguage.new(:name                                     => 'Ruby',
                                                                       # well, C extensions do not really count
                                                                       :allows_system_calls                      => false,
                                                                       :allows_manual_memory_management          => false,
                                                                       :approved_by_linus                        => false,
                                                                       :compiler_excels_at_utilizing_cpu_cache   => false,
                                                                       :is_very_high_level                       => true,
                                                                       :does_not_require_explicit_return_keyword => true,
                                                                       :allows_operator_overload                 => true,
                                                                       :allows_optional_parentheses              => true
                                                                       )
  end

  it_should_behave_like 'a good fit for DSLs'

  it_should_behave_like 'a poor candidate for kernel hacking'

  it_should_behave_like 'a poor candidate for game engine core'

  it 'has a (more or less) meaningful error message' do
    @model.valid?(:doing_system_programming)
    @model.errors.on(:ensure_appropriate_for_system_programming).should == [ 'try something that is closer to the metal' ]
  end
end


describe 'Scala' do
  before :all do
    @model = ::DataMapper::Validations::Fixtures::ProgrammingLanguage.new(:name                                     => 'Scala',
                                                                       :allows_system_calls                      => false,
                                                                       :allows_manual_memory_management          => false,
                                                                       :approved_by_linus                        => false,
                                                                       :compiler_excels_at_utilizing_cpu_cache   => false,
                                                                       :is_very_high_level                       => true,
                                                                       :does_not_require_explicit_return_keyword => true,
                                                                       :allows_operator_overload                 => true,
                                                                       :allows_optional_parentheses              => true
                                                                       )
  end

  it_should_behave_like 'a good fit for DSLs'

  it_should_behave_like 'a poor candidate for kernel hacking'

  it_should_behave_like 'a poor candidate for game engine core'

  it 'has a (more or less) meaningful error message' do
    @model.valid?(:doing_system_programming)
    @model.errors.on(:ensure_appropriate_for_system_programming).should == [ 'try something that is closer to the metal' ]
  end
end



describe 'Haskell' do
  before :all do
    @model = ::DataMapper::Validations::Fixtures::ProgrammingLanguage.new(
      :name                                     => 'Haskell',
      :allows_system_calls                      => false,
      :allows_manual_memory_management          => false,
      :approved_by_linus                        => false,
      :compiler_excels_at_utilizing_cpu_cache   => true,
      :is_very_high_level                       => true,
      :does_not_require_explicit_return_keyword => true,
      # operators are not different from any other function
      :allows_operator_overload                 => true,
      # or, allows explicit parentheses? who cares, we
      # are just trying to come up with a relatively
      # non-stupid spec example
      :allows_optional_parentheses              => true
    )
  end

  it_should_behave_like 'a good fit for DSLs'

  it_should_behave_like 'a poor candidate for kernel hacking'

  it_should_behave_like 'a poor candidate for game engine core'

  it 'has a (more or less) meaningful error message' do
    @model.valid?(:doing_system_programming)
    @model.errors.on(:ensure_appropriate_for_system_programming).should == [ 'try something that is closer to the metal' ]
  end
end


describe 'DataMapper::Validations::Fixtures::Event' do
  before :all do
    DataMapper::Validations::Fixtures::Event.auto_migrate!

    @model = DataMapper::Validations::Fixtures::Event.new(:name => 'Fools day 2009')
  end

  describe 'with start time before end time' do
    before :all do
      @model.starts_at = DateTime.new(2009, 4, 1, 00, 00, 01)
      @model.ends_at   = DateTime.new(2009, 4, 1, 23, 59, 59)
    end

    it_should_behave_like 'valid model'
  end

  describe 'with start time after end time' do
    before :all do
      @model.starts_at = DateTime.new(2009, 4, 1, 23, 59, 59)
      @model.ends_at   = DateTime.new(2009, 4, 1, 00, 00, 01)
    end

    it_should_behave_like 'invalid model'

    it 'uses custom error message for property starts_at' do
      @model.errors.on(:starts_at).should == [ 'Start time cannot be after end time' ]
    end
  end
end
