Use Ruby Thread instead of Java Thread.
"A Surprise Failure" in "A Test for Bidding" in chapter 12.

    org.jivesoftware.smack.XMPPException: conflict(409)
    org/jivesoftware/smack/SASLAuthentication.java:434:in
    `bindResourceAndEstablishSession'
    org/jivesoftware/smack/SASLAuthentication.java:331:in `authenticate'
    org/jivesoftware/smack/XMPPConnection.java:395:in `login'
    /Users/jamesmead/Code/freerange/gosling/app/main.rb:47:in `connection'
    /Users/jamesmead/Code/freerange/gosling/app/main.rb:31:in `main'
    /Users/jamesmead/Code/freerange/gosling/test/end-to-end/application_runner.rb:15:in
    `start_bidding_in'
The expected failure in "A Test for Bidding" in chapter 12.

Note that since JRuby closure conversion invokes the block on invocation
of *any* method, we have to explicitly determine whether the event is a
`WINDOW_CLOSED` event in `Main#disconnect_when_ui_closes`.

This is the test failure we are seeing :-

    Tried to look for...
        exactly 1 JLabel (with name "sniper status")
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing on
    screen)
        in all top level windows
    and check that its label text is "bidding"
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing on
    screen)
        contained 1 JLabel (with name "sniper status")
        label text was "lost"
        com/objogate/wl/PollingProber.java:38:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:74:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:142:in `has'
        com/objogate/wl/swing/driver/JLabelDriver.java:30:in `hasText'
        test/end-to-end/auction_sniper_driver.rb:25:in `shows_sniper_status'
        test/end-to-end/application_runner.rb:28:in `has_shown_sniper_is_bidding'
        test/end-to-end/auction_sniper_end_to_end_test.rb:31:in `test_0002_sniper_makes_a_higher_bid_but_loses'
"The AuctionMessageTranslator" & "Unpacking a Price Message" in chapter 12.

Note that the end-to-end test is still failing since we're in the middle
of implementing the "bidding" feature.

Notes :-

- I've introduced Mocha here rather than attempting to use JMock with
  JRuby.
- I've also been tempted into making some code slightly more idiomatic
  Ruby than a direct translation would have been.
Fix copy & paste error.
"Introducing AuctionSniper" in "The Sniper Makes a Bid" in chapter 13.

Notes :-

- I've deliberately chosen not to introduce any equivalent to Java
  interfaces like SniperListener. They don't seem to add much value in
  Ruby.
- The end-to-end test is still failing since we're still in the middle
  of implementing the "bidding" feature.
"Sending a Bid" in "The Sniper Makes a Bid" - chapter 13.

This first part of the section makes the end-to-end test pass.
"Extract XMPPAuction" in "Sending a Bid" in chapter 13.
"Extracting the User Interface" in "Sending a Bid" in chapter 13.

- I had to pass a reference to the `ui` to the `SniperStateDisplayer`. I
  don't think Ruby has a way for inner classes to get access to instance
  variables in the outer class instance.
- In my copy of the book, it looks like `sniper_id` is added to the
  constructor arguments for `AuctionMessageTranslator`, but I couldn't
  see why this was necessary, so I didn't do it in this commit.
"Tidying Up the Translator" in "Sending a Bid" in chapter 13.

- It's not possible to have *private* inner class in Ruby.
- I've continued to use the explicit methods on Hash i.e. `Hash#fetch`
  and `Hash#store` to keep the code closer to the Java equivalent.
  However the whole AuctionEvent class feels quite un-Ruby-ish.
"First a Failing Test" in "The Sniper Wins the Auction" in chapter 14.

I also tidied up the names of the end-to-end tests given that we're
using the MiniTest::Spec, we might as well make the test as readable as
possible.

Note that the newly added end-to-end test is currently failing, because
we are in the middle of implementing the feature about winning an
auction by bidding higher :-

    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JLabel (with name "sniper status")
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        in all top level windows
    and check that its label text is "winning"
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        contained 1 JLabel (with name "sniper status")
        label text was "bidding"
        com/objogate/wl/PollingProber.java:38:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:74:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:142:in `has'
        com/objogate/wl/swing/driver/JLabelDriver.java:30:in `hasText'
        test/end-to-end/auction_sniper_driver.rb:25:in
`shows_sniper_status'
        test/end-to-end/application_runner.rb:36:in
org.jruby.exceptions.RaiseException: (SystemExit) exit
    `has_shown_sniper_is_winning'
        test/end-to-end/auction_sniper_end_to_end_test.rb:45:in
