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.
Progress on end-to-end test in "Showing a Bidding Sniper" in chapter 15.

- The first step is to pass the new state parameter, which we've been
  ignoring,through `MainWindow` to a new method in `SnipersTableModel`.
- To get the new values visible on screen, we need to fix
  `SnipersTableModel` so that it makes them available to its `JTable`,
  starting with a unit test.
- We introduce a `Column` class to represent the columns in the table
  (it's more meaningful than just using integers).
- The `Column` class is an `enum` in the Java version, but I've just
  used a simple Ruby class derived from `Struct`.
- The table model needs to do two things when its state changes: hold
  onto the new values and notify the table that they've changed. The
  unit test drives out this behaviour using a mock `TableModelListener`.
- I've used a Mocha expectation matcher block to compare the properties
  of the event. This is a bit clumsier than
  `org.hamcrest.Matchers.samePropertyValuesAs`, but it'll do for now.
- Even thought it doesn't effect the tests, I changed the order in
  which the user interface components are added to the content pane
  so that the table is visible.
Rename `SniperState` in "Listening to the Mood Music" in chapter 15.

- `SniperState` is renamed to `SniperSnapshot`.
- `Column::SNIPER_STATUS` is renamed to `Column::SNIPER_STATE`.
- The book makes this sound like a trivial operation, but it's slightly
  more involved when using a text editor and a dynamically-typed
  language!
"Simplifying Sniper Events" in chapter 15.

- Introduced `SniperState` "enum" and added it as an attribute on
  newly renamed `SniperShapshot`.
- I've used another `Struct` for the newly introduced `SniperState`
  "enum" with the same style `.values` and `#ordinal` method as for
  `Column`.
- Removed the sniper_state parameter from the method signature.
- Rename `#sniper_bidding` to `#sniper_state_changed` to match its
  intended new role - a description of the sniper's relationship with
  the auction at a moment in time.
- In the table model, we use simple indexing to translate the "enum" into
  displayable text.
- Introduced a custom parameter matcher to check just the state of a
  snapshot. I've done this by converting a lambda into a block to pass
  to `Mocha::Expectation#with` which I think works quite nicely. This is
  instead of using JMock's `FeatureMatcher`. One possible disadvantage
  is that I think the error message probably isn't as good.
- Changed `#sniper_winning` to `#sniper_state_changed`.
- Changed `AuctionSniper` to retain its most recent values by holding
  on to the last snapshot.
- Remove `#sniper_winning` and add a value for "winning" to
  `SnipersTableModel::STATUS_TEXT`.
- End-to-end test now passes.
Extract custom Mocha parameter matcher into a method.

- Revisited 829549000749c30ce9159016a3dcc524a8d29643.
- Pass a lambda converted into a block into
  `Mocha::Expectation#with` to make the code more readable and more
  similar to the JMock custom matcher `aRowChangedEvent`.
Remove JLabel which was replaced by the JTable some time ago.

I suspect this was supposed to happen a while ago, but I don't think it
is mentioned in the book.
Use a SniperSnapshot builder method instead of direct construction.
"Follow Through - Converting Won and Lost" in chapter 15.

- Replace calls to `#sniper_won` and `#sniper_lost` with calls to
  `#sniper_state_changed`.
- No longer any need for `@is_winning` in `AuctionSniper`. I changed
  back to using a `case` statement so code is more similar to Java the
  Java code. Moved some decision-making into `SniperSnapshot` which
  will know whether sniper is winning or losing.
- `AuctionSniper` no longer refers to `SniperState`; it's hidden in
  `SniperSnapshot`.
- I've gone for a fairly literal translation of the Java
  `SniperState#when_auction_closed` method implmentations. I'm not sure
  this is the best or as Ruby-ish as it could be.
- Added a test for `SniperState` as per "Not Too Small to Test"
  call-out.
"Follow Through - Trimming the Table Model" in chapter 15.

- We remove the accessor `#set_status_text` that sets the state display string
  in `SnipersTableModel`, as everything uses `#sniper_status_changed` now.
- While we’re at it, we move the description string constants for the Sniper
  state over from MainWindow.
- The helper method, `.textFor`, helps with readability, and we also use it to
  get hold of the display strings in tests since the constants are no longer
  accessible from `MainWindow`.
- The Java version uses static imports to make the test code for this much
  terser, but the more explicit Ruby code won't do any harm for now.
"Follow Through - Object-Oriented Column" in chapter 15.

> We still have a couple of things to do before we finish this task. We start by
> removing all the old test code that didn’t specify the price details, filling
> in the expected values in the tests as required. The tests still run.

Note that I have removed `AuctionSniperDriver#shows_sniper_status_text` method
which I decided to add in 0062b02dff2988ac41eeb73beeea0f868514823e as a result
of a lack of clarity in the book.
"Follow Through - Object-Oriented Column" in chapter 15.

> The next change is to replace the switch statement which is noisy, not very
> object-oriented, and includes an unnecessary default: clause just to satisfy
> the compiler. It’s served its purpose, which was to get us through the
> previous coding stage. We add a method to `Column` that will extract the
> appropriate field.
>
> Of course, we write a unit test for `Column`. It may seem unnecessary now,
> but it will protect us when we make changes and forget to keep the column
> mapping up to date.
"Follow Through - Shortening the Event Path" in chapter 15.

> Finally, we see that we have some forwarding calls that we no longer need.
> `MainWindow` just forwards the update and `SniperStateDisplayer` has
> collapsed to almost nothing.
>
> `SniperStateDisplayer` still serves a useful purpose, which is to push
> updates onto the Swing event thread, but it no longer does any translation
> between domains in the code, and the call to `MainWindow` is unnecessary. We
> decide to simplify the connections by making `SnipersTableModel` implement
> `SniperListener`. We change `SniperStateDisplayer` to be a Decorator and
> rename it to `SwingThreadSniperListener`, and we rewire `Main` so that the
> `Sniper` connects to the table model rather than the window.
"Final Polish - A Test for Column Titles" in chapter 15.

> To make the user interface presentable, we need to fill in the column titles
> which, as we saw in Figure 15.3, are still missing. This isn’t difficult,
> since most of the implementation is built into Swing’s `TableModel`. As
> always, we start with the acceptance test. We add extra validation to
> `AuctionSniperDriver` that will be called by the method in
> `ApplicationRunner` that starts up the Sniper. For good measure, we throw
> in a check for the application’s displayed title.
>
> The test fails:

      1) Error:
    test_0001_joins_auction_until_auction_closes(AuctionsniperSpec):
    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JTableHeader ()
        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 headers with cells <label with text "Item">, <label with text "Last Price">, <label with text "Last Bid">, <label with text "State">
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing on screen)
        contained 1 JTableHeader ()
       it is not table with headers with cells <label with text "Item">, <label with text "Last Price">, <label with text "Last Bid">, <label with text "State">
        because component 0 text was "A"

