mac_bacon 1.2.1 → 1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +18 -0
- data/RDOX +43 -15
- data/{README → README.md} +142 -48
- data/Rakefile +4 -4
- data/TODO +2 -0
- data/lib/mac_bacon.rb +124 -21
- data/test/spec_helper.rb +26 -0
- data/test/spec_mac_bacon.rb +195 -10
- metadata +8 -19
    
        data/ChangeLog
    CHANGED
    
    | @@ -1,3 +1,21 @@ | |
| 1 | 
            +
            Sat Mar 12 15:47:27 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 2 | 
            +
              * Filter the backtraces.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            Sat Mar 12 15:34:41 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 5 | 
            +
              * Postponing blocks until a KVO message is received should work from before and after filters as well.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Sat Mar 12 15:06:26 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 8 | 
            +
              * Postponing blocks until Context#resume is called should work from before and after filters as well.
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Sat Mar 12 14:52:41 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 11 | 
            +
              * Postponing blocks for a fixed period of time should work from before and after filters as well.
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            Sat Mar 12 13:57:01 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 14 | 
            +
              * Add Context#wait_for_change(object_to_observe, key_path, timeout = 1), which resumes the postponed block until a KVO message is received.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Sat Mar 12 12:41:10 2011 +0100  Eloy Duran <eloy.de.enige@gmail.com>
         | 
| 17 | 
            +
              * Postpone a block until either Context#resume is called or the timeout has exceeded. The default timeout is 1s, or can be given by using Context#wait_max instead of Context#wait.
         | 
| 18 | 
            +
             | 
| 1 19 | 
             
            Mon Feb 28 12:34:55 2011 +0100  Klaas Speller <klaasspeller@gmail.com>
         | 
| 2 20 | 
             
              * Exit with other status than 0 on fails or errors
         | 
| 3 21 |  | 
    
        data/RDOX
    CHANGED
    
    | @@ -55,8 +55,36 @@ describe arguments | |
| 55 55 | 
             
              - should work with multiple arguments
         | 
| 56 56 |  | 
| 57 57 | 
             
            NSRunloop aware Bacon
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            concerning `wait' with a fixed time
         | 
| 58 60 | 
             
              - allows the user to postpone execution of a block for n seconds, which will halt any further execution of specs
         | 
| 59 61 |  | 
| 62 | 
            +
            concerning `wait' without a fixed time
         | 
| 63 | 
            +
              - allows the user to postpone execution of a block until Context#resume is called, from for instance a delegate callback
         | 
| 64 | 
            +
              - has a default timeout of 1 second after which the spec will fail and further scheduled calls to the Context are cancelled [FAILED]
         | 
| 65 | 
            +
              - takes an explicit timeout [FAILED]
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            concerning `wait_for_change'
         | 
| 68 | 
            +
              - resumes the postponed block once an observed value changes
         | 
| 69 | 
            +
              - has a default timeout of 1 second [FAILED]
         | 
| 70 | 
            +
              - takes an explicit timeout [FAILED]
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            postponing blocks should work from before/after filters as well
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            with `wait'
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            and an explicit time
         | 
| 77 | 
            +
              - starts later because of postponed blocks in the before filter
         | 
| 78 | 
            +
              - starts even later because of the postponed blocks in the after filter
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            and without explicit time
         | 
| 81 | 
            +
              - starts later because of postponed blocks in the before filter
         | 
| 82 | 
            +
              - starts even later because of the postponed blocks in the after filter
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            with `wait_for_change'
         | 
| 85 | 
            +
              - starts later because of postponed blocks in the before filter
         | 
| 86 | 
            +
              - starts even later because of the postponed blocks in the after filter
         | 
| 87 | 
            +
             | 
| 60 88 | 
             
            Nib helper
         | 
| 61 89 | 
             
              - takes a NIB path and instantiates the NIB with the given `owner' object
         | 
| 62 90 | 
             
              - also returns an array or other top level objects
         | 
| @@ -84,18 +112,18 @@ Bacon::Context | |
| 84 112 |  | 
| 85 113 | 
             
            Bacon::Context empty
         | 
| 86 114 |  | 
| 87 | 
            -
            Bacon::Error: not #<Proc: | 
| 88 | 
            -
            	/Users/eloy/ | 
| 89 | 
            -
            	/Users/eloy/ | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
            	/Users/eloy/ | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
            	/Users/eloy/ | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 115 | 
            +
            Bacon::Error: not #<Proc:0x200485980 (lambda)>.raise?(Bacon::Error) failed
         | 
| 116 | 
            +
            	/Users/eloy/code/MacRuby/MacBacon/test/spec_bacon.rb:9:in `block': Bacon - should have should.be.close
         | 
| 117 | 
            +
            	/Users/eloy/code/MacRuby/MacBacon/test/spec_bacon.rb:182:in `block'
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            Bacon::Error: timeout exceeded: concerning `wait' without a fixed time - has a default timeout of 1 second after which the spec will fail and further scheduled calls to the Context are cancelled
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            Bacon::Error: timeout exceeded: concerning `wait' without a fixed time - takes an explicit timeout
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            Bacon::Error: timeout exceeded: concerning `wait_for_change' - has a default timeout of 1 second
         | 
| 124 | 
            +
            	/Users/eloy/code/MacRuby/MacBacon/test/spec_helper.rb:23:in `finish_spec': concerning `wait_for_change' - has a default timeout of 1 second
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            Bacon::Error: timeout exceeded: concerning `wait_for_change' - takes an explicit timeout
         | 
| 127 | 
            +
            	/Users/eloy/code/MacRuby/MacBacon/test/spec_helper.rb:23:in `finish_spec': concerning `wait_for_change' - takes an explicit timeout
         | 
| 128 | 
            +
             | 
| 129 | 
            +
            64 specifications (411 requirements), 1 failures, 0 errors
         | 
    
        data/{README → README.md}
    RENAMED
    
    | @@ -1,6 +1,7 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            MacBacon -- small RSpec clone.
         | 
| 2 | 
            +
            ------------------------------
         | 
| 2 3 |  | 
| 3 | 
            -
             | 
| 4 | 
            +
                "Truth will sooner come out from error than from confusion."
         | 
| 4 5 | 
             
                                                           ---Francis Bacon
         | 
| 5 6 |  | 
| 6 7 | 
             
            Bacon is a small RSpec clone weighing less than 350 LoC but
         | 
| @@ -9,9 +10,10 @@ nevertheless providing all essential features. | |
| 9 10 | 
             
            This MacBacon fork is created and maintained by Eloy Durán (@alloy).
         | 
| 10 11 | 
             
            It differs with regular Bacon in that it operates properly in a
         | 
