symbiont 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +14 -0
  3. data/HISTORY.md +6 -0
  4. data/README.md +1 -1
  5. data/app/Gemfile +4 -0
  6. data/app/app.rb +167 -0
  7. data/app/config/database.rb +9 -0
  8. data/app/models/plan.rb +10 -0
  9. data/app/models/product.rb +10 -0
  10. data/app/models/study.rb +11 -0
  11. data/app/models/user.rb +13 -0
  12. data/app/public/css/style.css +138 -0
  13. data/app/views/create_plan.erb +21 -0
  14. data/app/views/create_product.erb +15 -0
  15. data/app/views/create_study.erb +24 -0
  16. data/app/views/create_user.erb +60 -0
  17. data/app/views/db_plans.erb +31 -0
  18. data/app/views/db_products.erb +29 -0
  19. data/app/views/db_studies.erb +33 -0
  20. data/app/views/db_users.erb +23 -0
  21. data/app/views/entity_list.erb +10 -0
  22. data/app/views/index.erb +7 -0
  23. data/app/views/layout.erb +39 -0
  24. data/app/views/login_page.erb +17 -0
  25. data/app/views/success_1.erb +2 -0
  26. data/app/views/success_2.erb +2 -0
  27. data/app/views/test_database.erb +13 -0
  28. data/app/views/test_events.erb +44 -0
  29. data/app/views/test_page.erb +164 -0
  30. data/lib/symbiont.rb +3 -0
  31. data/lib/symbiont/enclosers.rb +17 -0
  32. data/lib/symbiont/evaluators.rb +17 -0
  33. data/lib/symbiont/platform_watir/platform_object.rb +22 -2
  34. data/lib/symbiont/version.rb +1 -1
  35. data/lib/symbiont/web_objects/_common.rb +36 -1
  36. data/lib/symbiont/web_objects/table.rb +9 -0
  37. data/lib/symbiont/web_objects/table_row.rb +9 -0
  38. data/spec/symbiont/enclosers_spec.rb +5 -0
  39. data/spec/symbiont/evaluators_spec.rb +24 -0
  40. data/spec/symbiont/web_object_spec.rb +60 -2
  41. data/spec/symbiont/web_objects/table_row_spec.rb +9 -0
  42. data/spec/symbiont/web_objects/table_spec.rb +8 -0
  43. data/specs/button.feature +2 -0
  44. data/specs/definitions/pages.rb +17 -0
  45. data/specs/evaluators.feature +5 -0
  46. data/specs/events.feature +19 -0
  47. data/specs/link.feature +2 -0
  48. data/specs/support/test_steps/action_steps_buttons.rb +2 -0
  49. data/specs/support/test_steps/action_steps_evaluators.rb +3 -0
  50. data/specs/support/test_steps/action_steps_events.rb +40 -0
  51. data/specs/support/test_steps/action_steps_links.rb +2 -0
  52. data/specs/support/test_steps/action_steps_navigate.rb +4 -0
  53. data/specs/support/test_steps/action_steps_webobjects.rb +25 -0
  54. data/specs/web_object.feature +11 -0
  55. data/symbiont.gemspec +3 -3
  56. metadata +47 -13
@@ -3,9 +3,12 @@ require 'symbiont/logger'
3
3
  require 'symbiont/platforms'
4
4
  require 'symbiont/generators'
5
5
  require 'symbiont/enclosers'
6
+ require 'symbiont/evaluators'
6
7
 
7
8
  module Symbiont
8
9
  include Platforms
10
+ include Enclosers
11
+ include Evaluators
9
12
 
10
13
  # Used to make a platform object accessible. Will hold object
11
14
  # references like these:
@@ -22,5 +22,22 @@ module Symbiont
22
22
  block.call(encloser)
23
23
  end
24
24
 