`test_0003_wins_an_auction_by_bidding_higher'
Trap unexpected invocation in "Sniper Has More To Say" in chapter 14.

Shows unit test failing with unexpected invocation :-

      1) Failure:
    test_0003_reports_is_winning_when_current_price_comes_from_sniper(AuctionsniperSpec)
[app/auction_sniper.rb:9]:
    unexpected invocation: #<Mock:Auction>.bid(168)
    unsatisfied expectations:
    - expected at least once, not yet invoked:
      #<Mock:SniperListener>.sniper_winning(any_parameters)

So far I haven't been attempting to replicate the existence of
interfaces in the Java-based code from the book. This is the first time
I've felt a bit of pain from this - I decided to introduce PriceSource
as a top-level class, because it's needed by both AuctionSniper and
AuctionMessageTranslator and I have no AuctionEventListener interface in
which to put it.
Fixed first end-to-end test in "Sniper Has More to Say" in chapter 14.

Now the end-to-end test is failing, because the sniper thinks it has
lost when it has actually won :-

    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JLabel (with name "sniper status")
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        in all top level windows
    and check that its label text is "won"
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        contained 1 JLabel (with name "sniper status")
        label text was "lost"
        com/objogate/wl/PollingProber.java:38:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:74:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:142:in `has'
        com/objogate/wl/swing/driver/JLabelDriver.java:30:in `hasText'
        test/end-to-end/auction_sniper_driver.rb:25:in
`shows_sniper_status'
        test/end-to-end/application_runner.rb:40:in
`shows_sniper_has_won_auction'
        test/end-to-end/auction_sniper_end_to_end_test.rb:47:in
`test_0003_wins_an_auction_by_bidding_higher'
Failing unit test in "The Sniper Wins" in chapter 14.

This test now uses Mocha state machines. The expected failure is :-

      1) Failure:
    test_0003_reports_won_if_auction_closes_when_winning(AuctionsniperSpec)
[app/auction_sniper.rb:19]:
    unexpected invocation: #<Mock:SniperListener>.sniper_lost()
    unsatisfied expectations:
    - expected at least once, not yet invoked:
      #<Mock:SniperListener>.sniper_won(any_parameters); when sniper is
'winning'
    satisfied expectations:
    - allowed any number of times, invoked once:
      #<Mock:SniperListener>.sniper_winning(any_parameters)
    states:
    - sniper is 'winning'
All tests passing in "The Sniper Wins" at the end of chapter 14.

Now the sniper has some state.

- I couldn't resist combining the assignment of @is_winning in
  AuctionSniper with the conditional statement.
- It was also interesting that since I'm not using Java interfaces or
  anything similar, I didn't discover the missing Main#sniper_won method
  until I ran the end-to-end tests.
Failing end-to-end test in "Replacing JLabel" in chapter 15.

I found that I needed to provide a Hamcrest matcher to the JTableDriver
constructor, so I used the IsAnything matcher to (hopefully) keep the
behaviour the same as that in the code in the book.

The expected failing test illustrating the missing JTable is :-

    Tried to look for...
        exactly 1 JTable (ANYTHING)
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        in all top level windows
    and check that it is table with cell rendered cell label with text
"joining"
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        contained 0 JTable (ANYTHING)
        com/objogate/wl/PollingProber.java:38:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:74:in `check'
        com/objogate/wl/swing/driver/ComponentDriver.java:127:in `is'
        com/objogate/wl/swing/driver/JTableDriver.java:108:in `hasCell'
        end-to-end/auction_sniper_driver.rb:26:in `shows_sniper_status'
        end-to-end/application_runner.rb:24:in `start_bidding_in'
        end-to-end/auction_sniper_end_to_end_test.rb:20:in
`test_0001_joins_auction_until_auction_closes'
Fix end-to-end test in "Replacing JLabel" in chapter 15.

"We fix this test by retrofitting a minimal JTable implementation".

As usual I have had to replace the private `snipers` field and its
assignment with an instance variable and assignment within a constructor.
Failing end-to-end tests in "Displaying Price Details" in chapter 15.

The tests are failing because the table row has no details, only status
text :-

    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JTable (ANYTHING)
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        in all top level windows
    and check that it is table with row with cells <label with text
"item-54321">, <label with text "1000">, <label with text "1098">,
<label with text "bidding">
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing
on screen)
        contained 1 JTable (ANYTHING)
       it is not table with row with cells <label with text
"item-54321">, <label with text "1000">, <label with text "1098">,
<label with text "bidding">
        because
          in row 0: component 0 text was "bidding"

It is unclear, but in the book it looks like
`AuctionSniperDriver#shows_sniper_status` may have been overloaded so
there were different implementations for different sets of parameters.
I've decided to introduce `AuctionSniperDriver#driver.shows_sniper_status_text`
to avoid confusion and to reduce the number of changes needed in this
commit.
New unit test passing in "Sending State out of Sniper" in chapter 15.

The end-to-end tests are still failing as expected, because only the
status text is being shown, not the full details.

Note that I derived SniperState from the Ruby standard library Struct
class instead of using the Apache commons.lang library in JRuby.
Make assertions more specific now JTable has a name.

This is still slightly divergent from the code in the book which seems
to be using a different version of JTableDriver i.e. one which allows a
single constructor parameter.