kookaburra 0.21.1 → 0.22.0
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.
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -2
- data/README.markdown +19 -19
- data/VERSION +1 -1
- data/kookaburra.gemspec +7 -7
- data/lib/kookaburra/api_driver.rb +5 -8
- data/lib/kookaburra/assertion.rb +24 -0
- data/lib/kookaburra/configuration.rb +70 -0
- data/lib/kookaburra/dependency_accessor.rb +4 -1
- data/lib/kookaburra/given_driver.rb +13 -26
- data/lib/kookaburra/json_api_driver.rb +5 -4
- data/lib/kookaburra/test_helpers.rb +18 -17
- data/lib/kookaburra/ui_driver/ui_component/address_bar.rb +23 -0
- data/lib/kookaburra/ui_driver/ui_component.rb +19 -63
- data/lib/kookaburra/ui_driver.rb +17 -21
- data/lib/kookaburra.rb +29 -50
- data/spec/integration/test_a_rack_application_spec.rb +34 -30
- data/spec/kookaburra/api_driver_spec.rb +6 -4
- data/spec/kookaburra/configuration_spec.rb +18 -0
- data/spec/kookaburra/json_api_driver_spec.rb +12 -8
- data/spec/kookaburra/ui_driver/ui_component/address_bar_spec.rb +32 -0
- data/spec/kookaburra/ui_driver/ui_component_spec.rb +30 -64
- data/spec/kookaburra/ui_driver_spec.rb +7 -12
- data/spec/kookaburra_spec.rb +33 -29
- data/spec/support/shared_examples/it_can_make_assertions.rb +12 -0
- data/spec/support/shared_examples/it_has_a_dependency_accessor.rb +6 -9
- metadata +30 -41
- data/lib/kookaburra/null_browser.rb +0 -15
- data/spec/kookaburra/null_browser_spec.rb +0 -15
- data/spec/kookaburra/test_helpers_spec.rb +0 -48
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -4,7 +4,6 @@ GEM
|
|
4
4
|
activesupport (3.2.2)
|
5
5
|
i18n (~> 0.6)
|
6
6
|
multi_json (~> 1.0)
|
7
|
-
basic_object (0.0.1)
|
8
7
|
capybara (1.1.2)
|
9
8
|
mime-types (>= 1.16)
|
10
9
|
nokogiri (>= 1.3.3)
|
@@ -76,7 +75,6 @@ PLATFORMS
|
|
76
75
|
|
77
76
|
DEPENDENCIES
|
78
77
|
activesupport (>= 3.0)
|
79
|
-
basic_object
|
80
78
|
capybara
|
81
79
|
i18n
|
82
80
|
jeweler
|
data/README.markdown
CHANGED
@@ -52,17 +52,17 @@ For [RSpec] [RSpec] integration tests, just add the following to
|
|
52
52
|
require 'my_app/kookaburra/given_driver'
|
53
53
|
require 'my_app/kookaburra/ui_driver'
|
54
54
|
|
55
|
-
#
|
55
|
+
# c.app_host below should be set to whatever the root URL of your running
|
56
56
|
# application is.
|
57
|
-
Kookaburra.
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
Kookaburra.configure do |c|
|
58
|
+
c.given_driver_class = MyApp::Kookaburra::GivenDriver
|
59
|
+
c.ui_driver_class = MyApp::Kookaburra::UIDriver
|
60
|
+
c.app_host = 'http://my_app.example.com:1234'
|
61
|
+
c.browser = Capybara
|
62
|
+
c.server_error_detection { |browser|
|
63
63
|
browser.has_css?('head title', :text => 'Internal Server Error')
|
64
64
|
}
|
65
|
-
|
65
|
+
end
|
66
66
|
|
67
67
|
RSpec.configure do |c|
|
68
68
|
c.include(Kookaburra::TestHelpers, :type => :request)
|
@@ -76,17 +76,17 @@ For [Cucumber] [Cucumber], add the following to `features/support/kookaburra_set
|
|
76
76
|
require 'my_app/kookaburra/given_driver'
|
77
77
|
require 'my_app/kookaburra/ui_driver'
|
78
78
|
|
79
|
-
#
|
79
|
+
# c.app_host below should be set to whatever the root URL of your running
|
80
80
|
# application is.
|
81
|
-
Kookaburra.
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
Kookaburra.configure do |c|
|
82
|
+
c.given_driver_class = MyApp::Kookaburra::GivenDriver
|
83
|
+
c.ui_driver_class = MyApp::Kookaburra::UIDriver
|
84
|
+
c.app_host = 'http://my_app.example.com:1234'
|
85
|
+
c.browser = Capybara
|
86
|
+
c.server_error_detection { |browser|
|
87
87
|
browser.has_css?('head title', :text => 'Internal Server Error')
|
88
88
|
}
|
89
|
-
|
89
|
+
end
|
90
90
|
|
91
91
|
World(Kookaburra::TestHelpers)
|
92
92
|
|
@@ -326,7 +326,7 @@ for your application:
|
|
326
326
|
class MyApp::Kookaburra::GivenDriver < Kookaburra::GivenDriver
|
327
327
|
# Specify the APIDriver to use
|
328
328
|
def api
|
329
|
-
@api ||= MyApp::Kookaburra::APIDriver.new(
|
329
|
+
@api ||= MyApp::Kookaburra::APIDriver.new(configuration)
|
330
330
|
end
|
331
331
|
|
332
332
|
def existing_account(nickname)
|
@@ -394,8 +394,8 @@ within your subclass:
|
|
394
394
|
ui_component :sign_in_screen, SignInScreen
|
395
395
|
|
396
396
|
def sign_in(account_nickname)
|
397
|
-
account =
|
398
|
-
sign_in_screen
|
397
|
+
account = mental_model.accounts[account_nickname]
|
398
|
+
address_bar.go_to(sign_in_screen)
|
399
399
|
sign_in_screen.submit_login(account['username'], account['password'])
|
400
400
|
end
|
401
401
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.22.0
|
data/kookaburra.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "kookaburra"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.22.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["John Wilger", "Sam Livingston-Gray", "Ravi Gadad"]
|
@@ -30,24 +30,27 @@ Gem::Specification.new do |s|
|
|
30
30
|
"kookaburra.gemspec",
|
31
31
|
"lib/kookaburra.rb",
|
32
32
|
"lib/kookaburra/api_driver.rb",
|
33
|
+
"lib/kookaburra/assertion.rb",
|
34
|
+
"lib/kookaburra/configuration.rb",
|
33
35
|
"lib/kookaburra/dependency_accessor.rb",
|
34
36
|
"lib/kookaburra/exceptions.rb",
|
35
37
|
"lib/kookaburra/given_driver.rb",
|
36
38
|
"lib/kookaburra/json_api_driver.rb",
|
37
39
|
"lib/kookaburra/mental_model.rb",
|
38
|
-
"lib/kookaburra/null_browser.rb",
|
39
40
|
"lib/kookaburra/test_helpers.rb",
|
40
41
|
"lib/kookaburra/ui_driver.rb",
|
41
42
|
"lib/kookaburra/ui_driver/ui_component.rb",
|
43
|
+
"lib/kookaburra/ui_driver/ui_component/address_bar.rb",
|
42
44
|
"spec/integration/test_a_rack_application_spec.rb",
|
43
45
|
"spec/kookaburra/api_driver_spec.rb",
|
46
|
+
"spec/kookaburra/configuration_spec.rb",
|
44
47
|
"spec/kookaburra/json_api_driver_spec.rb",
|
45
48
|
"spec/kookaburra/mental_model_spec.rb",
|
46
|
-
"spec/kookaburra/
|
47
|
-
"spec/kookaburra/test_helpers_spec.rb",
|
49
|
+
"spec/kookaburra/ui_driver/ui_component/address_bar_spec.rb",
|
48
50
|
"spec/kookaburra/ui_driver/ui_component_spec.rb",
|
49
51
|
"spec/kookaburra/ui_driver_spec.rb",
|
50
52
|
"spec/kookaburra_spec.rb",
|
53
|
+
"spec/support/shared_examples/it_can_make_assertions.rb",
|
51
54
|
"spec/support/shared_examples/it_has_a_dependency_accessor.rb"
|
52
55
|
]
|
53
56
|
s.homepage = "http://github.com/projectdx/kookaburra"
|
@@ -60,7 +63,6 @@ Gem::Specification.new do |s|
|
|
60
63
|
s.specification_version = 3
|
61
64
|
|
62
65
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
63
|
-
s.add_runtime_dependency(%q<basic_object>, [">= 0"])
|
64
66
|
s.add_runtime_dependency(%q<i18n>, [">= 0"])
|
65
67
|
s.add_runtime_dependency(%q<activesupport>, [">= 3.0"])
|
66
68
|
s.add_runtime_dependency(%q<patron>, [">= 0"])
|
@@ -73,7 +75,6 @@ Gem::Specification.new do |s|
|
|
73
75
|
s.add_development_dependency(%q<reek>, [">= 0"])
|
74
76
|
s.add_development_dependency(%q<sinatra>, [">= 0"])
|
75
77
|
else
|
76
|
-
s.add_dependency(%q<basic_object>, [">= 0"])
|
77
78
|
s.add_dependency(%q<i18n>, [">= 0"])
|
78
79
|
s.add_dependency(%q<activesupport>, [">= 3.0"])
|
79
80
|
s.add_dependency(%q<patron>, [">= 0"])
|
@@ -87,7 +88,6 @@ Gem::Specification.new do |s|
|
|
87
88
|
s.add_dependency(%q<sinatra>, [">= 0"])
|
88
89
|
end
|
89
90
|
else
|
90
|
-
s.add_dependency(%q<basic_object>, [">= 0"])
|
91
91
|
s.add_dependency(%q<i18n>, [">= 0"])
|
92
92
|
s.add_dependency(%q<activesupport>, [">= 3.0"])
|
93
93
|
s.add_dependency(%q<patron>, [">= 0"])
|
@@ -4,17 +4,14 @@ require 'patron'
|
|
4
4
|
|
5
5
|
class Kookaburra
|
6
6
|
class APIDriver < SimpleDelegator
|
7
|
-
# Wraps
|
7
|
+
# Wraps `http_client` in a `SimpleDelegator` that causes request methods to
|
8
8
|
# either return the response body or raise an exception on an unexpected
|
9
9
|
# response status code.
|
10
10
|
#
|
11
|
-
# @
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
def initialize(options = {})
|
16
|
-
http_client = options[:http_client] || Patron::Session.new
|
17
|
-
http_client.base_url = options[:app_host] if options.has_key?(:app_host)
|
11
|
+
# @param [Kookaburra::Configuration] configuration
|
12
|
+
# @param [Patron::Session] http_client
|
13
|
+
def initialize(configuration, http_client = Patron::Session.new)
|
14
|
+
http_client.base_url = configuration.app_host
|
18
15
|
super(http_client)
|
19
16
|
end
|
20
17
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'kookaburra/exceptions'
|
2
|
+
|
3
|
+
class Kookaburra
|
4
|
+
# Include this module wherever you need to be able to make a quick,
|
5
|
+
# low-ceremony assertion.
|
6
|
+
module Assertion
|
7
|
+
protected
|
8
|
+
|
9
|
+
# Provides a mechanism to make assertions about the state of your
|
10
|
+
# UIComponent without relying on a specific testing framework. A good
|
11
|
+
# reason to use this would be to provide a more informative error message
|
12
|
+
# when a pre-condition is not met, rather than waiting on an operation
|
13
|
+
# further down the line to fail.
|
14
|
+
#
|
15
|
+
# @param [boolean expression] test an expression that will be evaluated in a boolean context
|
16
|
+
# @param [String] message the exception message that will be used if
|
17
|
+
# test is false
|
18
|
+
#
|
19
|
+
# @raise [Kookaburra::AssertionFailed] raised if test evaluates to false
|
20
|
+
def assert(test, message = "You might want to provide a better message, eh?")
|
21
|
+
test or raise AssertionFailed, message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'delegate'
|
3
|
+
require 'kookaburra/dependency_accessor'
|
4
|
+
|
5
|
+
class Kookaburra
|
6
|
+
# Provides access to the configuration data used throughout Kookaburra
|
7
|
+
class Configuration
|
8
|
+
extend DependencyAccessor
|
9
|
+
|
10
|
+
# The class to use as your GivenDriver
|
11
|
+
#
|
12
|
+
# @attribute [rw] given_driver_class
|
13
|
+
# @raise [Kookaburra::ConfigurationError] if you try to read this attribute
|
14
|
+
# without it having been set
|
15
|
+
dependency_accessor :given_driver_class
|
16
|
+
|
17
|
+
# The class to use as your UIDriver
|
18
|
+
#
|
19
|
+
# @attribute [rw] ui_driver_class
|
20
|
+
# @raise [Kookaburra::ConfigurationError] if you try to read this attribute
|
21
|
+
# without it having been set
|
22
|
+
dependency_accessor :ui_driver_class
|
23
|
+
|
24
|
+
# This object is used by {Kookaburra::UIDriver::UIComponent} to interface
|
25
|
+
# with the web browser. Typically it should be an instance of
|
26
|
+
# `Capybara::Session`
|
27
|
+
#
|
28
|
+
# @attribute [rw] browser
|
29
|
+
# @raise [Kookaburra::ConfigurationError] if you try to read this attribute
|
30
|
+
# without it having been set
|
31
|
+
dependency_accessor :browser
|
32
|
+
|
33
|
+
# This is the root URL of your running application, including the port
|
34
|
+
# number if necessary. (e.g. "http://my.example.com:12345")
|
35
|
+
#
|
36
|
+
# @attribute [rw] app_host
|
37
|
+
# @raise [Kookaburra::ConfigurationError] if you try to read this attribute
|
38
|
+
# without it having been set
|
39
|
+
dependency_accessor :app_host
|
40
|
+
|
41
|
+
# This is the {Kookaburra::MentalModel} that is shared between your
|
42
|
+
# GivenDriver and your UIDriver. This attribute is managed by {Kookaburra},
|
43
|
+
# so you shouldn't need to change it yourself.
|
44
|
+
#
|
45
|
+
# @attribute [rw] mental_model
|
46
|
+
# @raise [Kookaburra::ConfigurationError] if you try to read this attribute
|
47
|
+
# without it having been set
|
48
|
+
dependency_accessor :mental_model
|
49
|
+
|
50
|
+
# Specify a function that can be used to determine if a server error has
|
51
|
+
# occured within your application.
|
52
|
+
#
|
53
|
+
# If the function returns `true`, then Kookaburra will assume that the
|
54
|
+
# application has responded with an error.
|
55
|
+
#
|
56
|
+
# @yield whichever object was assigned to {#browser}
|
57
|
+
#
|
58
|
+
# @example If the page title is "Internal Server Error"
|
59
|
+
# config.server_error_detection { |browser|
|
60
|
+
# browser.has_css?('head title', :text => 'Internal Server Error')
|
61
|
+
# }
|
62
|
+
def server_error_detection(&blk)
|
63
|
+
if block_given?
|
64
|
+
@server_error_detection = blk
|
65
|
+
else
|
66
|
+
@server_error_detection
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -18,7 +18,10 @@ class Kookaburra
|
|
18
18
|
instance_variable_get("@#{name}") or raise "No %s object was set on %s initialization." \
|
19
19
|
% [name, [self.class.name, 'an Anonymous Class!!!'].reject(&:blank?).first]
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
|
+
define_method("#{name}=") do |value|
|
23
|
+
instance_variable_set("@#{name}", value)
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
2
|
|
3
3
|
class Kookaburra
|
4
4
|
# Your GivenDriver subclass is used to define your testing DSL for setting up
|
@@ -7,15 +7,14 @@ class Kookaburra
|
|
7
7
|
# comprised of several distinct API calls as well as access to Kookaburra's
|
8
8
|
# test data store.
|
9
9
|
#
|
10
|
-
# @abstract Subclass and implement your Given DSL.
|
11
|
-
# implementation of #api that returns an instance of your APIDriver.
|
10
|
+
# @abstract Subclass and implement your Given DSL.
|
12
11
|
#
|
13
12
|
# @example GivenDriver subclass
|
14
13
|
# module MyApp
|
15
14
|
# module Kookaburra
|
16
15
|
# class GivenDriver < ::Kookaburra::GivenDriver
|
17
16
|
# def api
|
18
|
-
# @api ||= APIDriver.new(
|
17
|
+
# @api ||= APIDriver.new(configuration)
|
19
18
|
# end
|
20
19
|
#
|
21
20
|
# def a_widget(name, attributes = {})
|
@@ -34,22 +33,23 @@ class Kookaburra
|
|
34
33
|
# end
|
35
34
|
# end
|
36
35
|
class GivenDriver
|
37
|
-
extend DependencyAccessor
|
38
|
-
|
39
36
|
# It is unlikely that you would call #initialize yourself; your GivenDriver
|
40
37
|
# object is instantiated for you by {Kookaburra#given}.
|
41
38
|
#
|
42
|
-
# @
|
43
|
-
|
44
|
-
|
45
|
-
# application (e.g. "http://my_app.example.com:12345")
|
46
|
-
def initialize(options = {})
|
47
|
-
@initialization_options = options
|
48
|
-
@mental_model = options[:mental_model]
|
39
|
+
# @param [Kookaburra::Configuration] configuration
|
40
|
+
def initialize(configuration)
|
41
|
+
@configuration = configuration
|
49
42
|
end
|
50
43
|
|
51
44
|
protected
|
52
45
|
|
46
|
+
attr_reader :configuration
|
47
|
+
|
48
|
+
# Access to the shared {Kookaburra::MentalModel} instance
|
49
|
+
#
|
50
|
+
# @attribute [rw] mental_model
|
51
|
+
delegate :mental_model, :to => :configuration
|
52
|
+
|
53
53
|
# Used to access your APIDriver in your own GivenDriver implementation
|
54
54
|
#
|
55
55
|
# @abstract
|
@@ -59,18 +59,5 @@ class Kookaburra
|
|
59
59
|
def api
|
60
60
|
raise ConfigurationError, "You must implement #api in your subclass."
|
61
61
|
end
|
62
|
-
|
63
|
-
# The full set of options passed in to {#initialize}
|
64
|
-
#
|
65
|
-
# Access is provided so that you can use these when instantiating your
|
66
|
-
# {APIDriver} in your {#api} implementation.
|
67
|
-
attr_reader :initialization_options
|
68
|
-
|
69
|
-
# A reference to the {Kookaburra::MentalModel} object that this GivenDriver
|
70
|
-
# instance was created with.
|
71
|
-
#
|
72
|
-
# @attribute [r]
|
73
|
-
# @return [Kookaburra::MentalModel]
|
74
|
-
dependency_accessor :mental_model
|
75
62
|
end
|
76
63
|
end
|
@@ -14,11 +14,12 @@ class Kookaburra
|
|
14
14
|
#
|
15
15
|
# Sets both the "Content-Type" and "Accept" headers to "application/json".
|
16
16
|
#
|
17
|
-
# @
|
17
|
+
# @param [Kookaburra::Configuration] configuration
|
18
|
+
# @param [Kookaburra::APIDriver] api_driver (Kookaburra::APIDriver.new)
|
18
19
|
# The APIDriver instance to be delegated to. Changing this is probably
|
19
|
-
# only useful for testing.
|
20
|
-
def initialize(
|
21
|
-
api_driver =
|
20
|
+
# only useful for testing Kookaburra itself.
|
21
|
+
def initialize(configuration, api_driver = nil)
|
22
|
+
api_driver = api_driver || APIDriver.new(configuration)
|
22
23
|
api_driver.headers.merge!(
|
23
24
|
'Content-Type' => 'application/json',
|
24
25
|
'Accept' => 'application/json'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'kookaburra'
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
2
3
|
|
3
4
|
class Kookaburra
|
4
5
|
# This module is intended to be mixed in to your testing context to provide
|
@@ -12,15 +13,15 @@ class Kookaburra
|
|
12
13
|
# require 'my_app/kookaburra/given_driver'
|
13
14
|
# require 'my_app/kookaburra/ui_driver'
|
14
15
|
#
|
15
|
-
# Kookaburra.
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
# browser.has_css?('h1', text: '
|
16
|
+
# Kookaburra.configure do |c|
|
17
|
+
# c.given_driver_class = myapp::kookaburra::givendriver,
|
18
|
+
# c.ui_driver_class = myapp::kookaburra::uidriver,
|
19
|
+
# c.app_host = 'http://my_app.example.com:12345',
|
20
|
+
# c.browser = capybara,
|
21
|
+
# c.server_error_detection { |browser|
|
22
|
+
# browser.has_css?('h1', text: 'internal server error')
|
22
23
|
# }
|
23
|
-
#
|
24
|
+
# end
|
24
25
|
#
|
25
26
|
# RSpec.configure do |c|
|
26
27
|
# c.include(Kookaburra::TestHelpers, :type => :request)
|
@@ -49,15 +50,15 @@ class Kookaburra
|
|
49
50
|
# require 'my_app/kookaburra/given_driver'
|
50
51
|
# require 'my_app/kookaburra/ui_driver'
|
51
52
|
#
|
52
|
-
# Kookaburra.
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
# browser.has_css?('h1', text: '
|
53
|
+
# Kookaburra.configure do |c|
|
54
|
+
# c.given_driver_class = myapp::kookaburra::givendriver,
|
55
|
+
# c.ui_driver_class = myapp::kookaburra::uidriver,
|
56
|
+
# c.app_host = 'http://my_app.example.com:12345',
|
57
|
+
# c.browser = capybara,
|
58
|
+
# c.server_error_detection { |browser|
|
59
|
+
# browser.has_css?('h1', text: 'internal server error')
|
59
60
|
# }
|
60
|
-
#
|
61
|
+
# end
|
61
62
|
#
|
62
63
|
# World(Kookaburra::TestHelpers)
|
63
64
|
#
|
@@ -85,7 +86,7 @@ class Kookaburra
|
|
85
86
|
#
|
86
87
|
# @return [Kookaburra]
|
87
88
|
def k
|
88
|
-
@k ||= Kookaburra.new
|
89
|
+
@k ||= Kookaburra.new
|
89
90
|
end
|
90
91
|
|
91
92
|
# @method given
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'kookaburra/ui_driver/ui_component'
|
2
|
+
|
3
|
+
class Kookaburra
|
4
|
+
class UIDriver
|
5
|
+
class UIComponent
|
6
|
+
# This represents the browser's address bar, so that you can tell your
|
7
|
+
# tests to explicitly visit a URL.
|
8
|
+
class AddressBar < UIComponent
|
9
|
+
# Causes the browser to explicitly navigate to the given url.
|
10
|
+
#
|
11
|
+
# @param [String, #url] addressable Can be either a URL string or an
|
12
|
+
# object that responds to #url and returns a URL string
|
13
|
+
def go_to(addressable)
|
14
|
+
if addressable.respond_to?(:url)
|
15
|
+
browser.visit(addressable.url)
|
16
|
+
else
|
17
|
+
browser.visit(addressable.to_s)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'kookaburra/exceptions'
|
2
|
+
require 'kookaburra/assertion'
|
2
3
|
require 'active_support/core_ext/object/try'
|
3
4
|
|
4
5
|
class Kookaburra
|
@@ -63,26 +64,21 @@ class Kookaburra
|
|
63
64
|
# element.
|
64
65
|
#
|
65
66
|
# @abstract Subclass and implement (at least) {#component_locator}. Unless
|
66
|
-
# you override the default implementation of {#
|
67
|
+
# you override the default implementation of {#url}, you must also
|
67
68
|
# override the {#component_path} method.
|
68
69
|
class UIComponent
|
70
|
+
include Assertion
|
71
|
+
|
69
72
|
# New UIComponent instances are typically created for you by your
|
70
73
|
# {Kookaburra::UIDriver} instance.
|
71
74
|
#
|
72
75
|
# @see Kookaburra::UIDriver.ui_component
|
73
76
|
#
|
74
|
-
# @
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# the object passed in to the :browser option as an argument and must
|
80
|
-
# return `true` if the server responded with an unexpected error or
|
81
|
-
# `false` if it did not.
|
82
|
-
def initialize(options = {})
|
83
|
-
@browser = options[:browser]
|
84
|
-
@app_host = options[:app_host]
|
85
|
-
@server_error_detection = options[:server_error_detection]
|
77
|
+
# @param [Kookaburra::Configuration] configuration
|
78
|
+
def initialize(configuration)
|
79
|
+
@browser = configuration.browser
|
80
|
+
@app_host = configuration.app_host
|
81
|
+
@server_error_detection = configuration.server_error_detection
|
86
82
|
end
|
87
83
|
|
88
84
|
# If the UIComponent is sent a message it does not understand, it will
|
@@ -107,27 +103,6 @@ class Kookaburra
|
|
107
103
|
super || browser.respond_to?(name)
|
108
104
|
end
|
109
105
|
|
110
|
-
# Causes the UIComponent to be visible.
|
111
|
-
#
|
112
|
-
# The browser to navigates directly to {#component_path} (unless the
|
113
|
-
# component is already visible).
|
114
|
-
#
|
115
|
-
# You may need to override this method in your own UIComponent subclasses,
|
116
|
-
# especially for components that are dynamically added/removed on the page
|
117
|
-
# in response to user actions. The implementation should not make any
|
118
|
-
# assumptions about the current state of the user interface before it is
|
119
|
-
# invoked.
|
120
|
-
#
|
121
|
-
# @param args Any arguments are passed to the {#component_path} method.
|
122
|
-
#
|
123
|
-
# @raise [RuntimeError] if the component is not visible after attempting
|
124
|
-
# to make it so.
|
125
|
-
def show(*args)
|
126
|
-
return if visible?
|
127
|
-
browser.visit component_url(*args)
|
128
|
-
assert visible?, "The #{self.class.name} component is not visible!"
|
129
|
-
end
|
130
|
-
|
131
106
|
# Is the component's element found on the page and is it considered
|
132
107
|
# "visible" by the browser driver.
|
133
108
|
def visible?
|
@@ -138,30 +113,16 @@ class Kookaburra
|
|
138
113
|
visible
|
139
114
|
end
|
140
115
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
# If no :browser option was specified in {#initialize}, it returns a
|
146
|
-
# default {Kookaburra::NullBrowser} instance.
|
147
|
-
def browser
|
148
|
-
@browser ||= NullBrowser.new
|
116
|
+
# Returns the full URL by appending {#component_path} to the value of the
|
117
|
+
# {Kookaburra::Configuration#app_host} from the initialized configuration.
|
118
|
+
def url(*args)
|
119
|
+
"#{@app_host}#{component_path(*args)}"
|
149
120
|
end
|
150
121
|
|
151
|
-
|
152
|
-
|
153
|
-
#
|
154
|
-
|
155
|
-
# further down the line to fail.
|
156
|
-
#
|
157
|
-
# @param test an expression that will be evaluated in a boolean context
|
158
|
-
# @param [String] message the exception message that will be used if
|
159
|
-
# test is false
|
160
|
-
#
|
161
|
-
# @raise [Kookaburra::AssertionFailed] raised if test evaluates to false
|
162
|
-
def assert(test, message = "You might want to provide a better message, eh?")
|
163
|
-
test or raise AssertionFailed, message
|
164
|
-
end
|
122
|
+
protected
|
123
|
+
|
124
|
+
# The browser object from the initialized configuration
|
125
|
+
attr_reader :browser
|
165
126
|
|
166
127
|
# @abstract
|
167
128
|
# @return [String] the URL path that should be loaded in order to reach this component
|
@@ -171,12 +132,6 @@ class Kookaburra
|
|
171
132
|
raise ConfigurationError, "You must define #{self.class.name}#component_path."
|
172
133
|
end
|
173
134
|
|
174
|
-
# Returns the full URL by appending {#component_path} to the value of the
|
175
|
-
# :app_host option passed to {#initialize}.
|
176
|
-
def component_url(*args)
|
177
|
-
"#{@app_host}#{component_path(*args)}"
|
178
|
-
end
|
179
|
-
|
180
135
|
# @abstract
|
181
136
|
# @return [String] the CSS3 selector that will find the element in the DOM
|
182
137
|
# @raise [Kookaburra::ConfigurationError] raised if you haven't provided
|
@@ -185,7 +140,8 @@ class Kookaburra
|
|
185
140
|
raise ConfigurationError, "You must define #{self.class.name}#component_locator."
|
186
141
|
end
|
187
142
|
|
188
|
-
# Runs the server error detection function specified in
|
143
|
+
# Runs the server error detection function specified in
|
144
|
+
# {Kookaburra::Configuration#server_error_detection}.
|
189
145
|
#
|
190
146
|
# It's a noop if no server error detection was specified.
|
191
147
|
#
|