kameleon 0.0.8 → 0.0.9

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 (58) hide show
  1. data/lib/kameleon.rb +16 -1
  2. data/lib/kameleon/dsl/act.rb +24 -12
  3. data/lib/kameleon/dsl/see.rb +15 -4
  4. data/lib/kameleon/session/capybara.rb +2 -25
  5. data/lib/kameleon/session/server.rb +21 -0
  6. data/lib/kameleon/session/session_pool.rb +45 -0
  7. data/lib/kameleon/user/abstract.rb +21 -24
  8. data/lib/kameleon/user/guest.rb +1 -3
  9. data/lib/kameleon/utils/configuration.rb +15 -0
  10. data/lib/kameleon/utils/helpers.rb +11 -0
  11. data/lib/patch/capybara_selenium_driver.rb +7 -0
  12. data/spec/sample_rack_app/hey.rb +13 -6
  13. data/spec/spec_helper.rb +26 -1
  14. data/spec/unit/act/click_spec.rb +1 -1
  15. data/spec/unit/act/fill_in/attach_file_spec.rb +14 -5
  16. data/spec/unit/act/fill_in/checkbox_spec.rb +1 -1
  17. data/spec/unit/act/fill_in/date_ranges_spec.rb +1 -1
  18. data/spec/unit/act/fill_in/multiple_select_spec.rb +1 -1
  19. data/spec/unit/act/fill_in/radio_button_spec.rb +1 -1
  20. data/spec/unit/act/fill_in/select_spec.rb +1 -1
  21. data/spec/unit/act/fill_in/text_area_spec.rb +1 -1
  22. data/spec/unit/act/fill_in/text_input_spec.rb +1 -1
  23. data/spec/unit/act/on_hover_spec.rb +1 -1
  24. data/spec/unit/dsl/not_see/form_elements/fields/empty_spec.rb +1 -1
  25. data/spec/unit/dsl/not_see/form_elements/fields/readonly_spec.rb +1 -1
  26. data/spec/unit/dsl/not_see/form_elements/fields_spec.rb +1 -1
  27. data/spec/unit/dsl/not_see/form_elements/textareas_spec.rb +1 -1
  28. data/spec/unit/dsl/not_see/form_elements/texts_spec.rb +1 -1
  29. data/spec/unit/dsl/not_see/in_scopes_spec.rb +3 -1
  30. data/spec/unit/dsl/not_see/special_elements/buttons_spec.rb +1 -1
  31. data/spec/unit/dsl/not_see/special_elements/error_message_for_spec.rb +1 -1
  32. data/spec/unit/dsl/not_see/special_elements/images_spec.rb +1 -1
  33. data/spec/unit/dsl/not_see/special_elements/links_spec.rb +1 -1
  34. data/spec/unit/dsl/not_see/special_elements/ordered_texts_spec.rb +3 -3
  35. data/spec/unit/dsl/not_see/special_selectors_spec.rb +9 -5
  36. data/spec/unit/dsl/not_see/texts_spec.rb +1 -1
  37. data/spec/unit/dsl/see/counted_elements_spec.rb +1 -1
  38. data/spec/unit/dsl/see/form_elements/checkboxes_spec.rb +1 -1
  39. data/spec/unit/dsl/see/form_elements/fields/disabled_spec.rb +1 -1
  40. data/spec/unit/dsl/see/form_elements/fields/empty_spec.rb +1 -1
  41. data/spec/unit/dsl/see/form_elements/fields/readonly_spec.rb +1 -1
  42. data/spec/unit/dsl/see/form_elements/fields_spec.rb +1 -1
  43. data/spec/unit/dsl/see/form_elements/multiple_selects_spec.rb +1 -1
  44. data/spec/unit/dsl/see/form_elements/radio_buttons_spec.rb +1 -1
  45. data/spec/unit/dsl/see/form_elements/selects_spec.rb +1 -1
  46. data/spec/unit/dsl/see/form_elements/textareas_spec.rb +1 -1
  47. data/spec/unit/dsl/see/form_elements/texts_spec.rb +1 -1
  48. data/spec/unit/dsl/see/in_scopes_spec.rb +4 -2
  49. data/spec/unit/dsl/see/special_elements/buttons_spec.rb +1 -1
  50. data/spec/unit/dsl/see/special_elements/error_message_for_spec.rb +1 -1
  51. data/spec/unit/dsl/see/special_elements/images_spec.rb +1 -1
  52. data/spec/unit/dsl/see/special_elements/links_spec.rb +1 -1
  53. data/spec/unit/dsl/see/special_elements/ordered_texts_spec.rb +3 -3
  54. data/spec/unit/dsl/see/special_selectors_spec.rb +10 -6
  55. data/spec/unit/dsl/see/texts_spec.rb +1 -1
  56. data/spec/unit/guest_spec.rb +8 -4
  57. data/spec/unit/user_base_spec.rb +6 -8
  58. 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
@@ -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) # if can_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
- locators = loc.respond_to?(:values) ? loc.values : loc
73
- one_or_all(locators).each do |locator|
74
- return false if unmodifiable?(locator)
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?(default_files_path.join(file_path))
83
- default_files_path.join(file_path)
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 #{default_files_path.join(file_path)}"
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
@@ -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.find_field(selector)[value].should ==(value.to_s)
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) << { :count => value }))
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.find_field(selector)[value].should rspec_world.be_nil
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 = find_or_create_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
- end
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
- else
22
- if args.last == :select_multiple
23
- node = find(*args)
24
- native = Nokogiri::HTML.parse(all(*args[0..-2]).map(&:native).map(&:to_s).join)
25
- base = Capybara::RackTest::Node.new(driver, native)
26
- ::Capybara::Node::Element.new(self,
27
- base,
28
- node.parent,
29
- node.instance_variable_get(:@selector))
30
- else
31
- find(*args)
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.class.name
106
- when 'Hash'
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
- session.all(:xpath, "//table//th").index { |n| n.text =~ /#{value}/ }
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 'Symbol'
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 'Array'
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
@@ -2,9 +2,7 @@ module Kameleon
2
2
  module User
3
3
  class Guest < Abstract
4
4
  def initialize(rspec_world, options={}, &block)
5
- super do
6
- session.visit('/') if load_homepage?
7
- end
5
+ super
8
6
  instance_eval(&block) if block_given?
9
7
  end
10
8
  end
@@ -0,0 +1,15 @@
1
+ module Kameleon
2
+ module Utils
3
+ module Configuration
4
+ attr_accessor :default_file_path
5
+
6
+ def configure
7
+ yield self
8
+ end
9
+
10
+ def default_file_path=(path)
11
+ @default_file_path = File.expand_path(path)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Kameleon
2
+ module Utils
3
+ module Helpers
4
+ class << self
5
+ def default_path_for_file(file_name)
6
+ File.join(Kameleon.default_file_path, file_name)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ class Capybara::Selenium::Driver
2
+ def initialize(app, options={})
3
+ @app = app
4
+ @options = DEFAULT_OPTIONS.merge(options)
5
+ @rack_server = ::Kameleon::Session::Server.server(app)
6
+ end
7
+ end
@@ -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
- [200, {"Content-Type" => "text/plain"}, [@body]]
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(File.dirname(__FILE__) + "/../dummy/#{filename}").read
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
- end
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