symbiont 0.1.9 → 0.2.0

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 (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