25
+ # Provides a context for an action that must succeed within a given time period.
26
+ # The logic here is simply that the result of the action will be true (meaning
27
+ # the action was carried out) or false, which means the action did not succeed
28
+ # in the time allotted.
29
+ #
30
+ # @param [Integer] timeout the amount of time in seconds to wait
31
+ # @param [String] message the text to return if the action did not occur in time
32
+ # @param [Proc] block the code that calls the desired action
33
+ #
34
+ # @example
35
+ # @page.wait_for(5, 'page with expected title not found') do
36
+ # @page.title.should == "Test App"
37
+ # end
38
+ def wait_for(timeout=10, message=nil, &block)
39
+ @platform.wait_for(timeout, message, &block)
40
+ end
41
+
25
42
  end # module: Enclosers
26
43
  end # module: Symbiont
@@ -0,0 +1,17 @@
1
+ module Symbiont
2
+ module Evaluators
3
+
4
+ # Visits a page via a specified URL. The URL can be specified as a domain
5
+ # address or as a file-based link.
6
+ # @param [String] url the full URL to navigate to
7
+ def visit(url)
8
+ @platform.visit(url)
9
+ end
10
+
11
+ # Returns the text of the current page.
12
+ def text
13
+ @platform.text
14
+ end
15
+
16
+ end # module: Evaluators
17
+ end # module: Symbiont
@@ -7,13 +7,33 @@ module Symbiont
7
7
  def initialize(browser)
8
8
  @browser = browser
9
9
  end
10
-
10
+
11
+ ## Browser-Level Actions ##
12
+
11
13
  # Platform method to make a call to a specified URL.
12
- # See Symbiont::Generators#url_is
14
+ # See Symbiont#visit
13
15
  def visit(url)
14
16
  @browser.goto(url)
15
17
  end
16
18
 
19
+ ## Page-Level Actions ##
20
+
21
+ # Platform method to retrieve text from the current page.
22
+ # See Symbiont#text
23
+ def text
24
+ @browser.text
25
+ end
26
+
27
+ ## Encloser Methods ##
28
+
29
+ # Platform method to wait for an action to complete in a given time.
30
+ # @see Symbiont::Enclosers#wait_for
31
+ def wait_for(timeout, message=nil, &block)
32
+ @browser.wait_until(timeout, message, &block)
33
+ end
34
+
35
+ ## Generator Methods ##
36
+
17
37
  # Platform method to return a link object.
18
38
  # Link objects are of type: Symbiont::WebObjects::Link
19
39
  # @see Symbiont::Generators#link
@@ -1,3 +1,3 @@
1
1
  module Symbiont
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -31,10 +31,45 @@ module Symbiont
31
31
  @web_object.text
32
32
  end
33
33
 
34
- def when_actionable(timeout)
34
+ def click
35
+ @web_object.click
36
+ end
37
+
38
+ def attribute(name)
39
+ @web_object.attribute_value(name)
40
+ end
41
+
42
+ def style(property)
43
+ @web_object.style(property)
44
+ end
45
+
46
+ def when_actionable(timeout=5)
35
47
  @web_object.wait_until_present(timeout)
36
48
  self
37
49
  end
50
+
51
+ alias :when_present :when_actionable
52
+
53
+ def when_visible(timeout=5)
54
+ Object::Watir::Wait.until(timeout, "object not visible within #{timeout} seconds.") do
55
+ visible?
56
+ end
57
+ self
58
+ end
59
+
60
+ def when_not_visible(timeout=5)
61
+ Object::Watir::Wait.while(timeout, "object still visible after #{timeout} seconds.") do
62
+ visible?
63
+ end
64
+ self
65
+ end
66
+
67
+ alias :must_be_visible :when_visible
68
+ alias :must_not_be_visible :when_not_visible
69
+
70
+ def wait_until(timeout, message=nil, &block)
71
+ Object::Watir::Wait.until(timeout, message, &block)
72
+ end
38
73
  end # class: WebObject
39
74
 
40
75
  end # module: WebObjects
@@ -9,6 +9,15 @@ module Symbiont
9
9
  Object::Symbiont::WebObjects::TableRow.new(@web_object[index])
10
10
  end
11
11
 
12
+ # This method is an iterator that returns a TableRow object each time through
13
+ # the loop.
14
+ # @return [Symbiont::WebObjects::TableRow]
15
+ def each
16
+ for index in 1..self.rows do
17
+ yield self[index - 1]
18
+ end
19
+ end
20
+
12
21
  # This method will return the number of rows in a table.
