symbiont 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.md +6 -0
- data/app/app.rb +0 -1
- data/app/views/test_events.erb +21 -21
- data/lib/symbiont/enclosers.rb +2 -2
- data/lib/symbiont/evaluators.rb +15 -0
- data/lib/symbiont/factory.rb +69 -0
- data/lib/symbiont/platform_watir/platform_object.rb +1 -1
- data/lib/symbiont/version.rb +1 -1
- data/lib/symbiont.rb +2 -1
- data/spec/symbiont/enclosers_spec.rb +3 -3
- data/spec/symbiont/evaluators_spec.rb +11 -0
- data/spec/symbiont/factory_spec.rb +89 -2
- data/specs/support/test_steps/action_steps_webobjects.rb +2 -2
- metadata +2 -2
data/HISTORY.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
Change Log and History
|
2
2
|
======================
|
3
3
|
|
4
|
+
Version 0.1.6 / 2012-09-30
|
5
|
+
--------------------------
|
6
|
+
|
7
|
+
This releases provides two bits of functionality. One is an ability to wait for pending Ajax requests. Currently this is very specific to jQuery only. The other ability is that of providing workflows. The idea behind this feature is that you can specify a workflow that starts with an action (method) on a particular definition (class). That workflow may have a series of steps that are required in order to allow the action to take place. This new logic will attempt to execute all of those steps. The rationale behind this addition is to make it easier to specify output-driven logic.
|
8
|
+
|
9
|
+
|
4
10
|
Version 0.1.5 / 2012-09-12
|
5
11
|
--------------------------
|
6
12
|
|
data/app/app.rb
CHANGED
data/app/views/test_events.erb
CHANGED
@@ -1,28 +1,28 @@
|
|
1
1
|
<script type="text/javascript">
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
function unhide() {
|
3
|
+
document.getElementById("conditional").style.display="block";
|
4
|
+
}
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
function hide() {
|
7
|
+
document.getElementById("conditional").style.display="none";
|
8
|
+
}
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
function addDiv() {
|
11
|
+
var button = document.createElement("input");
|
12
|
+
button.setAttribute("type", "button");
|
13
|
+
button.setAttribute("value", "Newly Created Button");
|
14
|
+
button.setAttribute("id", "new_button");
|
15
|
+
//document.body.appendChild(button);
|
16
|
+
var sectional = document.getElementById("created")
|
17
|
+
sectional.appendChild(button);
|
18
|
+
}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
function removeDiv() {
|
21
|
+
var button = document.getElementById("new_button");
|
22
|
+
//document.body.removeChild(button);
|
23
|
+
var sectional = document.getElementById("created")
|
24
|
+
sectional.removeChild(button);
|
25
|
+
}
|
26
26
|
</script>
|
27
27
|
|
28
28
|
<section id="test_events">
|
data/lib/symbiont/enclosers.rb
CHANGED
@@ -35,8 +35,8 @@ module Symbiont
|
|
35
35
|
# @page.wait_for(5, 'page with expected title not found') do
|
36
36
|
# @page.title.should == "Test App"
|
37
37
|
# end
|
38
|
-
def wait_for(
|
39
|
-
@platform.wait_for(
|
38
|
+
def wait_for(message=nil, timeout=10, &block)
|
39
|
+
@platform.wait_for(message, timeout, &block)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Provides a context for an action that will generate a JavaScript alert
|
data/lib/symbiont/evaluators.rb
CHANGED
@@ -51,5 +51,20 @@ module Symbiont
|
|
51
51
|
|
52
52
|
alias :execute_script :run_script
|
53
53
|
|
54
|
+
# Provides an evaluator that attempts to wait for any pending AJAX
|
55
|
+
# requests from the jQuery library.
|
56
|
+
#
|
57
|
+
# @param [Numeric] timeout amount of time to wait
|
58
|
+
# @param [String] message text to print if timeout period is exceeded
|
59
|
+
def wait_for_pending_requests(timeout=30, message=nil)
|
60
|
+
end_time = ::Time.now + timeout
|
61
|
+
until ::Time.now > end_time
|
62
|
+
return if @browser.run_script('return jQuery.active') == 0
|
63
|
+
sleep 0.5
|
64
|
+
end
|
65
|
+
message = "Pending requests never indicated completion" unless message
|
66
|
+
raise message
|
67
|
+
end
|
68
|
+
|
54
69
|
end # module: Evaluators
|
55
70
|
end # module: Symbiont
|
data/lib/symbiont/factory.rb
CHANGED
@@ -8,6 +8,7 @@ module Symbiont
|
|
8
8
|
# definition
|
9
9
|
# @return [Object] instance of the definition
|
10
10
|
def on(definition, &block)
|
11
|
+
return @active if @active.class == definition
|
11
12
|
@active = definition.new(@browser)
|
12
13
|
block.call @active if block
|
13
14
|
@active
|
@@ -29,5 +30,73 @@ module Symbiont
|
|
29
30
|
alias :during :on
|
30
31
|
alias :start_activity :on_view
|
31
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)
|
72
|
+
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
|
78
|
+
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
|
89
|
+
end
|
90
|
+
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
|
+
|
32
101
|
end # module: Factory
|
33
102
|
end # module: Symbiont
|
@@ -67,7 +67,7 @@ module Symbiont
|
|
67
67
|
|
68
68
|
# Platform method to wait for an action to complete in a given time.
|
69
69
|
# @see Symbiont::Enclosers#wait_for
|
70
|
-
def wait_for(
|
70
|
+
def wait_for(message="wait condition not found", timeout, &block)
|
71
71
|
@browser.wait_until(timeout, message, &block)
|
72
72
|
end
|
73
73
|
|
data/lib/symbiont/version.rb
CHANGED
data/lib/symbiont.rb
CHANGED
@@ -2,6 +2,7 @@ require 'symbiont/version'
|
|
2
2
|
require 'symbiont/logger'
|
3
3
|
require 'symbiont/platforms'
|
4
4
|
require 'symbiont/generators'
|
5
|
+
require 'symbiont/factory'
|
5
6
|
require 'symbiont/enclosers'
|
6
7
|
require 'symbiont/evaluators'
|
7
8
|
require 'symbiont/locators'
|
@@ -12,7 +13,7 @@ module Symbiont
|
|
12
13
|
include Enclosers
|
13
14
|
include Evaluators
|
14
15
|
include Locators
|
15
|
-
|
16
|
+
include DataSetter
|
16
17
|
|
17
18
|
# Used to make a platform object accessible. Will hold object
|
18
19
|
# references like these:
|
@@ -14,10 +14,10 @@ describe Symbiont::Enclosers do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should wait for a condition to be true" do
|
17
|
-
watir_browser.should_receive(:wait_until).with(5, "
|
18
|
-
watir_definition.wait_for(
|
17
|
+
watir_browser.should_receive(:wait_until).with(5, "some condition")
|
18
|
+
watir_definition.wait_for("some condition", 5)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it "should handle alert message boxes" do
|
22
22
|
watir_browser.should_receive(:wd).twice.and_return(watir_browser)
|
23
23
|
watir_browser.should_receive(:execute_script).twice
|
@@ -54,6 +54,17 @@ describe Symbiont::Enclosers do
|
|
54
54
|
watir_browser.should_receive(:type).and_return(:submit)
|
55
55
|
watir_definition.focus.class.should == Symbiont::WebObjects::Button
|
56
56
|
end
|
57
|
+
|
58
|
+
it "should wait for jquery pending requests to finish" do
|
59
|
+
watir_browser.should_receive(:run_script).with('return jQuery.active').and_return(0)
|
60
|
+
watir_definition.wait_for_pending_requests
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return an exception if pending requests did not finish" do
|
64
|
+
watir_browser.should_receive(:run_script).with('return jQuery.active')
|
65
|
+
watir_browser.should_receive(:run_script).with('return jQuery.active').and_return(1)
|
66
|
+
expect { watir_definition.wait_for_pending_requests(1) }.to raise_error
|
67
|
+
end
|
57
68
|
end
|
58
69
|
end
|
59
70
|
end
|
@@ -5,31 +5,118 @@ class TestFactory
|
|
5
5
|
include Symbiont::Factory
|
6
6
|
|
7
7
|
attr_accessor :browser
|
8
|
+
attr_accessor :active
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestFactorySecond
|
12
|
+
include Symbiont
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestFactoryThird
|
16
|
+
include Symbiont
|
8
17
|
end
|
9
18
|
|
10
19
|
describe Symbiont::Factory do
|
20
|
+
#let(:watir_browser) { mock_browser_for_watir }
|
21
|
+
#let(:factory) { TestFactory.new(watir_browser) }
|
22
|
+
|
11
23
|
before(:each) do
|
12
24
|
@factory = TestFactory.new
|
13
25
|
@factory.browser = mock_browser_for_watir
|
14
26
|
end
|
15
27
|
|
16
|
-
it "should create a new definition object" do
|
28
|
+
it "should create a new definition object, using on" do
|
17
29
|
@factory.on DefinitionTest do |page|
|
18
30
|
page.should be_instance_of DefinitionTest
|
19
31
|
end
|
20
32
|
end
|
21
33
|
|
22
|
-
it "should create a new definition object
|
34
|
+
it "should create a new definition object, using during" do
|
35
|
+
@factory.during DefinitionTest do |page|
|
36
|
+
page.should be_instance_of DefinitionTest
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should create a new definition object and view it, using on_view" do
|
23
41
|
@factory.browser.should_receive(:goto).twice
|
24
42
|
@factory.on_view DefinitionTest do |page|
|
25
43
|
page.should be_instance_of DefinitionTest
|
26
44
|
end
|
27
45
|
end
|
28
46
|
|
47
|
+
it "should create a new definition object and view it, using start_activity" do
|
48
|
+
@factory.browser.should_receive(:goto).twice
|
49
|
+
@factory.start_activity DefinitionTest do |page|
|
50
|
+
page.should be_instance_of DefinitionTest
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
29
54
|
it "should set a reference to be used outside the factory" do
|
30
55
|
active = @factory.on DefinitionTest
|
31
56
|
current = @factory.instance_variable_get "@active"
|
32
57
|
current.should === active
|
33
58
|
end
|
34
59
|
|
60
|
+
it "should use an existing definition when that definition is already active" do
|
61
|
+
@factory.instance_variable_set "@active", TestFactorySecond.new(@factory.browser)
|
62
|
+
@factory.on(TestFactorySecond) do |page|
|
63
|
+
page.should be_instance_of TestFactorySecond
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not execute block if definition is not the active definition" do
|
68
|
+
@factory.instance_variable_set "@active", TestFactorySecond.new(@factory.browser)
|
69
|
+
@factory.on(TestFactoryThird) do |page|
|
70
|
+
page.should_not be_instance_of TestFactorySecond
|
71
|
+
page.should be_instance_of TestFactoryThird
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should store a workflow path" do
|
76
|
+
workflow = ['stage1', 'stage2', 'stage3']
|
77
|
+
Symbiont::Factory.workflow = {default: workflow}
|
78
|
+
Symbiont::Factory.symbiont_workflow[:default].should == workflow
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should be unable to work without a default worfklow path" do
|
82
|
+
expect { Symbiont::Factory.workflow = {another: []} }.to raise_error
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should start a workflow path by using the default path" do
|
86
|
+
paths = [[TestFactory, :first_action], [TestFactorySecond, :second_action]]
|
87
|
+
Symbiont::Factory.workflow = {:default => paths}
|
88
|
+
mock_page = double("mock_page")
|
89
|
+
TestFactory.should_receive(:new).and_return(mock_page)
|
90
|
+
mock_page.should_receive(:first_action)
|
91
|
+
@factory.start_workflow(TestFactorySecond).class.should == TestFactorySecond
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not start a workflow when there is no proper path" do
|
95
|
+
Symbiont::Factory.workflow = {:default => ['default'], :standard => ['standard']}
|
96
|
+
expect { @factory.start_workflow(TestFactory, :using => :invalid_path) }.to raise_error
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should not use a workflow when an action is not specified" do
|
100
|
+
Symbiont::Factory.workflow = {:default => [[TestFactory, :action_1], [TestFactorySecond, :action_2]]}
|
101
|
+
mock_page = double("mock_page")
|
102
|
+
TestFactory.should_receive(:new).and_return(mock_page)
|
103
|
+
mock_page.should_receive(:respond_to?).with(:action_1).and_return(false)
|
104
|
+
expect { @factory.start_workflow(TestFactorySecond) }.to raise_error
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should be able to continue along a workflow" do
|
108
|
+
Symbiont::Factory.workflow = {
|
109
|
+
:default => [[TestFactory, :action_1],
|
110
|
+
[TestFactorySecond, :action_2],
|
111
|
+
[TestFactoryThird, :action_3]]
|
112
|
+
}
|
113
|
+
mock_page = double("mock_page")
|
114
|
+
TestFactorySecond.should_receive(:new).and_return(mock_page)
|
115
|
+
mock_page.should_receive(:respond_to?).with(:action_2).and_return(true)
|
116
|
+
mock_page.should_receive(:action_2)
|
117
|
+
@factory.active = TestFactory.new()
|
118
|
+
TestFactory.should_not_receive(:new)
|
119
|
+
@factory.continue_workflow(TestFactoryThird).class.should == TestFactoryThird
|
120
|
+
end
|
121
|
+
|
35
122
|
end
|
@@ -15,13 +15,13 @@ end
|
|
15
15
|
Then (/^the reference ID text field should have a black background$/) do
|
16
16
|
@web_object = @page.bookRefID_object
|
17
17
|
@style = @web_object.style('background-color')
|
18
|
-
@style.should == "rgba(0,0,0,1)"
|
18
|
+
@style.should == "rgba(0, 0, 0, 1)"
|
19
19
|
end
|
20
20
|
|
21
21
|
Then (/^the reference ID text field should have yellow text$/) do
|
22
22
|
@web_object = @page.bookRefID_object
|
23
23
|
@style = @web_object.style('color')
|
24
|
-
@style.should == "rgba(255,255,0,1)"
|
24
|
+
@style.should == "rgba(255, 255, 0, 1)"
|
25
25
|
end
|
26
26
|
|
27
27
|
Then (/^the book title text field should be an input field$/) do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: symbiont
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|