defmodule HTTParrot.PHandlerTest do use ExUnit.Case import :meck import HTTParrot.PHandler setup do new(HTTParrot.GeneralRequestInfo) new(JSX) new(:cowboy_req) on_exit(fn -> unload() end) :ok end Enum.each( [{"/post", "POST"}, {"/patch", "PATCH"}, {"/put", "PUT"}], fn {path, verb} -> test "allowed_methods return verb related to #{path}" do expect(:cowboy_req, :path, 1, unquote(path)) assert allowed_methods(:req1, :state) == {[unquote(verb)], :req1, :state} assert validate(:cowboy_req) end end ) test "returns json with general info and P[OST, ATCH, UT] form data" do expect(:cowboy_req, :read_urlencoded_body, 1, {:ok, :body_qs, :req2}) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(JSX, :encode!, [{[[:info, {:form, :body_qs}, {:data, ""}, {:json, nil}]], :response}]) assert post_form(:req1, :state) == {true, :req4, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, ATCH, UT] JSON body data" do expect(:cowboy_req, :read_body, 1, {:ok, "body", :req2}) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(JSX, :is_json?, 1, true) expect(JSX, :decode!, 1, :decoded_json) expect(JSX, :encode!, [ {[[:info, {:form, [{}]}, {:data, "body"}, {:json, :decoded_json}]], :response} ]) assert post_binary(:req1, :state) == {true, :req4, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, ATCH, UT] non-JSON body data" do expect(:cowboy_req, :read_body, 1, {:ok, "body", :req2}) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [{[[:info, {:form, [{}]}, {:data, "body"}, {:json, nil}]], :response}]) assert post_binary(:req1, :state) == {true, :req4, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, ATCH, UT] octet-stream body data" do expect(:cowboy_req, :read_body, 1, {:ok, <<0xFFFF::16>>, :req2}) expect(:cowboy_req, :set_resp_body, [{[:response, :req3], :req4}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req3}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[ [ :info, {:form, [{}]}, {:data, "data:application/octet-stream;base64,//8="}, {:json, nil} ] ], :response} ]) assert post_binary(:req1, :state) == {true, :req4, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, UT, ATCH] non-JSON body data for a chunked request" do first_chunk = "first chunk" second_chunk = "second chunk" expect(:cowboy_req, :read_body, fn req -> case req do :req1 -> {:more, first_chunk, :req2} :req2 -> {:ok, second_chunk, :req3} end end) expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[[:info, {:form, [{}]}, {:data, first_chunk <> second_chunk}, {:json, nil}]], :response} ]) assert post_binary(:req1, :state) == {true, :req5, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, UT, ATCH] octect-stream body data for a chunked request" do first_chunk = "first chunk" <> <<0xFFFF::16>> second_chunk = "second chunk" expect(:cowboy_req, :read_body, fn req -> case req do :req1 -> {:more, first_chunk, :req2} :req2 -> {:ok, second_chunk, :req3} end end) expect(:cowboy_req, :set_resp_body, [{[:response, :req4], :req5}]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req4}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[ [ :info, {:form, [{}]}, {:data, "data:application/octet-stream;base64,#{Base.encode64(first_chunk <> second_chunk)}"}, {:json, nil} ] ], :response} ]) assert post_binary(:req1, :state) == {true, :req5, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, ATCH, UT] form data for multipart request (simple)" do expect(:cowboy_req, :read_part, fn req -> case req do :req1 -> {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2} :req3 -> {:done, :req4} end end) expect(:cowboy_req, :read_part_body, [{[:req2], {:ok, "value1", :req3}}]) expect(:cowboy_req, :parse_header, [ {["content-type", :req4], {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}} ]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[[:info, {:form, [{"key1", "value1"}]}, {:files, [{}]}, {:data, ""}, {:json, nil}]], :response} ]) expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}]) assert post_multipart(:req1, :state) == {true, :req7, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, ATCH, UT] form data for multipart requests (multiple parts)" do expect(:cowboy_req, :read_part, fn req -> case req do :req1 -> {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2} :req3 -> {:ok, %{"content-disposition" => "form-data; name=\"key2\""}, :req4} :req5 -> {:done, :req6} end end) expect(:cowboy_req, :read_part_body, fn req -> case req do :req2 -> {:ok, "value1", :req3} :req4 -> {:ok, "value2", :req5} end end) expect(:cowboy_req, :parse_header, [ {["content-type", :req6], {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}} ]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[ [ :info, {:form, [{"key1", "value1"}, {"key2", "value2"}]}, {:files, [{}]}, {:data, ""}, {:json, nil} ] ], :response} ]) expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}]) assert post_multipart(:req1, :state) == {true, :req9, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, UT, ATCH] file data (one file)" do expect(:cowboy_req, :read_part, fn req -> case req do :req1 -> {:ok, %{ "content-disposition" => "form-data; name=\"file1\"; filename=\"testdata.txt\"", "content-type" => "text/plain" }, :req2} :req3 -> {:done, :req4} end end) expect(:cowboy_req, :read_part_body, [ {[:req2], {:ok, "here is some cool\ntest data.", :req3}} ]) expect(:cowboy_req, :parse_header, [ {["content-type", :req4], {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req5}} ]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req6}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[ [ :info, {:form, [{}]}, {:files, [{"file1", "here is some cool\ntest data."}]}, {:data, ""}, {:json, nil} ] ], :response} ]) expect(:cowboy_req, :set_resp_body, [{[:response, :req6], :req7}]) assert post_multipart(:req1, :state) == {true, :req7, nil} assert validate(HTTParrot.GeneralRequestInfo) end test "returns json with general info and P[OST, UT, ATCH] form data and file data (form-data plus one file)" do expect(:cowboy_req, :read_part, fn req -> case req do :req1 -> {:ok, %{"content-disposition" => "form-data; name=\"key1\""}, :req2} :req3 -> {:ok, %{ "content-disposition" => "form-data; name=\"file1\"; filename=\"testdata.txt\"", "content-type" => "text/plain" }, :req4} :req5 -> {:done, :req6} end end) expect(:cowboy_req, :read_part_body, fn req -> case req do :req2 -> {:ok, "value1", :req3} :req4 -> {:ok, "here is some cool\ntest data", :req5} end end) expect(:cowboy_req, :parse_header, [ {["content-type", :req6], {:ok, {"multipart", "form-data", [{"boundary", "----WebKitFormBoundary8BEQxJvZANFsvRV9"}]}, :req7}} ]) expect(HTTParrot.GeneralRequestInfo, :retrieve, 1, {[:info], :req8}) expect(JSX, :is_json?, 1, false) expect(JSX, :encode!, [ {[ [ :info, {:form, [{"key1", "value1"}]}, {:files, [{"file1", "here is some cool\ntest data"}]}, {:data, ""}, {:json, nil} ] ], :response} ]) expect(:cowboy_req, :set_resp_body, [{[:response, :req8], :req9}]) assert post_multipart(:req1, :state) == {true, :req9, nil} assert validate(HTTParrot.GeneralRequestInfo) end end