response 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +16 -0
- data/Changelog.md +3 -0
- data/Gemfile +6 -0
- data/Gemfile.devtools +60 -0
- data/Guardfile +18 -0
- data/LICENSE +20 -0
- data/README.md +39 -0
- data/Rakefile +2 -0
- data/TODO +2 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +3 -0
- data/config/reek.yml +92 -0
- data/config/roodi.yml +18 -0
- data/config/yardstick.yml +2 -0
- data/lib/response/html.rb +36 -0
- data/lib/response/json.rb +36 -0
- data/lib/response/redirect.rb +52 -0
- data/lib/response/status.rb +28 -0
- data/lib/response/text.rb +37 -0
- data/lib/response/xml.rb +36 -0
- data/lib/response.rb +271 -0
- data/response.gemspec +22 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/functional_command_method_behavior.rb +11 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/unit/response/body_spec.rb +22 -0
- data/spec/unit/response/cache_control_spec.rb +25 -0
- data/spec/unit/response/class_methods/build_spec.rb +31 -0
- data/spec/unit/response/content_type_spec.rb +26 -0
- data/spec/unit/response/headers_spec.rb +23 -0
- data/spec/unit/response/html/class_methods/build_spec.rb +18 -0
- data/spec/unit/response/json/class_methods/build_spec.rb +18 -0
- data/spec/unit/response/last_modified_spec.rb +25 -0
- data/spec/unit/response/merge_headers_spec.rb +20 -0
- data/spec/unit/response/rack_array_spec.rb +15 -0
- data/spec/unit/response/redirect/class_methods/build_spec.rb +28 -0
- data/spec/unit/response/status_spec.rb +22 -0
- data/spec/unit/response/text/class_methods/build_spec.rb +18 -0
- data/spec/unit/response/to_rack_response_spec.rb +26 -0
- data/spec/unit/response/valid_predicate_spec.rb +37 -0
- data/spec/unit/response/with_body_spec.rb +17 -0
- data/spec/unit/response/with_headers_spec.rb +17 -0
- data/spec/unit/response/with_status_spec.rb +17 -0
- data/spec/unit/response/xml/class_methods/build_spec.rb +18 -0
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/metrics/flay.rake +47 -0
- data/tasks/metrics/flog.rake +43 -0
- data/tasks/metrics/heckle.rake +208 -0
- data/tasks/metrics/metric_fu.rake +29 -0
- data/tasks/metrics/reek.rake +15 -0
- data/tasks/metrics/roodi.rake +15 -0
- data/tasks/metrics/yardstick.rake +23 -0
- data/tasks/spec.rake +45 -0
- data/tasks/yard.rake +9 -0
- metadata +187 -0
    
        data/lib/response.rb
    ADDED
    
    | @@ -0,0 +1,271 @@ | |
| 1 | 
            +
            #encoding: utf-8
         | 
| 2 | 
            +
            require 'time'
         | 
| 3 | 
            +
            require 'ice_nine'
         | 
| 4 | 
            +
            require 'adamantium'
         | 
| 5 | 
            +
            require 'concord'
         | 
| 6 | 
            +
            require 'abstract_type'
         | 
| 7 | 
            +
            require 'equalizer'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # Library to build rack compatible responses in a functional style
         | 
| 10 | 
            +
            class Response
         | 
| 11 | 
            +
              include Adamantium::Flat, Concord.new(:status, :headers, :body)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              # Error raised when finalizing responses with undefined components 
         | 
| 14 | 
            +
              class InvalidError < RuntimeError; end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              TEXT_PLAIN = 'text/plain; charset=UTF-8'.freeze
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              # Undefined response component
         | 
| 19 | 
            +
              #
         | 
| 20 | 
            +
              # A class to get nice #inspect behavior ootb
         | 
| 21 | 
            +
              #
         | 
| 22 | 
            +
              Undefined = Class.new.freeze
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              # Return status code
         | 
| 25 | 
            +
              #
         | 