13
22
  def rows
14
23
  @web_object.wd.find_elements(:xpath, row_xpath).size
@@ -9,6 +9,15 @@ module Symbiont
9
9
  Object::Symbiont::WebObjects::TableCell.new(@web_object[index])
10
10
  end
11
11
 
12
+ # This method is an iterator that returns a TableCell object each time through
13
+ # the loop.
14
+ # @return [Symbiont::WebObjects::TableCell]
15
+ def each
16
+ for index in 1..self.columns do
17
+ yield self[index - 1]
18
+ end
19
+ end
20
+
12
21
  # This method returns the number of columns in a table object.
13
22
  def columns
14
23
  @web_object.wd.find_elements(:xpath, cell_xpath).size
@@ -12,5 +12,10 @@ describe Symbiont::Enclosers do
12
12
  web_object.should_not be_nil
13
13
  web_object.should be_instance_of Symbiont::WebObjects::TextField
14
14
  end
15
+
16
+ it "should wait for a condition to be true" do
17
+ watir_browser.should_receive(:wait_until).with(5, "not quick enough")
18
+ watir_definition.wait_for(5, "not quick enough")
19
+ end
15
20
  end
16
21
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Symbiont::Enclosers do
4
+ let(:watir_browser) { mock_browser_for_watir }
5
+ let(:watir_definition) { DefinitionTest.new(watir_browser) }
6
+
7
+ describe "browser-level actions" do
8
+ context "a definition using watir-webdriver" do
9
+ it "should visit a page" do
10
+ watir_browser.should_receive(:goto).with("http://localhost:4567")
11
+ watir_definition.visit("http://localhost:4567")
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "page-level actions" do
17
+ context "a definition using watir-webdriver" do
18
+ it "should return all the text on a page" do
19
+ watir_browser.should_receive(:text).and_return("page text")
20
+ watir_definition.text.should == "page text"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,6 +4,16 @@ describe "Web Objects" do
4
4
  let(:watir_browser) { mock_browser_for_watir }
5
5
  let(:watir_definition) { ::Symbiont::WebObjects::WebObject.new(watir_browser) }
6
6
 
7
+ it "should retrieve the value of an attribute" do
8
+ watir_browser.should_receive(:attribute_value).and_return(true)
9
+ watir_definition.attribute("readonly").should be_true
10
+ end
11
+
12
+ it "should retrieve the style of a web object" do
13
+ watir_browser.should_receive(:style).with('display').and_return("none")
14
+ watir_definition.style('display').should == 'none'
15
+ end
16
+
7
17
  it "should determine if a web object is enabled" do
8
18
  watir_browser.should_receive(:enabled?).and_return(true)
9
19
  watir_definition.enabled?.should == true
@@ -19,19 +29,67 @@ describe "Web Objects" do
19
29
  watir_definition.exists?.should == true
20
30
  end
21
31
 
32
+ it "should determine if a web object does not exist" do
33
+ watir_browser.should_receive(:exists?).and_return(false)
34
+ watir_definition.exists?.should == false
35
+ end
36
+
22
37
  it "should determine if a web object is visible" do
23
38
  watir_browser.should_receive(:visible?).and_return(true)
24
39
  watir_definition.visible?.should == true
25
40
  end
26
41
 
42
+ it "should determine if a web object is not visible" do
43
+ watir_browser.should_receive(:visible?).and_return(false)
44
+ watir_definition.visible?.should == false
45
+ end
46
+
27
47
  it "should return the text contained by a web object" do
28
48
  watir_browser.should_receive(:text).and_return("testing")
29
49
  watir_definition.text.should == "testing"
30
50
  end
31
51
 
32
- it "should wait for web object to be actionable" do
33
- watir_browser.stub(:wait_until_present).with(5)
52
+ it "should simulate a click event on a web object" do
53
+ watir_browser.should_receive(:click)
54
+ watir_definition.click
55
+ end
56
+
57
+ it "should wait for a web object to be actionable" do
58
+ watir_browser.should_receive(:wait_until_present).twice.with(5)
59
+ watir_definition.when_actionable(5)
60
+ watir_definition.when_present(5)
61
+ end
62
+
63
+ it "should reference a web object when it is actionable" do
64
+ watir_browser.should_receive(:wait_until_present).with(5)
34
65
  web_object = watir_definition.when_actionable(5)
