akephalos-nerian 0.2.4-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.md +56 -0
  3. data/bin/akephalos +88 -0
  4. data/lib/akephalos.rb +19 -0
  5. data/lib/akephalos/capybara.rb +316 -0
  6. data/lib/akephalos/client.rb +112 -0
  7. data/lib/akephalos/client/cookies.rb +73 -0
  8. data/lib/akephalos/client/filter.rb +120 -0
  9. data/lib/akephalos/configuration.rb +49 -0
  10. data/lib/akephalos/console.rb +32 -0
  11. data/lib/akephalos/cucumber.rb +6 -0
  12. data/lib/akephalos/htmlunit.rb +38 -0
  13. data/lib/akephalos/htmlunit/ext/http_method.rb +30 -0
  14. data/lib/akephalos/node.rb +172 -0
  15. data/lib/akephalos/page.rb +113 -0
  16. data/lib/akephalos/remote_client.rb +84 -0
  17. data/lib/akephalos/server.rb +56 -0
  18. data/lib/akephalos/version.rb +3 -0
  19. data/src/htmlunit/apache-mime4j-0.6.jar +0 -0
  20. data/src/htmlunit/commons-codec-1.4.jar +0 -0
  21. data/src/htmlunit/commons-collections-3.2.1.jar +0 -0
  22. data/src/htmlunit/commons-io-1.4.jar +0 -0
  23. data/src/htmlunit/commons-lang-2.4.jar +0 -0
  24. data/src/htmlunit/commons-logging-1.1.1.jar +0 -0
  25. data/src/htmlunit/cssparser-0.9.5.jar +0 -0
  26. data/src/htmlunit/htmlunit-2.8.jar +0 -0
  27. data/src/htmlunit/htmlunit-core-js-2.8.jar +0 -0
  28. data/src/htmlunit/httpclient-4.0.1.jar +0 -0
  29. data/src/htmlunit/httpcore-4.0.1.jar +0 -0
  30. data/src/htmlunit/httpmime-4.0.1.jar +0 -0
  31. data/src/htmlunit/nekohtml-1.9.14.jar +0 -0
  32. data/src/htmlunit/sac-1.3.jar +0 -0
  33. data/src/htmlunit/serializer-2.7.1.jar +0 -0
  34. data/src/htmlunit/xalan-2.7.1.jar +0 -0
  35. data/src/htmlunit/xercesImpl-2.9.1.jar +0 -0
  36. data/src/htmlunit/xml-apis-1.3.04.jar +0 -0
  37. metadata +150 -0
