symbiont 0.1.9 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. data/Gemfile.lock +22 -7
  2. data/HISTORY.md +6 -0
  3. data/app/public/css/site.css +16 -0
  4. data/app/public/js/site.js +3 -1
  5. data/app/views/comics.erb +23 -1
  6. data/app/views/webobject.erb +1 -1
  7. data/lib/symbiont/data_setter.rb +7 -3
  8. data/lib/symbiont/enclosers.rb +24 -27
  9. data/lib/symbiont/evaluators.rb +52 -23
  10. data/lib/symbiont/factory.rb +19 -75
  11. data/lib/symbiont/generators.rb +172 -44
  12. data/lib/symbiont/platform_watir/platform_object.rb +202 -18
  13. data/lib/symbiont/version.rb +1 -1
  14. data/lib/symbiont/web_objects/button.rb +1 -1
  15. data/lib/symbiont/web_objects/checkbox.rb +1 -1
  16. data/lib/symbiont/web_objects/heading.rb +12 -0
  17. data/lib/symbiont/web_objects/hidden_field.rb +19 -0
  18. data/lib/symbiont/web_objects/label.rb +15 -0
  19. data/lib/symbiont/web_objects/list_item.rb +13 -0
  20. data/lib/symbiont/web_objects/ordered_list.rb +49 -0
  21. data/lib/symbiont/web_objects/radio.rb +1 -1
  22. data/lib/symbiont/web_objects/select_list.rb +1 -1
  23. data/lib/symbiont/web_objects/table.rb +4 -0
  24. data/lib/symbiont/web_objects/table_row.rb +4 -0
  25. data/lib/symbiont/web_objects/text_area.rb +26 -0
  26. data/lib/symbiont/web_objects/unordered_list.rb +49 -0
  27. data/lib/symbiont.rb +7 -0
  28. data/lucid.yml +6 -0
  29. data/spec/spec_helper.rb +70 -16
  30. data/spec/symbiont/data_setter_spec.rb +65 -62
  31. data/spec/symbiont/enclosers_spec.rb +76 -57
  32. data/spec/symbiont/evaluators_spec.rb +95 -75
  33. data/spec/symbiont/factory_spec.rb +174 -122
  34. data/spec/symbiont/generators/button_generators_spec.rb +34 -31
  35. data/spec/symbiont/generators/checkbox_generators_spec.rb +79 -75
  36. data/spec/symbiont/generators/div_generators_spec.rb +56 -52
  37. data/spec/symbiont/generators/hidden_field_generators_spec.rb +65 -0
  38. data/spec/symbiont/generators/link_generators_spec.rb +30 -27
  39. data/spec/symbiont/generators/paragraph_generators_spec.rb +22 -17
  40. data/spec/symbiont/generators/radio_generators_spec.rb +76 -77
  41. data/spec/symbiont/generators/select_list_generators_spec.rb +93 -77
  42. data/spec/symbiont/generators/span_generators_spec.rb +56 -52
  43. data/spec/symbiont/generators/{cell_generators_spec.rb → table_cell_generators_spec.rb} +56 -52
  44. data/spec/symbiont/generators/table_generators_spec.rb +56 -52
  45. data/spec/symbiont/generators/text_area_generators_spec.rb +72 -0
  46. data/spec/symbiont/generators/text_field_generators_spec.rb +30 -27
  47. data/spec/symbiont/generators_spec.rb +38 -28
  48. data/spec/symbiont/locators_spec.rb +68 -68
  49. data/spec/symbiont/platform_object_spec.rb +2 -4
  50. data/spec/symbiont/symbiont_spec.rb +10 -8
  51. data/spec/symbiont/web_object_spec.rb +194 -194
  52. data/spec/symbiont/web_objects/button_spec.rb +38 -30
  53. data/spec/symbiont/web_objects/checkbox_spec.rb +27 -27
  54. data/spec/symbiont/web_objects/div_spec.rb +18 -11
  55. data/spec/symbiont/web_objects/heading_spec.rb +22 -0
  56. data/spec/symbiont/web_objects/hidden_field_spec.rb +18 -0
  57. data/spec/symbiont/web_objects/label_spec.rb +18 -0
  58. data/spec/symbiont/web_objects/link_spec.rb +33 -33
  59. data/spec/symbiont/web_objects/list_item_spec.rb +18 -0
  60. data/spec/symbiont/web_objects/option_spec.rb +9 -9
  61. data/spec/symbiont/web_objects/ordered_list_spec.rb +53 -0
  62. data/spec/symbiont/web_objects/paragraph_spec.rb +9 -2
  63. data/spec/symbiont/web_objects/radio_spec.rb +27 -27
  64. data/spec/symbiont/web_objects/select_list_spec.rb +69 -69
  65. data/spec/symbiont/web_objects/span_spec.rb +18 -11
  66. data/spec/symbiont/web_objects/table_cell_spec.rb +19 -19
  67. data/spec/symbiont/web_objects/table_row_spec.rb +58 -58
  68. data/spec/symbiont/web_objects/table_spec.rb +61 -61
  69. data/spec/symbiont/web_objects/text_area_spec.rb +18 -0
  70. data/spec/symbiont/web_objects/text_field_spec.rb +39 -39
  71. data/spec/symbiont/web_objects/unordered_list_spec.rb +51 -0
  72. data/specs/common/support/browser.rb +25 -0
  73. data/specs/common/support/env.rb +6 -0
  74. data/specs/common/support/events.rb +15 -0
  75. data/specs/enclosers.feature +9 -0
  76. data/specs/evaluators.feature +26 -0
  77. data/specs/pages/characters.rb +22 -0
  78. data/specs/pages/home.rb +9 -0
  79. data/specs/pages/stardate.rb +23 -0
  80. data/specs/pages/web_objects.rb +77 -0
  81. data/specs/select_list.feature +53 -0
  82. data/specs/steps/enclosers_steps.rb +17 -0
  83. data/specs/steps/evaluators_steps.rb +44 -0
  84. data/specs/steps/navigation_steps.rb +14 -0
  85. data/specs/steps/select_list_steps.rb +94 -0
  86. data/specs/steps/table_cell_steps.rb +31 -0
  87. data/specs/steps/table_steps.rb +87 -0
  88. data/specs/table.feature +49 -0
  89. data/specs/table_cell.feature +27 -0
  90. data/symbiont.gemspec +4 -1
  91. metadata +72 -6
  92. data/cucumber.yml +0 -6
