"Adding Items through the UI - Update the Test" in chapter 16.

> Looking back at `AuctionSniperEndToEndTest`, it already expresses everything
> we want the application to do: it describes how the Sniper connects to one or
> more auctions and bids. The change is that we want to describe a different
> implementation of some of that behavior (establishing the connection through
> the user interface rather than the command line) which happens in the
> `ApplicationRunner`. We need a restructuring similar to the one we just made
> in `Main`, splitting the connection from the individual auctions. We pull out
> a `#start_sniper` method that starts up and checks the Sniper, and then
> starts bidding for each auction in turn.
>
> The other change to the test infrastructure is implementing the new method
> `#start_bidding_for` in `AuctionSniperDriver`. This finds and fills in the
> text field for the item identifier, then finds and clicks on the Join Auction
> button.
>
> Neither of these components exist yet, so the test fails looking for the text
> field.

      1) Error:
    test_0001_joins_auction_until_auction_closes(AuctionsniperSpec):
    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JTextField (with name "item id")
        in exactly 1 JFrame (with name "Auction Sniper Main" and showing on screen)
        in all top level windows
    and check that it is showing on screen
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing on screen)
        contained 0 JTextField (with name "item id")
"Adding Items through the UI - Adding an Action Bar" in ch 16.

> We address this failure by adding a new panel across the top to contain the
> text field for the identifier and the Join Auction button, wrapping up the
> activity in a `#make_controls` method to help express our intent. We realize
> that this code isn't very exciting, but we want to show its structure now
> before we add any behavior.
>
> With the action bar in place, our next test fails because we don't create the
> identified rows in the table model.

      1) Error:
    test_0003_wins_an_auction_by_bidding_higher(AuctionsniperSpec):
    NativeException: java.lang.AssertionError:
    Tried to look for...
        exactly 1 JTable (with name "Snipers Table")
        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 "0">, <label with text "0">, <label with text "joining">
    but...
        all top level windows
        contained 1 JFrame (with name "Auction Sniper Main" and showing on screen)
        contained 1 JTable (with name "Snipers Table")
       it is not table with row with cells <label with text "item-54321">, <label with text "0">, <label with text "0">, <label with text "joining">
"Adding Items through the UI - Another Level of Testing", ch 16.

> We want to write a test for our proposed new behavior, but we can't just
> write a simple unit test because of Swing threading. We can’t be sure that
> the Swing code will have finished running by the time we check any
> assertions at the end of the test, so we need something that will wait until
> the tested code has stabilized - what we usually call an integration test
> because it's testing how our code works with a third-party library. We can
> use WindowLicker for this level of testing as well as for our end-to-end
> tests.
>
> We create an empty implementation of `MainWindow#add_user_request_listener`,
> to get through the compiler, and the test fails:

      1) Error:
    test_0001_makes_user_request_when_join_button_clicked(MainwindowSpec):
    NativeException: java.lang.AssertionError:
    Tried to look for...
        join request "an item-id"
    but...
        join request "an item-id".  Received nothing
"Adding Items through the UI - Another Level of Testing", ch 16.

> To make this test pass, we fill in the request listener infrastructure in
> `MainWindow` using `Announcer`, a utility class that manages collections of
> listeners. We add a Swing `ActionListener` that extracts the item identifier
> and announces it to the request listeners.
"Adding Items through the UI - Implementing the UserRequestListener", ch 16.

> We return to `Main` to see where we can plug in our new
> `UserRequestListener`. The changes are minor because we did most of the work
> when we restructured the class earlier in this chapter. We decide to preserve
> most of the existing code for now (even though it's not quite the right
> shape) until we've made more progress, so we just inline our previous
> `#join_auction` method into the that of `UserRequestListener`. We're also
> pleased to remove the `#safely_add_item_to_model` wrapper, since the
> `UserRequestListener` will be called on the Swing thread. This is not obvious
> from the code as it stands; we make a note to address that later.
>
> We try our end-to-end tests again and find that they pass.