kameleon 0.2.0.alpha.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,247 @@
1
+ # Kameleon [chameleon]
2
+
3
+ [![Build Status](https://secure.travis-ci.org/cs3b/kameleon.png?branch=master)](http://travis-ci.org/cs3b/kameleon)
4
+
5
+ Kameleon is a high abstraction dsl for better writing acceptance and integrationtests using Capybara.
6
+ And "better" means: more easily to mimic how user interact with browser.
7
+
8
+ ## Setup
9
+
10
+ Kameleon requires:
11
+
12
+ * rspec
13
+ * capybara
14
+
15
+ Optionally is nice to use:
16
+
17
+ * selenium-wedriver && capybara-webkit for testing together with javascript
18
+ * thin (if you want run your specs faster - add gem 'thin' to Gemfile in your app)
19
+
20
+ Gemfile
21
+
22
+ ``` ruby
23
+ gem 'kameleon', '>= 0.2.0.alpha.2'
24
+ ```
25
+
26
+ Before you start using Kameleon ensure that capybara is properly loaded (in your test helper file)
27
+
28
+ ``` ruby
29
+ require 'kameleon/ext/rspec/all'
30
+ ```
31
+
32
+ or just components you want; `kemeleon/ext/rspec/all` by default loads:
33
+
34
+ ``` ruby
35
+ require 'kameleon/ext/rspec/dsl'
36
+ require 'kameleon/ext/rspec/garbage_collector'
37
+ require 'kameleon/ext/rspec/headless'
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ checkout this [slides from wrocloverb 2012](http://www.slideshare.net/cs3b/2012wrocloverbuserperspectivetestingusingruby)
43
+
44
+ ### Example One [listing products > should list existing products with correct sorting ]
45
+
46
+ kameleon
47
+
48
+ ``` ruby
49
+ click "Products"
50
+ within('table.index') do
51
+ see :ordered => [ "apache baseball cap",
52
+ "zomg shirt" ]
53
+ end
54
+ click "admin_products_listing_name_title"
55
+ within('table.index') do
56
+ see :ordered => [ "zomg shirt",
57
+ "apache baseball cap"]
58
+ end
59
+ ```
60
+
61
+ vs capybara
62
+
63
+ ``` ruby
64
+ click_link "Products"
65
+ within('table.index tr:nth-child(2)') { page.should have_content("apache baseball cap") }
66
+ within('table.index tr:nth-child(3)') { page.should have_content("zomg shirt") }
67
+ click_link "admin_products_listing_name_title"
68
+ within('table.index tr:nth-child(2)') { page.should have_content("zomg shirt") }
69
+ within('table.index tr:nth-child(3)') { page.should have_content("apache baseball cap") }
70
+ ```
71
+
72
+ taken from: https://github.com/spree/spree/blob/master/core/spec/requests/admin/products/products_spec.rb#L22
73
+
74
+
75
+ ### Example Two [should allow an admin to create a new product and variants from a prototype]
76
+
77
+ kameleon
78
+
79
+ ``` ruby
80
+ click "Products",
81
+ "admin_new_product"
82
+ fill_in "Baseball Cap" => "product_name",
83
+ "B100" => "product_sku",
84
+ "100" => "product_price",
85
+ "2012/01/24" => "product_available_on",
86
+ :select => { "Size" => "Prototype" },
87
+ :check => "Large"
88
+ click "Create"
89
+ see "successfully created!"
90
+ ```
91
+
92
+ vs capybara
93
+
94
+ ``` ruby
95
+ click_link "Products"
96
+ click_link "admin_new_product"
97
+ fill_in "product_name", :with => "Baseball Cap"
98
+ fill_in "product_sku", :with => "B100"
99
+ fill_in "product_price", :with => "100"
100
+ fill_in "product_available_on", :with => "2012/01/24"
101
+ select "Size", :from => "Prototype"
102
+ check "Large"
103
+ click_button "Create"
104
+ page.should have_content("successfully created!")
105
+ ```
106
+
107
+ taken from: https://github.com/spree/spree/blob/master/core/spec/requests/admin/products/products_spec.rb#L77
108
+
109
+
110
+ ### Example Three [admin editing an adjustment > successfully > should update the adjustment]
111
+
112
+ kameleon
113
+
114
+ ``` ruby
115
+ within(:row => 2).click "Edit"
116
+ fill_in 99 => "adjustment_amount",
117
+ "rebate 99" => "adjustment_label"
118
+ click "Continue"
119
+ see "successfully updated!",
120
+ "rebate 99",
121
+ "$99.00"
122
+ ```
123
+
124
+ vs capybara
125
+
126
+ ``` ruby
127
+ within(:css, 'table.index tr:nth-child(2)') { click_link "Edit" }
128
+ fill_in "adjustment_amount", :with => "99"
129
+ fill_in "adjustment_label", :with => "rebate 99"
130
+ click_button "Continue"
131
+ page.should have_content("successfully updated!")
132
+ page.should have_content("rebate 99")
133
+ page.should have_content("$99.00")
134
+ ```
135
+
136
+ taken from: https://github.com/spree/spree/blob/master/core/spec/requests/admin/orders/adjustments_spec.rb#L48
137
+
138
+ ### Example Four [payment method > should be able to list, edit, and create payment methods for an order]
139
+
140
+ kameleon
141
+
142
+ ``` ruby
143
+ click "Orders"
144
+ within('table#listing_orders', :row => 1).click_link "R100"
145
+ click "Payments"
146
+ within('#payment_status').see "Payment: balance due"
147
+ within(:cell => [2, 2]).see "$39.98"
148
+ within(:cell => [2, 3]).see "Credit Card"
149
+ within(:cell => [2, 4]).see "pending"
150
+ ```
151
+ vs capybara
152
+
153
+ ``` ruby
154
+ visit spree.admin_path
155
+ click_link "Orders"
156
+ within('table#listing_orders tbody tr:nth-child(1)') { click_link "R100" }
157
+ click_link "Payments"
158
+ within('#payment_status') { page.should have_content("Payment: balance due") }
159
+ find('table.index tbody tr:nth-child(2) td:nth-child(2)').text.should == "$39.98"
160
+ find('table.index tbody tr:nth-child(2) td:nth-child(3)').text.should == "Credit Card"
161
+ find('table.index tbody tr:nth-child(2) td:nth-child(4)').text.should == "pending"
162
+ ```
163
+
164
+ #### part II
165
+
166
+ kameleon
167
+
168
+ ``` ruby
169
+ click "Void"
170
+ within('#payment_status').see "Payment: balance due"
171
+ see "Payment Updated"
172
+ within(:cell => [2,2]).see "$39.98"
173
+ within(:cell => [2,3]).see "Credit Card"
174
+ within(:cell => [2,4]).see "void"
175
+ ```
176
+
177
+ vs capybara
178
+
179
+ ``` ruby
180
+ click_button "Void"
181
+ within('#payment_status') { page.should have_content("Payment: balance due") }
182
+ page.should have_content("Payment Updated")
183
+ find('table.index tbody tr:nth-child(2) td:nth-child(2)').text.should == "$39.98"
184
+ find('table.index tbody tr:nth-child(2) td:nth-child(3)').text.should == "Credit Card"
185
+ find('table.index tbody tr:nth-child(2) td:nth-child(4)').text.should == "void"
186
+ ```
187
+
188
+ #### part III
189
+
190
+ kameleon
191
+
192
+ ``` ruby
193
+ click "New Payment"
194
+ see "New Payment"
195
+ click "Continue",
196
+ "Capture"
197
+ within('#payment_status').see "Payment: paid"
198
+ see :element => '#new_payment_section'
199
+
200
+ click "Shipments",
201
+ "New Shipment"
202
+ within('table.index', :row => 2).check "#inventory_unit"
203
+
204
+ click "Create"
205
+ see "successfully created!"
206
+ ```
207
+ vs capybara
208
+
209
+ ``` ruby
210
+ click_on "New Payment"
211
+ page.should have_content("New Payment")
212
+ click_button "Continue"
213
+ click_button "Capture"
214
+ within('#payment_status') { page.should have_content("Payment: paid") }
215
+ page.should_not have_css('#new_payment_section')
216
+
217
+ click_link "Shipments"
218
+ click_on "New Shipment"
219
+ within('table.index tbody tr:nth-child(2)') { check "#inventory_unit" }
220
+ click_button "Create"
221
+ page.should have_content("successfully created!")
222
+ ```
223
+
224
+ taken from: https://github.com/spree/spree/blob/master/core/spec/requests/admin/orders/payments_spec.rb#L32
225
+
226
+
227
+ ## Tips & Tricks
228
+
229
+ * You have access to page variable. So if you think that something cannot be accomplished by the Kameleon DSL, you can just write using RSpec matchers and page variable. Like this: `page.should have_css("li.banner_message", :count => 10)`. Of course, after you've submitted feature request to the owner of the original repository ;)
230
+ * It is handy to define a common set of areas, that user often follows navigating on the site. Here is an example
231
+
232
+ ``` ruby
233
+ Kameleon::Session.defined_areas.merge!({ :menu => [:xpath, "//nav/ul"],
234
+ :main => '.main_body',
235
+ :right_column => '.col_aside',
236
+ :ordered_list => '.ordered_list',
237
+ :favourites => '.favourites_list',
238
+ :gallery_tiny => '.gallery_tiny',
239
+ :gallery_list => '.gallery_list',
240
+ :content => '.col_content',
241
+ :col_aside => '.col_aside' })
242
+ ```
243
+
244
+ ## Credits
245
+ * [Michał Czyż](http://selleo.com/people/michal-czyz)
246
+ * [Radosław Jędryszczak](http://selleo.com/people/radoslaw-jedryszczak)
247
+ * [Szymon Kieloch](http://selleo.com/people)
@@ -56,8 +56,7 @@ module Kameleon
56
56
  if block_given?
57
57
  super(*parse_selector(scope).selector)
58
58
  else
59
- #! we need proxy object to make it working
60
- raise 'not impelemented'
59
+ ScopeProxy.new(self, scope)
61
60
  end
62
61
  end
63
62
 
@@ -94,5 +93,18 @@ module Kameleon
94
93
  def parse_selector(scope)
95
94
  Kameleon::DSL::Context::Scope.new(scope)
96
95
  end
96
+
97
+
98
+ class ScopeProxy < Struct.new(:world, :scope)
99
+
100
+ Kameleon::DSL.instance_methods.each do |method|
101
+ define_method method do |args|
102
+ world.within(scope) do
103
+ world.send(method, args)
104
+ end
105
+ end
106
+ end
107
+
108
+ end
97
109
  end
98
110
  end
@@ -22,11 +22,44 @@ module Kameleon
22
22
  case param
23
23
  when String
24
24
  actions << Action.new(:click_on, param)
25
+ when Symbol
26
+ prepare_actions(:element => param)
25
27
  when Hash
26
28
  param.each_pair do |type, values|
27
29
  case type
28
- when :non_implemented
29
- raise "not implemented"
30
+ when :element
31
+ actions << Action.new(:block, values) do |element|
32
+ selector = Kameleon::DSL::Context::Scope.new(element).selector
33
+ find(*selector).click
34
+ end
35
+
36
+ when :image
37
+ #! Looks like Rack Test doesn't propagate click event up - this is simply hack
38
+ # It's not perfect it would work only when "a" is parent of image (not one of ancestor)
39
+ prepend_text = "/.." if ::Capybara.current_driver == :rack_test
40
+
41
+ prepare_actions(:element => [:xpath, ".//img[@alt=\"#{values}\"]#{prepend_text}"])
42
+
43
+ when :and_accept
44
+ unless Capybara.current_driver == :rack_test
45
+ #! js hack - problem with selenium native alerts usage
46
+ #! it switch to alert window but no reaction on accept or dismiss
47
+ actions << Action.new(:block, values) do |element|
48
+ evaluate_script("window.alert = function(msg) { return true; }")
49
+ evaluate_script("window.confirm = function(msg) { return true; }")
50
+ end
51
+ end
52
+ prepare_actions(values)
53
+
54
+ when :and_dismiss
55
+ unless Capybara.current_driver == :rack_test
56
+ actions << Action.new(:block, values) do |element|
57
+ evaluate_script("window.alert = function(msg) { return true; }")
58
+ evaluate_script("window.confirm = function(msg) { return false; }")
59
+ end
60
+ prepare_actions(values)
61
+ end
62
+
30
63
  else
31
64
  raise "not implemented"
32
65
  end
@@ -54,6 +87,4 @@ module Kameleon
54
87
  end
55
88
 
56
89
  #! click and dismiss
57
- #! click and accept
58
- #! click on image
59
- #! click on element
90
+ #! click and accept
@@ -44,8 +44,10 @@ module Kameleon
44
44
  normalize(default_selector)
45
45
  elsif params.size == 1
46
46
  [::Capybara.default_selector] + params
47
- else
47
+ elsif [:xpath, :css].include?(params.first)
48
48
  params
49
+ else
50
+ JoinInToOne.new(params, self).selector
49
51
  end
50
52
  end
51
53
  end
@@ -72,7 +74,7 @@ module Kameleon
72
74
  end
73
75
  end
74
76
 
75
- def self.row_and_column(param)
77
+ def self.cell(param)
76
78
  value_in_row, value_in_column = *param
77
79
  if value_in_row.is_a?(Fixnum) and value_in_column.is_a?(Fixnum)
78
80
  [:xpath, "//tbody/tr[#{value_in_row}]/td[#{value_in_column}]"]
@@ -89,6 +91,32 @@ module Kameleon
89
91
  # return [:xpath, ".//table//th[#{position + 1}] | .//table//td[#{position + 1}]", :select_multiple]
90
92
  end
91
93
  end
94
+
95
+ class JoinInToOne < Struct.new(:params, :scope)
96
+
97
+ def selector
98
+ [:xpath, xpath_selector]
99
+ end
100
+
101
+ private
102
+
103
+ def xpath_selector
104
+ ([xpaths.first] + cleanup(xpaths[1..-1])).join("//")
105
+ end
106
+
107
+ def cleanup(others)
108
+ others.collect { |xpath| xpath.gsub(/^\.+/, '').gsub(/^\/+/, '') }
109
+ end
110
+
111
+ def xpaths
112
+ @xpaths ||= normalized.map { |param| param.first == :css ? ::Nokogiri::CSS.xpath_for(param.last).first : param.last }
113
+ end
114
+
115
+ # TODO detect_selector should be in module
116
+ def normalized
117
+ params.map { |param| scope.send(:detect_selector, param) }
118
+ end
119
+ end
92
120
  end
93
121
  end
94
122
  end
@@ -22,6 +22,8 @@ module Kameleon
22
22
  case param
23
23
  when String
24
24
  conditions << Condition.new(:have_content, param)
25
+ when Symbol
26
+ prepare_conditions(:element => param)
25
27
  when Hash
26
28
  param.each_pair do |type, values|
27
29
  case type
@@ -47,6 +49,8 @@ module Kameleon
47
49
  conditions.concat TextInput.new(nil, values).conditions
48
50
  when :empty
49
51
  conditions.concat EmptyInput.new(values).conditions
52
+ when :element
53
+ conditions.concat Element.new(values).conditions
50
54
  else
51
55
  raise "not implemented"
52
56
  end
@@ -123,6 +127,33 @@ module Kameleon
123
127
  end
124
128
  end
125
129
 
130
+ class Element
131
+ attr_reader :conditions, :expression
132
+
133
+ def initialize(expression)
134
+ @expression = expression
135
+ @conditions = [condition]
136
+ end
137
+
138
+ private
139
+
140
+ def condition
141
+ Condition.new(have_selector_method, selector_expression)
142
+ end
143
+
144
+ def have_selector_method
145
+ "have_#{selector.first}".to_sym
146
+ end
147
+
148
+ def selector
149
+ @selector ||= Kameleon::DSL::Context::Scope.new(expression).selector
150
+ end
151
+
152
+ def selector_expression
153
+ selector.last
154
+ end
155
+ end
156
+
126
157
  class Quantity
127
158
  attr_reader :conditions
128
159
  attr_reader :quantity
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.alpha.2
5
- prerelease: 6
4
+ version: 0.2.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Michał Czyż [cs3b]
@@ -11,11 +11,11 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-03-08 00:00:00.000000000 Z
14
+ date: 2012-05-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rspec
18
- requirement: &18233400 !ruby/object:Gem::Requirement
18
+ requirement: !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
21
  - - ! '>='
@@ -23,10 +23,15 @@ dependencies:
23
23
  version: '0'
24
24
  type: :runtime
25
25
  prerelease: false
26
- version_requirements: *18233400
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
27
32
  - !ruby/object:Gem::Dependency
28
33
  name: capybara
29
- requirement: &18232320 !ruby/object:Gem::Requirement
34
+ requirement: !ruby/object:Gem::Requirement
30
35
  none: false
31
36
  requirements:
32
37
  - - ! '>='
@@ -34,10 +39,15 @@ dependencies:
34
39
  version: '0'
35
40
  type: :runtime
36
41
  prerelease: false
37
- version_requirements: *18232320
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
38
48
  - !ruby/object:Gem::Dependency
39
49
  name: headless
40
- requirement: &18231100 !ruby/object:Gem::Requirement
50
+ requirement: !ruby/object:Gem::Requirement
41
51
  none: false
42
52
  requirements:
43
53
  - - ! '>='
@@ -45,10 +55,15 @@ dependencies:
45
55
  version: '0'
46
56
  type: :runtime
47
57
  prerelease: false
48
- version_requirements: *18231100
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
49
64
  - !ruby/object:Gem::Dependency
50
65
  name: rspec
51
- requirement: &18230160 !ruby/object:Gem::Requirement
66
+ requirement: !ruby/object:Gem::Requirement
52
67
  none: false
53
68
  requirements:
54
69
  - - ! '>='
@@ -56,10 +71,15 @@ dependencies:
56
71
  version: '0'
57
72
  type: :development
58
73
  prerelease: false
59
- version_requirements: *18230160
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
60
80
  - !ruby/object:Gem::Dependency
61
81
  name: capybara
62
- requirement: &18469680 !ruby/object:Gem::Requirement
82
+ requirement: !ruby/object:Gem::Requirement
63
83
  none: false
64
84
  requirements:
65
85
  - - ! '>='
@@ -67,10 +87,15 @@ dependencies:
67
87
  version: '0'
68
88
  type: :development
69
89
  prerelease: false
70
- version_requirements: *18469680
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
71
96
  - !ruby/object:Gem::Dependency
72
97
  name: headless
73
- requirement: &18468320 !ruby/object:Gem::Requirement
98
+ requirement: !ruby/object:Gem::Requirement
74
99
  none: false
75
100
  requirements:
76
101
  - - ! '>='
@@ -78,10 +103,15 @@ dependencies:
78
103
  version: '0'
79
104
  type: :development
80
105
  prerelease: false
81
- version_requirements: *18468320
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
82
112
  - !ruby/object:Gem::Dependency
83
113
  name: guard-rspec
84
- requirement: &18467220 !ruby/object:Gem::Requirement
114
+ requirement: !ruby/object:Gem::Requirement
85
115
  none: false
86
116
  requirements:
87
117
  - - ! '>='
@@ -89,10 +119,15 @@ dependencies:
89
119
  version: '0'
90
120
  type: :development
91
121
  prerelease: false
92
- version_requirements: *18467220
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
93
128
  - !ruby/object:Gem::Dependency
94
129
  name: selenium-webdriver
95
- requirement: &18466000 !ruby/object:Gem::Requirement
130
+ requirement: !ruby/object:Gem::Requirement
96
131
  none: false
97
132
  requirements:
98
133
  - - ! '>='
@@ -100,10 +135,15 @@ dependencies:
100
135
  version: '0'
101
136
  type: :development
102
137
  prerelease: false
103
- version_requirements: *18466000
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
104
144
  - !ruby/object:Gem::Dependency
105
145
  name: capybara-webkit
106
- requirement: &18465140 !ruby/object:Gem::Requirement
146
+ requirement: !ruby/object:Gem::Requirement
107
147
  none: false
108
148
  requirements:
109
149
  - - ! '>='
@@ -111,7 +151,12 @@ dependencies:
111
151
  version: '0'
112
152
  type: :development
113
153
  prerelease: false
114
- version_requirements: *18465140
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
115
160
  description: high abstraction dsl for end user perspective tests, kameleon - it's
116
161
  a polish word for chameleon
117
162
  email: michalczyz@gmail.com
@@ -119,30 +164,30 @@ executables: []
119
164
  extensions: []
120
165
  extra_rdoc_files: []
121
166
  files:
122
- - lib/kameleon/utils/configuration.rb
167
+ - lib/kameleon.rb
123
168
  - lib/kameleon/utils/debug_console.rb
169
+ - lib/kameleon/utils/configuration.rb
170
+ - lib/kameleon/session.rb
171
+ - lib/kameleon/dsl.rb
172
+ - lib/kameleon/dsl/verify/presence.rb
173
+ - lib/kameleon/dsl/verify/absence.rb
174
+ - lib/kameleon/dsl/utils/debug.rb
124
175
  - lib/kameleon/dsl/act/form.rb
125
176
  - lib/kameleon/dsl/act/mouse.rb
126
177
  - lib/kameleon/dsl/context/scope.rb
127
- - lib/kameleon/dsl/utils/debug.rb
128
- - lib/kameleon/dsl/verify/absence.rb
129
- - lib/kameleon/dsl/verify/presence.rb
130
- - lib/kameleon/dsl.rb
131
- - lib/kameleon/ext/active_record/shared_single_connection.rb
132
- - lib/kameleon/ext/capybara/server.rb
133
178
  - lib/kameleon/ext/capybara/session_pool.rb
134
- - lib/kameleon/ext/rspec/all.rb
135
- - lib/kameleon/ext/rspec/dsl.rb
179
+ - lib/kameleon/ext/capybara/server.rb
180
+ - lib/kameleon/ext/session/devise.rb
181
+ - lib/kameleon/ext/ruby/deferred_garbage_collector.rb
136
182
  - lib/kameleon/ext/rspec/garbage_collector.rb
137
- - lib/kameleon/ext/rspec/headless.rb
183
+ - lib/kameleon/ext/rspec/dsl.rb
138
184
  - lib/kameleon/ext/rspec/pool.rb
139
185
  - lib/kameleon/ext/rspec/transactional_examples.rb
140
- - lib/kameleon/ext/ruby/deferred_garbage_collector.rb
141
- - lib/kameleon/ext/session/devise.rb
142
- - lib/kameleon/session.rb
143
- - lib/kameleon.rb
186
+ - lib/kameleon/ext/rspec/headless.rb
187
+ - lib/kameleon/ext/rspec/all.rb
188
+ - lib/kameleon/ext/active_record/shared_single_connection.rb
144
189
  - LICENCE
145
- - README.textile
190
+ - README.md
146
191
  homepage: https://github.com/cs3b/kameleon
147
192
  licenses:
148
193
  - MIT
@@ -159,12 +204,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
159
204
  required_rubygems_version: !ruby/object:Gem::Requirement
160
205
  none: false
161
206
  requirements:
162
- - - ! '>'
207
+ - - ! '>='
163
208
  - !ruby/object:Gem::Version
164
- version: 1.3.1
209
+ version: '0'
165
210
  requirements: []
166
211
  rubyforge_project:
167
- rubygems_version: 1.8.17
212
+ rubygems_version: 1.8.24
168
213
  signing_key:
169
214
  specification_version: 3
170
215
  summary: high abstraction dsl for end user perspective tests
@@ -1,157 +0,0 @@
1
- h1. Kameleon [chameleon]
2
-
3
- "!https://secure.travis-ci.org/cs3b/kameleon.png?branch=master!":http://travis-ci.org/cs3b/kameleon
4
-
5
- Kameleon is a high abstraction dsl for better writing acceptance and integrationtests using Capybara.
6
- And "better" means: more easily to mimic how user interact with browser.
7
-
8
- h2. Setup:
9
-
10
- Kameleon requires:
11
- * rspec
12
- * capybara
13
-
14
- Optional is nice to use
15
- * devise ( Kameleon uses paths suplied by devise. So if you're using some other authentication solution, you might want to overwrite it )
16
- * selenium-wedriver && capybara-webkit for testing full site
17
- * thin (if you want run your specs faster - add gem 'thin' to Gemfile in your app)
18
-
19
- Gemfile
20
-
21
- <pre>
22
- gem 'kameleon', '>= 0.2.0'
23
- </pre>
24
-
25
- Before you start using Kameleon ensure that capybara is properly loaded (in your test helper file)
26
-
27
- <pre>
28
- require 'kameleon/ext/rspec/all'
29
- </pre>
30
-
31
- or just components you want, kemeleon/ext/rspec/all by default loads:
32
-
33
- <pre>
34
- require 'kameleon/ext/rspec/dsl'
35
- require 'kameleon/ext/rspec/garbage_collector'
36
- require 'kameleon/ext/rspec/headless'
37
- </pre>
38
-
39
- h2. Usage:
40
-
41
- below few examples for more please check spec/integration tests suite
42
-
43
- bc. background do
44
- @admin = Factory.create(:user)
45
- end
46
-
47
- scenario "opening list of news", :status => 'done' do
48
- click "homepage",
49
- "community",
50
- "news"
51
-
52
- see "new medicine developed last weekend"
53
- within(:row => 'some cell text') do
54
- see 'see all values in row that contains that text'
55
- end
56
- see :ordered => 'Z', 'X', 'Y'
57
- click :and_confirm => "Cancel", :and_dismiss => "Cancel"
58
- end
59
-
60
- Another example
61
-
62
- bc. feature "Products", :driver => :selenium do
63
- background do
64
- @admin = Factory.create(:user)
65
- create_session(:admin)
66
- visit spree.admin_path
67
- end
68
-
69
- context "listing products" do
70
- scenario "products sorting" do
71
- Factory(:product, :name => 'apache baseball cap',
72
- :available_on => '2011-01-06 18:21:13:',
73
- :count_on_hand => '0')
74
- Factory(:product, :name => 'zomg shirt',
75
- :available_on => '2125-01-06 18:21:13',
76
- :count_on_hand => '5')
77
-
78
- act_as(:admin) do
79
- click "Products"
80
- see :ordered => ["apache baseball cap", "zomg shirt"]
81
-
82
- click "admin_products_listing_name_title"
83
- see :ordered => ["zomg shirt", "apache baseball cap"]
84
- end
85
- end
86
- end
87
-
88
- And more complex example, with two user sessions:
89
-
90
- bc. scenario "admin adds a product and user buys it", :status => "done", :driver => :selenium do
91
- create_session(:admin)
92
- @admin = Factory.create(:admin_user)
93
- create_session(:user)
94
-
95
- act_as(:admin) do
96
- visit spree.admin_path
97
- click "Products", "admin_new_product"
98
- within('#new_product') do
99
- see "SKU"
100
- end
101
- fill_in "product_name" => "Baseball Cap",
102
- "product_sku" => "B100",
103
- "product_price"=> "100",
104
- "product_available_on"=> "2012/01/24"
105
-
106
- click "Create"
107
- see "successfully created!"
108
-
109
- fill_in "product_on_hand" => "100"
110
- click "Update"
111
- see "successfully updated!"
112
- end
113
-
114
- act_as(:user) do
115
- visit spree.root_path
116
- click "Baseball Cap", "add-to-cart-button", "Checkout"
117
- within("span.out-of-stock") do
118
- see "Baseball Cap added to your cart"
119
- end
120
- end
121
- end
122
-
123
-
124
- h2. Tips & Tricks:
125
- * You have access to page variable. So if you think that something cannot be accomplished by the Kameleon DSL, you can just write using RSpec matchers and page variable. Like this: <pre> page.should have_css("li.banner_message", :count => 10) </pre> Of course, after you've submitted feature request to the owner of the original repository ;)
126
- * It is handy to define a common set of areas, that user often follows navigating on the site. Here is an example:
127
- <pre> Kameleon::Session.defined_areas.merge!({
128
- :menu => [:xpath, "//nav/ul"],
129
- :main => '.main_body',
130
- :right_column => '.col_aside',
131
- :ordered_list => '.ordered_list',
132
- :favourites => '.favourites_list',
133
- :gallery_tiny => '.gallery_tiny',
134
- :gallery_list => '.gallery_list',
135
- :content => '.col_content',
136
- :col_aside => '.col_aside'
137
- })
138
-
139
- </pre>
140
-
141
- soon we will merge with new capybara approach for that
142
-
143
- h2. Tips & Tricks:
144
-
145
- h3. Session pooling
146
-
147
- Kameleon has useful technique of session pooling implemented, that can speed up test suite greatly.
148
- In order to enable it, you need to pass this to the RSpec.configure block, in spec_helper.rb:
149
-
150
- bc. config.after(:each) do
151
- ::SessionPool.release_all
152
- end
153
-
154
- h2. Credits:
155
- * <a href="http://selleo.com/people/michal-czyz">Michał Czyż</a>
156
- * <a href="http://selleo.com/people/radoslaw-jedryszczak">Radosław Jędryszczak</a>
157
- * <a href="http://selleo.com/people">Szymon Kieloch</a>