35
66
  web_object.should === watir_definition
36
67
  end
68
+
69
+ it "should wait for a web object to become visible" do
70
+ watir_browser.should_receive(:visible?).and_return(true)
71
+ watir_definition.when_visible(5)
72
+ end
73
+
74
+ it "should reference a web object when it is visible" do
75
+ watir_browser.should_receive(:visible?).and_return(true)
76
+ web_object = watir_definition.when_visible(5)
77
+ web_object.should === watir_definition
78
+ end
79
+
80
+ it "should wait for a web object to become invisible" do
81
+ watir_browser.should_receive(:visible?).and_return(false)
82
+ watir_definition.when_not_visible(5)
83
+ end
84
+
85
+ it "should reference a web object when it is not visible" do
86
+ watir_browser.stub(:visible?).and_return(false)
87
+ web_object = watir_definition.when_not_visible(5)
88
+ web_object.should === watir_definition
89
+ end
90
+
91
+ it "should wait until a specific condition occurs" do
92
+ Object::Watir::Wait.stub(:until).with(5, "Condition occurred.")
93
+ watir_definition.wait_until(5, "Condition occurred.") { true }
94
+ end
37
95
  end
@@ -19,6 +19,15 @@ describe Symbiont::WebObjects::TableRow do
19
19
  table_row_object.should_receive(:size).and_return(3)
20
20
  table_row.columns.should == 3
21
21
  end
22
+
23
+ it "should iterate over the table columns" do
24
+ table_row = Symbiont::WebObjects::TableRow.new(table_row_object)
25
+ table_row.should_receive(:columns).and_return(2)
26
+ table_row.stub(:[]).and_return(table_row_object)
27
+ count = 0
28
+ table_row.each { |e| count += 1 }
29
+ count.should == 2
30
+ end
22
31
  end
23
32
  end
24
33
  end
@@ -28,6 +28,14 @@ describe Symbiont::WebObjects::Table do
28
28
  table_object.should_receive(:size).and_return(2)
29
29
  watir_table.rows.should == 2
30
30
  end
31
+
32
+ it "should iterate over the table rows" do
33
+ watir_table.should_receive(:rows).and_return(2)
34
+ table_object.stub(:[]).and_return(table_object)
35
+ count = 0
36
+ watir_table.each { |e| count += 1 }
37
+ count.should == 2
38
+ end
31
39
  end
32
40
  end
33
41
  end
@@ -39,3 +39,5 @@ Feature: Ability to Support Button Web Objects
39
39
  | class |
40
40
  | xpath |
41
41
  | index |
42
+ | value |
43
+ | text |
@@ -21,12 +21,16 @@ class SimpleObjectPage
21
21
  link :avengersClass, class: "avengersClass"
22
22
  link :avengersXPath, xpath: "id('avengersID')"
23
23
  link :avengersIndex, {id: "avengersID", index: 0}
24
+ link :avengersText, text: "Avengers Assemble"
25
+ link :avengersHref, href: "success_1"
24
26
 
25
27
  button :clickmeID, id: "clickmeID"
26
28
  button :clickmeName, name: "clickmeName"
27
29
  button :clickmeClass, class: "clickmeClass"
28
30
  button :clickmeXPath, xpath: "//input[@id='clickmeID']"
29
31
  button :clickmeIndex, {id: "clickmeID", index: 0}
32
+ button :clickmeValue, value: "Click Me"
33
+ button :clickmeText, text: "Click Me"
30
34
 
31
35
  button :cantClickMeID, id: "cantclickmeID"
32
36
 
@@ -38,6 +42,7 @@ class SimpleObjectPage
38
42
  text_field :bookTitleXPath, xpath: "//input[@id='bookTitleID']"
39
43
  text_field :bookTitleIndex, {id: "bookTitleID", index: 0}
40
44
 