| 11 12 | 
             
            NSRunloop based environment. I.e. MacRuby/Objective-C. See the
         | 
| 12 | 
            -
             | 
| 13 | 
            +
            Objective-C runloop macros section for more info.
         | 
| 13 14 |  | 
| 14 | 
            -
             | 
| 15 | 
            +
            Whirl-wind tour
         | 
| 16 | 
            +
            ===============
         | 
| 15 17 |  | 
| 16 18 | 
             
                require 'mac_bacon'
         | 
| 17 19 |  | 
| @@ -135,7 +137,8 @@ As of Bacon 1.1, it also supports Knock: | |
| 135 137 | 
             
            (knock is available from http://github.com/chneukirchen/knock/)
         | 
| 136 138 |  | 
| 137 139 |  | 
| 138 | 
            -
             | 
| 140 | 
            +
            Implemented assertions
         | 
| 141 | 
            +
            ======================
         | 
| 139 142 |  | 
| 140 143 | 
             
            * should.<predicate> and should.be.<predicate>
         | 
| 141 144 | 
             
            * should.equal
         | 
| @@ -147,7 +150,8 @@ As of Bacon 1.1, it also supports Knock: | |
| 147 150 | 
             
            * should.satisfy { |object| }
         | 
| 148 151 |  | 
| 149 152 |  | 
| 150 | 
            -
             | 
| 153 | 
            +
            Added core predicates
         | 
| 154 | 
            +
            =====================
         | 
| 151 155 |  | 
| 152 156 | 
             
            * Object#true?
         | 
| 153 157 | 
             
            * Object#false?
         | 
| @@ -157,7 +161,8 @@ As of Bacon 1.1, it also supports Knock: | |
| 157 161 | 
             
            * Numeric#close?
         | 
| 158 162 |  | 
| 159 163 |  | 
| 160 | 
            -
             | 
| 164 | 
            +
            before/after
         | 
| 165 | 
            +
            ============
         | 
| 161 166 |  | 
| 162 167 | 
             
            before and after need to be defined before the first specification in
         | 
| 163 168 | 
             
            a context and are run before and after each specification.
         | 
| @@ -165,7 +170,8 @@ a context and are run before and after each specification. | |
| 165 170 | 
             
            As of Bacon 1.1, before and after do nest in nested contexts.
         | 
| 166 171 |  | 
| 167 172 |  | 
| 168 | 
            -
             | 
| 173 | 
            +
            Shared contexts
         | 
| 174 | 
            +
            ===============
         | 
| 169 175 |  | 
| 170 176 | 
             
            You can define shared contexts in Bacon like this:
         | 
| 171 177 |  | 
| @@ -186,59 +192,132 @@ behaves_like in other contexts.  You can use shared contexts to | |
| 186 192 | 
             
            structure suites with many recurring specifications.
         | 
| 187 193 |  | 
| 188 194 |  | 
| 189 | 
            -
             | 
| 195 | 
            +
            Matchers
         | 
| 196 | 
            +
            ========
         | 
| 190 197 |  | 
| 191 198 | 
             
            Custom matchers are simply lambdas returning a boolean value, for
         | 
| 192 199 | 
             
            example:
         | 
| 193 200 |  | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 201 | 
            +
                def shorter_than(max_size)
         | 
| 202 | 
            +
                  lambda { |obj| obj.size < max_size }
         | 
| 203 | 
            +
                end
         | 
| 204 | 
            +
                
         | 
| 205 | 
            +
                [1,2,3].should.be shorter_than(5)
         | 
| 199 206 |  | 
| 200 207 | 
             
            You can use modules and extend to group matchers for use in multiple
         | 
| 201 208 | 
             
            contexts.
         | 
| 202 209 |  | 
| 203 210 |  | 
| 204 | 
            -
             | 
| 211 | 
            +
            Objective-C runloop macros
         | 
| 212 | 
            +
            ==========================
         | 
| 213 | 
            +
             | 
| 205 214 |  | 
| 206 215 | 
             
            Often in Objective-C apps, code will *not* execute immediately, but
         | 
| 207 216 | 
             
            scheduled on a runloop for later execution. Therefor a mechanism is
         | 
| 208 | 
            -
             | 
| 209 | 
            -
            time. This is where the `wait` macro comes in:
         | 
| 217 | 
            +
            provided that will postpone execution of blocks for a period of time.
         | 
| 210 218 |  | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 219 | 
            +
            You can event nest these blocks. However, with the exception of `wait`
         | 
| 220 | 
            +
            with an explicit time, you can *not* have multiple at the same time.
         | 
| 221 | 
            +
             | 
| 222 | 
            +
            All these macros may be used in before and after filters as well.
         | 
| 223 | 
            +
             | 
| 224 | 
            +
             | 
| 225 | 
            +
            ### `wait` with fixed period of time
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                it 'should perform a long running operation' do
         | 
| 228 | 
            +
                  # Here a method call is scheduled to be performed ~0.5 seconds in the future
         | 
| 229 | 
            +
                  @ary.performSelector("addObject:", withObject:"soup", afterDelay:0.5)
         | 
| 230 | 
            +
                  wait 0.6 do
         | 
| 231 | 
            +
                    # This block is executed ~0.6 seconds in the future
         | 
| 232 | 
            +
                    @ary.size.should.be 1
         | 
| 233 | 
            +
                  end
         | 
| 234 | 
            +
                end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
             | 
| 237 | 
            +
            ### `wait` without fixed period of time, until `resume` is called
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            By default this usage of `wait` will wait for 1 second. If `resume`
         | 
| 240 | 
            +
            has not been called by that time, the spec fails. If you want to
         | 
| 241 | 
            +
            specify the timeout use `wait_max(timeout, &block)` instead.
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                def aDelegateCallbackMethod(sender)
         | 
| 244 | 
            +
                  @delegateCallbackMethodCalled = true
         | 
| 245 | 
            +
                  resume
         | 
| 246 | 
            +
                end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                it 'should wait until notified' do
         | 
| 249 | 
            +
                  # Here a method is called that in the near future will result in the object calling back the delegate
         | 
| 250 | 
            +
                  @object.delegate = self
         | 
| 251 | 
            +
                  @object.startLongRunningMethod
         | 
| 252 | 
            +
                  wait do
         | 
| 253 | 
            +
                    # This block is executed once aDelegateCallbackMethod is called
         | 
| 254 | 
            +
                    @delegateCallbackMethodCalled.should == true
         | 
| 218 255 | 
             
                  end
         | 
| 256 | 
            +
                end
         | 
| 257 | 
            +
             | 
| 219 258 |  | 
| 220 | 
            -
             | 
| 221 | 
            -
            the runloop as well. This means that your runloop based code will have
         | 
| 222 | 
            -
            a chance to perform its job before the assertions in the block are
         | 
| 223 | 
            -
            executed.
         | 
| 259 | 
            +
            ### `wait_for_change` (Key-Value Observing)
         | 
| 224 260 |  | 
| 225 | 
            -
             | 
| 261 | 
            +
            This macro makes the specification an observer of the key path of the
         | 
| 262 | 
            +
            given object for the duration of the specification.
         | 
| 226 263 |  | 
| 264 | 
            +
            By default this usage of `wait_for_change` will wait for 1 second. If
         | 
| 265 | 
            +
            the KVO message has not arrived by that time, the spec fails. If you
         | 
| 266 | 
            +
            want to specify the timeout use
         | 
| 267 | 
            +
            `wait_for_change(observable, key_path, timeout)` instead.
         | 
| 227 268 |  | 
| 228 | 
            -
             | 
| 269 | 
            +
                class AKeyValueObservableClass
         | 
| 270 | 
            +
                  attr_accessor :an_attribute
         | 
| 229 271 |  | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
              -o, --output FORMAT      do FORMAT (SpecDox/TestUnit/Tap) output
         | 
| 235 | 
            -
              -Q, --no-backtrace       don't print backtraces  
         | 
| 236 | 
            -
              -a, --automatic          gather tests from ./test/, include ./lib/
         | 
| 237 | 
            -
              -n, --name NAME          runs tests matching regexp NAME
         | 
| 238 | 
            -
              -t, --testcase TESTCASE  runs tests in TestCases matching regexp TESTCASE
         | 
| 272 | 
            +
                  def compute_an_attribute
         | 
| 273 | 
            +
                    # trust me, this takes a few ms
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
                end
         | 
| 239 276 |  | 
| 277 | 
            +
                it 'should wait until AKeyValueObservableClass#an_attribute changes' do
         | 
| 278 | 
            +
                  # Here a method is called that in the near future will update the 'an_attribute' value of the object
         | 
| 279 | 
            +
                  observable.compute_an_attribute
         | 
| 280 | 
            +
                  wait_for_change observable, 'an_attribute' do
         | 
| 281 | 
            +
                    # This block is executed once 'an_attribute' has changed value
         | 
| 282 | 
            +
                    observable.an_attribute.should == 'changed'
         | 
| 283 | 
            +
                  end
         | 
| 284 | 
            +
                end
         | 
| 240 285 |  | 
| 241 | 
            -
             | 
| 286 | 
            +
             | 
| 287 | 
            +
            Load NIBs
         | 
| 288 | 
            +
            =========
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            In case you have a NIB that defines the UI for the controller you're testing,
         | 
| 291 | 
            +
            then you can use the `load_nib` method to easily do so:
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                describe "PreferencesController" do
         | 
| 294 | 
            +
                  before do
         | 
| 295 | 
            +
                    @controller = PreferencesController.new
         | 
| 296 | 
            +
                    nib_path = File.join(SRC_ROOT, 'app/views/PreferencesWindow.xib')
         | 
| 297 | 
            +
                    @top_level_objects = load_nib(nib_path, @controller)
         | 
| 298 | 
            +
                  end
         | 
| 299 | 
            +
                  
         | 
| 300 | 
            +
                  # tests...
         | 
| 301 | 
            +
                  
         | 
| 302 | 
            +
                end
         | 
| 303 | 
            +
             | 
| 304 | 
            +
             | 
| 305 | 
            +
            bacon standalone runner
         | 
| 306 | 
            +
            =======================
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                -s, --specdox            do AgileDox-like output (default)
         | 
| 309 | 
            +
                -q, --quiet              do Test::Unit-like non-verbose output
         | 
| 310 | 
            +
                -p, --tap                do TAP (Test Anything Protocol) output
         | 
| 311 | 
            +
                -k, --knock              do Knock output
         | 
| 312 | 
            +
                -o, --output FORMAT      do FORMAT (SpecDox/TestUnit/Tap) output
         | 
| 313 | 
            +
                -Q, --no-backtrace       don't print backtraces  
         | 
| 314 | 
            +
                -a, --automatic          gather tests from ./test/, include ./lib/
         | 
| 315 | 
            +
                -n, --name NAME          runs tests matching regexp NAME
         | 
| 316 | 
            +
                -t, --testcase TESTCASE  runs tests in TestCases matching regexp TESTCASE
         | 
| 317 | 
            +
             | 
| 318 | 
            +
             | 
| 319 | 
            +
            Object#should
         | 
| 320 | 
            +
            =============
         | 
| 242 321 |  | 
| 243 322 | 
             
            You can use Object#should outside of contexts, where the result of
         | 
| 244 323 | 
             
            assertion will be returned as a boolean.  This is nice for
         | 
| @@ -251,7 +330,8 @@ demonstrations, quick checks and doctest tests. | |
| 251 330 | 
             
                => false
         | 
| 252 331 |  | 
| 253 332 |  | 
| 254 | 
            -
             | 
| 333 | 
            +
            Converting specs
         | 
| 334 | 
            +
            ================
         | 
| 255 335 |  | 
| 256 336 | 
             
            spec-converter is a simple tool to convert test-unit or dust style
         | 
| 257 337 | 
             
            tests to test/spec specs.
         | 
| @@ -259,7 +339,8 @@ tests to test/spec specs. | |
| 259 339 | 
             
            It can be found at http://opensource.thinkrelevance.com/wiki/spec_converter.
         | 
| 260 340 |  | 
| 261 341 |  | 
| 262 | 
            -
             | 
| 342 | 
            +
            Thanks to
         | 
| 343 | 
            +
            =========
         | 
| 263 344 |  | 
| 264 345 | 
             
            * Michael Fellinger, for fixing Bacon for 1.9 and various improvements.
         | 
| 265 346 | 
             
            * Gabriele Renzi, for implementing Context#should.
         | 
| @@ -268,7 +349,8 @@ It can be found at http://opensource.thinkrelevance.com/wiki/spec_converter. | |
| 268 349 | 
             
            * everyone contributing bug fixes.
         | 
| 269 350 |  | 
| 270 351 |  | 
| 271 | 
            -
             | 
| 352 | 
            +
            History
         | 
| 353 | 
            +
            =======
         | 
| 272 354 |  | 
| 273 355 | 
             
            * January 7, 2008: First public release 0.9.
         | 
| 274 356 |  | 
| @@ -288,10 +370,17 @@ It can be found at http://opensource.thinkrelevance.com/wiki/spec_converter. | |
| 288 370 |  | 
| 289 371 | 
             
            * January 10th, 2011: MacBacon fork release 1.1
         | 
| 290 372 | 
             
              * Make it work in a NSRunloop environment
         | 
| 291 | 
            -
              * Add `wait | 
| 373 | 
            +
              * Add `wait`
         | 
| 292 374 | 
             
              * Remove extras, for now
         | 
| 293 375 |  | 
| 294 | 
            -
             | 
| 376 | 
            +
            * March 12th, 2011: MacBacon fork release 1.3
         | 
| 377 | 
            +
              * Add NIB helper
         | 
| 378 | 
            +
              * exit with non-zero status when there were failures/errors
         | 
| 379 | 
            +
              * Add `wait` without explicit time
         | 
| 380 | 
            +
              * Add `wait_for_change`
         | 
| 381 | 
            +
             | 
| 382 | 
            +
            Contact
         | 
| 383 | 
            +
            =======
         | 
| 295 384 |  | 
| 296 385 | 
             
            Please mail bugs, suggestions and patches for Bacon to
         | 
| 297 386 | 
             
            <mailto:chneukirchen@gmail.com>
         | 
| @@ -307,18 +396,23 @@ And repository location: | |
| 307 396 | 
             
            https://github.com/alloy/MacBacon
         | 
| 308 397 | 
             
            git://github.com/alloy/MacBacon.git
         | 
| 309 398 |  | 
| 310 | 
            -
             | 
| 399 | 
            +
            Copying
         | 
| 400 | 
            +
            =======
         | 
| 311 401 |  | 
| 312 | 
            -
            Copyright (C) 2007 | 
| 402 | 
            +
            Copyright (C) 2007 - 2011 Christian Neukirchen <purl.org/net/chneukirchen>
         | 
| 403 | 
            +
            Copyright (C) 2011 Eloy Durán <eloy.de.enige@gmail.com>
         | 
| 313 404 |  | 
| 314 405 | 
             
            Bacon is freely distributable under the terms of an MIT-style license.
         | 
| 315 406 | 
             
            See COPYING or http://www.opensource.org/licenses/mit-license.php.
         | 
| 316 407 |  | 
| 317 408 |  | 
| 318 | 
            -
             | 
| 409 | 
            +
            Links
         | 
| 410 | 
            +
            =====
         | 
| 319 411 |  | 
| 320 412 | 
             
            Behavior-Driven Development:: <http://behaviour-driven.org/>
         | 
| 321 413 | 
             
            RSpec:: <http://rspec.rubyforge.org/>
         | 
| 322 414 | 
             
            test/spec:: <http://test-spec.rubyforge.org/>
         | 
| 323 415 |  | 
| 324 416 | 
             
            Christian Neukirchen:: <http://chneukirchen.org/>
         | 
| 417 | 
            +
            Eloy Durán:: <http://soup.superalloy.nl/>
         | 
| 418 | 
            +
             | 
    
        data/Rakefile
    CHANGED
    
    | @@ -27,7 +27,7 @@ def git_tree_version | |
| 27 27 | 
             
                #$: << "lib"
         | 
| 28 28 | 
             
                #require 'mac_bacon'
         | 
| 29 29 | 
             
                #@tree_version = Bacon::VERSION
         | 
| 30 | 
            -
                @tree_version = "1. | 
| 30 | 
            +
                @tree_version = "1.3"
         | 
| 31 31 | 
             
              end
         | 
| 32 32 | 
             
              @tree_version
         | 
| 33 33 | 
             
            end
         | 
| @@ -116,7 +116,7 @@ https://github.com/alloy/MacBacon | |
| 116 116 | 
             
                s.executables     << 'macbacon'
         | 
| 117 117 | 
             
                s.require_path    = 'lib'
         | 
| 118 118 | 
             
                s.has_rdoc        = true
         | 
| 119 | 
            -
                s.extra_rdoc_files = ['README', 'RDOX']
         | 
| 119 | 
            +
                s.extra_rdoc_files = ['README.md', 'RDOX']
         | 
| 120 120 | 
             
                s.test_files      = []
         | 
| 121 121 |  | 
| 122 122 | 
             
                s.author          = 'Eloy Durán'
         | 
| @@ -137,11 +137,11 @@ end | |
| 137 137 | 
             
            desc "Generate RDoc documentation"
         | 
| 138 138 | 
             
            Rake::RDocTask.new(:rdoc) do |rdoc|
         | 
| 139 139 | 
             
              rdoc.options << '--line-numbers' << '--inline-source' <<
         | 
| 140 | 
            -
                '--main' << 'README' <<
         | 
| 140 | 
            +
                '--main' << 'README.md' <<
         | 
| 141 141 | 
             
                '--title' << 'Bacon Documentation' <<
         | 
| 142 142 | 
             
                '--charset' << 'utf-8'
         | 
| 143 143 | 
             
              rdoc.rdoc_dir = "doc"
         | 
| 144 | 
            -
              rdoc.rdoc_files.include 'README'
         | 
| 144 | 
            +
              rdoc.rdoc_files.include 'README.md'
         | 
| 145 145 | 
             
              rdoc.rdoc_files.include 'COPYING'
         | 
| 146 146 | 
             
              rdoc.rdoc_files.include 'RDOX'
         | 
| 147 147 | 
             
              rdoc.rdoc_files.include('lib/mac_bacon.rb')
         | 
    
        data/lib/mac_bacon.rb
    CHANGED
    
    | @@ -11,7 +11,7 @@ framework "Cocoa" | |
| 11 11 | 
             
            require "mac_bacon/helpers"
         | 
| 12 12 |  | 
| 13 13 | 
             
            module Bacon
         | 
| 14 | 
            -
              VERSION = "1. | 
| 14 | 
            +
              VERSION = "1.3"
         | 
| 15 15 |  | 
| 16 16 | 
             
              Counter = Hash.new(0)
         | 
| 17 17 | 
             
              ErrorLog = ""
         | 
| @@ -137,31 +137,43 @@ module Bacon | |
| 137 137 | 
             
                  @before_filters, @after_filters = before_filters.dup, after_filters.dup
         | 
| 138 138 |  | 
| 139 139 | 
             
                  @postponed_blocks_count = 0
         | 
| 140 | 
            +
                  @ran_spec_block = false
         | 
| 141 | 
            +
                  @ran_after_filters = false
         | 
| 140 142 | 
             
                  @exception_occurred = false
         | 
| 141 143 | 
             
                  @error = ""
         | 
| 142 144 | 
             
                end
         | 
| 143 145 |  | 
| 146 | 
            +
                def postponed?
         | 
| 147 | 
            +
                  @postponed_blocks_count != 0
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
             | 
| 144 150 | 
             
                def run_before_filters
         | 
| 145 | 
            -
                  @before_filters.each { |f| @context.instance_eval(&f) }
         | 
| 151 | 
            +
                  execute_block { @before_filters.each { |f| @context.instance_eval(&f) } }
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def run_spec_block
         | 
| 155 | 
            +
                  @ran_spec_block = true
         | 
| 156 | 
            +
                  # If an exception occurred, we definitely don't need to perform the actual spec anymore
         | 
| 157 | 
            +
                  unless @exception_occurred
         | 
| 158 | 
            +
                    execute_block { @context.instance_eval(&@block) }
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
                  finish_spec unless postponed?
         | 
| 146 161 | 
             
                end
         | 
| 147 162 |  | 
| 148 163 | 
             
                def run_after_filters
         | 
| 149 | 
            -
                  @ | 
| 164 | 
            +
                  @ran_after_filters = true
         | 
| 165 | 
            +
                  execute_block { @after_filters.each { |f| @context.instance_eval(&f) } }
         | 
| 150 166 | 
             
                end
         | 
| 151 167 |  | 
| 152 168 | 
             
                def run
         | 
| 153 169 | 
             
                  Bacon.handle_requirement_begin(@description)
         | 
| 154 | 
            -
                   | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
                    @context.instance_eval(&@block)
         | 
| 159 | 
            -
                  end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                  finalize if @postponed_blocks_count == 0
         | 
| 170 | 
            +
                  Counter[:depth] += 1
         | 
| 171 | 
            +
                  run_before_filters
         | 
| 172 | 
            +
                  @number_of_requirements_before = Counter[:requirements]
         | 
| 173 | 
            +
                  run_spec_block unless postponed?
         | 
| 162 174 | 
             
                end
         | 
| 163 175 |  | 
| 164 | 
            -
                def  | 
| 176 | 
            +
                def schedule_block(seconds, &block)
         | 
| 165 177 | 
             
                  # If an exception occurred, we definitely don't need to schedule any more blocks
         | 
| 166 178 | 
             
                  unless @exception_occurred
         | 
| 167 179 | 
             
                    @postponed_blocks_count += 1
         | 
| @@ -169,22 +181,97 @@ module Bacon | |
| 169 181 | 
             
                  end
         | 
| 170 182 | 
             
                end
         | 
| 171 183 |  | 
| 184 | 
            +
                def postpone_block(timeout = 1, &block)
         | 
| 185 | 
            +
                  # If an exception occurred, we definitely don't need to schedule any more blocks
         | 
| 186 | 
            +
                  unless @exception_occurred
         | 
| 187 | 
            +
                    if @postponed_block
         | 
| 188 | 
            +
                      raise "Only one indefinite `wait' block at the same time is allowed!"
         | 
| 189 | 
            +
                    else
         | 
| 190 | 
            +
                      @postponed_blocks_count += 1
         | 
| 191 | 
            +
                      @postponed_block = block
         | 
| 192 | 
            +
                      performSelector("postponed_block_timeout_exceeded", withObject:nil, afterDelay:timeout)
         | 
| 193 | 
            +
                    end
         | 
| 194 | 
            +
                  end
         | 
| 195 | 
            +
                end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                def postpone_block_until_change(object_to_observe, key_path, timeout = 1, &block)
         | 
| 198 | 
            +
                  # If an exception occurred, we definitely don't need to schedule any more blocks
         | 
| 199 | 
            +
                  unless @exception_occurred
         | 
| 200 | 
            +
                    if @postponed_block
         | 
| 201 | 
            +
                      raise "Only one indefinite `wait' block at the same time is allowed!"
         | 
| 202 | 
            +
                    else
         | 
| 203 | 
            +
                      @postponed_blocks_count += 1
         | 
| 204 | 
            +
                      @postponed_block = block
         | 
| 205 | 
            +
                      @observed_object_and_key_path = [object_to_observe, key_path]
         | 
| 206 | 
            +
                      object_to_observe.addObserver(self, forKeyPath:key_path, options:0, context:nil)
         | 
| 207 | 
            +
                      performSelector("postponed_change_block_timeout_exceeded", withObject:nil, afterDelay:timeout)
         | 
| 208 | 
            +
                    end
         | 
| 209 | 
            +
                  end
         | 
| 210 | 
            +
                end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                def observeValueForKeyPath(key_path, ofObject:object, change:_, context:__)
         | 
| 213 | 
            +
                  resume
         | 
| 214 | 
            +
                end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                def postponed_change_block_timeout_exceeded
         | 
| 217 | 
            +
                  remove_observer!
         | 
| 218 | 
            +
                  postponed_block_timeout_exceeded
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                def remove_observer!
         | 
| 222 | 
            +
                  if @observed_object_and_key_path
         | 
| 223 | 
            +
                    object, key_path = @observed_object_and_key_path
         | 
| 224 | 
            +
                    object.removeObserver(self, forKeyPath:key_path)
         | 
| 225 | 
            +
                    @observed_object_and_key_path = nil
         | 
| 226 | 
            +
                  end
         | 
| 227 | 
            +
                end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                def postponed_block_timeout_exceeded
         | 
| 230 | 
            +
                  cancel_scheduled_requests!
         | 
| 231 | 
            +
                  execute_block { raise Error.new(:failed, "timeout exceeded: #{@context.name} - #{@description}") }
         | 
| 232 | 
            +
                  @postponed_blocks_count = 0
         | 
| 233 | 
            +
                  finish_spec
         | 
| 234 | 
            +
                end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                def resume
         | 
| 237 | 
            +
                  NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:'postponed_block_timeout_exceeded', object:nil)
         | 
