symbiont 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|