-
-
Notifications
You must be signed in to change notification settings - Fork 158
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add current_page? helper for pages. (#1074)
Closes #1073
- Loading branch information
Showing
3 changed files
with
284 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
require "../spec_helper" | ||
|
||
include ContextHelper | ||
|
||
describe Lucky::UrlHelpers do | ||
describe "#current_page?" do | ||
context "given a string" do | ||
it "tests if a path matches the request path or not" do | ||
view_for("/").current_page?("/").should be_true | ||
view_for("/action").current_page?("/gum").should be_false | ||
view_for("/action").current_page?("/action").should be_true | ||
view_for("/action").current_page?("/action/").should be_true | ||
view_for("/action/").current_page?("/action").should be_true | ||
view_for("/action/").current_page?("/action/").should be_true | ||
end | ||
|
||
it "tests if the path of a url matches request path or not" do | ||
view_for("/") | ||
.current_page?("https://example.com/") | ||
.should be_true | ||
view_for("/action") | ||
.current_page?("https://example.com/action") | ||
.should be_true | ||
view_for("/action", host_with_port: "example.io") | ||
.current_page?("https://example.com/action") | ||
.should be_false | ||
view_for("/action", host_with_port: "example.com:3000") | ||
.current_page?("https://example.com/action") | ||
.should be_false | ||
view_for("/action", host_with_port: "example.com:3000") | ||
.current_page?("https://example.com:3000/action") | ||
.should be_true | ||
view_for("/action", host_with_port: "example.com:3000") | ||
.current_page?("http://example.com:3000/action") | ||
.should be_true | ||
end | ||
|
||
it "only tests positive for get and head requests" do | ||
view_for("/get", "GET").current_page?("/get").should be_true | ||
view_for("/head", "HEAD").current_page?("/head").should be_true | ||
view_for("/post", "POST").current_page?("/post").should be_false | ||
view_for("/put", "PUT").current_page?("/put").should be_false | ||
view_for("/patch", "PATCH").current_page?("/patch").should be_false | ||
view_for("/delete", "DELETE").current_page?("/delete").should be_false | ||
end | ||
|
||
it "ignores query parameters by default" do | ||
view_for("/action?order=desc&page=1").current_page?("/action") | ||
.should be_true | ||
view_for("/action").current_page?("/action?order=desc&page=1") | ||
.should be_true | ||
view_for("/action?order=desc&page=1").current_page?("/action/123") | ||
.should be_false | ||
end | ||
|
||
it "deals with escaped characters in query params" do | ||
view_for("/pages?description=Some%20d%C3%A9scription") | ||
.current_page?("/pages?description=Some déscription", check_query_params: true) | ||
.should be_true | ||
view_for("/pages?description=Some%20d%C3%A9scription") | ||
.current_page?("/pages?description=Some%20d%C3%A9scription", check_query_params: true) | ||
.should be_true | ||
end | ||
|
||
it "checks query params if explicitly required" do | ||
view_for("/action?order=desc&page=1") | ||
.current_page?("/action?order=desc&page=1", check_query_params: true) | ||
.should be_true | ||
view_for("/action") | ||
.current_page?("/action", check_query_params: true) | ||
.should be_true | ||
view_for("/action") | ||
.current_page?("/action?order=desc&page=1", check_query_params: true) | ||
.should be_false | ||
view_for("/action?order=desc&page=1") | ||
.current_page?("/action", check_query_params: true) | ||
.should be_false | ||
end | ||
|
||
it "does not care about the order of query params" do | ||
view_for("/action?order=desc&page=1") | ||
.current_page?("/action?order=desc&page=1", check_query_params: true) | ||
.should be_true | ||
view_for("/action?order=desc&page=1") | ||
.current_page?("/action?page=1&order=desc", check_query_params: true) | ||
.should be_true | ||
end | ||
|
||
it "ignores anchors" do | ||
view_for("/pages/123").current_page?("/pages/123#section") | ||
.should be_true | ||
view_for("/pages/123#section").current_page?("/pages/123") | ||
.should be_true | ||
view_for("/pages/123#section").current_page?("/pages/123#section") | ||
.should be_true | ||
view_for("/pages/123") | ||
.current_page?("/pages/123#section", check_query_params: true) | ||
.should be_true | ||
end | ||
end | ||
|
||
context "given a browser action" do | ||
it "tests if the path matches or not" do | ||
view_for("/pages/123").current_page?(Pages::Show.with(123)) | ||
.should be_true | ||
view_for("/pages/123").current_page?(Pages::Show.with(12)) | ||
.should be_false | ||
view_for("/pages").current_page?(Pages::Index) | ||
.should be_true | ||
view_for("/pages") | ||
.current_page?(Pages::Index.with(page: 2)) | ||
.should be_true | ||
view_for("/pages?page=2") | ||
.current_page?(Pages::Index) | ||
.should be_true | ||
end | ||
|
||
it "checks query params if explicitly required" do | ||
view_for("/pages") | ||
.current_page?(Pages::Index, check_query_params: true) | ||
.should be_true | ||
view_for("/pages?page=2") | ||
.current_page?(Pages::Index.with(page: 2), check_query_params: true) | ||
.should be_true | ||
view_for("/pages") | ||
.current_page?(Pages::Index.with(page: 2), check_query_params: true) | ||
.should be_false | ||
view_for("/pages?page=2") | ||
.current_page?(Pages::Index, check_query_params: true) | ||
.should be_false | ||
end | ||
|
||
it "ignores anchors" do | ||
view_for("/pages/123") | ||
.current_page?(Pages::Show.with(123, anchor: "section")) | ||
.should be_true | ||
view_for("/pages/123#section") | ||
.current_page?(Pages::Show.with(123)) | ||
.should be_true | ||
view_for("/pages/123#section") | ||
.current_page?(Pages::Show.with(123, anchor: "section")) | ||
.should be_true | ||
view_for("/pages/123") | ||
.current_page?(Pages::Show.with(123, anchor: "section"), check_query_params: true) | ||
.should be_true | ||
end | ||
end | ||
end | ||
end | ||
|
||
private def view_for( | ||
path : String, | ||
method : String = "GET", | ||
host_with_port : String = "example.com" | ||
) | ||
request = HTTP::Request.new(method, path) | ||
request.headers["Host"] = host_with_port | ||
TestPage.new(build_context(path: path, request: request)) | ||
end | ||
|
||
private class TestPage | ||
include Lucky::HTMLPage | ||
include Lucky::UrlHelpers | ||
end | ||
|
||
class Pages::Index < TestAction | ||
param page : Int32 = 1 | ||
|
||
get "/pages" do | ||
plain_text "I'm just a list of pages" | ||
end | ||
end | ||
|
||
class Pages::Show < TestAction | ||
get "/pages/:id" do | ||
plain_text "I'm just a page" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
module Lucky::UrlHelpers | ||
# Tests if the given path matches the current request path. | ||
# | ||
# ``` | ||
# # Let's say we are visiting https://example.com/shop/products?order=desc&page=1 | ||
# current_page?("/shop/checkout") | ||
# # => false | ||
# current_page?("/shop/products") | ||
# # => true | ||
# current_page?("/shop/products/") | ||
# # => true | ||
# current_page?("/shop/products?order=desc&page=1") | ||
# # => true | ||
# current_page?("/shop/products", check_query_params: true) | ||
# # => false | ||
# current_page?("/shop/products?order=desc&page=1", check_query_params: true) | ||
# # => true | ||
# current_page?("https://example.com/shop/products") | ||
# # => true | ||
# current_page?("https://example.io/shop/products") | ||
# # => false | ||
# current_page?("https://example.com/shop/products", check_query_params: true) | ||
# # => false | ||
# current_page?("https://example.com/shop/products?order=desc&page=1") | ||
# # => true | ||
# ``` | ||
def current_page?( | ||
value : String, | ||
check_query_params : Bool = false | ||
) | ||
request = @context.request | ||
|
||
return false unless {"GET", "HEAD"}.includes?(request.method) | ||
|
||
uri = URI.parse(value) | ||
request_uri = URI.parse(request.resource) | ||
path = uri.path | ||
resource = request_uri.path | ||
|
||
unless path == "/" | ||
path = path.chomp("/") | ||
resource = resource.chomp("/") | ||
end | ||
|
||
if check_query_params | ||
path += comparable_query_params(uri.query_params) | ||
resource += comparable_query_params(request_uri.query_params) | ||
end | ||
|
||
if value.match(/^\w+:\/\//) | ||
host_with_port = uri.port ? "#{uri.host}:#{uri.port}" : uri.host | ||
"#{host_with_port}#{path}" == "#{request.host_with_port}#{resource}" | ||
else | ||
path == resource | ||
end | ||
end | ||
|
||
# Tests if the given path matches the current request path. | ||
# | ||
# ``` | ||
# # Visiting https://example.com/pages/123 | ||
# current_page?(Pages::Show.with(123)) | ||
# # => true | ||
# current_page?(Posts::Show.with(123)) | ||
# # => false | ||
# # Visiting https://example.com/pages | ||
# current_page?(Pages::Index) | ||
# # => true | ||
# current_page?(Blog::Index) | ||
# # => false | ||
# # Visiting https://example.com/pages?page=2 | ||
# current_page?(Pages::Index.with) | ||
# # => true | ||
# current_page?(Pages::Index.with(page: 2)) | ||
# # => true | ||
# current_page?(Pages::Index.with, check_query_params: true) | ||
# # => false | ||
# current_page?(Pages::Index.with(page: 2), check_query_params: true) | ||
# # => true | ||
# ``` | ||
def current_page?( | ||
action : Lucky::Action.class | Lucky::RouteHelper, | ||
check_query_params : Bool = false | ||
) | ||
current_page?(action.path, check_query_params) | ||
end | ||
|
||
private def comparable_query_params(query_params : HTTP::Params) : String | ||
URI.decode(query_params.map(&.join).sort!.join) | ||
end | ||
end |