| 238 | 
            +
                  NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:'postponed_change_block_timeout_exceeded', object:nil)
         | 
| 239 | 
            +
                  remove_observer!
         | 
| 240 | 
            +
                  block, @postponed_block = @postponed_block, nil
         | 
| 241 | 
            +
                  run_postponed_block(block)
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
             | 
| 172 244 | 
             
                def run_postponed_block(block)
         | 
| 173 245 | 
             
                  # If an exception occurred, we definitely don't need execute any more blocks
         | 
| 174 246 | 
             
                  execute_block(&block) unless @exception_occurred
         | 
| 175 247 | 
             
                  @postponed_blocks_count -= 1
         | 
| 176 | 
            -
                   | 
| 248 | 
            +
                  unless postponed?
         | 
| 249 | 
            +
                    if @ran_after_filters
         | 
| 250 | 
            +
                      exit_spec
         | 
| 251 | 
            +
                    elsif @ran_spec_block
         | 
| 252 | 
            +
                      finish_spec
         | 
| 253 | 
            +
                    else
         | 
| 254 | 
            +
                      run_spec_block
         | 
| 255 | 
            +
                    end
         | 
| 256 | 
            +
                  end
         | 
| 177 257 | 
             
                end
         | 
| 178 258 |  | 
| 179 | 
            -
                def  | 
