summary refs log tree commit
path: root/test/spec_mock_request.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/spec_mock_request.rb')
-rw-r--r--test/spec_mock_request.rb273
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