Note that I had to pass `JTableHeader.java_class` into the `JTableHeaderDriver`
constructor instead of `JTableHeader.class` to avoid the following exception:

    NativeException: java.lang.IllegalStateException: probe failed
"Final Polish - Implementing the TableModel" in chapter 15.

> Swing allows a `JTable` to query its `TableModel` for the column headers,
> which is the mechanism we’ve chosen to use. We already have `Column` to
> represent the columns, so we extend this enum by adding a field for the
> header text which we reference in `SnipersTableModel`.
>
> All we really need to check in the unit test for `SniperTablesModel` is the
> link between a `Column` value and a column name, but it’s so simple to
> iterate that we check them all.
>
> The acceptance test passes, and we can see the result in Figure 15.5.

Note that I'd already given the `Column` a name attribute in order to make a
Ruby equivalent of a Java `enum`.
"Testing for Multiple Items - A Tale of Two Items" in chapter 16.

> As always, we start with a test. We want our new test to show that the
> application can bid for and win two different items, so we start by looking
> at the tests we already have. Our current test for a successful bid, in
> "First, a Failing Test", assumes that the application has only one auction
> it's implicit in code such as:

    application.hasShownSniperIsBidding(1000, 1098);

> We prepare for multiple items by passing an auction into each of the
> `ApplicationRunner` calls, so the code now looks like:

    application.hasShownSniperIsBidding(auction, 1000, 1098);

> Within the `ApplicationRunner`, we remove the `itemId` field and instead
> extract the item identifier from the auction parameters.
"Testing for Multiple Items - The Application Runner" in ch 16.

> The rest is similar, which means we can write a new test.
>
> Following the protocol convention, we also remember to add a new user,
> `auction-item-65432`, to the chat server to represent the new auction.
>
> The one significant change we have to make in the `ApplicationRunner` is to
> the `#start_bidding_in` method. Now it needs to accept a variable number of
> auctions passed through to the Sniper’s command line. The conversion is a
> bit messy since we have to unpack the item identifiers and append them to the
> end of the other command-line arguments — this is the best we can do with
> Java arrays.
>
> We run the test and watch it fail:

      1) Error:
    test_0004_bids_for_multiple_items(AuctionsniperSpec):
    NativeException: java.lang.AssertionError: Message
    Expected: is not null
         but: was null

Notes:

* Using the Ruby splat operator and `Array#map` I've avoided the need for
  the `#arguments` method mentioned in the book.
* In order to see the test fail in the way described in the book, I found that
  I needed to postpone to a later commit the change to
  `ApplicationRunner#start_bidding_in` which checks the sniper status in the UI
  for *each* auction.
"Testing for Multiple Items - A Diversion" in chapter 16.

> Fixing the Failure Message.
>
> We first saw this cryptic failure message in Chapter 11. It wasn't so bad
> then because it could only occur in one place and there wasn't much code
> to test anyway. Now it's more annoying because we have to find this method
> and figure out what we’re missing. We’d like to combine these two
> assertions and provide a more meaningful failure. We could write a custom
> matcher for the message body but, given that the structure of `Message` is
> not going to change soon, we can use a `PropertyMatcher` which produces
> this more helpful failure report:

      1) Error:
    test_0004_bids_for_multiple_items(AuctionsniperSpec):
    NativeException: java.lang.AssertionError:
    Expected: hasProperty("body", "SQLVersion: 1.1; Command: JOIN;")
         but: was null