kameleon 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/kameleon.rb +16 -1
- data/lib/kameleon/dsl/act.rb +24 -12
- data/lib/kameleon/dsl/see.rb +15 -4
- data/lib/kameleon/session/capybara.rb +2 -25
- data/lib/kameleon/session/server.rb +21 -0
- data/lib/kameleon/session/session_pool.rb +45 -0
- data/lib/kameleon/user/abstract.rb +21 -24
- data/lib/kameleon/user/guest.rb +1 -3
- data/lib/kameleon/utils/configuration.rb +15 -0
- data/lib/kameleon/utils/helpers.rb +11 -0
- data/lib/patch/capybara_selenium_driver.rb +7 -0
- data/spec/sample_rack_app/hey.rb +13 -6
- data/spec/spec_helper.rb +26 -1
- data/spec/unit/act/click_spec.rb +1 -1
- data/spec/unit/act/fill_in/attach_file_spec.rb +14 -5
- data/spec/unit/act/fill_in/checkbox_spec.rb +1 -1
- data/spec/unit/act/fill_in/date_ranges_spec.rb +1 -1
- data/spec/unit/act/fill_in/multiple_select_spec.rb +1 -1
- data/spec/unit/act/fill_in/radio_button_spec.rb +1 -1
- data/spec/unit/act/fill_in/select_spec.rb +1 -1
- data/spec/unit/act/fill_in/text_area_spec.rb +1 -1
- data/spec/unit/act/fill_in/text_input_spec.rb +1 -1
- data/spec/unit/act/on_hover_spec.rb +1 -1
- data/spec/unit/dsl/not_see/form_elements/fields/empty_spec.rb +1 -1
- data/spec/unit/dsl/not_see/form_elements/fields/readonly_spec.rb +1 -1
- data/spec/unit/dsl/not_see/form_elements/fields_spec.rb +1 -1
- data/spec/unit/dsl/not_see/form_elements/textareas_spec.rb +1 -1
- data/spec/unit/dsl/not_see/form_elements/texts_spec.rb +1 -1
- data/spec/unit/dsl/not_see/in_scopes_spec.rb +3 -1
- data/spec/unit/dsl/not_see/special_elements/buttons_spec.rb +1 -1
- data/spec/unit/dsl/not_see/special_elements/error_message_for_spec.rb +1 -1
- data/spec/unit/dsl/not_see/special_elements/images_spec.rb +1 -1
- data/spec/unit/dsl/not_see/special_elements/links_spec.rb +1 -1
- data/spec/unit/dsl/not_see/special_elements/ordered_texts_spec.rb +3 -3
- data/spec/unit/dsl/not_see/special_selectors_spec.rb +9 -5
- data/spec/unit/dsl/not_see/texts_spec.rb +1 -1
- data/spec/unit/dsl/see/counted_elements_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/checkboxes_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/fields/disabled_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/fields/empty_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/fields/readonly_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/fields_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/multiple_selects_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/radio_buttons_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/selects_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/textareas_spec.rb +1 -1
- data/spec/unit/dsl/see/form_elements/texts_spec.rb +1 -1
- data/spec/unit/dsl/see/in_scopes_spec.rb +4 -2
- data/spec/unit/dsl/see/special_elements/buttons_spec.rb +1 -1
- data/spec/unit/dsl/see/special_elements/error_message_for_spec.rb +1 -1
- data/spec/unit/dsl/see/special_elements/images_spec.rb +1 -1
- data/spec/unit/dsl/see/special_elements/links_spec.rb +1 -1
- data/spec/unit/dsl/see/special_elements/ordered_texts_spec.rb +3 -3
- data/spec/unit/dsl/see/special_selectors_spec.rb +10 -6
- data/spec/unit/dsl/see/texts_spec.rb +1 -1
- data/spec/unit/guest_spec.rb +8 -4
- data/spec/unit/user_base_spec.rb +6 -8
- metadata +29 -23
data/lib/kameleon.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
|
+
require 'kameleon/utils/configuration'
|
2
|
+
require 'kameleon/utils/helpers'
|
3
|
+
|
1
4
|
require 'kameleon/session/capybara'
|
5
|
+
require 'kameleon/session/server'
|
6
|
+
require 'kameleon/session/session_pool'
|
2
7
|
require 'kameleon/dsl/see'
|
3
8
|
require 'kameleon/dsl/act'
|
4
9
|
|
5
10
|
require 'kameleon/user/abstract'
|
6
11
|
require 'kameleon/user/base'
|
7
|
-
require 'kameleon/user/guest'
|
12
|
+
require 'kameleon/user/guest'
|
13
|
+
|
14
|
+
|
15
|
+
module Kameleon
|
16
|
+
extend Utils::Configuration
|
17
|
+
end
|
18
|
+
|
19
|
+
# Set up default configuration for Kameleon
|
20
|
+
Kameleon.configure do |config|
|
21
|
+
config.default_file_path = 'spec/dummy'
|
22
|
+
end
|
data/lib/kameleon/dsl/act.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Kameleon
|
2
2
|
module Dsl
|
3
3
|
module Act
|
4
|
+
include Kameleon::Utils
|
4
5
|
|
5
6
|
def click(*links)
|
6
7
|
links.each do |link|
|
@@ -37,7 +38,7 @@ module Kameleon
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def fill_in(locators)
|
40
|
-
fill(locators)
|
41
|
+
fill(locators) if can_fill?(locators)
|
41
42
|
end
|
42
43
|
|
43
44
|
private
|
@@ -69,27 +70,38 @@ module Kameleon
|
|
69
70
|
|
70
71
|
def can_fill?(locators)
|
71
72
|
locators.values.each do |loc|
|
72
|
-
|
73
|
-
one_or_all(
|
74
|
-
return false if unmodifiable?(
|
73
|
+
selectors = loc.respond_to?(:values) ? loc.values : loc
|
74
|
+
one_or_all(selectors).each do |selector|
|
75
|
+
return false if unmodifiable?(selector)
|
75
76
|
end
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
80
|
+
def unmodifiable?(locator)
|
81
|
+
field = session.find_field(locator)
|
82
|
+
case session.driver
|
83
|
+
when Capybara::Selenium::Driver
|
84
|
+
# In driver field attributes - disabled and readonly may be:
|
85
|
+
# 1) string - false or true
|
86
|
+
# 2) nil value
|
87
|
+
return eval(field[:disabled].to_s) || eval(field[:readonly].to_s)
|
88
|
+
when Capybara::RackTest::Driver
|
89
|
+
# In rack field attributes - disabled and readonly may be:
|
90
|
+
# 1) nil value
|
91
|
+
# 2) string - disabled or readonly
|
92
|
+
return field[:disabled] || field[:readonly]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
79
96
|
def get_full_test_asset_path(file_path)
|
80
97
|
if File.file?(file_path)
|
81
98
|
file_path
|
82
|
-
elsif File.file?(
|
83
|
-
|
99
|
+
elsif File.file?(Helpers.default_path_for_file(file_path))
|
100
|
+
Helpers.default_path_for_file(file_path)
|
84
101
|
else
|
85
|
-
raise "Sorry but we didn't found that file in: #{file_path}, neither #{
|
102
|
+
raise "Sorry but we didn't found that file in: #{file_path}, neither #{Helpers.default_path_for_file(file_path)}"
|
86
103
|
end
|
87
104
|
end
|
88
|
-
|
89
|
-
def unmodifiable?(locator)
|
90
|
-
field = session.find_field(locator)
|
91
|
-
field[:readonly] || field[:disabled]
|
92
|
-
end
|
93
105
|
end
|
94
106
|
end
|
95
107
|
end
|
data/lib/kameleon/dsl/see.rb
CHANGED
@@ -27,7 +27,12 @@ module Kameleon
|
|
27
27
|
when :disabled, :readonly
|
28
28
|
one_or_all(locator).each do |selector|
|
29
29
|
see :field => selector
|
30
|
-
session.
|
30
|
+
case session.driver
|
31
|
+
when Capybara::Selenium::Driver
|
32
|
+
session.find_field(selector)[value].should == 'true'
|
33
|
+
when Capybara::RackTest::Driver
|
34
|
+
session.find_field(selector)[value].should ==(value.to_s)
|
35
|
+
end
|
31
36
|
end
|
32
37
|
when :empty
|
33
38
|
one_or_all(locator).each do |selector|
|
@@ -63,13 +68,14 @@ module Kameleon
|
|
63
68
|
one_or_all(locator).each { |text| session.should rspec_world.have_link(text) }
|
64
69
|
end
|
65
70
|
when :ordered
|
71
|
+
#! we should extend this beyond simply text match (allow to pass full xpath)
|
66
72
|
nodes = session.all(:xpath, locator.collect { |n| "//node()[text()= \"#{n}\"]" }.join(' | '))
|
67
73
|
nodes.map(&:text).should == locator
|
68
74
|
else
|
69
75
|
raise("User can not see #{value} - you need to teach him how")
|
70
76
|
end
|
71
77
|
when 'Fixnum'
|
72
|
-
session.should ::Capybara::RSpecMatchers::HaveMatcher.new(*(get_selector(locator) << {
|
78
|
+
session.should ::Capybara::RSpecMatchers::HaveMatcher.new(*(get_selector(locator) << {:count => value}))
|
73
79
|
else
|
74
80
|
session.should rspec_world.have_field(locator, :with => value)
|
75
81
|
end
|
@@ -122,7 +128,12 @@ module Kameleon
|
|
122
128
|
when :readonly
|
123
129
|
one_or_all(locators).each do |selector|
|
124
130
|
see :field => selector
|
125
|
-
session.
|
131
|
+
case session.driver
|
132
|
+
when Capybara::Selenium::Driver
|
133
|
+
session.find_field(selector)[value].should == 'false'
|
134
|
+
when Capybara::RackTest::Driver
|
135
|
+
session.find_field(selector)[value].should rspec_world.be_nil
|
136
|
+
end
|
126
137
|
end
|
127
138
|
when :empty
|
128
139
|
one_or_all(locators).each do |locator|
|
@@ -141,4 +152,4 @@ module Kameleon
|
|
141
152
|
end
|
142
153
|
end
|
143
154
|
end
|
144
|
-
end
|
155
|
+
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
module Kameleon
|
2
2
|
module Session
|
3
3
|
module Capybara
|
4
|
-
|
5
|
-
attr_accessor :session_name
|
6
4
|
attr_accessor :driver_name
|
7
5
|
|
8
6
|
def set_session
|
9
|
-
@session =
|
10
|
-
current_session
|
7
|
+
@session = ::SessionPool.session(current_driver)
|
11
8
|
end
|
12
9
|
|
13
10
|
def refresh_page
|
@@ -23,26 +20,6 @@ module Kameleon
|
|
23
20
|
|
24
21
|
private
|
25
22
|
|
26
|
-
def find_or_create_session
|
27
|
-
find_session ||
|
28
|
-
create_session
|
29
|
-
end
|
30
|
-
|
31
|
-
#! in future we should print notice when selected drive is different then session that have been chosen
|
32
|
-
def find_session
|
33
|
-
session_pool[session_name]
|
34
|
-
end
|
35
|
-
|
36
|
-
def create_session
|
37
|
-
::Capybara::Session.new(current_driver, ::Capybara.app).tap do |session|
|
38
|
-
session_pool[session_name] = session
|
39
|
-
end if session_name
|
40
|
-
end
|
41
|
-
|
42
|
-
def session_pool
|
43
|
-
::Capybara.send(:session_pool)
|
44
|
-
end
|
45
|
-
|
46
23
|
def current_session
|
47
24
|
::Capybara.current_session
|
48
25
|
end
|
@@ -51,6 +28,6 @@ module Kameleon
|
|
51
28
|
driver_name ||
|
52
29
|
::Capybara.current_driver
|
53
30
|
end
|
54
|
-
|
31
|
+
end
|
55
32
|
end
|
56
33
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
module Kameleon
|
3
|
+
module Session
|
4
|
+
class Server
|
5
|
+
include ::Singleton
|
6
|
+
class << self
|
7
|
+
def server(app)
|
8
|
+
@server ||= start_new_server(app)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def start_new_server(app)
|
14
|
+
rack_server = ::Capybara::Server.new(app)
|
15
|
+
rack_server.boot
|
16
|
+
rack_server
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
class SessionPool
|
3
|
+
include Singleton
|
4
|
+
class << self
|
5
|
+
attr_writer :nice
|
6
|
+
def session(driver)
|
7
|
+
take_idle(driver) || create(driver)
|
8
|
+
end
|
9
|
+
|
10
|
+
def release_all
|
11
|
+
idle.concat(busy)
|
12
|
+
busy.clear
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def idle
|
18
|
+
@idle ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
def busy
|
22
|
+
@busy ||= []
|
23
|
+
end
|
24
|
+
|
25
|
+
def take_idle(driver)
|
26
|
+
if session = find_idle(driver)
|
27
|
+
session.reset!
|
28
|
+
session.tap do |s|
|
29
|
+
idle.delete(s)
|
30
|
+
busy.push(s)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_idle(driver)
|
36
|
+
idle.detect { |session| session.mode == driver }
|
37
|
+
end
|
38
|
+
|
39
|
+
def create(driver)
|
40
|
+
::Capybara::Session.new(driver, ::Capybara.app).tap do |session|
|
41
|
+
busy.push(session)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -18,21 +18,24 @@ module Kameleon
|
|
18
18
|
def within(*args)
|
19
19
|
new_scope = if args.size == 1 && Capybara::Node::Base === args.first
|
20
20
|
args.first
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
elsif args.last == :select_multiple
|
22
|
+
case driver
|
23
|
+
when Capybara::Selenium::Driver
|
24
|
+
raise "So far Unsupported in this driver"
|
25
|
+
when Capybara::RackTest::Driver
|
26
|
+
node = find(*args)
|
27
|
+
native = Nokogiri::HTML.parse(html).xpath(args[1])
|
28
|
+
base = Capybara::RackTest::Node.new(driver, native)
|
29
|
+
::Capybara::Node::Element.new(self,
|
30
|
+
base,
|
31
|
+
node.parent,
|
32
|
+
node.instance_variable_get(:@selector))
|
32
33
|
end
|
34
|
+
else
|
35
|
+
find(*args)
|
33
36
|
end
|
34
37
|
begin
|
35
|
-
scopes.push(new_scope)
|
38
|
+
scopes.push(*new_scope)
|
36
39
|
yield
|
37
40
|
ensure
|
38
41
|
scopes.pop
|
@@ -102,25 +105,24 @@ module Kameleon
|
|
102
105
|
if (selector.is_a?(Array) && selector.size == 1)
|
103
106
|
selector = selector.first
|
104
107
|
end
|
105
|
-
case selector
|
106
|
-
when
|
108
|
+
case selector
|
109
|
+
when Hash
|
107
110
|
selector.each_pair do |key, value|
|
108
111
|
case key
|
109
112
|
when :row
|
110
113
|
return [:xpath, "//tr[*='#{value}'][1]"]
|
111
114
|
when :column
|
112
|
-
position =
|
113
|
-
|
114
|
-
return [:xpath, "//table//th[#{position + 1}] | //table//td[#{position + 1}]", :select_multiple]
|
115
|
+
position = session.all(:xpath, "//table//th").index { |n| n.text =~ /#{value}/ }
|
116
|
+
return [:xpath, ".//table//th[#{position + 1}] | .//table//td[#{position + 1}]", :select_multiple]
|
115
117
|
else
|
116
118
|
raise "not supported selectors"
|
117
119
|
end
|
118
120
|
end
|
119
|
-
when
|
121
|
+
when Symbol
|
120
122
|
page_areas[selector].is_a?(Array) ?
|
121
123
|
page_areas[selector] :
|
122
124
|
[Capybara.default_selector, page_areas[selector]]
|
123
|
-
when
|
125
|
+
when Array
|
124
126
|
selector
|
125
127
|
else
|
126
128
|
[Capybara.default_selector, selector]
|
@@ -131,11 +133,6 @@ module Kameleon
|
|
131
133
|
page_areas[:main]
|
132
134
|
end
|
133
135
|
|
134
|
-
#! rails dependency
|
135
|
-
def default_files_path
|
136
|
-
::Rails.root.join('spec')
|
137
|
-
end
|
138
|
-
|
139
136
|
def one_or_all(elements)
|
140
137
|
elements.is_a?(Array) ? elements : [elements]
|
141
138
|
end
|
data/lib/kameleon/user/guest.rb
CHANGED
data/spec/sample_rack_app/hey.rb
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
class Hey
|
2
|
-
def initialize(filename = 'default')
|
3
|
-
@body = get_body(filename)
|
4
|
-
end
|
5
|
-
|
6
2
|
def call(env)
|
7
|
-
[
|
3
|
+
if env["PATH_INFO"] == "/"
|
4
|
+
[200, {"Content-Type" => "text"}, ['welcome on homepage']]
|
5
|
+
else
|
6
|
+
[200, {"Content-Type" => "text/html"}, [get_body(env['PATH_INFO'])]]
|
7
|
+
end
|
8
8
|
end
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def get_body(filename)
|
13
|
-
File.open(
|
13
|
+
file = File.open(file_path(filename))
|
14
|
+
body = file.read
|
15
|
+
file.close
|
16
|
+
body
|
14
17
|
rescue
|
15
18
|
filename
|
16
19
|
end
|
20
|
+
|
21
|
+
def file_path(filename)
|
22
|
+
File.dirname(__FILE__) + "/../dummy/#{filename}"
|
23
|
+
end
|
17
24
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,15 +2,40 @@ require 'kameleon'
|
|
2
2
|
require 'capybara/dsl'
|
3
3
|
require 'capybara/rspec/matchers'
|
4
4
|
|
5
|
+
require 'capybara/selenium/driver'
|
6
|
+
# one server on all sessions for selenium
|
7
|
+
# require 'patch/capybara_selenium_driver'
|
8
|
+
require 'headless'
|
9
|
+
|
5
10
|
Dir["#{File.expand_path("../", __FILE__)}/support/**/*.rb"].each { |f| require f }
|
6
11
|
|
7
12
|
require 'sample_rack_app/hey'
|
8
13
|
|
9
14
|
RSpec.configure do |config|
|
15
|
+
config.before(:suite) do
|
16
|
+
@headless = Headless.new(:display => '100')
|
17
|
+
@headless.start
|
18
|
+
end
|
19
|
+
|
10
20
|
config.before(:all) do
|
11
21
|
DeferredGarbageCollection.start
|
12
22
|
end
|
23
|
+
|
24
|
+
config.after(:each) do
|
25
|
+
::SessionPool.release_all
|
26
|
+
end
|
27
|
+
|
13
28
|
config.after(:all) do
|
14
29
|
DeferredGarbageCollection.reconsider
|
15
30
|
end
|
16
|
-
|
31
|
+
|
32
|
+
config.after(:suite) do
|
33
|
+
@headless.stop if defined?(@headless)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Capybara.app = Hey.new
|
38
|
+
|
39
|
+
Capybara.configure do |c|
|
40
|
+
c.default_driver= (ENV['CAPYBARA_DEFAULT_DRIVER']||:rack_test).to_sym
|
41
|
+
end
|