data/Gemfile.lock CHANGED
@@ -1,23 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- symbiont (0.1.9)
5
- selenium-webdriver (= 2.29.0)
4
+ symbiont (0.2.0)
5
+ selenium-webdriver (= 2.31.0)
6
6
  watir-webdriver (= 0.6.2)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- childprocess (0.3.7)
12
- ffi (~> 1.0, >= 1.0.6)
13
- ffi (1.3.1-x86-mingw32)
14
- multi_json (1.5.0)
11
+ childprocess (0.3.9)
12
+ ffi (~> 1.0, >= 1.0.11)
13
+ diff-lcs (1.2.1)
14
+ ffi (1.5.0-x86-mingw32)
15
+ multi_json (1.7.1)
16
+ rspec (2.13.0)
17
+ rspec-core (~> 2.13.0)
18
+ rspec-expectations (~> 2.13.0)
19
+ rspec-mocks (~> 2.13.0)
20
+ rspec-core (2.13.1)
21
+ rspec-expectations (2.13.0)
22
+ diff-lcs (>= 1.1.3, < 2.0)
23
+ rspec-mocks (2.13.0)
15
24
  rubyzip (0.9.9)
16
- selenium-webdriver (2.29.0)
25
+ selenium-webdriver (2.31.0)
17
26
  childprocess (>= 0.2.5)