@@ -0,0 +1,112 @@
1
+ require 'akephalos/configuration'
2
+
3
+ if RUBY_PLATFORM != "java"
4
+ require 'akephalos/remote_client'
5
+ Akephalos::Client = Akephalos::RemoteClient
6
+ else
7
+ require 'akephalos/htmlunit'
8
+ require 'akephalos/htmlunit/ext/http_method'
9
+
10
+ require 'akephalos/page'
11
+ require 'akephalos/node'
12
+
13
+ require 'akephalos/client/cookies'
14
+ require 'akephalos/client/filter'
15
+
16
+ module Akephalos
17
+
18
+ # Akephalos::Client wraps HtmlUnit's WebClient class. It is the main entry
19
+ # point for all interaction with the browser, exposing its current page and
20
+ # allowing navigation.
21
+ class Client
22
+ attr_reader :page
23
+
24
+ def initialize
25
+ @_client = java.util.concurrent.FutureTask.new do
26
+ client = HtmlUnit::WebClient.new
27
+
28
+ Filter.new(client)
29
+ client.setThrowExceptionOnFailingStatusCode(false)
30
+ client.setAjaxController(HtmlUnit::NicelyResynchronizingAjaxController.new)
31
+ client.setCssErrorHandler(HtmlUnit::SilentCssErrorHandler.new)
32
+ client.setThrowExceptionOnScriptError(false);
33
+ client
34
+ end
35
+ Thread.new { @_client.run }
36
+ end
37
+
38
+ # Set the global configuration settings for Akephalos.
39
+ #
40
+ # @note This is only used when communicating over DRb, since just a
41
+ # single client instance is exposed.
42
+ # @param [Hash] config the configuration settings
43
+ # @return [Hash] the configuration
44
+ def configuration=(config)
45
+ Akephalos.configuration = config
46
+ end
47
+
48
+ # Visit the requested URL and return the page.
49
+ #
50
+ # @param [String] url the URL to load
51
+ # @return [Page] the loaded page
52
+ def visit(url)
53
+ client.getPage(url)
54
+ page
55
+ end
56
+
57
+ # @return [Cookies] the cookies for this session
58
+ def cookies
59
+ @cookies ||= Cookies.new(client.getCookieManager)
60
+ end
61
+
62
+ # @return [String] the current user agent string
63
+ def user_agent
64
+ @user_agent || client.getBrowserVersion.getUserAgent
65
+ end
66
+
67
+ # Set the User-Agent header for this session. If :default is given, the
68
+ # User-Agent header will be reset to the default browser's user agent.
69
+ #
70
+ # @param [:default] user_agent the default user agent
71
+ # @param [String] user_agent the user agent string to use
72
+ def user_agent=(user_agent)
73
+ if user_agent == :default
74
+ @user_agent = nil
75
+ client.removeRequestHeader("User-Agent")
76
+ else
77
+ @user_agent = user_agent
78
+ client.addRequestHeader("User-Agent", user_agent)
79
+ end
80
+ end
81
+
82
+ # @return [Page] the current page
83
+ def page
84
+ self.page = client.getCurrentWindow.getTopWindow.getEnclosedPage
85
+ @page
86
+ end
87
+
88
+ # Update the current page.
89
+ #
90
+ # @param [HtmlUnit::HtmlPage] _page the new page
91
+ # @return [Page] the new page
92
+ def page=(_page)
93
+ if @page != _page
94
+ @page = Page.new(_page)
95
+ end
96
+ @page
97
+ end
98
+
99
+ private
100
+
101
+ # Call the future set up in #initialize and return the WebCLient
102
+ # instance.
103
+ #
104
+ # @return [HtmlUnit::WebClient] the WebClient instance
105
+ def client
106
+ @client ||= @_client.get.tap do |client|
107
+ client.getCurrentWindow.getHistory.ignoreNewPages_.set(true)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,73 @@
1
+ module Akephalos
2
+ class Client
3
+ # Interface for working with HtmlUnit's CookieManager, providing a basic
4
+ # API for manipulating the cookies in a session.
5
+ class Cookies
6
+ include Enumerable
7
+
8
+ # @param [HtmlUnit::CookieManager] cookie manager
9
+ def initialize(cookie_manager)
10
+ @cookie_manager = cookie_manager
11
+ end
12
+
13
+ # @param [name] the cookie name
14
+ # @return [Cookie] the cookie with the given name
15
+ # @return [nil] when no cookie is found
16
+ def [](name)
17
+ cookie = @cookie_manager.getCookie(name)
18
+ Cookie.new(cookie) if cookie
19
+ end
20
+
21
+ # Clears all cookies for this session.
22
+ def clear
23
+ @cookie_manager.clearCookies
24
+ end
25
+
26
+ # Iterator for all cookies in the current session.
27
+ def each
28
+ @cookie_manager.getCookies.each do |cookie|
29
+ yield Cookie.new(cookie)
30
+ end
31
+ end
32
+
33
+ # Remove the cookie from the session.
34
+ #
35
+ # @param [Cookie] the cookie to remove
36
+ def delete(cookie)
37
+ @cookie_manager.removeCookie(cookie.native)
38
+ end
39
+
40
+ # @return [true, false] whether there are any cookies
41
+ def empty?
42
+ !any?
43
+ end
44
+
45
+ class Cookie
46
+
47
+ attr_reader :domain, :expires, :name, :path, :value
48
+
49
+ # @param [HtmlUnit::Cookie] the cookie
50
+ def initialize(cookie)
51
+ @_cookie = cookie
52
+ @domain = cookie.getDomain
53
+ @expires = cookie.getExpires
54
+ @name = cookie.getName
55
+ @path = cookie.getPath
56
+ @value = cookie.getValue
57
+ @secure = cookie.isSecure
58
+ end
59
+
60
+ def secure?
61
+ !!@secure
62
+ end
63
+
64
+ # @return [HtmlUnit::Cookie] the native cookie object
65
+ # @api private
66
+ def native
67
+ @_cookie
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,120 @@
1
+ module Akephalos
2
+ class Client
3
+
4
+ # Akephalos::Client::Filter extends HtmlUnit's WebConnectionWrapper to
5
+ # enable filtering outgoing requests generated interally by HtmlUnit.
6
+ #
7
+ # When a request comes through, it will be tested against the filters
8
+ # defined in Akephalos.filters and return a mock response if a match is
9
+ # found. If no filters are defined, or no filters match the request, then
10
+ # the response will bubble up to HtmlUnit for the normal request/response
11
+ # cycle.
12
+ class Filter < HtmlUnit::Util::WebConnectionWrapper
13
+ # Filters an outgoing request, and if a match is found, returns the mock
14
+ # response.
15
+ #
16
+ # @param [WebRequest] request the pending HTTP request
17
+ # @return [WebResponseImpl] when the request matches a defined filter
18
+ # @return [nil] when no filters match the request
19
+ def filter(request)
20
+ if filter = find_filter(request)
21
+ start_time = Time.now
22
+ headers = filter[:headers].map do |name, value|
23
+ HtmlUnit::Util::NameValuePair.new(name.to_s, value.to_s)
24
+ end
25
+ response = HtmlUnit::WebResponseData.new(
26
+ filter[:body].to_s.to_java_bytes,
27
+ filter[:status],
28
+ HTTP_STATUS_CODES.fetch(filter[:status], "Unknown"),
29
+ headers
30
+ )
31
+ HtmlUnit::WebResponseImpl.new(response, request, Time.now - start_time)
32
+ end
33
+ end
34
+
35
+ # Searches for a filter which matches the request's HTTP method and url.
36
+ #
37
+ # @param [WebRequest] request the pending HTTP request
38
+ # @return [Hash] when a filter matches the request
39
+ # @return [nil] when no filters match the request
40
+ def find_filter(request)
41
+ Akephalos.filters.find do |filter|
42
+ request.http_method === filter[:method] && request.url.to_s =~ filter[:filter]
43
+ end
44
+ end
45
+
46
+ # This method is called by WebClient when a page is requested, and will
47
+ # return a mock response if the request matches a defined filter or else
48
+ # return the actual response.
49
+ #
50
+ # @api htmlunit
51
+ # @param [WebRequest] request the pending HTTP request
52
+ # @return [WebResponseImpl]
53
+ def getResponse(request)
54
+ filter(request) || super
55
+ end
56
+
57
+ # Map of status codes to their English descriptions.
58
+ HTTP_STATUS_CODES = {
59
+ 100 => "Continue",
60
+ 101 => "Switching Protocols",
61
+ 102 => "Processing",
62
+ 200 => "OK",
63
+ 201 => "Created",
64
+ 202 => "Accepted",
65
+ 203 => "Non-Authoritative Information",
66
+ 204 => "No Content",
67
+ 205 => "Reset Content",
68
+ 206 => "Partial Content",
69
+ 207 => "Multi-Status",
70
+ 300 => "Multiple Choices",
71
+ 301 => "Moved Permanently",
72
+ 302 => "Found",
73
+ 303 => "See Other",
74
+ 304 => "Not Modified",
75
+ 305 => "Use Proxy",
76
+ 306 => "Switch Proxy",
77
+ 307 => "Temporary Redirect",
78
+ 400 => "Bad Request",
79
+ 401 => "Unauthorized",
80
+ 402 => "Payment Required",
81
+ 403 => "Forbidden",
82
+ 404 => "Not Found",
83
+ 405 => "Method Not Allowed",
84
+ 406 => "Not Acceptable",
85
+ 407 => "Proxy Authentication Required",
86
+ 408 => "Request Timeout",
87
+ 409 => "Conflict",
88
+ 410 => "Gone",
89
+ 411 => "Length Required",
90
+ 412 => "Precondition Failed",
91
+ 413 => "Request Entity Too Large",
92
+ 414 => "Request-URI Too Long",
93
+ 415 => "Unsupported Media Type",
94
+ 416 => "Requested Range Not Satisfiable",
95
+ 417 => "Expectation Failed",
96
+ 418 => "I'm a teapot",
97
+ 421 => "There are too many connections from your internet address",
98
+ 422 => "Unprocessable Entity",
99
+ 423 => "Locked",
100
+ 424 => "Failed Dependency",
101
+ 425 => "Unordered Collection",
102
+ 426 => "Upgrade Required",
103
+ 449 => "Retry With",
104
+ 450 => "Blocked by Windows Parental Controls",
105
+ 500 => "Internal Server Error",
106
+ 501 => "Not Implemented",
107
+ 502 => "Bad Gateway",
108
+ 503 => "Service Unavailable",
109
+ 504 => "Gateway Timeout",
110
+ 505 => "HTTP Version Not Supported",
111
+ 506 => "Variant Also Negotiates",
112
+ 507 => "Insufficient Storage",
113
+ 509 => "Bandwidth Limit Exceeded",
114
+ 510 => "Not Extended",
115
+ 530 => "User access denied"
116
+ }.freeze
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,49 @@
1
+ module Akephalos
2
+
3
+ @configuration = {}
4
+
5
+ class << self
6
+ # @return [Hash] the configuration
7
+ attr_accessor :configuration
8
+ end
9
+
10
+ module Filters
11
+ # @return [Array] all defined filters
12
+ def filters
13
+ configuration[:filters] ||= []
14
+ end
15
+
16
+ # Defines a new filter to be tested by Akephalos::Filter when executing
17
+ # page requests. An HTTP method and a regex or string to match against the
18
+ # URL are required for defining a filter.
19
+ #
20
+ # You can additionally pass the following options to define how the
21
+ # filtered request should respond:
22
+ #
23
+ # :status (defaults to 200)
24
+ # :body (defaults to "")
25
+ # :headers (defaults to {})
26
+ #
27
+ # If we define a filter with no additional options, then, we will get an
28
+ # empty HTML response:
29
+ #
30
+ # Akephalos.filter :post, "http://example.com"
31
+ # Akephalos.filter :any, %r{http://.*\.com}
32
+ #
33
+ # If you instead, say, wanted to simulate a failure in an external system,
34
+ # you could do this:
35
+ #
36
+ # Akephalos.filter :post, "http://example.com",
37
+ # :status => 500, :body => "Something went wrong"
38
+ #
39
+ # @param [Symbol] method the HTTP method to match
40
+ # @param [RegExp, String] regex URL matcher
41
+ # @param [Hash] options response values
42
+ def filter(method, regex, options = {})
43
+ regex = Regexp.new(Regexp.escape(regex)) if regex.is_a?(String)
44
+ filters << {:method => method, :filter => regex, :status => 200, :body => "", :headers => {}}.merge!(options)
45
+ end
46
+ end
47
+
48
+ extend Filters
49
+ end
@@ -0,0 +1,32 @@
1
+ # Begin a new Capybara session, by default connecting to localhost on port
2
+ # 3000.
3
+ def session
4
+ Capybara.app_host ||= "http://localhost:3000"
5
+ @session ||= Capybara::Session.new(:Akephalos)
6
+ end
7
+ alias page session
8
+
9
+ module Akephalos
10
+ # Simple class for starting an IRB session.
11
+ class Console
12
+
13
+ # Start an IRB session. Tries to load irb/completion, and also loads a
14
+ # .irbrc file if it exists.
15
+ def self.start
16
+ require 'irb'
17
+
18
+ begin
19
+ require 'irb/completion'
20
+ rescue Exception
21
+ # No readline available, proceed anyway.
22
+ end
23
+
24
+ if ::File.exists? ".irbrc"
25
+ ENV['IRBRC'] = ".irbrc"
26
+ end
27
+
28
+ IRB.start
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,6 @@
1
+ require 'capybara/cucumber'
2
+
3
+ Before('@akephalos') do
4
+ Capybara.current_driver = :akephalos
5
+ end
6
+
@@ -0,0 +1,38 @@
1
+ require "pathname"
2
+ require "java"
3
+
4
+ dependency_directory = $:.detect { |path| Dir[File.join(path, 'htmlunit/htmlunit-*.jar')].any? }
5
+
6
+ raise "Could not find htmlunit/htmlunit-VERSION.jar in load path:\n [ #{$:.join(",\n ")}\n ]" unless dependency_directory
7
+
8
+ Dir[File.join(dependency_directory, "htmlunit/*.jar")].each do |jar|
9
+ require jar
10
+ end
11
+
12
+ java.lang.System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog")
13
+ java.lang.System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "fatal")
14
+ java.lang.System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true")
15
+
16
+ # Container module for com.gargoylesoftware.htmlunit namespace.
17
+ module HtmlUnit
18
+ java_import "com.gargoylesoftware.htmlunit.BrowserVersion"
19
+ java_import "com.gargoylesoftware.htmlunit.History"
20
+ java_import "com.gargoylesoftware.htmlunit.HttpMethod"
21
+ java_import "com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController"
22
+ java_import "com.gargoylesoftware.htmlunit.SilentCssErrorHandler"
23
+ java_import "com.gargoylesoftware.htmlunit.WebClient"
24
+ java_import "com.gargoylesoftware.htmlunit.WebResponseData"
25
+ java_import "com.gargoylesoftware.htmlunit.WebResponseImpl"
26
+
27
+ # Container module for com.gargoylesoftware.htmlunit.util namespace.
28
+ module Util
29
+ java_import "com.gargoylesoftware.htmlunit.util.NameValuePair"
30
+ java_import "com.gargoylesoftware.htmlunit.util.WebConnectionWrapper"
31
+ end
32
+
33
+ # Disable history tracking
34
+ History.field_reader :ignoreNewPages_
35
+
36
+ # Run in Firefox compatibility mode
37
+ BrowserVersion.setDefault(BrowserVersion::FIREFOX_3)
38
+ end
@@ -0,0 +1,30 @@
1
+ module HtmlUnit
2
+ # Reopen HtmlUnit's HttpMethod class to add convenience methods.
3
+ class HttpMethod
4
+
5
+ # Loosely compare HttpMethod with another object, accepting either an
6
+ # HttpMethod instance or a symbol describing the method. Note that :any is a
7
+ # special symbol which will always return true.
8
+ #
9
+ # @param [HttpMethod] other an HtmlUnit HttpMethod object
10
+ # @param [Symbol] other a symbolized representation of an http method
11
+ # @return [true/false]
12
+ def ===(other)
13
+ case other
14
+ when HttpMethod
15
+ super
16
+ when :any
17
+ true
18
+ when :get
19
+ self == self.class::GET
20
+ when :post
21
+ self == self.class::POST
22
+ when :put
23
+ self == self.class::PUT
24
+ when :delete
25
+ self == self.class::DELETE
26
+ end
27
+ end
28
+
29
+ end
30
+ end