| 26 | 
            +
              # @return [Response::Status]
         | 
| 27 | 
            +
              #   if set
         | 
| 28 | 
            +
              #
         | 
| 29 | 
            +
              # @return [undefined]
         | 
| 30 | 
            +
              #   otherwise
         | 
| 31 | 
            +
              #
         | 
| 32 | 
            +
              # @api private
         | 
| 33 | 
            +
              #
         | 
| 34 | 
            +
              attr_reader :status
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              # Return headers code
         | 
| 37 | 
            +
              #
         | 
| 38 | 
            +
              # @return [Hash]
         | 
| 39 | 
            +
              #   if set
         | 
| 40 | 
            +
              #
         | 
| 41 | 
            +
              # @return [undefined]
         | 
| 42 | 
            +
              #   otherwise
         | 
| 43 | 
            +
              #
         | 
| 44 | 
            +
              # @api private
         | 
| 45 | 
            +
              #
         | 
| 46 | 
            +
              attr_reader :headers
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              # Return status code
         | 
| 49 | 
            +
              #
         | 
| 50 | 
            +
              # @return [#each]
         | 
| 51 | 
            +
              #   if set
         | 
| 52 | 
            +
              #
         | 
| 53 | 
            +
              # @return [undefined]
         | 
| 54 | 
            +
              #   otherwise
         | 
| 55 | 
            +
              #
         | 
| 56 | 
            +
              # @api private
         | 
| 57 | 
            +
              #
         | 
| 58 | 
            +
              attr_reader :body
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              # Return response with new status
         | 
| 61 | 
            +
              #
         | 
| 62 | 
            +
              # @param [Fixnum] status
         | 
| 63 | 
            +
              #   the status for the response
         | 
| 64 | 
            +
              #
         | 
| 65 | 
            +
              # @return [Response]
         | 
| 66 | 
            +
              #   new response object with status set
         | 
| 67 | 
            +
              #
         | 
| 68 | 
            +
              # @example
         | 
| 69 | 
            +
              #
         | 
| 70 | 
            +
              #   response = Response.new
         | 
| 71 | 
            +
              #   response = response.with_status(200)
         | 
| 72 | 
            +
              #   response.status # => 200
         | 
| 73 | 
            +
              #
         | 
| 74 | 
            +
              # @api public
         | 
| 75 | 
            +
              #
         | 
| 76 | 
            +
              def with_status(status)
         | 
| 77 | 
            +
                self.class.new(status, headers, body)
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              # Return response with new body
         | 
| 81 | 
            +
              #
         | 
| 82 | 
            +
              # @param [Object] body
         | 
| 83 | 
            +
              #   the body for the response
         | 
| 84 | 
            +
              #
         | 
| 85 | 
            +
              # @return [Response]
         | 
| 86 | 
            +
              #   new response with body set
         | 
| 87 | 
            +
              #
         | 
| 88 | 
            +
              # @example
         | 
| 89 | 
            +
              #
         | 
| 90 | 
            +
              #   response = Response.new
         | 
| 91 | 
            +
              #   response = response.with_body('Hello')
         | 
| 92 | 
            +
              #   response.body # => 'Hello'
         | 
| 93 | 
            +
              #
         | 
| 94 | 
            +
              # @api public
         | 
| 95 | 
            +
              #
         | 
| 96 | 
            +
              def with_body(body)
         | 
| 97 | 
            +
                self.class.new(status, headers, body)
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              # Return response with new headers
         | 
| 101 | 
            +
              #
         | 
| 102 | 
            +
              # @param [Hash] headers
         | 
| 103 | 
            +
              #   the header for the response
         | 
| 104 | 
            +
              #
         | 
| 105 | 
            +
              # @return [Response]
         | 
| 106 | 
            +
              #   new response with headers set
         | 
| 107 | 
            +
              #
         | 
| 108 | 
            +
              # @example
         | 
| 109 | 
            +
              #
         | 
| 110 | 
            +
              #   response = Response.new
         | 