45
+ text_field :bookRefID, id: "bookRefID"
41
46
  text_field :bookPubID, id: "bookPubID"
42
47
  text_field :fake_text_field, id: "fake_text_field"
43
48
 
@@ -91,6 +96,18 @@ class SimpleObjectPage
91
96
  span :spanTextClass, class: "spanTextClass"
92
97
  end
93
98
 
99
+ class SimpleEventsPage
100
+ include Symbiont
101
+
102
+ url_is "http://localhost:4567/test_events"
103
+
104
+ button :conditional, id: "conditional"
105
+ button :hideButton, value: "Hide Button"
106
+ button :revealButton, value: "Reveal Button"
107
+ button :createButton, value: "Create Button"
108
+ button :removeButton, value: "Remove Button"
109
+ end
110
+
94
111
  class LoggingIn
95
112
  include Symbiont
96
113
  begin_at "http://localhost:4567/test_database"
@@ -0,0 +1,5 @@
1
+ Feature: Ability to handle browser and page actions.
2
+
3
+ Scenario: Getting web page text
4
+ When on the object test page
5
+ Then the page should contain the text "Multiphasic Temporal Convergence"
@@ -0,0 +1,19 @@
1
+ Feature: Ability to Handle Events or Time-Based Situations
2
+
3
+ Scenario: Waiting for a general condition
4
+ When performing a successful action on the object test page
5
+ Then the test should wait for a success page
6
+
7
+ Scenario: Waiting for an object to be invisible
8
+ When on the events test page
9
+ Then the conditional button can be clicked
10
+ When the conditional button is hidden
11
+ Then the test will wait until the conditional button is invisible
12
+ And after that time the conditional button should not be visible
13
+
14
+ Scenario: Waiting for an object to be visible
15
+ When the conditional button on the events test page is invisible
16
+ And the conditional button is revealed
17
+ Then the test will wait until the conditional button is visible before clicking it
18
+
19
+
@@ -30,3 +30,5 @@ Feature: Ability to Support Link Web Objects
30
30
  | class |
31
31
  | xpath |
32
32
  | index |
33
+ | text |
34
+ | href |
@@ -10,6 +10,8 @@ When (/^the click me button on the object test page is clicked by "([^"]*)"$/) d
10
10
  @page.clickmeClass if locator == "class"
11
11
  @page.clickmeXPath if locator == "xpath"
12
12
  @page.clickmeIndex if locator == "index"
13
+ @page.clickmeValue if locator == "value"
14
+ @page.clickmeText if locator == "text"
13
15
  end
14
16
 
15
17
  Then (/^the click me button should exist$/) do
@@ -0,0 +1,3 @@
1
+ Then (/^the page should contain the text "([^"]*)"$/) do |text|
2
+ @page.text.include? text
3
+ end
@@ -0,0 +1,40 @@
1
+ When (/^performing a successful action on the object test page$/) do
2
+ step %{on the object test page}
3
+ @page.clickmeID
4
+ end
5
+
6
+ When (/^the conditional button is hidden$/) do
7
+ @page.hideButton
8
+ end
9
+
10
+ When (/^the conditional button is revealed$/) do
11
+ @page.revealButton
12
+ end
13
+
14
+ When (/^the conditional button on the events test page is invisible$/) do
15
+ step %{on the events test page}
16
+ step %{the conditional button is hidden}
17
+ end
18
+
19
+ Then (/^the test should wait for a success page$/) do
20
+ @page.wait_for(10, "success page did not come up in time") do
21
+ @page.text.include? 'Success'
22
+ end
23
+ end
24
+
25
+ Then (/^the conditional button can be clicked$/) do
26
+ @page.conditional
27
+ end
28
+
29
+ Then (/^the test will wait until the conditional button is invisible$/) do
30
+ @page.conditional_button.when_not_visible
31
+ end
32
+
33
+ Then (/^after that time the conditional button should not be visible$/) do
34
+ @page.conditional_visible?.should == false
35
+ end
36
+
37
+ Then (/^the test will wait until the conditional button is visible before clicking it$/) do
38
+ @page.conditional_button.when_visible
39
+ @page.conditional
40
+ end