18
27
  multi_json (~> 1.0)
19
28
  rubyzip
20
29
  websocket (~> 1.0.4)
30
+ simplecov (0.7.1)
31
+ multi_json (~> 1.0)
32
+ simplecov-html (~> 0.7.1)
33
+ simplecov-html (0.7.1)
21
34
  watir-webdriver (0.6.2)
22
35
  selenium-webdriver (>= 2.18.0)
23
36
  websocket (1.0.7)
@@ -26,4 +39,6 @@ PLATFORMS
26
39
  x86-mingw32
27
40
 
28
41
  DEPENDENCIES
42
+ rspec
43
+ simplecov
29
44
  symbiont!
data/HISTORY.md CHANGED
@@ -1,6 +1,12 @@
1
1
  Change Log and History
2
2
  ======================
3
3
 
4
+ Version 0.2.0 / 2013-03-28
5
+ --------------------------
6
+
7
+ This release adds in more web objects, like labels, headings, and lists. I have also begun putting the unit tests back in place. An initial start has been made at recognizing multiple elements of a given type.
8
+
9
+
4
10
  Version 0.1.9 / 2013-02-06
5
11
  --------------------------
6
12
 
@@ -428,3 +428,19 @@ div.expanded {
428
428
  background-color: rgb(110,138,195);
429
429
  }
430
430
  /* End: Login Form */