| 111 | 
            +
              #   response = response.with_header({'Foo' => 'Bar'})
         | 
| 112 | 
            +
              #   response.headers # => {'Foo' => 'Bar'}
         | 
| 113 | 
            +
              #
         | 
| 114 | 
            +
              # @api public
         | 
| 115 | 
            +
              #
         | 
| 116 | 
            +
              def with_headers(headers)
         | 
| 117 | 
            +
                self.class.new(status, headers, body)
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
              # Return response with merged headers
         | 
| 121 | 
            +
              #
         | 
| 122 | 
            +
              # @param [Hash] headers
         | 
| 123 | 
            +
              #   the headers to merge
         | 
| 124 | 
            +
              #
         | 
| 125 | 
            +
              # @example
         | 
| 126 | 
            +
              #
         | 
| 127 | 
            +
              #   response = Response.new(200, {'Foo' => 'Baz', 'John' => 'Doe'})
         | 
| 128 | 
            +
              #   response = response.merge_header({'Foo' => 'Bar'})
         | 
| 129 | 
            +
              #   response.headers # => {'Foo' => 'Bar', 'John' => 'Doe'}
         | 
| 130 | 
            +
              #
         | 
| 131 | 
            +
              # @api public
         | 
| 132 | 
            +
              #
         | 
| 133 | 
            +
              # @return [Response]
         | 
| 134 | 
            +
              #   returns new response with merged header
         | 
| 135 | 
            +
              #
         | 
| 136 | 
            +
              def merge_headers(headers)
         | 
| 137 | 
            +
                self.class.new(status, self.headers.merge(headers), body)
         | 
| 138 | 
            +
              end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
              # Return rack compatible array after asserting response is valid
         | 
| 141 | 
            +
              #
         | 
| 142 | 
            +
              # @return [Array]
         | 
| 143 | 
            +
              #   rack compatible array
         | 
| 144 | 
            +
              #
         | 
| 145 | 
            +
              # @raise InvalidError
         | 
| 146 | 
            +
              #   raises InvalidError when request containts undefined components
         | 
| 147 | 
            +
              #
         | 
| 148 | 
            +
              # @api private
         | 
| 149 | 
            +
              #
         | 
| 150 | 
            +
              def to_rack_response
         | 
| 151 | 
            +
                assert_valid
         | 
| 152 | 
            +
                rack_array
         | 
| 153 | 
            +
              end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              # Test if object is a valid response
         | 
| 156 | 
            +
              #
         | 
| 157 | 
            +
              # @return [true]
         | 
| 158 | 
            +
              #   if all required fields are present
         | 
| 159 | 
            +
              #
         | 
| 160 | 
            +
              # @return [false]
         | 
| 161 | 
            +
              #   otherwise
         | 
| 162 | 
            +
              #
         | 
| 163 | 
            +
              # @api private
         | 
| 164 | 
            +
              #
         | 
| 165 | 
            +
              def valid?
         | 
| 166 | 
            +
                ![status, headers, body].any? { |item| item.equal?(Undefined) }
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
              memoize :valid?
         | 
| 169 | 
            +
             | 
| 170 | 
            +
              # Return rack compatible array
         | 
| 171 | 
            +
              #
         | 
| 172 | 
            +
              # @return [Array]
         | 
| 173 | 
            +
              #   rack compatible array
         | 
| 174 | 
            +
              #
         | 
| 175 | 
            +
              # @example
         | 
| 176 | 
            +
              #
         | 
| 177 | 
            +
              #   response = Response.new(200, {'Foo' => 'Bar'}, 'Hello World')
         | 
| 178 | 
            +
              #   response.rack_array # => [200, {'Foo' => 'Bar'}, 'Hello World']
         | 
| 179 | 
            +
              #
         | 
| 180 | 
            +
              # @api public
         | 
| 181 | 
            +
              #
         | 
| 182 | 
            +
              def rack_array
         | 
| 183 | 
            +
                [status.code, headers, body]
         | 
