kameleon 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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