First test - Page85 - sniper joins auction and after that auction closes
First test implementation - Page93
Page94 - added a MessageListener to the chat

Added a MessageListener to the chat to accept messages from the Sniper. This
means that we need to coordinate between the thread that runs the test and
the Smack thread that feeds messages to the listenerÎíÎñthe test has to
wait for messages to arrive and time out if they dont.
Page97 - added a UI MainWindow
Page99 - connection from the Sniper to the auction

We write a simplistic implementation to get us past this failure. It
connects to the chat in Main and sends an empty message. We create a null
MessageListener to allow us to create a Chat for sending the empty initial
message, since we donÎéÎ÷t yet care about receiving message
Page101 - UI attached to chat

We need to attach the user interface to the chat so it can
receive the response from the auction, so we create a connection and pass
it to Main to create the Chat object. joinAuction() creates a
MessageListener that sets the status label, using an invokeLater() call to
avoid blocking the Smack library. As with the Join message, we donÎéÎ÷t
bother with the contents of the incoming message since thereÎéÎ÷s only one
possible response the auction can send at the moment. While we're at
it, we rename connect() to connection() to make the code read better
Page106 - Test for Bidding
Page107 - implementing to pass the previous test

reportPrice(): has to send a Price message through the chat;
hasReceivedBid(): is a little more complex - It has to check that the
auction re- ceived the right values from the Sniper. Instead of parsing
the incoming message, we construct the expected message and just compare
strings. We also pull up the Matcher clause from the SingleMessageListener
to give the FakeAuctionServer more ÎõÎéexibility in deÎõÎéning what it
will accept as a message.
Page110 - refactoring previous Test

Notice that we check the SniperÎéÎ÷s identiÎõÎéer after we check the
contents of the message. This forces the server to wait until the message
has arrived, which means that it must have accepted a connection and set
up currentChat. Otherwise the test would fail by checking the SniperÎéÎ÷s
identiÎõÎéer prematurely
Page112 - Getting ready to bid

The server is configured, like Southabees On-Line, to reject
multiple open connections, so the second test fails because the server
thinks that the first is still connected. In production, our application
would work because weÎéÎ÷d stop the whole process when closing, which
would break the connection. Our little com- promise (of starting the
application in a new thread) has caught us out. The Right Thing to do here
is to add a callback to disconnect the client when we close the window so
that the application will clean up after itself
Page114 - We start with the simpler event type.

Close event has no valuesÎíÎñitÎéÎ÷s a simple trigger. When the translator
receives one, we want it to call its listener appropriately.
The ÎõÎérst test says that the translator will tell anything thatÎéÎ÷s
listening that the auction has closed when it receives a raw Close
message.
Page115 - use null value when argument not matter

use null when argument does not matter!!!
dont need to fill all the fields for the Chat object
Page116 - AuctionMessageTranslatorTest implement

 First, we need to connect the translator and listener so that they can
 communicate. We decide to pass the lis- tener into the translatorÎéÎ÷s
 constructor; it's simple and ensures that the translator is always set
 up correctly with a listener
 The second thing we need to do is call the auctionClosed() method
Page118 - Main refactor

Now Main class implementing AuctionEventListener.
Page119 - AuctionMessageTranslatorTest 2.test

notifiesBidDetailsWhenCurrentPriceMessageReceived
Page120 - AuctionMessageTranslatorTest 2.implement

the code called the wrong method, auctionClosed(), during the test.
This implementation breaks the message body into a set of key/value pairs,
which it interprets as an auction event so it can notify the
AuctionEventListener. We also have to ÎõÎéx the FakeAuctionServer to send
a real Close event rather than the current empty message

We dont want to break the flow of getting features to work, so we
add error handling to the to-do list to come back to it later
Page124 - AuctionSniper Test

Given that an AuctionSniper should respond to Price events, we decide to
make it implement AuctionEventListener rather than Main. The question is
what to do about the user interface
Page125 - AuctionSniper implement

Our solution is to insulate the AuctionSniper by introducing a new
relationship: it will notify a SniperListener of changes in its status.
The interface and the ÎõÎérst unit test look like this:
which says that Sniper should report that it has lost if it receives a
Close event from the auction.
Page126 - AuctionSniper Bids Test

The first step is to implement the response to a Price event, so we
start by adding a new unit test for the AuctionSniper. It says that the
Sniper, when it receives a Price update, sends an incremented bid to the
auction. It also notiÎõÎées its listener that itÎéÎ÷s now bidding, so we
add a sniperBidding() method. We're making an implicit assumption that
the Auction knows which bidder the Sniper represents, so the Sniper does
not have to pass in that information with the bid.

On the other hand, we do care that we send a bid exactly once, so we use a one() clause for its ex- pectation. In practice, of course, well probably only call the listener once, but this loosening of the conditions in the test expresses our intent about the two relationships.
Page128 - Bidding with the AuctionSniper

 We implement the new sniperBidding() method on Main and, to avoid having
 code that doesnÎéÎ÷t compile for too long, we pass the AuctionSniper a
 null implementation of Auction.