require 'rfuzz/session'
include RFuzz


context "Conditional Responses Should Be" do

  setup do
    @client = HttpClient.new("localhost", 3000)
    @path = "/index.html"
    @r = @client.get(@path)
    (@etag = @r['ETAG']).should_not_be_nil
    (@last_modified = @r['LAST_MODIFIED']).should_not_be_nil
    (@content_length = @r['CONTENT_LENGTH']).should_not_be_nil
  end

   specify "304 Not Modified when If-None-Match is the matching ETag" do
     get_head_status_should_be "304", 'If-None-Match' => @etag
   end
 
   specify "304 Not Modified when If-Modified-Since is the matching Last-Modified date" do
     get_head_status_should_be "304", 'If-Modified-Since' => @last_modified
   end
 
   specify "304 Not Modified when If-None-Match is the matching ETag and If-Modified-Since is the matching Last-Modified date" do
     get_head_status_should_be "304", 'If-None-Match' => @etag, 'If-Modified-Since' => @last_modified
   end
 
   specify "200 OK when If-None-Match is invalid" do
     get_head_status_should_be "200", 'If-None-Match' => 'invalid'
     get_head_status_should_be "200", 'If-None-Match' => 'invalid', 'If-Modified-Since' => @last_modified
   end
 
   specify "200 OK when If-Modified-Since is invalid" do
     get_head_status_should_be "200",                           'If-Modified-Since' => 'invalid'
     get_head_status_should_be "200", 'If-None-Match' => @etag, 'If-Modified-Since' => 'invalid'
   end
 
   specify "304 Not Modified when If-Modified-Since is greater than the Last-Modified header, but less than the system time" do
     sleep 2
     last_modified_plus_1 = (Time.httpdate(@last_modified) + 1).httpdate
     get_head_status_should_be "304",                           'If-Modified-Since' => last_modified_plus_1
     get_head_status_should_be "304", 'If-None-Match' => @etag, 'If-Modified-Since' => last_modified_plus_1
   end
 
   specify "200 OK when If-Modified-Since is less than the Last-Modified header" do
     last_modified_minus_1 = (Time.httpdate(@last_modified) - 1).httpdate
     get_head_status_should_be "200",                           'If-Modified-Since' => last_modified_minus_1
     get_head_status_should_be "200", 'If-None-Match' => @etag, 'If-Modified-Since' => last_modified_minus_1
   end
 
   specify "200 OK when If-Modified-Since is a date in the future" do
     the_future = Time.at(2**31-1).httpdate
     get_head_status_should_be "200",                           'If-Modified-Since' => the_future
     get_head_status_should_be "200", 'If-None-Match' => @etag, 'If-Modified-Since' => the_future
   end

  specify "200 OK when If-None-Match is a wildcard" do
    get_head_status_should_be "200", 'If-None-Match' => '*'
    get_head_status_should_be "200", 'If-None-Match' => '*', 'If-Modified-Since' => @last_modified
  end

  def get_head_status_should_be(http_status, headers = {})
      %w{ get head }.each do |method|
        res = @client.send(method, @path, :head => headers)
        res.http_status.should_equal http_status
        res['ETAG'].should_equal @etag
        case res.http_status
        when '304' then
          res['LAST_MODIFIED'].should_be_nil
          res['CONTENT_LENGTH'].should_be_nil
        when '200' then
          @last_modified.should_equal res['LAST_MODIFIED']
          @content_length.should_equal res['CONTENT_LENGTH']
        else
          fail "Incorrect HTTP status code: #{res.http_status}"
        end
      end
  end
end