| 184 | 
            +
              end
         | 
| 185 | 
            +
              memoize :rack_array
         | 
| 186 | 
            +
             | 
| 187 | 
            +
              # Return contents of content type header
         | 
| 188 | 
            +
              #
         | 
| 189 | 
            +
              # @return [String]
         | 
| 190 | 
            +
              #
         | 
| 191 | 
            +
              # @api private
         | 
| 192 | 
            +
              #
         | 
| 193 | 
            +
              def content_type
         | 
| 194 | 
            +
                headers['Content-Type']
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              # Return last modified 
         | 
| 198 | 
            +
              #
         | 
| 199 | 
            +
              # @return [Time]
         | 
| 200 | 
            +
              #   if last modified header is present
         | 
| 201 | 
            +
              #
         | 
| 202 | 
            +
              # @return [nil]
         | 
| 203 | 
            +
              #   otherwise
         | 
| 204 | 
            +
              #
         | 
| 205 | 
            +
              # @api private
         | 
| 206 | 
            +
              #
         | 
| 207 | 
            +
              def last_modified
         | 
| 208 | 
            +
                value = headers.fetch('Last-Modified') { return }
         | 
| 209 | 
            +
                Time.httpdate(value)
         | 
| 210 | 
            +
              end
         | 
| 211 | 
            +
              memoize :last_modified
         | 
| 212 | 
            +
             | 
| 213 | 
            +
              # Return contents of cache control header
         | 
| 214 | 
            +
              #
         | 
| 215 | 
            +
              # @return [String]
         | 
| 216 | 
            +
              #
         | 
| 217 | 
            +
              # @api private
         | 
| 218 | 
            +
              #
         | 
| 219 | 
            +
              def cache_control
         | 
| 220 | 
            +
                headers['Cache-Control']
         | 
| 221 | 
            +
              end
         | 
| 222 | 
            +
             | 
| 223 | 
            +
              # Build response with a dsl like interface
         | 
| 224 | 
            +
              #
         | 
| 225 | 
            +
              # @example
         | 
| 226 | 
            +
              #
         | 
| 227 | 
            +
              #   response = Response.build(200) do |response|
         | 
| 228 | 
            +
              #     response.
         | 
| 229 | 
            +
              #       with_headers('Foo' => 'Bar').
         | 
| 230 | 
            +
              #       with_body('Hello')
         | 
| 231 | 
            +
              #   end
         | 
| 232 | 
            +
              #
         | 
| 233 | 
            +
              #   response.status  # => 200
         | 
| 234 | 
            +
              #   response.headers # => {'Foo' => 'Bar' }
         | 
| 235 | 
            +
              #   response.body    # => 'Hello'
         | 
| 236 | 
            +
              #
         | 
| 237 | 
            +
              # @return [Array]
         | 
| 238 | 
            +
              #   rack compatible array
         | 
| 239 | 
            +
              #
         | 
| 240 | 
            +
              # @api public
         | 
| 241 | 
            +
              #
         | 
| 242 | 
            +
              def self.build(status = Undefined, headers = {}, body = Undefined)
         | 
| 243 | 
            +
                response = new(status, headers, body)
         | 
| 244 | 
            +
                response = yield response if block_given?
         | 
| 245 | 
            +
                response
         | 
| 246 | 
            +
              end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
            private
         | 
| 249 | 
            +
             | 
| 250 | 
            +
              # Raise error when request containts undefined components
         | 
| 251 | 
            +
              #
         | 
| 252 | 
            +
              # @raise InvalidError
         | 
| 253 | 
            +
              #   raises InvalidError when request containts undefined components
         | 
| 254 | 
            +
              #
         | 
| 255 | 
            +
              # @return [undefined]
         | 
| 256 | 
            +
              #
         | 
| 257 | 
            +
              # @api private
         | 
| 258 | 
            +
              #
         | 
| 259 | 
            +
              def assert_valid
         | 
| 260 | 
            +
                unless valid?
         | 