431
+
432
+ #pub-grid {
433
+ border: 1px solid black;
434
+ color: white;
435
+ background-color: green;
436
+ }
437
+
438
+ #pub-grid thead {
439
+ border-bottom: 1px solid black;
440
+ vertical-align: center;
441
+ }
442
+
443
+ #pub-grid td {
444
+ vertical-align: bottom;
445
+ padding: 20px;
446
+ }
@@ -1,5 +1,7 @@
1
1
  $(document).ready(function() {
2
-
2
+
3
+ $('#name').focus();
4
+
3
5
  // Position the areas panel
4
6
  $('#areas').show().delay(500).animate({left:'-48em'},250).animate({left:'-51em'},250);
5
7
 
data/app/views/comics.erb CHANGED
@@ -1,6 +1,6 @@
1
1
  <section>
2
2
 
3
- <table id="comic-grid" class="display">
3
+ <table id="comic-grid" name="comic-grid" class="display">
4
4
  <thead>
5
5
  <tr>
6
6
  <th>Name</th>
@@ -319,4 +319,26 @@
319
319
  </tbody>
320
320
  </table>
321
321
 
322
+ <p>Basic Data:</p>
323
+ <table id="pub-grid">
324
+ <thead>
325
+ <tr>
326
+ <th>Publisher</th>
327
+ <th>Founded</th>
328
+ <th>Original Name</th>
329
+ </tr>
330
+ </thead>
331
+ <tbody>
332
+ <tr>
333
+ <td>DC</td>
334
+ <td id="dc_founded" name="dc_founded" class="pub">1934</td>
335
+ <td>National Allied Publications</td>
336
+ </tr>
337
+ <tr>
338
+ <td>Marvel</td>
339
+ <td id="marvel_founded" name="marvel_founded" class="pub">1939</td>
340
+ <td>Timely Publications</td>
341
+ </tr>
342
+ </tbody>
343
+ </table>
322
344
  </section>
@@ -30,7 +30,7 @@
30
30
  </div>
31
31
  <div>
32
32
  <label for="dob" class="label">Date of Birth</label>
33
- <input name="dob" type="text" id="dob" class="date" title="Please type your date of birth using this format: 01/19/2000"></input>
33
+ <input name="dob" type="text" id="dob" class="date" title="Please type your date of birth using this format: 01/19/2000">
34
34
  </div>
35
35
  <div>
36
36
  <label for="password" class="label">Password</label>
@@ -21,12 +21,15 @@ module Symbiont
21
21
  end
22
22
 
23
23
  def use_check_data_with(key, value)
24
- return self.send "check_#{key}" if value
25
- return self.send "uncheck_#{key}"
24
+ if value
25
+ self.send "check_#{key}"
26
+ else
27
+ self.send "uncheck_#{key}"
28
+ end
26
29
  end
27
30
 
28
31
  def use_select_data_with(key, value)
29
- return self.send "select_#{key}" if value
32
+ self.send "select_#{key}" if value
30
33
  end
31
34
 
32
35
  def text_settable_for(key)
@@ -42,6 +45,7 @@ module Symbiont
42
45
  end
43
46
 
44
47
  def object_enabled_for(key)
48
+ return true if (self.send "#{key}_object").tag_name == "textarea"
45
49
  self.send("#{key}_object").enabled?
46
50
  end
47
51
 
@@ -1,5 +1,21 @@
1
1
  module Symbiont
2
2
  module Enclosers
3
+ # Provides a context for an action that must succeed within a given time period.
4
+ # The logic here is simply that the result of the action will be true (meaning
5
+ # the action was carried out) or false, which means the action did not succeed
6
+ # in the time allotted.
7
+ #
8
+ # @param [Integer] timeout the amount of time in seconds to wait
9
+ # @param [String] message the text to return if the action did not occur in time
10
+ # @param [Proc] block the code that calls the desired action
11
+ #
12
+ # @example
13
+ # @page.wait_for(5, 'page with expected title not found') do
14
+ # @page.title.should == "Test App"
15
+ # end
16
+ def wait_for(timeout=Symbiont.page_level_wait, message=nil, &block)
17
+ platform.wait_for(timeout, message, &block)
18
+ end
3
19
 
4
20
  # Used to identify a web object or action on a web object as existing
5
21
  # within an enclosing window object. The window can be referenced using
@@ -33,9 +49,7 @@ module Symbiont
33
49
  # button :login, id: "btnSubmit", frame: encloser
34
50
  # end
35
51
  def within_frame(locator, encloser=nil, &block)
36
- encloser = [] if encloser.nil?
37
- encloser << locator
38
- block.call(encloser)
52
+ platform.within_frame(locator, encloser, &block)
39
53
  end
40
54
 
41
55
  # Used to identify a web object as existing within an enclosing object
@@ -54,23 +68,6 @@ module Symbiont
54
68
  yield if block_given?
55
69
  end
56
70
 
57
- # Provides a context for an action that must succeed within a given time period.
58
- # The logic here is simply that the result of the action will be true (meaning
59
- # the action was carried out) or false, which means the action did not succeed
60
- # in the time allotted.
61
- #
62
- # @param [Integer] timeout the amount of time in seconds to wait
63
- # @param [String] message the text to return if the action did not occur in time
64
- # @param [Proc] block the code that calls the desired action
65
- #
66
- # @example
67
- # @page.wait_for(5, 'page with expected title not found') do
68
- # @page.title.should == "Test App"
69
- # end
70
- def wait_for(timeout=Symbiont.page_level_wait, message=nil, &block)
71
- platform.wait_for(timeout, message, &block)
72
- end
73
-
74
71
  # Provides a context for an action that will generate a JavaScript alert
75
72
  # message box. The alert invocation will be overridden by the platform.
76
73
  #
@@ -81,15 +78,15 @@ module Symbiont
81
78
  # response = @page.will_alert do
82
79
  # @page.submitForm
83
80
  # end
84
- def will_alert(&block)
85
- platform.will_alert(&block)
81
+ def will_alert(encloser=nil, &block)
82
+ platform.will_alert(encloser, &block)
86
83
  end
87
84
 
88
85
  # Provides a context for an action that will generate a JavaScript
89
86
  # confirmation message box. The confirmation invocation will be
90
87
  # overridden by the platform.
91
88
  #
92
- # @param [bool] true to accept the confirmation, false to cancel it
89
+ # @param [bool] response true to accept the confirmation, false to cancel it
93
90
  # @param [Proc] block the code that generates the confirmation
94
91
  # @return [String] the message contained in the confirmation message box
95
92
  #
@@ -97,8 +94,8 @@ module Symbiont
97
94
  # response = @page.will_confirm(true) do
98
95
  # @page.areYouSure
99
96
  # end
100
- def will_confirm(response, &block)
101
- platform.will_confirm(response, &block)
97
+ def will_confirm(response, encloser=nil, &block)
98
+ platform.will_confirm(response, encloser, &block)
102
99
  end
103
100
 
104
101
  # Provides a context for an action that will generate a JavaScript prompt
@@ -113,8 +110,8 @@ module Symbiont
113
110
  # response = @page.will_prompt("use this") do
114
111
  # @page.useValue
115
112
  # end
116
- def will_prompt(response, &block)
117
- platform.will_prompt(response, &block)
113
+ def will_prompt(response, encloser=nil, &block)
114
+ platform.will_prompt(response, encloser, &block)
118
115
  end
119
116
 
120
117
  end # module: Enclosers
@@ -1,52 +1,81 @@
1
1
  module Symbiont
2
2
  module Evaluators
3
-
3
+
4
+ ## Browser-Level Actions ##
5
+
4
6
  def visit(url)
5
7
  platform.visit(url)
6
8
  end
7
-
8
- def text
9
- platform.text
10
- end
11
-
12
- def markup
13
- platform.markup
14
- end
15
-
16
- alias_method :html, :markup
17
-
18
- def title
19
- platform.title
20
- end
21
-
9
+
10
+ alias_method :navigate_to, :visit
11
+
22
12
  def url
23
13
  platform.url
24
14
  end
25
-
15
+
16
+ alias_method :current_url, :url
17
+
26
18
  # Save a snapshot of the current screen to a provided file location.
27
19
  # The file will be saved as a PNG file in the path specified or in the
28
20
  # location where the tests are being run from.
29
21
  def screenshot(file)
30
22
  platform.screenshot file
31
- end
32
-
33
- def focus
34
- platform.focus
35
23
  end
36
24
 
37
- alias_method :what_has_focus?, :focus
25
+ alias_method :save_screenshot, :screenshot
38
26
 
39
27
  # Executes JavaScript against the browser instance.
40
28
  def run_script(script)
41
29
  platform.run_script(script)
42
30
  end
43
-
31
+
44
32
  alias_method :execute_script, :run_script
45
33
 
46
34
  def back
47
35
  platform.back
48
36
  end
49
37
 
38
+ def forward
39
+ platform.forward
40
+ end
41
+
42
+ def refresh
43
+ platform.refresh
44
+ end
45
+
46
+ def remove_cookies
47
+ platform.remove_cookies
48
+ end
49
+
50
+ alias_method :clear_cookies, :remove_cookies
51
+
52
+ ## Page-Level Actions ##
53
+
54
+ def text
55
+ platform.text
56
+ end
57
+
58
+ def markup
59
+ platform.markup
60
+ end
61
+
62
+ alias_method :html, :markup
63
+
64
+ def title
65
+ platform.title
66
+ end
67
+
68
+ # Returns the element on a page that has the focus.
69
+ def focus
70
+ platform.focus
71
+ end
72
+
73
+ alias_method :what_has_focus?, :focus
74
+
75
+ def wait_for_app(value=1)
76
+ sleep value
77
+ end
78
+
50
79
  # Provides an evaluator that attempts to wait for any pending AJAX
51
80
  # requests from the jQuery library.
52
81
  def wait_for_pending_requests(time_limit=30, message_if_timeout=nil)
@@ -7,9 +7,9 @@ module Symbiont
7
7
  # @param [optional] block Logic to execute within the context of the
8
8
  # definition
9
9
  # @return [Object] instance of the definition
10
- def on(definition, &block)
11
- return @active if @active.class == definition
12
- @active = definition.new(@browser)
10
+ def on(definition, visit=false, &block)
11
+ definition = get_object_for(definition) if definition.is_a? String
12
+ @active = definition.new(@browser, visit)
13
13
  block.call @active if block
14
14
  @active
15
15
  end
@@ -22,81 +22,25 @@ module Symbiont
22
22
  # definition
23
23
  # @return [Object] instance of the definition
24
24
  def on_view(definition, &block)
25
- @active = definition.new(@browser, true)
26
- block.call @active if block
27
- @active
28
- end
29
-
30
- alias :during :on
31
- alias :start_activity :on_view
32
-
33
- # Starts a workflow, which is a set of predefined actions. You can use
34
- # this to navigate through a set of actions (and thus a set of
35
- # definitions). This is done by calling an action that is specified as
36
- # part of the workflow path. This action will be called on the relevant
37
- # definition at each point of the workflow.
38
- #
39
- # @param [Class] definition an instance of the definition; note this
40
- # instance must have the workflow action defined on it.
41
- # @param [Hash] elements a hash that contains an element with the
42
- # key :using. This is used to lookup the actions for the workflow.
43
- # @param [optional] block Logic to execute within the context of the
44
- # workflow.
45
- # @return [Object] the definition being used at that point of the
46
- # workflow.
47
- def start_workflow(definition, elements = {:using => :default}, &block)
48
- path = workflow_path_for(elements)
49
- to_element = find_element_for(path, definition) - 1
50
- go_through_definitions(path[0..to_element])
51
- on(definition, &block)
52
- end
53
-
54
- # This provides a way to start a workflow from somewhere other than the
55
- # start of the workflow. Specifically, the workflow will start from whatever
56
- # the active definition is.
57
- #
58
- # @param [Class] definition an instance of the definition; note this
59
- # instance must have the workflow action defined on it.
60
- # @param [Hash] elements a hash that contains an element with the
61
- # key :using. This is used to lookup the actions for the workflow.
62
- # @param [optional] block Logic to execute within the context of the
63
- # workflow.
64
- # @return [Object] the definition being used at that point of the
65
- # workflow.
66
- def continue_workflow(definition, elements = {:using => :default}, &block)
67
- path = workflow_path_for(elements)
68
- from_element = find_element_for(path, @active.class) + 1
69
- to_element = find_element_for(path, definition) - 1
70
- go_through_definitions(path[from_element..to_element])
71
- on(definition, &block)
25
+ on(definition, true, &block)
72
26
  end
73
-
74
- def workflow_path_for(elements)
75
- path = Symbiont::Factory.symbiont_workflow[elements[:using]]
76
- fail("Factory workflow :#{elements[:using].to_s} does not exist.") if path.nil?
77
- path
27
+
28
+ def if_on(definition, &block)
29
+ definition = get_object_for(definition) if definition.is_a? String
30
+ return @active unless @active.class == definition
31
+ on(definition, false, &block)
78
32
  end
79
-
80
- def find_element_for(path, definition)
81
- path.each_with_index { |each, index| return index if each[0] == definition }
82
- end
83
-
84
- def go_through_definitions(elements)
85
- elements.each do |definition, action|
86
- element = on(definition)
87
- fail("Action called #{action} not specified on #{definition}.") unless element.respond_to? action
88
- element.send action
33
+
34
+ alias_method :during, :on
35
+ alias_method :start_activity, :on_view
36
+ alias_method :start_on, :on_view
37
+
38
+ private
39
+
40
+ def get_object_for(definition)
41
+ definition.split('::').inject(Object) do |obj, name|
42
+ obj.const_get(name)
89
43
  end
90
44
  end
91
-
92
- class << self
93
- attr_accessor :symbiont_workflow
94
-
95
- def workflow=(path)
96
- raise("A default workflow path for a Factory workflow must exist.") unless path[:default]
97
- @symbiont_workflow = path
98
- end
99
- end
100
-
101
45
  end # module: Factory
102
46
  end # module: Symbiont