symbiont 0.1.0 → 0.1.1
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.
- data/.gitignore +1 -0
- data/.travis.yml +14 -0
- data/HISTORY.md +6 -0
- data/README.md +1 -1
- data/app/Gemfile +4 -0
- data/app/app.rb +167 -0
- data/app/config/database.rb +9 -0
- data/app/models/plan.rb +10 -0
- data/app/models/product.rb +10 -0
- data/app/models/study.rb +11 -0
- data/app/models/user.rb +13 -0
- data/app/public/css/style.css +138 -0
- data/app/views/create_plan.erb +21 -0
- data/app/views/create_product.erb +15 -0
- data/app/views/create_study.erb +24 -0
- data/app/views/create_user.erb +60 -0
- data/app/views/db_plans.erb +31 -0
- data/app/views/db_products.erb +29 -0
- data/app/views/db_studies.erb +33 -0
- data/app/views/db_users.erb +23 -0
- data/app/views/entity_list.erb +10 -0
- data/app/views/index.erb +7 -0
- data/app/views/layout.erb +39 -0
- data/app/views/login_page.erb +17 -0
- data/app/views/success_1.erb +2 -0
- data/app/views/success_2.erb +2 -0
- data/app/views/test_database.erb +13 -0
- data/app/views/test_events.erb +44 -0
- data/app/views/test_page.erb +164 -0
- data/lib/symbiont.rb +3 -0
- data/lib/symbiont/enclosers.rb +17 -0
- data/lib/symbiont/evaluators.rb +17 -0
- data/lib/symbiont/platform_watir/platform_object.rb +22 -2
- data/lib/symbiont/version.rb +1 -1
- data/lib/symbiont/web_objects/_common.rb +36 -1
- data/lib/symbiont/web_objects/table.rb +9 -0
- data/lib/symbiont/web_objects/table_row.rb +9 -0
- data/spec/symbiont/enclosers_spec.rb +5 -0
- data/spec/symbiont/evaluators_spec.rb +24 -0
- data/spec/symbiont/web_object_spec.rb +60 -2
- data/spec/symbiont/web_objects/table_row_spec.rb +9 -0
- data/spec/symbiont/web_objects/table_spec.rb +8 -0
- data/specs/button.feature +2 -0
- data/specs/definitions/pages.rb +17 -0
- data/specs/evaluators.feature +5 -0
- data/specs/events.feature +19 -0
- data/specs/link.feature +2 -0
- data/specs/support/test_steps/action_steps_buttons.rb +2 -0
- data/specs/support/test_steps/action_steps_evaluators.rb +3 -0
- data/specs/support/test_steps/action_steps_events.rb +40 -0
- data/specs/support/test_steps/action_steps_links.rb +2 -0
- data/specs/support/test_steps/action_steps_navigate.rb +4 -0
- data/specs/support/test_steps/action_steps_webobjects.rb +25 -0
- data/specs/web_object.feature +11 -0
- data/symbiont.gemspec +3 -3
- metadata +47 -13
data/lib/symbiont.rb
CHANGED
@@ -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:
|
data/lib/symbiont/enclosers.rb
CHANGED
@@ -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
|
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
|
data/lib/symbiont/version.rb
CHANGED
@@ -31,10 +31,45 @@ module Symbiont
|
|
31
31
|
@web_object.text
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
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
|
33
|
-
watir_browser.
|
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
|
data/specs/button.feature
CHANGED
data/specs/definitions/pages.rb
CHANGED
@@ -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,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
|
+
|
data/specs/link.feature
CHANGED
@@ -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,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
|