| 261 | 
            +
                  raise InvalidError, "Not a valid response: #{self.inspect}"
         | 
| 262 | 
            +
                end
         | 
| 263 | 
            +
              end
         | 
| 264 | 
            +
            end
         | 
| 265 | 
            +
             | 
| 266 | 
            +
            require 'response/status'
         | 
| 267 | 
            +
            require 'response/redirect'
         | 
| 268 | 
            +
            require 'response/html'
         | 
| 269 | 
            +
            require 'response/xml'
         | 
| 270 | 
            +
            require 'response/json'
         | 
| 271 | 
            +
            require 'response/text'
         | 
    
        data/response.gemspec
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Gem::Specification.new do |gem|
         | 
| 4 | 
            +
              gem.name        = 'response'
         | 
| 5 | 
            +
              gem.version     = '0.0.2'
         | 
| 6 | 
            +
              gem.authors     = [ 'Markus Schirp' ]
         | 
| 7 | 
            +
              gem.email       = [ 'mbj@seonic.net' ]
         | 
| 8 | 
            +
              gem.description = 'Build rack responses with functional style'
         | 
| 9 | 
            +
              gem.summary     = gem.description
         | 
| 10 | 
            +
              gem.homepage    = 'https://github.com/mbj/response'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              gem.require_paths    = [ 'lib' ]
         | 
| 13 | 
            +
              gem.files            = `git ls-files`.split("\n")
         | 
| 14 | 
            +
              gem.test_files       = `git ls-files -- {spec}/*`.split("\n")
         | 
| 15 | 
            +
              gem.extra_rdoc_files = %w[LICENSE README.md TODO]
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              gem.add_dependency('ice_nine',      '~> 0.7.0')
         | 
| 18 | 
            +
              gem.add_dependency('adamantium',    '~> 0.0.7')
         | 
| 19 | 
            +
              gem.add_dependency('equalizer',     '~> 0.0.5')
         | 
| 20 | 
            +
              gem.add_dependency('abstract_type', '~> 0.0.5')
         | 
| 21 | 
            +
              gem.add_dependency('concord',       '~> 0.1.0')
         | 
| 22 | 
            +
            end
         | 
    
        data/spec/rcov.opts
    ADDED
    
    
    
        data/spec/spec_helper.rb
    ADDED
    
    
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#body' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { object.body }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context 'when unset' do
         | 
| 8 | 
            +
                let(:object) { described_class.build }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                it { should be(Response::Undefined) }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              context 'when set' do
         | 
