content: module Feature.Query.QueryLimitedSpec where
  
  import Network.Wai (Application)
  
  import Network.HTTP.Types
  import Test.Hspec
  import Test.Hspec.Wai
  import Test.Hspec.Wai.JSON
  
  import Protolude  hiding (get)
  import SpecHelper
  
  spec :: SpecWith ((), Application)
  spec =
    describe "Requesting many items with server limits(max-rows) enabled" $ do
      it "restricts results" $
        get "/items?order=id"
          `shouldRespondWith`
            [json| [{"id":1},{"id":2}] |]
            { matchHeaders = ["Content-Range" <:> "0-1/*"] }
  
      it "respects additional client limiting" $ do
        request methodGet  "/items"
            (rangeHdrs $ ByteRangeFromTo 0 0)
            ""
          `shouldRespondWith`
            [json| [{"id":1}] |]
            { matchHeaders = ["Content-Range" <:> "0-0/*"] }
  
      it "works on all levels" $
        get "/users?select=id,tasks(id)&order=id.asc&tasks.order=id.asc"
          `shouldRespondWith`
            [json|[{"id":1,"tasks":[{"id":1},{"id":2}]},{"id":2,"tasks":[{"id":5},{"id":6}]}]|]
            { matchHeaders = ["Content-Range" <:> "0-1/*"] }
  
      it "succeeds in getting parent embeds despite the limit, see #647" $
        get "/tasks?select=id,project:projects(id)&id=gt.5"
          `shouldRespondWith`
            [json|[{"id":6,"project":{"id":3}},{"id":7,"project":{"id":4}}]|]
            { matchHeaders = ["Content-Range" <:> "0-1/*"] }
  
      it "can offset the parent embed, being consistent with the other embed types" $
        get "/tasks?select=id,project:projects(id)&id=gt.5&project.offset=1"
          `shouldRespondWith`
            [json|[{"id":6,"project":null}, {"id":7,"project":null}]|]
            { matchHeaders = ["Content-Range" <:> "0-1/*"] }
  
      context "count=estimated" $ do
        it "uses the query planner guess when query rows > maxRows" $
          request methodHead "/getallprojects_view"
              [("Prefer", "count=estimated")]
              ""
            `shouldRespondWith`
              ""
              { matchStatus  = 206
              , matchHeaders = [ matchContentTypeJson
                               , "Content-Range" <:> "0-1/2019" ]
              }
  
        it "gives exact count when query rows <= maxRows" $
          request methodHead "/getallprojects_view?id=lt.3"
              [("Prefer", "count=estimated")]
              ""
            `shouldRespondWith`
              ""
              { matchHeaders = [ matchContentTypeJson
                               , "Content-Range" <:> "0-1/2" ]
              }
  
        it "only uses the query planner guess if it's indeed greater than the exact count" $
          request methodHead "/get_projects_above_view"
              [("Prefer", "count=estimated")]
              ""
            `shouldRespondWith`
              ""
              { matchStatus  = 206
              , matchHeaders = [ matchContentTypeJson
                               , "Content-Range" <:> "0-1/3" ]
              }
  
      context "max-rows=2 on mutations" $ do
        it "doesn't affect insertions" $
          request methodPost "/projects?select=id,name"
              [("Prefer", "return=representation")]
              [json| [
                { "id": 6, "name": "BeOS" },
                { "id": 7, "name": "PopOS" },
                { "id": 8, "name": "HaikuOS" } ]|]
            `shouldRespondWith`
              [json| [
                { "id": 6, "name": "BeOS" },
                { "id": 7, "name": "PopOS" },
                { "id": 8, "name": "HaikuOS" } ]|]
              { matchStatus  = 201 }
  
        it "doesn't affect updates(2 rows would be modified if it did)" $
          request methodPatch "/employees?select=first_name,last_name,occupation"
              [("Prefer", "return=representation")]
              [json| [{"occupation": "Barista"}] |]
            `shouldRespondWith`
              [json|[
                  { "first_name": "Frances M.", "last_name": "Roe", "occupation": "Barista" },
                  { "first_name": "Daniel B.", "last_name": "Lyon", "occupation": "Barista" },
                  { "first_name": "Edwin S.", "last_name": "Smith", "occupation": "Barista" } ]|]
              { matchStatus  = 200 }
  
        it "doesn't affect deletions" $
          request methodDelete "/employees?select=first_name,last_name"
              [("Prefer", "return=representation")]
              mempty
            `shouldRespondWith`
              [json| [
                { "first_name": "Frances M.", "last_name": "Roe" },
                { "first_name": "Daniel B.", "last_name": "Lyon" },
                { "first_name": "Edwin S.", "last_name": "Smith" } ]|]
              { matchStatus  = 200 }
  
      context "max-rows is set and limits are requested" $ do
        it "should work with limit 0" $
          get "/items?limit=0"
            `shouldRespondWith`
              [json| [] |]
              { matchHeaders = ["Content-Range" <:> "*/*"] }
  