test: update cursor-based pagination test cases
This commit is contained in:
+145
-15
@@ -97,7 +97,7 @@ describe "App::Controllers::Link" do
|
||||
})
|
||||
|
||||
response.headers["Location"].should eq(link)
|
||||
response.headers["X-Forwarded-User-Agent"].should eq(user_agent)
|
||||
response.headers["User-Agent"].should eq(user_agent)
|
||||
response.headers.has_key?("X-Forwarded-For").should be_true
|
||||
end
|
||||
|
||||
@@ -161,8 +161,8 @@ describe "App::Controllers::Link" do
|
||||
end
|
||||
|
||||
describe "All" do
|
||||
it "should return all links" do
|
||||
links = ["https://google.com", "google.com", "google.com.co"]
|
||||
it "should return all links with pagination" do
|
||||
links = ["https://sjdonado.com", "sjdonado.com", "sjdonado.com.co"]
|
||||
test_user = create_test_user()
|
||||
|
||||
links.each do |link|
|
||||
@@ -171,14 +171,58 @@ describe "App::Controllers::Link" do
|
||||
|
||||
get("/api/links", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Array(Hash(String, String | Int64 | Array(Hash(String, String))))).from_json(response.body)
|
||||
parsed_response["data"][0]["origin"].should eq(links[0])
|
||||
parsed_response["data"][1]["origin"].should eq(links[1])
|
||||
parsed_response["data"][2]["origin"].should eq(links[2])
|
||||
parsed_response = Hash(String, Array(Hash(String, String | Int64)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
|
||||
# Check that each link is in the response data
|
||||
origins = parsed_response["data"].as(Array).map { |link| link["origin"] }
|
||||
links.each do |link|
|
||||
origins.should contain(link)
|
||||
end
|
||||
|
||||
parsed_response["pagination"].as(Hash)["has_more"].should be_false
|
||||
end
|
||||
|
||||
it "should respect custom limit parameter" do
|
||||
test_user = create_test_user()
|
||||
|
||||
5.times do |i|
|
||||
create_test_link(test_user, "https://example.com/#{i}")
|
||||
end
|
||||
|
||||
get("/api/links?limit=2", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Array(Hash(String, String | Int64)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
parsed_response["data"].as(Array).size.should eq(2)
|
||||
parsed_response["pagination"].as(Hash)["has_more"].should be_true
|
||||
parsed_response["pagination"].as(Hash)["next"].should_not be_nil
|
||||
end
|
||||
|
||||
it "should support cursor-based pagination" do
|
||||
test_user = create_test_user()
|
||||
|
||||
5.times do |i|
|
||||
create_test_link(test_user, "https://example.com/#{i}")
|
||||
end
|
||||
|
||||
# Get first page
|
||||
get("/api/links?limit=2", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
first_page = Hash(String, Array(Hash(String, String | Int64)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
cursor = first_page["pagination"].as(Hash)["next"]
|
||||
|
||||
# Get second page using cursor
|
||||
get("/api/links?limit=2&cursor=#{cursor}", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
second_page = Hash(String, Array(Hash(String, String | Int64)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
|
||||
# Ensure different links are returned
|
||||
first_page_ids = first_page["data"].as(Array).map { |link| link["id"] }
|
||||
second_page_ids = second_page["data"].as(Array).map { |link| link["id"] }
|
||||
|
||||
# Check that no IDs from first page appear in second page
|
||||
(first_page_ids & second_page_ids).empty?.should be_true
|
||||
end
|
||||
|
||||
it "should return owned links only" do
|
||||
links = ["https://google.de", "google.de", "google.edu.co", "x.com"]
|
||||
links = ["https://donado.co", "donado.co", "uninorte.edu.co", "kagi.com"]
|
||||
test_user = create_test_user()
|
||||
|
||||
links[0..2].each do |link|
|
||||
@@ -190,11 +234,14 @@ describe "App::Controllers::Link" do
|
||||
|
||||
get("/api/links", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Array(Hash(String, String | Int64 | Array(Hash(String, String))))).from_json(response.body)
|
||||
parsed_response["data"].size.should eq(3)
|
||||
parsed_response["data"][0]["origin"].should eq(links[0])
|
||||
parsed_response["data"][1]["origin"].should eq(links[1])
|
||||
parsed_response["data"][2]["origin"].should eq(links[2])
|
||||
parsed_response = Hash(String, Array(Hash(String, String | Int64)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
parsed_response["data"].as(Array).size.should eq(3)
|
||||
|
||||
origins = parsed_response["data"].as(Array).map { |link| link["origin"] }
|
||||
links[0..2].each do |link|
|
||||
origins.should contain(link)
|
||||
end
|
||||
origins.should_not contain(links[3])
|
||||
end
|
||||
|
||||
it "should return 401 - missing api key" do
|
||||
@@ -207,16 +254,20 @@ describe "App::Controllers::Link" do
|
||||
end
|
||||
|
||||
describe "Get" do
|
||||
it "should return the specified link with click details" do
|
||||
it "should return the specified link with limited click details" do
|
||||
link = "https://bing.com"
|
||||
test_user = create_test_user()
|
||||
test_link = create_test_link(test_user, link)
|
||||
|
||||
110.times do
|
||||
create_test_click(test_link)
|
||||
end
|
||||
|
||||
get("/api/links/#{test_link.id}", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Hash(String, String | Int64 | Array(Hash(String, String)))).from_json(response.body)
|
||||
parsed_response["data"]["origin"].should eq(link)
|
||||
parsed_response["data"]["clicks"].should be_a(Array(Hash(String, String)))
|
||||
parsed_response["data"]["clicks"].as(Array).size.should eq(100)
|
||||
end
|
||||
|
||||
it "should return 404 - link does not exist" do
|
||||
@@ -238,6 +289,85 @@ describe "App::Controllers::Link" do
|
||||
end
|
||||
end
|
||||
|
||||
describe "Clicks" do
|
||||
it "should return paginated clicks for a link" do
|
||||
link = "https://example.com"
|
||||
test_user = create_test_user()
|
||||
test_link = create_test_link(test_user, link)
|
||||
|
||||
5.times do
|
||||
create_test_click(test_link)
|
||||
end
|
||||
|
||||
get("/api/links/#{test_link.id}/clicks", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Array(Hash(String, String)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
parsed_response["data"].as(Array).size.should eq(5)
|
||||
parsed_response["pagination"].as(Hash)["has_more"].should be_false
|
||||
end
|
||||
|
||||
it "should respect limit parameter" do
|
||||
link = "https://example.com"
|
||||
test_user = create_test_user()
|
||||
test_link = create_test_link(test_user, link)
|
||||
|
||||
10.times do
|
||||
create_test_click(test_link)
|
||||
end
|
||||
|
||||
get("/api/links/#{test_link.id}/clicks?limit=3", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
parsed_response = Hash(String, Array(Hash(String, String)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
parsed_response["data"].as(Array).size.should eq(3)
|
||||
parsed_response["pagination"].as(Hash)["has_more"].should be_true
|
||||
parsed_response["pagination"].as(Hash)["next"].should_not be_nil
|
||||
end
|
||||
|
||||
it "should support cursor-based pagination" do
|
||||
link = "https://example.com"
|
||||
test_user = create_test_user()
|
||||
test_link = create_test_link(test_user, link)
|
||||
|
||||
10.times do
|
||||
create_test_click(test_link)
|
||||
end
|
||||
|
||||
# Get first page
|
||||
get("/api/links/#{test_link.id}/clicks?limit=3", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
first_page = Hash(String, Array(Hash(String, String)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
cursor = first_page["pagination"].as(Hash)["next"]
|
||||
|
||||
# Get second page using cursor
|
||||
get("/api/links/#{test_link.id}/clicks?limit=3&cursor=#{cursor}", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
second_page = Hash(String, Array(Hash(String, String)) | Hash(String, Bool | String?)).from_json(response.body)
|
||||
|
||||
# Ensure different clicks are returned
|
||||
first_page_ids = first_page["data"].as(Array).map { |click| click["id"] }
|
||||
second_page_ids = second_page["data"].as(Array).map { |click| click["id"] }
|
||||
|
||||
# Check that no IDs from first page appear in second page
|
||||
(first_page_ids & second_page_ids).empty?.should be_true
|
||||
end
|
||||
|
||||
it "should return 404 - link does not exist" do
|
||||
test_user = create_test_user()
|
||||
|
||||
get("/api/links/nonexistent_id/clicks", headers: HTTP::Headers{"X-Api-Key" => test_user.api_key.to_s})
|
||||
|
||||
expected = {"error" => "Resource not found"}.to_json
|
||||
response.status_code.should eq(404)
|
||||
response.body.should eq(expected)
|
||||
end
|
||||
|
||||
it "should return 401 - missing api key" do
|
||||
get("/api/links/1/clicks")
|
||||
|
||||
expected = {"error" => "Unauthorized access"}.to_json
|
||||
response.status_code.should eq(401)
|
||||
response.body.should eq(expected)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Update" do
|
||||
it "should update link url" do
|
||||
link = "https://github.com"
|
||||
|
||||
@@ -4,7 +4,7 @@ describe "App::Controllers::Ping" do
|
||||
it "should return pong" do
|
||||
get "/api/ping"
|
||||
|
||||
expected = {"pong" => "ok"}.to_json
|
||||
expected = {"data" => "pong"}.to_json
|
||||
response.body.should eq(expected)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -55,6 +55,26 @@ def create_test_link(user, url)
|
||||
link
|
||||
end
|
||||
|
||||
def create_test_click(link)
|
||||
click = App::Models::Click.new
|
||||
click.id = UUID.v4.to_s
|
||||
click.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:127.0) Gecko/20100101 Firefox/127.0"
|
||||
click.browser = "Firefox"
|
||||
click.os = "Mac OS X"
|
||||
click.referer = "example.com"
|
||||
click.country = "US"
|
||||
click.created_at = Time.utc
|
||||
click.link = link
|
||||
click.link_id = link.id
|
||||
|
||||
changeset = App::Lib::Database.insert(click)
|
||||
unless changeset.valid?
|
||||
error_messages = changeset.errors.map { |error| "#{error}" }.join(", ")
|
||||
raise "Test click creation failed: #{error_messages}"
|
||||
end
|
||||
click
|
||||
end
|
||||
|
||||
def get_test_link(link_id)
|
||||
query = App::Lib::Database::Query.where(id: link_id.as(String)).limit(1)
|
||||
link = App::Lib::Database.all(App::Models::Link, query, preload: [:clicks]).first?
|
||||
|
||||
Reference in New Issue
Block a user