| 14 | 
            +
                let(:body) { mock('Body') }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                let(:object) { described_class.build.with_body(body) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it { should be(body) }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#cache_control' do
         | 
| 4 | 
            +
              subject { object.cache_control }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:object) { Response.build.with_headers(header) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              context 'when Cache-Control header is present' do
         | 
| 9 | 
            +
                let(:header) { { 'Cache-Control' => value } }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                let(:value) { mock('Value') }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it { should be(value) }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              context 'when Cache-Control header is not present' do
         | 
| 19 | 
            +
                let(:header) { {} }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it { should be(nil) }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '.build' do
         | 
| 4 | 
            +
              subject { object.build(&block) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:object) { described_class }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              context 'without arguments and block' do
         | 
| 9 | 
            +
                let(:block)   { nil }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                its(:valid?)  { should be(false)               }
         | 
| 12 | 
            +
                its(:headers) { should eql({})                 }
         | 
| 13 | 
            +
                its(:status)  { should be(Response::Undefined) }
         | 
| 14 | 
            +
                its(:body)    { should be(Response::Undefined) }
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              context 'with block' do
         | 
| 18 | 
            +
                let(:yields) { [] }
         | 
| 19 | 
            +
                let(:value) { mock('Value') }
         | 
| 20 | 
            +
                let(:block) { lambda { |response| yields << response; value } }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                it 'should return value from block' do
         | 
| 23 | 
            +
                  should be(value)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                it 'should call block with response' do
         | 
| 27 | 
            +
                  subject
         | 
| 28 | 
            +
                  yields.should eql([Response.build])
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#content_type' do
         | 
| 4 | 
            +
              subject { object.content_type }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:object) { Response.build.with_headers(header) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              context 'when Content-Type header is present' do
         | 
| 9 | 
            +
                let(:header) { { 'Content-Type' => value } }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                let(:value) { mock('Value') }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it { should be(value) }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              context 'when Content-Type header is not present' do
         | 
| 19 | 
            +
                let(:header) { {} }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it { should be(nil) }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#headers' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { object.headers }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context 'when unset' do
         | 
| 8 | 
            +
                let(:object) { described_class.build }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                it { should eql({}) }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              context 'when set' do
         | 
| 14 | 
            +
                let(:headers) { mock('Headers') }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                let(:object) { described_class.build.with_headers(headers) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it { should be(headers) }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response::HTML, '.build' do
         | 
| 4 | 
            +
              subject { object.build(body) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:body)    { mock('Body')    }
         | 
| 7 | 
            +
              let(:object)  { described_class }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              its(:status)  { should be(Response::Status::OK)  }
         | 
| 10 | 
            +
              its(:body)    { should be(body) }
         | 
| 11 | 
            +
              its(:headers) { should eql('Content-Type' => 'text/html; charset=UTF-8') }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'allows to modify response' do
         | 
| 14 | 
            +
                object.build(body) do |response|
         | 
| 15 | 
            +
                  response.with_status(Response::Status::NOT_FOUND)
         | 
| 16 | 
            +
                end.status.should be(Response::Status::NOT_FOUND)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response::JSON, '.build' do
         | 
| 4 | 
            +
              subject { object.build(body) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:body)   { mock('Body')    }
         | 
| 7 | 
            +
              let(:object) { described_class }
         | 
| 8 | 
            +
                            
         | 
| 9 | 
            +
              its(:status)  { should be(Response::Status::OK)                                 }
         | 
| 10 | 
            +
              its(:body)    { should be(body)                                                 }
         | 
| 11 | 
            +
              its(:headers) { should eql('Content-Type' => 'application/json; charset=UTF-8') }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'allows to modify response' do
         | 
| 14 | 
            +
                object.build(body) do |response|
         | 
| 15 | 
            +
                  response.with_status(404)
         | 
| 16 | 
            +
                end.status.should be(404)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#last_modified' do
         | 
| 4 | 
            +
              subject { object.last_modified }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:object) { Response.build.with_headers(header) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              let(:time) { Time.httpdate(Time.now.httpdate) }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              context 'when Content-Type header is present' do
         | 
| 11 | 
            +
                let(:header) { { 'Last-Modified' => time.httpdate } }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it { should eql(time) }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              context 'when Content-Type header is not present' do
         | 
| 19 | 
            +
                let(:header) { {} }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it { should be(nil) }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#merge_headers' do
         | 
| 4 | 
            +
              subject { object.merge_headers(update_headers) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:object)           { described_class.build(status, original_headers, body)  }
         | 
| 7 | 
            +
              let(:status)           { Response::Status::OK }
         | 
| 8 | 
            +
              let(:update_headers)   { { 'Baz' => 'Zot' }   }
         | 
| 9 | 
            +
              let(:original_headers) { { 'Foo' => 'Bar' }   }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              let(:status)  { mock('Status')    }
         | 
| 12 | 
            +
              let(:body)    { mock('Body')      }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              its(:status)  { should be(status) }
         | 
| 15 | 
            +
              its(:body)    { should be(body)   }
         | 
| 16 | 
            +
              its(:headers) { should eql('Foo' => 'Bar', 'Baz' => 'Zot') }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              it_should_behave_like 'a functional command method'
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#rack_array' do
         | 
| 4 | 
            +
              subject { object.rack_array }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:status)  { Response::Status::OK  }
         | 
| 7 | 
            +
              let(:headers) { mock('Headers') }
         | 
| 8 | 
            +
              let(:body)    { mock('Body')    }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              let(:object) { described_class.build(status, headers, body) }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              it { should eql([200, headers, body]) }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              it_should_behave_like 'an idempotent method'
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response::Redirect::Found, '#build' do
         | 
| 4 | 
            +
              
         | 
| 5 | 
            +
              subject { object.build(location) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              let(:object) { described_class }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              let(:location) { mock('Location', :to_s => 'THE-LOCATION') }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              its(:status)  { should be(Response::Status::FOUND) }
         | 
| 12 | 
            +
              its(:headers) { should eql('Location' => location, 'Content-Type' => 'text/plain; charset=UTF-8') }
         | 
| 13 | 
            +
              its(:body)    { should eql('You are beeing redirected to: THE-LOCATION') }
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            describe Response::Redirect::Permanent, '#build' do
         | 
| 17 | 
            +
              
         | 
| 18 | 
            +
              subject { object.build(location) }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              let(:object) { described_class }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              let(:location) { mock('Location', :to_s => 'THE-LOCATION') }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              its(:status)  { should be(Response::Status::MOVED_PERMANENTLY) }
         | 
| 25 | 
            +
              its(:headers) { should eql('Location' => location, 'Content-Type' => 'text/plain; charset=UTF-8') }
         | 
| 26 | 
            +
              its(:body)    { should eql('You are beeing redirected to: THE-LOCATION') }
         | 
| 27 | 
            +
            end
         | 
| 28 | 
            +
             | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#status' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { object.status }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              context 'when unset' do
         | 
| 8 | 
            +
                let(:object) { described_class.build }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                it { should be(Response::Undefined) }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              context 'when set' do
         | 
| 14 | 
            +
                let(:status) { mock('Status') }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                let(:object) { described_class.build.with_status(status) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it { should be(status) }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response::Text, '.build' do
         | 
| 4 | 
            +
              subject { object.build(body) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:body)    { mock('Body')    }
         | 
| 7 | 
            +
              let(:object)  { described_class }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              its(:status)  { should be(Response::Status::OK)  }
         | 
| 10 | 
            +
              its(:body)    { should be(body) }
         | 
| 11 | 
            +
              its(:headers) { should eql('Content-Type' => 'text/plain; charset=UTF-8') }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it 'allows to modify response' do
         | 
| 14 | 
            +
                object.build(body) do |response|
         | 
| 15 | 
            +
                  response.with_status(Response::Status::NOT_FOUND)
         | 
| 16 | 
            +
                end.status.should be(Response::Status::NOT_FOUND)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#to_rack_response' do
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { object.to_rack_response }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              let(:status)  { Response::Status::OK }
         | 
| 8 | 
            +
              let(:headers) { mock('Headers') }
         | 
| 9 | 
            +
              let(:body)    { mock('Body') }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              context 'with valid response' do
         | 
| 12 | 
            +
                let(:object) { Response.build(status, headers, body) }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                it { should eql([200, headers, body]) }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              context 'with invalid response' do
         | 
| 20 | 
            +
                let(:object) { Response.build }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                it 'should raise error' do
         | 
| 23 | 
            +
                  expect { subject }.to raise_error(Response::InvalidError, "Not a valid response: #{object.inspect}")
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Response, '#valid?' do
         | 
| 4 | 
            +
              subject { object.valid? }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              context 'with status and body' do
         | 
| 7 | 
            +
                let(:object) { described_class.build(Response::Status::OK, {}, mock('Body')) }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                it { should be(true) }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              context 'without body' do
         | 
| 15 | 
            +
                let(:object) { described_class.build.with_status(Response::Status::OK) }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                it { should be(false) }
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              context 'without status' do
         | 
| 23 | 
            +
                let(:object) { described_class.build.with_body(mock('Body')) }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                it { should be(false) }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              context 'without status and body' do
         | 
| 31 | 
            +
                let(:object) { described_class.build }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                it { should be(false) }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it_should_behave_like 'an idempotent method'
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         |