| 180 | 
            -
                  if Counter[:requirements] == @number_of_requirements_before
         | 
| 259 | 
            +
                def finish_spec
         | 
| 260 | 
            +
                  if !@exception_occurred && Counter[:requirements] == @number_of_requirements_before
         | 
| 181 261 | 
             
                    # the specification did not contain any requirements, so it flunked
         | 
| 182 | 
            -
                    # TODO ugh, exceptions for control flow, need to clean this up
         | 
| 183 262 | 
             
                    execute_block { raise Error.new(:missing, "empty specification: #{@context.name} #{@description}") }
         | 
| 184 263 | 
             
                  end
         | 
| 264 | 
            +
                  run_after_filters
         | 
| 265 | 
            +
                  exit_spec unless postponed?
         | 
| 266 | 
            +
                end
         | 
| 185 267 |  | 
| 186 | 
            -
             | 
| 268 | 
            +
                def cancel_scheduled_requests!
         | 
| 269 | 
            +
                  NSObject.cancelPreviousPerformRequestsWithTarget(@context)
         | 
| 270 | 
            +
                  NSObject.cancelPreviousPerformRequestsWithTarget(self)
         | 
| 271 | 
            +
                end
         | 
| 187 272 |  | 
| 273 | 
            +
                def exit_spec
         | 
