summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorILYA Khlopotov <iilyak@apache.org>2020-05-14 12:47:29 -0700
committerILYA Khlopotov <iilyak@apache.org>2020-05-15 11:58:34 -0700
commit02e4c3e96aad6f653af9a9550c8c7a9340fc2e58 (patch)
tree94070f0dc27499cbc21eeb3818a938f5a132dd9c
parentb8a13a531fd682329572e61eb17b3acdb35a6a13 (diff)
downloadcouchdb-02e4c3e96aad6f653af9a9550c8c7a9340fc2e58.tar.gz
Add tests for pagination API
-rw-r--r--src/chttpd/test/exunit/pagination_test.exs771
1 files changed, 771 insertions, 0 deletions
diff --git a/src/chttpd/test/exunit/pagination_test.exs b/src/chttpd/test/exunit/pagination_test.exs
index 4b12c8b2f..fcb8f9add 100644
--- a/src/chttpd/test/exunit/pagination_test.exs
+++ b/src/chttpd/test/exunit/pagination_test.exs
@@ -68,6 +68,52 @@ defmodule Couch.Test.Pagination do
%{view_name: "all", ddoc_id: ddoc_id}
end
+ defp all_docs(context) do
+ assert Map.has_key?(context, :page_size), "Please define '@describetag page_size: 4'"
+
+ assert Map.has_key?(context, :descending),
+ "Please define '@describetag descending: false'"
+
+ resp =
+ Couch.Session.get(context.session, "/#{context.db_name}/_all_docs",
+ query: %{page_size: context.page_size, descending: context.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ %{
+ response: resp.body
+ }
+ end
+
+ defp paginate(context) do
+ if Map.has_key?(context.response, "next") do
+ bookmark = context.response["next"]
+ pages = Map.get(context, :pages, [context.response])
+ assert length(pages) < div(context.n_docs, context.page_size) + 1
+
+ resp =
+ Couch.Session.get(context.session, "/#{context.db_name}/_all_docs",
+ query: %{bookmark: bookmark}
+ )
+
+ context =
+ Map.merge(context, %{
+ pages: [resp.body | pages],
+ response: resp.body
+ })
+
+ paginate(context)
+ else
+ context =
+ Map.update(context, :pages, [], fn acc ->
+ Enum.reverse(acc)
+ end)
+
+ context
+ end
+ end
+
def create_db(session, db_name, opts \\ []) do
retry_until(fn ->
resp = Couch.Session.put(session, "/#{db_name}", opts)
@@ -298,5 +344,730 @@ defmodule Couch.Test.Pagination do
assert q1 == Enum.reverse(q2)
assert q1 == Enum.sort(q1)
end
+
+ test "ensure we paginate starting from first query", ctx do
+ queries = %{
+ queries: [%{descending: false}, %{descending: true}]
+ }
+
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size},
+ body: :jiffy.encode(queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ [q1, q2] = resp.body["results"]
+ q1 = Enum.map(q1["rows"], fn row -> row["id"] end)
+ q2 = Enum.map(q2["rows"], fn row -> row["id"] end)
+ assert ctx.page_size == length(q1)
+ assert q2 == []
+ end
+ end
+
+ describe "Pagination API (10 docs)" do
+ @describetag n_docs: 10
+ @describetag page_size: 4
+ setup [:with_session, :random_db, :with_docs]
+
+ test ": _all_docs?page_size=4", ctx do
+ %{session: session, db_name: db_name} = ctx
+
+ resp =
+ Couch.Session.get(session, "/#{db_name}/_all_docs",
+ query: %{page_size: ctx.page_size}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ end
+
+ test ": _all_docs/queries should limit number of queries", ctx do
+ queries = %{
+ queries: [%{}, %{}, %{}, %{}, %{}]
+ }
+
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size},
+ body: :jiffy.encode(queries)
+ )
+
+ assert resp.status_code == 400
+
+ assert resp.body["reason"] ==
+ "Provided number of queries is more than given page_size"
+ end
+
+ test ": _all_docs/queries should forbid `page_size` in queries", ctx do
+ queries = %{
+ queries: [%{page_size: 3}]
+ }
+
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size},
+ body: :jiffy.encode(queries)
+ )
+
+ assert resp.status_code == 400
+
+ assert resp.body["reason"] ==
+ "You cannot specify `page_size` inside the query"
+ end
+
+ test ": _all_docs should forbid `page_size` and `keys`", ctx do
+ body = %{
+ page_size: 3,
+ keys: [
+ "002",
+ "004"
+ ]
+ }
+
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs",
+ body: :jiffy.encode(body)
+ )
+
+ assert resp.status_code == 400
+
+ assert resp.body["reason"] ==
+ "`page_size` is incompatible with `keys`"
+ end
+
+ test ": _all_docs should limit 'skip' parameter", ctx do
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{page_size: ctx.page_size, skip: 3000}
+ )
+
+ assert resp.status_code == 400
+
+ assert resp.body["reason"] ==
+ "`skip` should be an integer in range [0 .. 2000]"
+ end
+
+ test ": _all_docs should forbid extra parameters when 'bookmark' is present", ctx do
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{page_size: ctx.page_size, skip: 3000, bookmark: ""}
+ )
+
+ assert resp.status_code == 400
+
+ assert resp.body["reason"] ==
+ "Cannot use `bookmark` with other options"
+ end
+ end
+
+ for descending <- [false, true] do
+ for n <- [4, 9] do
+ describe "Pagination API (10 docs) : _all_docs?page_size=#{n}&descending=#{
+ descending
+ }" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_docs, :all_docs]
+
+ test "should return 'next' bookmark", ctx do
+ body = ctx.response
+ assert Map.has_key?(body, "next")
+ end
+
+ test "total_rows matches the length of rows array", ctx do
+ body = ctx.response
+ assert body["total_rows"] == length(body["rows"])
+ end
+
+ test "total_rows matches the requested page_size", ctx do
+ body = ctx.response
+ assert body["total_rows"] == ctx.page_size
+ end
+
+ test "can use 'next' bookmark to get remaining results", ctx do
+ bookmark = ctx.response["next"]
+
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{bookmark: bookmark}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ body = resp.body
+ assert body["total_rows"] == length(body["rows"])
+ assert body["total_rows"] <= ctx.page_size
+ end
+ end
+
+ describe "Pagination API (10 docs) : _all_docs?page_size=#{n}&descending=#{
+ descending
+ } : range" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_docs]
+
+ test "start_key is respected", ctx do
+ head_pos = 2
+ tail_pos = ctx.n_docs - head_pos
+ doc_ids = Enum.map(ctx.docs, fn doc -> doc["id"] end)
+
+ {start_pos, doc_ids} =
+ if ctx.descending do
+ {head_pos, Enum.reverse(Enum.drop(Enum.sort(doc_ids), -tail_pos))}
+ else
+ {tail_pos, Enum.drop(Enum.sort(doc_ids), tail_pos - 1)}
+ end
+
+ start_key = ~s("#{docid(start_pos)}")
+
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{descending: ctx.descending, start_key: start_key}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ ids = Enum.map(resp.body["rows"], fn row -> row["id"] end)
+ assert doc_ids == ids
+ end
+
+ test "end_key is respected", ctx do
+ head_pos = 2
+ tail_pos = ctx.n_docs - head_pos
+ doc_ids = Enum.map(ctx.docs, fn doc -> doc["id"] end)
+
+ {end_pos, doc_ids} =
+ if ctx.descending do
+ {tail_pos, Enum.reverse(Enum.drop(Enum.sort(doc_ids), tail_pos - 1))}
+ else
+ {head_pos, Enum.drop(Enum.sort(doc_ids), -tail_pos)}
+ end
+
+ end_key = ~s("#{docid(end_pos)}")
+
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{descending: ctx.descending, end_key: end_key}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ ids = Enum.map(resp.body["rows"], fn row -> row["id"] end)
+ assert doc_ids == ids
+ end
+
+ test "range between start_key and end_key works", ctx do
+ head_pos = 2
+ slice_size = 3
+ doc_ids = Enum.sort(Enum.map(ctx.docs, fn doc -> doc["id"] end))
+ # -1 due to 0 based indexing
+ # -2 is due to 0 based indexing and inclusive end
+ slice = Enum.slice(doc_ids, (head_pos - 1)..(head_pos + slice_size - 2))
+
+ {start_key, end_key, doc_ids} =
+ if ctx.descending do
+ reversed = Enum.reverse(slice)
+ [first | _] = reversed
+ [last | _] = slice
+ {~s("#{first}"), ~s("#{last}"), reversed}
+ else
+ [first | _] = slice
+ [last | _] = Enum.reverse(slice)
+ {~s("#{first}"), ~s("#{last}"), slice}
+ end
+
+ assert length(doc_ids) == slice_size
+
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{descending: ctx.descending, start_key: start_key, end_key: end_key}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ ids = Enum.map(resp.body["rows"], fn row -> row["id"] end)
+ assert doc_ids == ids
+ end
+ end
+ end
+ end
+
+ for descending <- [false, true] do
+ for n <- [4, 9] do
+ describe "Pagination API (10 docs) : _all_docs?page_size=#{n}&descending=#{
+ descending
+ } : pages" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_docs, :all_docs, :paginate]
+
+ test "final page doesn't include 'next' bookmark", ctx do
+ assert not Map.has_key?(ctx.response, "next")
+ assert ctx.response["total_rows"] == rem(ctx.n_docs, ctx.page_size)
+ end
+
+ test "each but last page has page_size rows", ctx do
+ pages = Enum.drop(ctx.pages, -1)
+
+ assert Enum.all?(pages, fn resp ->
+ length(resp["rows"]) == ctx.page_size
+ end)
+ end
+
+ test "sum of rows on all pages is equal to number of documents", ctx do
+ pages = ctx.pages
+ n = Enum.reduce(pages, 0, fn resp, acc -> acc + length(resp["rows"]) end)
+ assert n == ctx.n_docs
+ end
+
+ test "the rows are correctly sorted", ctx do
+ pages = ctx.pages
+
+ ids =
+ Enum.reduce(pages, [], fn resp, acc ->
+ acc ++ Enum.map(resp["rows"], fn row -> row["id"] end)
+ end)
+
+ if ctx.descending do
+ assert Enum.reverse(Enum.sort(ids)) == ids
+ else
+ assert Enum.sort(ids) == ids
+ end
+ end
+ end
+ end
+ end
+
+ for n <- 10..11 do
+ describe "Pagination API (10 docs) : _all_docs?page_size=#{n}" do
+ @describetag n_docs: 10
+ @describetag descending: false
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_docs, :all_docs]
+
+ test "should not return 'next' bookmark", ctx do
+ body = ctx.response
+ assert not Map.has_key?(body, "next")
+ end
+
+ test "total_rows matches the length of rows array", ctx do
+ body = ctx.response
+ assert body["total_rows"] == length(body["rows"])
+ end
+
+ test "total_rows less than the requested page_size", ctx do
+ body = ctx.response
+ assert body["total_rows"] <= ctx.page_size
+ end
+ end
+ end
+
+ for descending <- [false, true] do
+ for n <- [4, 9] do
+ describe "Pagination API (10 docs) : _all_docs/queries?page_size=#{n}&descending=#{
+ descending
+ } : pages" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+
+ @describetag queries: %{
+ queries: [
+ %{
+ descending: true
+ },
+ %{
+ limit: n + 1,
+ skip: 2
+ }
+ ]
+ }
+
+ setup [:with_session, :random_db, :with_docs]
+
+ test "one of the results contains 'next' bookmark", ctx do
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+ assert Enum.any?(results, fn result -> Map.has_key?(result, "next") end)
+ end
+
+ test "each 'next' bookmark is working", ctx do
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ bookmarks =
+ results
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> Map.get(result, "next") end)
+
+ assert [] != bookmarks
+
+ Enum.each(bookmarks, fn bookmark ->
+ resp =
+ Couch.Session.get(ctx.session, "/#{ctx.db_name}/_all_docs",
+ query: %{bookmark: bookmark}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert [] != resp.body["rows"]
+ end)
+
+ assert Enum.any?(results, fn result -> Map.has_key?(result, "next") end)
+ end
+
+ test "can post bookmarks to queries", ctx do
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ queries =
+ results
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> %{bookmark: Map.get(result, "next")} end)
+
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ body: :jiffy.encode(%{queries: queries})
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ Enum.each(resp.body["results"], fn result ->
+ assert [] != result["rows"]
+ end)
+ end
+
+ test "respect request page_size", ctx do
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ Enum.each(results ++ resp.body["results"], fn result ->
+ assert length(result["rows"]) <= ctx.page_size
+ end)
+ end
+
+ test "independent page_size in the bookmark", ctx do
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ queries =
+ resp.body["results"]
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> %{bookmark: Map.get(result, "next")} end)
+
+ resp =
+ Couch.Session.post(ctx.session, "/#{ctx.db_name}/_all_docs/queries",
+ body: :jiffy.encode(%{queries: queries})
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ Enum.each(resp.body["results"], fn result ->
+ assert length(result["rows"]) > ctx.page_size
+ end)
+ end
+ end
+ end
+ end
+
+ for descending <- [false, true] do
+ for n <- [4, 9] do
+ describe "Pagination API (10 docs) : /{db}/_design/{ddoc}/_view?page_size=#{n}&descending=#{
+ descending
+ }" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_view, :with_docs]
+
+ test "should return 'next' bookmark", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert Map.has_key?(resp.body, "next")
+ end
+
+ test "total_rows matches the length of rows array", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ body = resp.body
+ assert body["total_rows"] == length(body["rows"])
+ end
+
+ test "total_rows matches the requested page_size", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert resp.body["total_rows"] == ctx.page_size
+ end
+
+ test "can use 'next' bookmark to get remaining results", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ bookmark = resp.body["next"]
+
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{bookmark: bookmark}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ body = resp.body
+ assert body["total_rows"] == length(body["rows"])
+ assert body["total_rows"] <= ctx.page_size
+ end
+ end
+ end
+ end
+
+ for n <- 10..11 do
+ describe "Pagination API (10 docs) : /{db}/_design/{ddoc}/_view?page_size=#{n}" do
+ @describetag n_docs: 10
+ @describetag descending: false
+ @describetag page_size: n
+ setup [:with_session, :random_db, :with_view, :with_docs]
+
+ test "should not return 'next' bookmark", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert not Map.has_key?(resp.body, "next")
+ end
+
+ test "total_rows matches the length of rows array", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ body = resp.body
+ assert body["total_rows"] == length(body["rows"])
+ end
+
+ test "total_rows less than the requested page_size", ctx do
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{page_size: ctx.page_size, descending: ctx.descending}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert resp.body["total_rows"] <= ctx.page_size
+ end
+ end
+ end
+
+ for descending <- [false, true] do
+ for n <- [4, 9] do
+ describe "Pagination API (10 docs) : /{db}/_design/{ddoc}/_view/queries?page_size=#{
+ n
+ }&descending=#{descending} : pages" do
+ @describetag n_docs: 10
+ @describetag descending: descending
+ @describetag page_size: n
+
+ @describetag queries: %{
+ queries: [
+ %{
+ descending: true
+ },
+ %{
+ limit: n + 1,
+ skip: 2
+ }
+ ]
+ }
+ setup [:with_session, :random_db, :with_view, :with_docs]
+
+ test "one of the results contains 'next' bookmark", ctx do
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+ assert Enum.any?(results, fn result -> Map.has_key?(result, "next") end)
+ end
+
+ test "each 'next' bookmark is working", ctx do
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ bookmarks =
+ results
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> Map.get(result, "next") end)
+
+ assert [] != bookmarks
+
+ Enum.each(bookmarks, fn bookmark ->
+ resp =
+ Couch.Session.get(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}",
+ query: %{bookmark: bookmark}
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ assert [] != resp.body["rows"]
+ end)
+
+ assert Enum.any?(results, fn result -> Map.has_key?(result, "next") end)
+ end
+
+ test "can post bookmarks to queries", ctx do
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ queries =
+ results
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> %{bookmark: Map.get(result, "next")} end)
+
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ body: :jiffy.encode(%{queries: queries})
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ Enum.each(resp.body["results"], fn result ->
+ assert [] != result["rows"]
+ end)
+ end
+
+ test "respect request page_size", ctx do
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+ results = resp.body["results"]
+
+ Enum.each(results ++ resp.body["results"], fn result ->
+ assert length(result["rows"]) <= ctx.page_size
+ end)
+ end
+
+ test "independent page_size in the bookmark", ctx do
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ query: %{page_size: ctx.page_size, descending: ctx.descending},
+ body: :jiffy.encode(ctx.queries)
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ queries =
+ resp.body["results"]
+ |> Enum.filter(fn result -> Map.has_key?(result, "next") end)
+ |> Enum.map(fn result -> %{bookmark: Map.get(result, "next")} end)
+
+ resp =
+ Couch.Session.post(
+ ctx.session,
+ "/#{ctx.db_name}/_design/#{ctx.ddoc_id}/_view/#{ctx.view_name}/queries",
+ body: :jiffy.encode(%{queries: queries})
+ )
+
+ assert resp.status_code == 200, "got error #{inspect(resp.body)}"
+
+ Enum.each(resp.body["results"], fn result ->
+ assert length(result["rows"]) > ctx.page_size
+ end)
+ end
+ end
+ end
end
end