require 'osx/cocoa'
include OSX
require 'flexmock/test_unit'

class Observed < OSX::NSObject
  kvc_accessor :value

  def init
    @value = 0
    super_init
  end

  # The need for this is, I think, a bug in RubyCocoa.
  def self.automaticallyNotifiesObserversForKey(key)
    false
  end
end

class Watcher < OSX::NSObject
  def observeValueForKeyPath_ofObject_change_context(
             keyPath, object, change, context)
  end
end


class KVOTests < Test::Unit::TestCase

  def setup
    super
    @observed = Observed.alloc.init
    @watcher = flexmock(Watcher.alloc.init)
    @observed.addObserver_forKeyPath_options_context(
                @watcher, 'value',
                OSX::NSKeyValueObservingOptionNew | OSX::NSKeyValueObservingOptionOld,
                nil)
  end

  def teardown
    @observed.removeObserver_forKeyPath(@watcher, 'value')
    super
  end

  def this_change(expected)
    @watcher.should_receive(:observeValueForKeyPath_ofObject_change_context).
             once.
             with('value',
                  @observed,
                  on { | actuals | 
                       actuals[:old] == expected[:old] &&
                       actuals[:new] == expected[:new]
                  },
                  nil)
  end

  def test_setting_in_ruby_style
    newval = 5
    during { 
      @observed.value = newval
    }.behold! {
      this_change(:old => @observed.value, :new => newval)
    }
    assert_equal(newval, @observed.value)
  end

  def because(&block)
    @because = block
    self
  end
  alias_method :during, :because
  
  def behold!
    yield
    @because.call
  end

end