| 274 | 
            +
                  cancel_scheduled_requests!
         | 
| 188 275 | 
             
                  Counter[:depth] -= 1
         | 
| 189 276 | 
             
                  Bacon.handle_requirement_end(@error)
         | 
| 190 277 | 
             
                  @context.specification_did_finish(self)
         | 
| @@ -197,8 +284,8 @@ module Bacon | |
| 197 284 | 
             
                    @exception_occurred = true
         | 
| 198 285 |  | 
| 199 286 | 
             
                    ErrorLog << "#{e.class}: #{e.message}\n"
         | 
| 200 | 
            -
                    e.backtrace.find_all { |line| line !~ /bin\/ | 
| 201 | 
            -
             | 
| 287 | 
            +
                    lines = $DEBUG ? e.backtrace : e.backtrace.find_all { |line| line !~ /bin\/macbacon|\/mac_bacon\.rb:\d+/ }
         | 
| 288 | 
            +
                    lines.each_with_index { |line, i|
         | 
| 202 289 | 
             
                      ErrorLog << "\t#{line}#{i==0 ? ": #{@context.name} - #{@description}" : ""}\n"
         | 
| 203 290 | 
             
                    }
         | 
| 204 291 | 
             
                    ErrorLog << "\n"
         | 
| @@ -315,8 +402,24 @@ module Bacon | |
| 315 402 | 
             
                  context
         | 
| 316 403 | 
             
                end
         | 
| 317 404 |  | 
| 318 | 
            -
                def wait(seconds, &block)
         | 
| 319 | 
            -
                   | 
| 405 | 
            +
                def wait(seconds = nil, &block)
         | 
| 406 | 
            +
                  if seconds
         | 
| 407 | 
            +
                    current_specification.schedule_block(seconds, &block)
         | 
| 408 | 
            +
                  else
         | 
| 409 | 
            +
                    current_specification.postpone_block(&block)
         | 
| 410 | 
            +
                  end
         | 
| 411 | 
            +
                end
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                def wait_max(timeout, &block)
         | 
| 414 | 
            +
                  current_specification.postpone_block(timeout, &block)
         | 
| 415 | 
            +
                end
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                def wait_for_change(object_to_observe, key_path, timeout = 1, &block)
         | 
| 418 | 
            +
                  current_specification.postpone_block_until_change(object_to_observe, key_path, timeout, &block)
         | 
| 419 | 
            +
                end
         | 
| 420 | 
            +
             | 
| 421 | 
            +
                def resume
         | 
| 422 | 
            +
                  current_specification.resume
         | 
| 320 423 | 
             
                end
         | 
| 321 424 |  | 
| 322 425 | 
             
                def raise?(*args, &block); block.raise?(*args); end
         | 
    
        data/test/spec_helper.rb
    CHANGED
    
    | @@ -1,2 +1,28 @@ | |
| 1 1 | 
             
            $:.unshift File.expand_path('../../lib', __FILE__)
         | 
| 2 2 | 
             
            require 'mac_bacon'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Bacon
         | 
| 5 | 
            +
              class Specification
         | 
| 6 | 
            +
                alias_method :_real_finish_spec, :finish_spec
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              class Context
         | 
| 10 | 
            +
                def failures_before
         | 
| 11 | 
            +
                  @failures_before
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def expect_spec_to_fail!
         | 
| 15 | 
            +
                  @failures_before = Bacon::Counter[:failed]
         | 
| 16 | 
            +
                  Bacon::Specification.class_eval do
         | 
| 17 | 
            +
                    def finish_spec
         | 
| 18 | 
            +
                      @exception_occurred.should == true
         | 
| 19 | 
            +
                      @exception_occurred = nil
         | 
| 20 | 
            +
                      Bacon::Counter[:failed].should == @context.failures_before + 1
         | 
| 21 | 
            +
                      Bacon::Counter[:failed] = @context.failures_before
         | 
| 22 | 
            +
                      self.class.class_eval { alias_method :finish_spec, :_real_finish_spec }
         | 
| 23 | 
            +
                      _real_finish_spec
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
    
        data/test/spec_mac_bacon.rb
    CHANGED
    
    | @@ -1,19 +1,204 @@ | |
| 1 1 | 
             
            require File.expand_path('../spec_helper', __FILE__)
         | 
| 2 2 |  | 
| 3 | 
            +
            class MockObservable
         | 
| 4 | 
            +
              attr_accessor :an_attribute
         | 
| 5 | 
            +
            end
         | 
| 6 | 
            +
             | 
| 3 7 | 
             
            describe "NSRunloop aware Bacon" do
         | 
| 4 | 
            -
               | 
| 5 | 
            -
                 | 
| 6 | 
            -
             | 
| 8 | 
            +
              describe "concerning `wait' with a fixed time" do
         | 
| 9 | 
            +
                it "allows the user to postpone execution of a block for n seconds, which will halt any further execution of specs" do
         | 
| 10 | 
            +
                  started_at_1 = started_at_2 = started_at_3 = Time.now
         | 
| 11 | 
            +
                  number_of_specs_before = Bacon::Counter[:specifications]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  wait 0.5 do
         | 
| 14 | 
            +
                    (Time.now - started_at_1).should.be.close(0.5, 0.5)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  wait 1 do
         | 
| 17 | 
            +
                    (Time.now - started_at_2).should.be.close(1, 0.5)
         | 
| 18 | 
            +
                    wait 1.5 do
         | 
| 19 | 
            +
                      (Time.now - started_at_3).should.be.close(2.5, 0.5)
         | 
| 20 | 
            +
                      Bacon::Counter[:specifications].should == number_of_specs_before
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              describe "concerning `wait' without a fixed time" do
         | 
| 27 | 
            +
                def delegateCallbackMethod
         | 
| 28 | 
            +
                  @delegateCallbackCalled = true
         | 
| 29 | 
            +
                  resume
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                it "allows the user to postpone execution of a block until Context#resume is called, from for instance a delegate callback" do
         | 
| 33 | 
            +
                  performSelector('delegateCallbackMethod', withObject:nil, afterDelay:0.1)
         | 
| 34 | 
            +
                  @delegateCallbackCalled.should == nil
         | 
| 35 | 
            +
                  wait do
         | 
| 36 | 
            +
                    @delegateCallbackCalled.should == true
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def delegateCallbackTookTooLongMethod
         | 
| 41 | 
            +
                  raise "Oh noes, I must never be called!"
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                # This spec adds a failure to the ErrorLog!
         | 
| 45 | 
            +
                it "has a default timeout of 1 second after which the spec will fail and further scheduled calls to the Context are cancelled" do
         | 
| 46 | 
            +
                  expect_spec_to_fail!
         | 
| 47 | 
            +
                  performSelector('delegateCallbackTookTooLongMethod', withObject:nil, afterDelay:1.2)
         | 
| 48 | 
            +
                  wait do
         | 
| 49 | 
            +
                    # we must never arrive here, because the default timeout of 1 second will have passed
         | 
| 50 | 
            +
                    raise "Oh noes, we shouldn't have arrived in this postponed block!"
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # This spec adds a failure to the ErrorLog!
         | 
| 55 | 
            +
                it "takes an explicit timeout" do
         | 
| 56 | 
            +
                  expect_spec_to_fail!
         | 
| 57 | 
            +
                  performSelector('delegateCallbackTookTooLongMethod', withObject:nil, afterDelay:0.8)
         | 
| 58 | 
            +
                  wait_max 0.3 do
         | 
| 59 | 
            +
                    # we must never arrive here, because the default timeout of 1 second will have passed
         | 
| 60 | 
            +
                    raise "Oh noes, we shouldn't have arrived in this postponed block!"
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              describe "concerning `wait_for_change'" do
         | 
| 66 | 
            +
                before do
         | 
| 67 | 
            +
                  @observable = MockObservable.new
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def triggerChange
         | 
| 71 | 
            +
                  @observable.an_attribute = 'changed'
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                it "resumes the postponed block once an observed value changes" do
         | 
| 75 | 
            +
                  wait_for_change @observable, 'an_attribute' do
         | 
| 76 | 
            +
                    @value = @observable.an_attribute
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                  @value.should == nil
         | 
| 79 | 
            +
                  performSelector('triggerChange', withObject:nil, afterDelay:0.1)
         | 
| 80 | 
            +
                  wait 0.2 do
         | 
| 81 | 
            +
                    @value.should == 'changed'
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                # This spec adds a failure to the ErrorLog!
         | 
| 86 | 
            +
                it "has a default timeout of 1 second" do
         | 
| 87 | 
            +
                  expect_spec_to_fail!
         | 
| 88 | 
            +
                  wait_for_change(@observable, 'an_attribute') do
         | 
| 89 | 
            +
                    raise "Oh noes, I must never be called!"
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
                  performSelector('triggerChange', withObject:nil, afterDelay:1.1)
         | 
| 92 | 
            +
                  wait 1.2 do
         | 
| 93 | 
            +
                    # we must never arrive here, because the default timeout of 1 second will have passed
         | 
| 94 | 
            +
                    raise "Oh noes, we shouldn't have arrived in this postponed block!"
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                # This spec adds a failure to the ErrorLog!
         | 
| 99 | 
            +
                it "takes an explicit timeout" do
         | 
| 100 | 
            +
                  expect_spec_to_fail!
         | 
| 101 | 
            +
                  wait_for_change(@observable, 'an_attribute', 0.3) do
         | 
| 102 | 
            +
                    raise "Oh noes, I must never be called!"
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                  performSelector('triggerChange', withObject:nil, afterDelay:0.8)
         | 
| 105 | 
            +
                  wait 0.9 do
         | 
| 106 | 
            +
                    # we must never arrive here, because the default timeout of 1 second will have passed
         | 
| 107 | 
            +
                    raise "Oh noes, we shouldn't have arrived in this postponed block!"
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              describe "postponing blocks should work from before/after filters as well" do
         | 
| 113 | 
            +
                shared "waiting in before/after filters" do
         | 
| 114 | 
            +
                  it "starts later because of postponed blocks in the before filter" do
         | 
| 115 | 
            +
                    (Time.now - @started_at).should.be.close(1, 0.5)
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  it "starts even later because of the postponed blocks in the after filter" do
         | 
| 119 | 
            +
                    (Time.now - @started_at).should.be.close(3, 0.5)
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                describe "with `wait'" do
         | 
| 124 | 
            +
                  describe "and an explicit time" do
         | 
| 125 | 
            +
                    before do
         | 
| 126 | 
            +
                      @started_at ||= Time.now
         | 
| 127 | 
            +
                      wait 0.5 do
         | 
| 128 | 
            +
                        wait 0.5 do
         | 
| 129 | 
            +
                        end
         | 
| 130 | 
            +
                      end
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                    after do
         | 
| 134 | 
            +
                      wait 0.5 do
         | 
| 135 | 
            +
                        wait 0.5 do
         | 
| 136 | 
            +
                          @time ||= 0
         | 
| 137 | 
            +
                          @time += 2
         | 
| 138 | 
            +
                          (Time.now - @started_at).should.be.close(@time, 0.2)
         | 
| 139 | 
            +
                        end
         | 
| 140 | 
            +
                      end
         | 
| 141 | 
            +
                    end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                    behaves_like "waiting in before/after filters"
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  describe "and without explicit time" do
         | 
| 147 | 
            +
                    before do
         | 
| 148 | 
            +
                      @started_at ||= Time.now
         | 
| 149 | 
            +
                      performSelector('resume', withObject:nil, afterDelay:0.5)
         | 
| 150 | 
            +
                      wait do
         | 
| 151 | 
            +
                        performSelector('resume', withObject:nil, afterDelay:0.5)
         | 
| 152 | 
            +
                        wait do
         | 
| 153 | 
            +
                        end
         | 
| 154 | 
            +
                      end
         | 
| 155 | 
            +
                    end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                    after do
         | 
| 158 | 
            +
                      performSelector('resume', withObject:nil, afterDelay:0.5)
         | 
| 159 | 
            +
                      wait do
         | 
| 160 | 
            +
                        performSelector('resume', withObject:nil, afterDelay:0.5)
         | 
| 161 | 
            +
                        wait do
         | 
| 162 | 
            +
                          @time ||= 0
         | 
| 163 | 
            +
                          @time += 2
         | 
| 164 | 
            +
                          (Time.now - @started_at).should.be.close(@time, 0.2)
         | 
| 165 | 
            +
                        end
         | 
| 166 | 
            +
                      end
         | 
| 167 | 
            +
                    end
         | 
| 7 168 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
                   | 
| 169 | 
            +
                    behaves_like "waiting in before/after filters"
         | 
| 170 | 
            +
                  end
         | 
| 10 171 | 
             
                end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
                   | 
| 14 | 
            -
                     | 
| 15 | 
            -
                     | 
| 172 | 
            +
             | 
| 173 | 
            +
                describe "with `wait_for_change'" do
         | 
| 174 | 
            +
                  before do
         | 
| 175 | 
            +
                    @observable = MockObservable.new
         | 
| 176 | 
            +
                    @started_at ||= Time.now
         | 
| 177 | 
            +
                    performSelector('triggerChange', withObject:nil, afterDelay:0.5)
         | 
| 178 | 
            +
                    wait_for_change @observable, 'an_attribute' do
         | 
| 179 | 
            +
                      performSelector('triggerChange', withObject:nil, afterDelay:0.5)
         | 
| 180 | 
            +
                      wait_for_change @observable, 'an_attribute' do
         | 
| 181 | 
            +
                      end
         | 
| 182 | 
            +
                    end
         | 
| 183 | 
            +
                  end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                  after do
         | 
| 186 | 
            +
                    performSelector('triggerChange', withObject:nil, afterDelay:0.5)
         | 
| 187 | 
            +
                    wait_for_change @observable, 'an_attribute' do
         | 
| 188 | 
            +
                      performSelector('triggerChange', withObject:nil, afterDelay:0.5)
         | 
| 189 | 
            +
                      wait_for_change @observable, 'an_attribute' do
         | 
| 190 | 
            +
                        @time ||= 0
         | 
| 191 | 
            +
                        @time += 2
         | 
| 192 | 
            +
                        (Time.now - @started_at).should.be.close(@time, 1)
         | 
| 193 | 
            +
                      end
         | 
| 194 | 
            +
                    end
         | 
| 16 195 | 
             
                  end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  def triggerChange
         | 
| 198 | 
            +
                    @observable.an_attribute = 'changed'
         | 
| 199 | 
            +
                  end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                  behaves_like "waiting in before/after filters"
         | 
| 17 202 | 
             
                end
         | 
| 18 203 | 
             
              end
         | 
| 19 204 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: mac_bacon
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
               | 
| 5 | 
            -
              prerelease: false
         | 
| 6 | 
            -
              segments: 
         | 
| 7 | 
            -
              - 1
         | 
| 8 | 
            -
              - 2
         | 
| 9 | 
            -
              - 1
         | 
| 10 | 
            -
              version: 1.2.1
         | 
| 4 | 
            +
              version: "1.3"
         | 
| 11 5 | 
             
            platform: ruby
         | 
| 12 6 | 
             
            authors: 
         | 
| 13 7 | 
             
            - "Eloy Dur\xC3\xA1n"
         | 
| @@ -15,7 +9,7 @@ autorequire: | |
| 15 9 | 
             
            bindir: bin
         | 
| 16 10 | 
             
            cert_chain: []
         | 
| 17 11 |  | 
| 18 | 
            -
            date: 2011-03- | 
| 12 | 
            +
            date: 2011-03-12 00:00:00 +01:00
         | 
| 19 13 | 
             
            default_executable: 
         | 
| 20 14 | 
             
            dependencies: []
         | 
| 21 15 |  | 
| @@ -34,12 +28,13 @@ executables: | |
| 34 28 | 
             
            extensions: []
         | 
| 35 29 |  | 
| 36 30 | 
             
            extra_rdoc_files: 
         | 
| 37 | 
            -
            - README
         | 
| 31 | 
            +
            - README.md
         | 
| 38 32 | 
             
            - RDOX
         | 
| 39 33 | 
             
            files: 
         | 
| 40 34 | 
             
            - COPYING
         | 
| 41 | 
            -
            - README
         | 
| 35 | 
            +
            - README.md
         | 
| 42 36 | 
             
            - Rakefile
         | 
| 37 | 
            +
            - TODO
         | 
| 43 38 | 
             
            - bin/macbacon
         | 
| 44 39 | 
             
            - lib/mac_bacon.rb
         | 
| 45 40 | 
             
            - lib/mac_bacon/helpers.rb
         | 
| @@ -63,27 +58,21 @@ rdoc_options: [] | |
| 63 58 | 
             
            require_paths: 
         | 
| 64 59 | 
             
            - lib
         | 
| 65 60 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 66 | 
            -
              none: false
         | 
| 67 61 | 
             
              requirements: 
         | 
| 68 62 | 
             
              - - ">="
         | 
| 69 63 | 
             
                - !ruby/object:Gem::Version 
         | 
| 70 | 
            -
                  hash: 3
         | 
| 71 | 
            -
                  segments: 
         | 
| 72 | 
            -
                  - 0
         | 
| 73 64 | 
             
                  version: "0"
         | 
| 65 | 
            +
              version: 
         | 
| 74 66 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 75 | 
            -
              none: false
         | 
| 76 67 | 
             
              requirements: 
         | 
| 77 68 | 
             
              - - ">="
         | 
| 78 69 | 
             
                - !ruby/object:Gem::Version 
         | 
| 79 | 
            -
                  hash: 3
         | 
| 80 | 
            -
                  segments: 
         | 
| 81 | 
            -
                  - 0
         | 
| 82 70 | 
             
                  version: "0"
         | 
| 71 | 
            +
              version: 
         | 
| 83 72 | 
             
            requirements: []
         | 
| 84 73 |  | 
| 85 74 | 
             
            rubyforge_project: 
         | 
| 86 | 
            -
            rubygems_version: 1.3. | 
| 75 | 
            +
            rubygems_version: 1.3.5
         | 
| 87 76 | 
             
            signing_key: 
         | 
| 88 77 | 
             
            specification_version: 3
         | 
| 89 78 | 
             
            summary: a small RSpec clone for MacRuby
         |