From e5373f4cb8626de9edf2d733588afec9d57adc3d Mon Sep 17 00:00:00 2001 From: Anton Maminov Date: Tue, 16 Nov 2021 10:27:04 +0200 Subject: [PATCH 1/3] Sets a Referer header --- spec/agent_spec.cr | 14 ++++++++++++++ src/mechanize/http/agent.cr | 12 ++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/spec/agent_spec.cr b/spec/agent_spec.cr index 542e15e..661f53c 100644 --- a/spec/agent_spec.cr +++ b/spec/agent_spec.cr @@ -65,4 +65,18 @@ describe "Mechanize Agent test" do File.exists?("mechanizecr_example.html").should eq true File.delete("mechanizecr_example.html") end + + it "should set referer header" do + page_url = "http://example.com/form" + + agent = Mechanize.new + page = agent.get(page_url) + form = page.forms[0] + form.field_with("name").value = "foo" + form.field_with("email").value = "bar" + page = agent.submit(form) + + page.not_nil!.code.should eq 200 + agent.request_headers["Referer"].should eq(page_url) + end end diff --git a/src/mechanize/http/agent.cr b/src/mechanize/http/agent.cr index b8edaf5..d27acdf 100644 --- a/src/mechanize/http/agent.cr +++ b/src/mechanize/http/agent.cr @@ -19,11 +19,12 @@ module MechanizeCr @user_agent = "" end - def fetch(uri, method = :get, headers = HTTP::Headers.new, params = Hash(String, String).new, + def fetch(uri, method = :get, headers = ::HTTP::Headers.new, params = Hash(String, String).new, referer = (current_page unless history.empty?)) uri = resolve_url(uri, referer) set_request_headers(uri, headers) set_user_agent + set_request_referer(referer) uri, params = resolve_parameters(uri, method, params) response = http_request(uri, method, params) body = response.not_nil!.body @@ -47,7 +48,7 @@ module MechanizeCr headers.delete("Content-Type") headers.delete("Content-Length") - @context.not_nil!.get(uri) + fetch(uri) end def http_request(uri, method, params) @@ -94,6 +95,13 @@ module MechanizeCr end end + # Sets a Referer header. + def set_request_referer(referer : MechanizeCr::Page?) + return unless referer + + request_headers["Referer"] = referer.uri.to_s + end + private def resolve_parameters(uri, method, params) case method when :get From a20b63a51585d9037e17272d0f49a89c41331e53 Mon Sep 17 00:00:00 2001 From: Anton Maminov Date: Mon, 15 Nov 2021 22:09:38 +0200 Subject: [PATCH 2/3] MechanizeCr -> Mechanize --- spec/form/select_list_spec.cr | 2 +- src/mechanize.cr | 46 +++++------ src/mechanize/errors/base_error.cr | 4 +- .../errors/element_not_found_error.cr | 2 +- src/mechanize/file.cr | 16 ++-- src/mechanize/form.cr | 52 ++++++------ src/mechanize/form/button.cr | 2 +- src/mechanize/form/check_box.cr | 2 +- src/mechanize/form/field.cr | 4 +- src/mechanize/form/hidden.cr | 2 +- src/mechanize/form/image_button.cr | 2 +- src/mechanize/form/multi_select_list.cr | 4 +- src/mechanize/form/option.cr | 2 +- src/mechanize/form/radio_button.cr | 2 +- src/mechanize/form/reset_button.cr | 2 +- src/mechanize/form/select_list.cr | 2 +- src/mechanize/form/submit_button.cr | 2 +- src/mechanize/form/text.cr | 2 +- src/mechanize/form/textarea.cr | 2 +- src/mechanize/history.cr | 40 +++++----- src/mechanize/http/agent.cr | 6 +- src/mechanize/page.cr | 80 ++++++++++--------- src/mechanize/page/link.cr | 4 +- src/mechanize/utils/element_matcher.cr | 14 ++-- 24 files changed, 153 insertions(+), 143 deletions(-) diff --git a/spec/form/select_list_spec.cr b/spec/form/select_list_spec.cr index 61d0096..e55d346 100644 --- a/spec/form/select_list_spec.cr +++ b/spec/form/select_list_spec.cr @@ -27,7 +27,7 @@ describe "Form Fields Select List" do form.selectboxes.size.should eq 1 end - selectbox = form.selectboxes[0].as(MechanizeCr::FormContent::SelectList) + selectbox = form.selectboxes[0].as(Mechanize::FormContent::SelectList) it "returns selectbox options size" do selectbox.options.size.should eq 3 diff --git a/src/mechanize.cr b/src/mechanize.cr index 9c87ceb..bca31f3 100644 --- a/src/mechanize.cr +++ b/src/mechanize.cr @@ -35,7 +35,7 @@ class Mechanize } def initialize - @agent = MechanizeCr::HTTP::Agent.new + @agent = Mechanize::HTTP::Agent.new @agent.context = self @agent.user_agent = USER_AGENT["Mechanize"] end @@ -51,8 +51,8 @@ class Mechanize # headers: HTTP::Headers{"Foo" => "Bar"}) # ``` def get(uri : String | URI, - headers = HTTP::Headers.new, - params : Hash(String, String | Array(String)) = Hash(String, String).new) : MechanizeCr::Page + headers = ::HTTP::Headers.new, + params : Hash(String, String | Array(String)) = Hash(String, String).new) : Mechanize::Page method = :get page = @agent.fetch uri, method, headers, params add_to_history(page) @@ -71,17 +71,17 @@ class Mechanize # headers: HTTP::Headers{"Foo" => "Bar"}) # ``` def post(uri : String | URI, - headers = HTTP::Headers.new, - query : Hash(String, String | Array(String)) = Hash(String, String).new) : MechanizeCr::Page + headers = ::HTTP::Headers.new, + query : Hash(String, String | Array(String)) = Hash(String, String).new) : Mechanize::Page node = Node.new node["method"] = "POST" node["enctype"] = "application/x-www-form-urlencoded" - form = MechanizeCr::Form.new(node) + form = Mechanize::Form.new(node) query.each do |k, v| node = Node.new node["name"] = k - form.fields << MechanizeCr::FormContent::Field.new(node, v) + form.fields << Mechanize::FormContent::Field.new(node, v) end post_form(uri, form, headers) end @@ -125,18 +125,18 @@ class Mechanize # get the page mechanize last visited. # # ``` - # agent.current_page => # + # agent.current_page => # # ``` - def current_page : MechanizeCr::Page + def current_page : Mechanize::Page @agent.current_page end # get the latest page recorded in history, and the page is deleted from history. # # ``` - # agent.back => # + # agent.back => # # ``` - def back : MechanizeCr::Page + def back : Mechanize::Page @agent.history.pop end @@ -151,7 +151,7 @@ class Mechanize # form.field_with("foo").value = "bar" # agent.submit(form) # ``` - def submit(form, button = nil) : MechanizeCr::Page? + def submit(form, button = nil) : Mechanize::Page? form.add_button_to_query(button) if button case form.method.upcase when "POST" @@ -162,19 +162,19 @@ class Mechanize # parse response. it is used internally. def parse(uri, response, body) code = response.not_nil!.status_code - MechanizeCr::Page.new(uri, response, body, code, self) + Mechanize::Page.new(uri, response, body, code, self) end - # get the history (`MechanizeCr::History`). + # get the history (`Mechanize::History`). # the requests mechanize send is recorded in this history. # ``` - # agent.history => # + # agent.history => # # ``` - def history : MechanizeCr::History + def history : Mechanize::History @agent.history end - # add page to history (`MechanizeCr::History`). + # add page to history (`Mechanize::History`). # # if you send request, mechanize calls this method and records page, # so you don't need to call this on your own. @@ -207,7 +207,7 @@ class Mechanize # link = page.links.first # page2 = agent.click(link) # ``` - def click(link : MechanizeCr::PageContent::Link) : MechanizeCr::Page + def click(link : Mechanize::PageContent::Link) : Mechanize::Page href = link.href get href end @@ -219,13 +219,13 @@ class Mechanize # ``` def download(uri : URI | String, filename : String, - headers = HTTP::Headers.new, + headers = ::HTTP::Headers.new, params : Hash(String, String | Array(String)) = Hash(String, String).new) transact do page = get(uri, headers, params) case page - when MechanizeCr::File - File.write(filename, page.body) + when Mechanize::File + ::File.write(filename, page.body) end end end @@ -233,7 +233,7 @@ class Mechanize # Runs given block, then resets the page history as it was before. private def transact # save the previous history status. - history_backup = MechanizeCr::History.new(@agent.history.max_size, @agent.history.array.dup) + history_backup = Mechanize::History.new(@agent.history.max_size, @agent.history.array.dup) begin yield self ensure @@ -243,7 +243,7 @@ class Mechanize end # send POST request from form. - private def post_form(uri, form, headers) : MechanizeCr::Page + private def post_form(uri, form, headers) : Mechanize::Page cur_page = form.page || (current_page unless history.empty?) request_data = form.request_data diff --git a/src/mechanize/errors/base_error.cr b/src/mechanize/errors/base_error.cr index 67be8ce..86ffb19 100644 --- a/src/mechanize/errors/base_error.cr +++ b/src/mechanize/errors/base_error.cr @@ -1,3 +1,5 @@ # Base Error class -class MechanizeCr::Error < RuntimeError +class Mechanize + class Error < RuntimeError + end end diff --git a/src/mechanize/errors/element_not_found_error.cr b/src/mechanize/errors/element_not_found_error.cr index 92ca786..fd35a4a 100644 --- a/src/mechanize/errors/element_not_found_error.cr +++ b/src/mechanize/errors/element_not_found_error.cr @@ -1,6 +1,6 @@ require "./base_error" -class MechanizeCr::ElementNotFoundError < MechanizeCr::Error +class Mechanize::ElementNotFoundError < Mechanize::Error getter element : Symbol getter conditions : String diff --git a/src/mechanize/file.cr b/src/mechanize/file.cr index fd0e6fb..02539b4 100644 --- a/src/mechanize/file.cr +++ b/src/mechanize/file.cr @@ -1,12 +1,14 @@ require "http/client" -class MechanizeCr::File - # property :body, :filename - property :body, :code, uri, :response +class Mechanize + class File + # property :body, :filename + property :body, :code, uri, :response - def initialize(uri : URI, response : ::HTTP::Client::Response, body : String, code : Int32) - @uri = uri - @body = body - @code = code + def initialize(uri : URI, response : ::HTTP::Client::Response, body : String, code : Int32) + @uri = uri + @body = body + @code = code + end end end diff --git a/src/mechanize/form.cr b/src/mechanize/form.cr index 86da5bb..bbd3e8f 100644 --- a/src/mechanize/form.cr +++ b/src/mechanize/form.cr @@ -8,33 +8,33 @@ require "./form/button" require "./form/select_list" require "./utils/element_matcher" -class MechanizeCr::Form - include MechanizeCr::ElementMatcher +class Mechanize::Form + include Mechanize::ElementMatcher getter node : Node | Lexbor::Node - getter fields : Array(FormContent::Field) - getter checkboxes : Array(FormContent::CheckBox) - getter radiobuttons : Array(FormContent::RadioButton) - getter selectboxes : Array(FormContent::MultiSelectList) - getter buttons : Array(FormContent::Button) + getter fields : Array(Mechanize::FormContent::Field) + getter checkboxes : Array(Mechanize::FormContent::CheckBox) + getter radiobuttons : Array(Mechanize::FormContent::RadioButton) + getter selectboxes : Array(Mechanize::FormContent::MultiSelectList) + getter buttons : Array(Mechanize::FormContent::Button) getter enctype : String getter method : String getter name : String - getter page : Page? + getter page : Mechanize::Page? property action : String - def initialize(node : Node | Lexbor::Node, page : Page? = nil) + def initialize(node : Node | Lexbor::Node, page : Mechanize::Page? = nil) @enctype = node.fetch("enctype", "application/x-www-form-urlencoded") @node = node - @fields = Array(FormContent::Field).new - @checkboxes = Array(FormContent::CheckBox).new - @radiobuttons = Array(FormContent::RadioButton).new - @selectboxes = Array(FormContent::MultiSelectList).new - @buttons = Array(FormContent::Button).new + @fields = Array(Mechanize::FormContent::Field).new + @checkboxes = Array(Mechanize::FormContent::CheckBox).new + @radiobuttons = Array(Mechanize::FormContent::RadioButton).new + @selectboxes = Array(Mechanize::FormContent::MultiSelectList).new + @buttons = Array(Mechanize::FormContent::Button).new @action = node.fetch("action", "") @method = node.fetch("method", "GET").upcase @name = node.fetch("name", "") - @clicked_buttons = Array(FormContent::Button).new + @clicked_buttons = Array(Mechanize::FormContent::Button).new @page = page # @mech = mech @@ -68,25 +68,25 @@ class MechanizeCr::Form type = (html_node["type"]? || "text").downcase case type when "checkbox" - checkboxes << FormContent::CheckBox.new(html_node, self) + checkboxes << Mechanize::FormContent::CheckBox.new(html_node, self) when "radio" - radiobuttons << FormContent::RadioButton.new(html_node, self) + radiobuttons << Mechanize::FormContent::RadioButton.new(html_node, self) when "button" - buttons << FormContent::Button.new(html_node, @node) + buttons << Mechanize::FormContent::Button.new(html_node, @node) when "submit" - buttons << FormContent::SubmitButton.new(html_node, @node) + buttons << Mechanize::FormContent::SubmitButton.new(html_node, @node) when "reset" - buttons << FormContent::ResetButton.new(html_node, @node) + buttons << Mechanize::FormContent::ResetButton.new(html_node, @node) when "image" - buttons << FormContent::ImageButton.new(html_node, @node) + buttons << Mechanize::FormContent::ImageButton.new(html_node, @node) when "text" - fields << FormContent::Text.new(html_node) + fields << Mechanize::FormContent::Text.new(html_node) when "hidden" - fields << FormContent::Hidden.new(html_node) + fields << Mechanize::FormContent::Hidden.new(html_node) when "textarea" - fields << FormContent::Textarea.new(html_node) + fields << Mechanize::FormContent::Textarea.new(html_node) else - fields << FormContent::Field.new(html_node) + fields << Mechanize::FormContent::Field.new(html_node) end end @@ -149,7 +149,7 @@ class MechanizeCr::Form # raise Mechanize::Error, # "radiobuttons #{values} are checked in the #{name} group, " \ # "only one is allowed" - raise MechanizeCr::Error.new + raise Mechanize::Error.new else successful_controls << checked.first unless checked.empty? end diff --git a/src/mechanize/form/button.cr b/src/mechanize/form/button.cr index 2b30795..8a610bf 100644 --- a/src/mechanize/form/button.cr +++ b/src/mechanize/form/button.cr @@ -1,4 +1,4 @@ -class MechanizeCr::FormContent::Button < MechanizeCr::FormContent::Field +class Mechanize::FormContent::Button < Mechanize::FormContent::Field getter form_node : Node | Lexbor::Node def initialize(node : Node | Lexbor::Node, form_node : Node | Lexbor::Node, value = nil) diff --git a/src/mechanize/form/check_box.cr b/src/mechanize/form/check_box.cr index 23496bc..e383441 100644 --- a/src/mechanize/form/check_box.cr +++ b/src/mechanize/form/check_box.cr @@ -1,4 +1,4 @@ -class MechanizeCr::FormContent::CheckBox < MechanizeCr::FormContent::RadioButton +class Mechanize::FormContent::CheckBox < Mechanize::FormContent::RadioButton def check @checked = true end diff --git a/src/mechanize/form/field.cr b/src/mechanize/form/field.cr index 7994bae..4eb7c23 100644 --- a/src/mechanize/form/field.cr +++ b/src/mechanize/form/field.cr @@ -1,4 +1,4 @@ -class MechanizeCr::FormContent::Field +class Mechanize::FormContent::Field property value : String? getter name : String getter type : String @@ -29,7 +29,7 @@ class MechanizeCr::FormContent::Field def inspect # :nodoc: "[%s:0x%x type: %s name: %s value: %s]" % [ - self.class.name.sub(/MechanizeCr::FormContent::/, "").downcase, + self.class.name.sub(/Mechanize::FormContent::/, "").downcase, object_id, type, name, value, ] end diff --git a/src/mechanize/form/hidden.cr b/src/mechanize/form/hidden.cr index dffb1da..ca409dd 100644 --- a/src/mechanize/form/hidden.cr +++ b/src/mechanize/form/hidden.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::Hidden < MechanizeCr::FormContent::Field +class Mechanize::FormContent::Hidden < Mechanize::FormContent::Field end diff --git a/src/mechanize/form/image_button.cr b/src/mechanize/form/image_button.cr index 49e2d9f..1cd1d68 100644 --- a/src/mechanize/form/image_button.cr +++ b/src/mechanize/form/image_button.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::ImageButton < MechanizeCr::FormContent::Button +class Mechanize::FormContent::ImageButton < Mechanize::FormContent::Button end diff --git a/src/mechanize/form/multi_select_list.cr b/src/mechanize/form/multi_select_list.cr index 7d27705..f55f518 100644 --- a/src/mechanize/form/multi_select_list.cr +++ b/src/mechanize/form/multi_select_list.cr @@ -1,6 +1,6 @@ require "./option" -class MechanizeCr::FormContent::MultiSelectList +class Mechanize::FormContent::MultiSelectList getter node : Lexbor::Node getter name : String getter type : String @@ -54,7 +54,7 @@ class MechanizeCr::FormContent::MultiSelectList def inspect # :nodoc: "[%s:0x%x type: %s name: %s values: [%s]]" % [ - self.class.name.sub(/MechanizeCr::FormContent::/, "").downcase, + self.class.name.sub(/Mechanize::FormContent::/, "").downcase, object_id, type, name, values.join(','), ] end diff --git a/src/mechanize/form/option.cr b/src/mechanize/form/option.cr index 91d79bf..2079b22 100644 --- a/src/mechanize/form/option.cr +++ b/src/mechanize/form/option.cr @@ -1,4 +1,4 @@ -class MechanizeCr::FormContent::Option +class Mechanize::FormContent::Option getter select_list : FormContent::MultiSelectList getter node : Lexbor::Node getter text : String diff --git a/src/mechanize/form/radio_button.cr b/src/mechanize/form/radio_button.cr index fd4f000..1987d95 100644 --- a/src/mechanize/form/radio_button.cr +++ b/src/mechanize/form/radio_button.cr @@ -1,4 +1,4 @@ -class MechanizeCr::FormContent::RadioButton < MechanizeCr::FormContent::Field +class Mechanize::FormContent::RadioButton < Mechanize::FormContent::Field property :checked, :form def initialize(node : Node | Lexbor::Node, form : Form) diff --git a/src/mechanize/form/reset_button.cr b/src/mechanize/form/reset_button.cr index 3183853..baa3970 100644 --- a/src/mechanize/form/reset_button.cr +++ b/src/mechanize/form/reset_button.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::ResetButton < MechanizeCr::FormContent::Button +class Mechanize::FormContent::ResetButton < Mechanize::FormContent::Button end diff --git a/src/mechanize/form/select_list.cr b/src/mechanize/form/select_list.cr index e00e5fb..b3acde2 100644 --- a/src/mechanize/form/select_list.cr +++ b/src/mechanize/form/select_list.cr @@ -1,6 +1,6 @@ require "./multi_select_list" -class MechanizeCr::FormContent::SelectList < MechanizeCr::FormContent::MultiSelectList +class Mechanize::FormContent::SelectList < Mechanize::FormContent::MultiSelectList def initialize(node) super node # only one selected option is allowed diff --git a/src/mechanize/form/submit_button.cr b/src/mechanize/form/submit_button.cr index 14aaee8..691da00 100644 --- a/src/mechanize/form/submit_button.cr +++ b/src/mechanize/form/submit_button.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::SubmitButton < MechanizeCr::FormContent::Button +class Mechanize::FormContent::SubmitButton < Mechanize::FormContent::Button end diff --git a/src/mechanize/form/text.cr b/src/mechanize/form/text.cr index 6ed9f1f..894dafd 100644 --- a/src/mechanize/form/text.cr +++ b/src/mechanize/form/text.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::Text < MechanizeCr::FormContent::Field +class Mechanize::FormContent::Text < Mechanize::FormContent::Field end diff --git a/src/mechanize/form/textarea.cr b/src/mechanize/form/textarea.cr index 53db27e..b7c825a 100644 --- a/src/mechanize/form/textarea.cr +++ b/src/mechanize/form/textarea.cr @@ -1,2 +1,2 @@ -class MechanizeCr::FormContent::Textarea < MechanizeCr::FormContent::Field +class Mechanize::FormContent::Textarea < Mechanize::FormContent::Field end diff --git a/src/mechanize/history.cr b/src/mechanize/history.cr index 6e1600b..b5d4fd2 100644 --- a/src/mechanize/history.cr +++ b/src/mechanize/history.cr @@ -1,28 +1,30 @@ require "./page" -class MechanizeCr::History - property max_size : Int32 - property array : Array(MechanizeCr::Page) +class Mechanize + class History + property max_size : Int32 + property array : Array(Mechanize::Page) - delegate :size, :empty?, :last, to: array + delegate :size, :empty?, :last, to: array - def initialize(max_size = 100, array = Array(MechanizeCr::Page).new) - @max_size = max_size - @array = array - end - - def push(page, uri = nil) - @array.push(page) - while size > @max_size - @array.shift + def initialize(max_size = 100, array = Array(Mechanize::Page).new) + @max_size = max_size + @array = array end - self - end - def pop - if size == 0 - # TODO: raise error + def push(page, uri = nil) + @array.push(page) + while size > @max_size + @array.shift + end + self + end + + def pop + if size == 0 + # TODO: raise error + end + page = @array.pop end - page = @array.pop end end diff --git a/src/mechanize/http/agent.cr b/src/mechanize/http/agent.cr index d27acdf..41727a8 100644 --- a/src/mechanize/http/agent.cr +++ b/src/mechanize/http/agent.cr @@ -3,16 +3,16 @@ require "http/client" require "../cookie" require "../history" -module MechanizeCr +class Mechanize module HTTP class Agent property :request_headers, :context - property history : MechanizeCr::History + property history : Mechanize::History property user_agent : String property request_cookies : ::HTTP::Cookies def initialize(@context : Mechanize | Nil = nil) - @history = MechanizeCr::History.new + @history = Mechanize::History.new @request_headers = ::HTTP::Headers.new @context = context @request_cookies = ::HTTP::Cookies.new diff --git a/src/mechanize/page.cr b/src/mechanize/page.cr index 9b082bd..9bd1f2a 100644 --- a/src/mechanize/page.cr +++ b/src/mechanize/page.cr @@ -6,50 +6,52 @@ require "./page/link" # If you send request, it returns the instance of Page. # You can get status code, title, and page body, and search html node using css selector. -class MechanizeCr::Page < MechanizeCr::File - include MechanizeCr::ElementMatcher - delegate :css, to: parser +class Mechanize + class Page < Mechanize::File + include Mechanize::ElementMatcher + delegate :css, to: parser - property mech : Mechanize + property mech : Mechanize - def initialize(uri, response, body, code, mech) - @mech = mech - super(uri, response, body, code) - end - - # parser to parse response body. - # TODO: now it's Lexbor::Parser. I want to also support other parsers like JSON. - def parser : Lexbor::Parser - @parser ||= Lexbor::Parser.new(@body) - end - - # return page title. - def title : String - title_node = css("title") - if title_node.empty? - "" - else - title_node.first.inner_text + def initialize(uri, response, body, code, mech) + @mech = mech + super(uri, response, body, code) end - end - # return all forms(`MechanizeCr::Form`) in the page. - def forms : Array(MechanizeCr::Form) - forms = css("form").map do |html_form| - form = Form.new(html_form, self) - form.action ||= @uri.to_s - form - end.to_a - end + # parser to parse response body. + # TODO: now it's Lexbor::Parser. I want to also support other parsers like JSON. + def parser : Lexbor::Parser + @parser ||= Lexbor::Parser.new(@body) + end - # return all links(`MechanizeCr::PageContent::Link) in the page. - def links : Array(MechanizeCr::PageContent::Link) - links = %w{a area}.map do |tag| - css(tag).map do |node| - PageContent::Link.new(node, @mech, self) + # return page title. + def title : String + title_node = css("title") + if title_node.empty? + "" + else + title_node.first.inner_text end - end.flatten - end + end - elements_with "form" + # return all forms(`Mechanize::Form`) in the page. + def forms : Array(Mechanize::Form) + forms = css("form").map do |html_form| + form = Mechanize::Form.new(html_form, self) + form.action ||= @uri.to_s + form + end.to_a + end + + # return all links(`Mechanize::PageContent::Link) in the page. + def links : Array(Mechanize::PageContent::Link) + links = %w{a area}.map do |tag| + css(tag).map do |node| + Mechanize::PageContent::Link.new(node, @mech, self) + end + end.flatten + end + + elements_with "form" + end end diff --git a/src/mechanize/page/link.cr b/src/mechanize/page/link.cr index 048d2ab..1ecab2e 100644 --- a/src/mechanize/page/link.cr +++ b/src/mechanize/page/link.cr @@ -1,6 +1,6 @@ -class MechanizeCr::PageContent::Link +class Mechanize::PageContent::Link getter node : Lexbor::Node - getter page : Page + getter page : Mechanize::Page getter mech : Mechanize getter href : String getter text : String diff --git a/src/mechanize/utils/element_matcher.cr b/src/mechanize/utils/element_matcher.cr index 70c2056..33f3e71 100644 --- a/src/mechanize/utils/element_matcher.cr +++ b/src/mechanize/utils/element_matcher.cr @@ -1,14 +1,15 @@ -module MechanizeCr::ElementMatcher - macro elements_with(singular, plural = "") +class Mechanize + module ElementMatcher + macro elements_with(singular, plural = "") {% plural = "#{singular.id}s" if plural.empty? %} # search {{ singular.id }} which matches condition. - # + # # Examples # ``` # # if you specify String like "foo", it searches form which name is "foo". # # like {
} - # page.form_with("foo") - # + # page.form_with("foo") + # # # you can specify tag's attribute and its' value by NamedTuple or Hash(String, String). # ex)
# page.form_with("class" => "foo") @@ -46,8 +47,9 @@ module MechanizeCr::ElementMatcher def {{singular.id}}_with(criteria) f = {{plural.id}}_with(criteria) # TODO: Write correct error message. - raise ElementNotFoundError.new(:{{singular.id}}, "") if f.empty? + raise Mechanize::ElementNotFoundError.new(:{{singular.id}}, "") if f.empty? f.first end end + end end From 0c0c9110773c1cfbffeca978f2716cc840fb867e Mon Sep 17 00:00:00 2001 From: Anton Maminov Date: Tue, 16 Nov 2021 10:51:44 +0200 Subject: [PATCH 3/3] Update agent.cr --- src/mechanize/http/agent.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mechanize/http/agent.cr b/src/mechanize/http/agent.cr index 41727a8..f546ff9 100644 --- a/src/mechanize/http/agent.cr +++ b/src/mechanize/http/agent.cr @@ -96,7 +96,7 @@ class Mechanize end # Sets a Referer header. - def set_request_referer(referer : MechanizeCr::Page?) + def set_request_referer(referer : Mechanize::Page?) return unless referer request_headers["Referer"] = referer.uri.to_s