diff options
Diffstat (limited to 'test/spec_mock_request.rb')
-rw-r--r-- | test/spec_mock_request.rb | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/test/spec_mock_request.rb b/test/spec_mock_request.rb new file mode 100644 index 00000000..889c8a9f --- /dev/null +++ b/test/spec_mock_request.rb @@ -0,0 +1,273 @@ +# frozen_string_literal: true + +require_relative 'helper' +require 'yaml' +require_relative 'psych_fix' + +separate_testing do + require_relative '../lib/rack/mock_request' + require_relative '../lib/rack/lint' + require_relative '../lib/rack/request' + require_relative '../lib/rack/body_proxy' +end + +app = Rack::Lint.new(lambda { |env| + req = Rack::Request.new(env) + + env["mock.postdata"] = env["rack.input"].read + if req.GET["error"] + env["rack.errors"].puts req.GET["error"] + env["rack.errors"].flush + end + + body = req.head? ? "" : env.to_yaml + response = Rack::Response.new( + body, + req.GET["status"] || 200, + "content-type" => "text/yaml" + ) + response.set_cookie("session_test", { value: "session_test", domain: ".test.com", path: "/" }) + response.set_cookie("secure_test", { value: "secure_test", domain: ".test.com", path: "/", secure: true }) + response.set_cookie("persistent_test", { value: "persistent_test", max_age: 15552000, path: "/" }) + response.set_cookie("persistent_with_expires_test", { value: "persistent_with_expires_test", expires: Time.httpdate("Thu, 31 Oct 2021 07:28:00 GMT"), path: "/" }) + response.set_cookie("expires_and_max-age_test", { value: "expires_and_max-age_test", expires: Time.now + 15552000 * 2, max_age: 15552000, path: "/" }) + response.finish +}) + +describe Rack::MockRequest do + it "return a MockResponse" do + res = Rack::MockRequest.new(app).get("") + res.must_be_kind_of Rack::MockResponse + end + + it "be able to only return the environment" do + env = Rack::MockRequest.env_for("") + env.must_be_kind_of Hash + end + + it "should handle a non-GET request with both :input and :params" do + env = Rack::MockRequest.env_for("/", method: :post, input: nil, params: {}) + env["PATH_INFO"].must_equal "/" + env.must_be_kind_of Hash + env['rack.input'].read.must_equal '' + end + + it "return an environment with a path" do + env = Rack::MockRequest.env_for("http://www.example.com/parse?location[]=1&location[]=2&age_group[]=2") + env["QUERY_STRING"].must_equal "location[]=1&location[]=2&age_group[]=2" + env["PATH_INFO"].must_equal "/parse" + env.must_be_kind_of Hash + end + + it "provide sensible defaults" do + res = Rack::MockRequest.new(app).request + + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["SERVER_NAME"].must_equal "example.org" + env["SERVER_PORT"].must_equal "80" + env["SERVER_PROTOCOL"].must_equal "HTTP/1.1" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/" + env["SCRIPT_NAME"].must_equal "" + env["rack.url_scheme"].must_equal "http" + env["mock.postdata"].must_be :empty? + end + + it "allow GET/POST/PUT/DELETE/HEAD" do + res = Rack::MockRequest.new(app).get("", input: "foo") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + + res = Rack::MockRequest.new(app).post("", input: "foo") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "POST" + + res = Rack::MockRequest.new(app).put("", input: "foo") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "PUT" + + res = Rack::MockRequest.new(app).patch("", input: "foo") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "PATCH" + + res = Rack::MockRequest.new(app).delete("", input: "foo") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "DELETE" + + Rack::MockRequest.env_for("/", method: "HEAD")["REQUEST_METHOD"] + .must_equal "HEAD" + + Rack::MockRequest.env_for("/", method: "OPTIONS")["REQUEST_METHOD"] + .must_equal "OPTIONS" + end + + it "set content length" do + env = Rack::MockRequest.env_for("/", input: "foo") + env["CONTENT_LENGTH"].must_equal "3" + + env = Rack::MockRequest.env_for("/", input: StringIO.new("foo")) + env["CONTENT_LENGTH"].must_equal "3" + + env = Rack::MockRequest.env_for("/", input: Tempfile.new("name").tap { |t| t << "foo" }) + env["CONTENT_LENGTH"].must_equal "3" + + env = Rack::MockRequest.env_for("/", input: IO.pipe.first) + env["CONTENT_LENGTH"].must_be_nil + end + + it "allow posting" do + res = Rack::MockRequest.new(app).get("", input: "foo") + env = YAML.unsafe_load(res.body) + env["mock.postdata"].must_equal "foo" + + res = Rack::MockRequest.new(app).post("", input: StringIO.new("foo")) + env = YAML.unsafe_load(res.body) + env["mock.postdata"].must_equal "foo" + end + + it "use all parts of an URL" do + res = Rack::MockRequest.new(app). + get("https://bla.example.org:9292/meh/foo?bar") + res.must_be_kind_of Rack::MockResponse + + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["SERVER_NAME"].must_equal "bla.example.org" + env["SERVER_PORT"].must_equal "9292" + env["QUERY_STRING"].must_equal "bar" + env["PATH_INFO"].must_equal "/meh/foo" + env["rack.url_scheme"].must_equal "https" + end + + it "set SSL port and HTTP flag on when using https" do + res = Rack::MockRequest.new(app). + get("https://example.org/foo") + res.must_be_kind_of Rack::MockResponse + + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["SERVER_NAME"].must_equal "example.org" + env["SERVER_PORT"].must_equal "443" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/foo" + env["rack.url_scheme"].must_equal "https" + env["HTTPS"].must_equal "on" + end + + it "prepend slash to uri path" do + res = Rack::MockRequest.new(app). + get("foo") + res.must_be_kind_of Rack::MockResponse + + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["SERVER_NAME"].must_equal "example.org" + env["SERVER_PORT"].must_equal "80" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/foo" + env["rack.url_scheme"].must_equal "http" + end + + it "properly convert method name to an uppercase string" do + res = Rack::MockRequest.new(app).request(:get) + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + end + + it "accept :script_name option to set SCRIPT_NAME" do + res = Rack::MockRequest.new(app).get("/", script_name: '/foo') + env = YAML.unsafe_load(res.body) + env["SCRIPT_NAME"].must_equal "/foo" + end + + it "accept :http_version option to set SERVER_PROTOCOL" do + res = Rack::MockRequest.new(app).get("/", http_version: 'HTTP/1.0') + env = YAML.unsafe_load(res.body) + env["SERVER_PROTOCOL"].must_equal "HTTP/1.0" + end + + it "accept params and build query string for GET requests" do + res = Rack::MockRequest.new(app).get("/foo?baz=2", params: { foo: { bar: "1" } }) + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["QUERY_STRING"].must_include "baz=2" + env["QUERY_STRING"].must_include "foo[bar]=1" + env["PATH_INFO"].must_equal "/foo" + env["mock.postdata"].must_equal "" + end + + it "accept raw input in params for GET requests" do + res = Rack::MockRequest.new(app).get("/foo?baz=2", params: "foo[bar]=1") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "GET" + env["QUERY_STRING"].must_include "baz=2" + env["QUERY_STRING"].must_include "foo[bar]=1" + env["PATH_INFO"].must_equal "/foo" + env["mock.postdata"].must_equal "" + end + + it "accept params and build url encoded params for POST requests" do + res = Rack::MockRequest.new(app).post("/foo", params: { foo: { bar: "1" } }) + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "POST" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/foo" + env["CONTENT_TYPE"].must_equal "application/x-www-form-urlencoded" + env["mock.postdata"].must_equal "foo[bar]=1" + end + + it "accept raw input in params for POST requests" do + res = Rack::MockRequest.new(app).post("/foo", params: "foo[bar]=1") + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "POST" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/foo" + env["CONTENT_TYPE"].must_equal "application/x-www-form-urlencoded" + env["mock.postdata"].must_equal "foo[bar]=1" + end + + it "accept params and build multipart encoded params for POST requests" do + files = Rack::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt")) + res = Rack::MockRequest.new(app).post("/foo", params: { "submit-name" => "Larry", "files" => files }) + env = YAML.unsafe_load(res.body) + env["REQUEST_METHOD"].must_equal "POST" + env["QUERY_STRING"].must_equal "" + env["PATH_INFO"].must_equal "/foo" + env["CONTENT_TYPE"].must_equal "multipart/form-data; boundary=AaB03x" + # The gsub accounts for differences in YAMLs affect on the data. + env["mock.postdata"].gsub("\r", "").length.must_equal 206 + end + + it "behave valid according to the Rack spec" do + url = "https://bla.example.org:9292/meh/foo?bar" + Rack::MockRequest.new(app).get(url, lint: true). + must_be_kind_of Rack::MockResponse + end + + it "call close on the original body object" do + called = false + body = Rack::BodyProxy.new(['hi']) { called = true } + capp = proc { |e| [200, { 'content-type' => 'text/plain' }, body] } + called.must_equal false + Rack::MockRequest.new(capp).get('/', lint: true) + called.must_equal true + end + + it "defaults encoding to ASCII 8BIT" do + req = Rack::MockRequest.env_for("/foo") + + keys = [ + Rack::REQUEST_METHOD, + Rack::SERVER_NAME, + Rack::SERVER_PORT, + Rack::QUERY_STRING, + Rack::PATH_INFO, + Rack::HTTPS, + Rack::RACK_URL_SCHEME + ] + keys.each do |k| + assert_equal Encoding::ASCII_8BIT, req[k].encoding + end + end +end |