kameleon 0.0.1.pre
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/LICENCE +20 -0
- data/lib/kameleon.rb +7 -0
- data/lib/kameleon/dsl/act.rb +27 -0
- data/lib/kameleon/dsl/see.rb +43 -0
- data/lib/kameleon/session/capybara.rb +45 -0
- data/lib/kameleon/user/abstract.rb +35 -0
- data/lib/kameleon/user/base.rb +7 -0
- data/lib/kameleon/user/guest.rb +14 -0
- data/spec/sample_rack_app/hey.rb +10 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/unit/act_spec.rb +38 -0
- data/spec/unit/guest_spec.rb +63 -0
- data/spec/unit/see_spec.rb +177 -0
- metadata +82 -0
data/LICENCE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Michał Czyż <http://linkd.in/michalczyz> @cs3b
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/kameleon.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Kameleon
|
2
|
+
module Dsl
|
3
|
+
module Act
|
4
|
+
|
5
|
+
def click(*links)
|
6
|
+
links.each do |link|
|
7
|
+
session.click_on(link)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# def click(link_text, options={:within => DEFAULT_AREA})
|
12
|
+
# yield if block_given?
|
13
|
+
# rspec_world.within(options[:within]) do
|
14
|
+
# begin
|
15
|
+
# rspec_world.click_on(self_or_translation_for(link_text))
|
16
|
+
# rescue Capybara::ElementNotFound => e
|
17
|
+
# attr_value, attr_type = within_value_and_type(options[:within])
|
18
|
+
# xpath = attr_type ? "//*[@#{attr_type}='#{attr_value}']//*[*='%s']/*" : "//*[#{attr_type}]//*[*='%s']/*"
|
19
|
+
# rspec_world.find(:xpath, xpath % self_or_translation_for(link_text)).click
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#end
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Kameleon
|
2
|
+
module Dsl
|
3
|
+
module See
|
4
|
+
def see(*content)
|
5
|
+
options = extract_options(content)
|
6
|
+
|
7
|
+
case options.class.name
|
8
|
+
when 'String'
|
9
|
+
session.should rspec_world.have_content(options)
|
10
|
+
when 'Array'
|
11
|
+
options.each do |content_part|
|
12
|
+
session.should rspec_world.have_content(content_part)
|
13
|
+
end
|
14
|
+
when 'Hash'
|
15
|
+
options.each_pair do |value, locator|
|
16
|
+
session.should rspec_world.have_field(locator, :with => value)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
raise "Not Implemented Structure #{options} :: #{options.class}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def not_see(*content)
|
24
|
+
options = extract_options(content)
|
25
|
+
|
26
|
+
case options.class.name
|
27
|
+
when 'String'
|
28
|
+
session.should_not rspec_world.have_content(options)
|
29
|
+
when 'Array'
|
30
|
+
options.each do |content_part|
|
31
|
+
session.should_not rspec_world.have_content(content_part)
|
32
|
+
end
|
33
|
+
when 'Hash'
|
34
|
+
options.each_pair do |value, locator|
|
35
|
+
session.should_not rspec_world.have_field(locator, :with => value)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise "Not Implemented Structure #{options} :: #{options.class}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Kameleon
|
2
|
+
module Session
|
3
|
+
module Capybara
|
4
|
+
|
5
|
+
attr_accessor :session_name
|
6
|
+
attr_accessor :driver_name
|
7
|
+
|
8
|
+
def set_session
|
9
|
+
@session = find_or_create_session ||
|
10
|
+
current_session
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def find_or_create_session
|
16
|
+
find_session ||
|
17
|
+
create_session
|
18
|
+
end
|
19
|
+
|
20
|
+
#! in future we should print notice when selected drive is different then session that have been chosen
|
21
|
+
def find_session
|
22
|
+
session_pool[session_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_session
|
26
|
+
::Capybara::Session.new(current_driver, ::Capybara.app).tap do |session|
|
27
|
+
session_pool[session_name] = session
|
28
|
+
end if session_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def session_pool
|
32
|
+
::Capybara.send(:session_pool)
|
33
|
+
end
|
34
|
+
|
35
|
+
def current_session
|
36
|
+
::Capybara.current_session
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_driver
|
40
|
+
driver_name ||
|
41
|
+
::Capybara.current_driver
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Kameleon
|
2
|
+
module User
|
3
|
+
class Abstract
|
4
|
+
attr_accessor :options
|
5
|
+
attr_accessor :rspec_world
|
6
|
+
attr_accessor :session
|
7
|
+
|
8
|
+
include Kameleon::Session::Capybara
|
9
|
+
include Kameleon::Dsl::See
|
10
|
+
include Kameleon::Dsl::Act
|
11
|
+
|
12
|
+
def visit(page)
|
13
|
+
session.visit(page)
|
14
|
+
end
|
15
|
+
|
16
|
+
def will(&block)
|
17
|
+
instance_eval(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def load_homepage?
|
23
|
+
!options[:skip_page_autoload]
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract_options(opts)
|
27
|
+
if opts.size == 1
|
28
|
+
opts.first
|
29
|
+
else
|
30
|
+
opts
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Kameleon
|
2
|
+
module User
|
3
|
+
class Guest < Abstract
|
4
|
+
def initialize(rspec_world, options={})
|
5
|
+
@rspec_world = rspec_world
|
6
|
+
@driver_name = options.delete(:driver)
|
7
|
+
@session_name = options.delete(:session_name)
|
8
|
+
@options = options
|
9
|
+
set_session
|
10
|
+
session.visit('/') if load_homepage?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Act" do
|
4
|
+
include ::Capybara::DSL
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Capybara.app = Hey.new(%q{
|
8
|
+
<h1>This is simple app</h1>
|
9
|
+
<a href="next_page.html">Load Next Page</a>
|
10
|
+
<form>
|
11
|
+
|
12
|
+
<input type="submit" value="Save changes" class="btn primary">
|
13
|
+
<button class="btn" type="reset">Cancel</button>
|
14
|
+
|
15
|
+
</form>
|
16
|
+
|
17
|
+
})
|
18
|
+
@user = Kameleon::User::Guest.new(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "clicks on link" do
|
22
|
+
@user.click "Load Next Page"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "clicks on buttons" do
|
26
|
+
@user.click "Save changes"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "allow to chain many clicks - with success" do
|
30
|
+
@user.click "Save changes", "Load Next Page", "Save changes"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "allow to chain many clicks - raise error, if at least one of them not found" do
|
34
|
+
lambda {
|
35
|
+
@user.click "Save changes", "Load Next Page", "Submit", "Load Next Page"
|
36
|
+
}.should raise_error(Capybara::ElementNotFound)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Kameleon::User::Guest" do
|
4
|
+
include ::Capybara::DSL
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Capybara.app = Hey.new("Hello You :-)")
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
context "guest user" do
|
12
|
+
before(:all) do
|
13
|
+
@guest = Kameleon::User::Guest.new(self, {:session_name => :see_world})
|
14
|
+
@another_guest = Kameleon::User::Guest.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "sessions" do
|
18
|
+
it "by default user should get current session" do
|
19
|
+
@another_guest.session.should == Capybara.current_session
|
20
|
+
end
|
21
|
+
|
22
|
+
it "guests should have separate session if param :session_name defined" do
|
23
|
+
@guest.session.should_not == Capybara.current_session
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "driver" do
|
28
|
+
it "will not change if not defined in params" do
|
29
|
+
@guest.session.driver.should be_a Capybara.current_session.driver.class
|
30
|
+
end
|
31
|
+
|
32
|
+
context "selecting custom driver" do
|
33
|
+
before(:all) do
|
34
|
+
@selenium = Kameleon::User::Guest.new(self, {:session_name => :new_world, :driver => :selenium, :skip_page_autoload => true})
|
35
|
+
end
|
36
|
+
it "should set Selenium if params :driver => :selenium" do
|
37
|
+
@selenium.session.driver.should be_a Capybara::Selenium::Driver
|
38
|
+
end
|
39
|
+
it "shouldn't change drivers for other users'" do
|
40
|
+
[@guest, @another_guest].each do |user|
|
41
|
+
user.session.driver.should be_a Capybara::RackTest::Driver
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "perform request" do
|
49
|
+
before(:all) do
|
50
|
+
@user = Kameleon::User::Guest.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should be able to see response" do
|
54
|
+
@user.see("Hello")
|
55
|
+
end
|
56
|
+
|
57
|
+
it "using will block" do
|
58
|
+
@user.will do
|
59
|
+
see "Hello"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "See" do
|
4
|
+
include ::Capybara::DSL
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
Capybara.app = Hey.new(%q{
|
8
|
+
<h1>This is simple app</h1>
|
9
|
+
<p>and there is many lines</p>
|
10
|
+
<p>i that app</p>
|
11
|
+
|
12
|
+
<form>
|
13
|
+
<fieldset>
|
14
|
+
<legend>Example form legend</legend>
|
15
|
+
<label for="xlInput">X-Large input</label>
|
16
|
+
<input type="text" size="30" name="xlInput" id="xlInput" value="this is great value" class="xlarge">
|
17
|
+
|
18
|
+
<label for="normalSelect">Select</label>
|
19
|
+
<select id="normalSelect" name="normalSelect">
|
20
|
+
<option>1</option>
|
21
|
+
<option>2</option>
|
22
|
+
<option>3</option>
|
23
|
+
<option>4</option>
|
24
|
+
<option>5</option>
|
25
|
+
</select>
|
26
|
+
|
27
|
+
<label for="mediumSelect">Select</label>
|
28
|
+
<select id="mediumSelect" name="mediumSelect" class="medium">
|
29
|
+
<option>1</option>
|
30
|
+
<option>2</option>
|
31
|
+
<option>3</option>
|
32
|
+
<option>4</option>
|
33
|
+
<option>5</option>
|
34
|
+
</select>
|
35
|
+
<label for="multiSelect">Multiple select</label>
|
36
|
+
<select id="multiSelect" name="multiSelect" multiple="multiple" size="5" class="medium">
|
37
|
+
<option>1</option>
|
38
|
+
<option>2</option>
|
39
|
+
<option>3</option>
|
40
|
+
<option>4</option>
|
41
|
+
<option>5</option>
|
42
|
+
</select>
|
43
|
+
|
44
|
+
<label for="disabledInput">Disabled input</label>
|
45
|
+
<input type="text" disabled="" placeholder="Disabled input here carry on." size="30" name="disabledInput" id="disabledInput" class="xlarge disabled">
|
46
|
+
|
47
|
+
<label for="disabledInput">Disabled textarea</label>
|
48
|
+
<textarea disabled="" rows="3" id="textarea" name="textarea" class="xxlarge"></textarea>
|
49
|
+
</fieldset>
|
50
|
+
|
51
|
+
<fieldset>
|
52
|
+
<label for="prependedInput">Prepended text</label>
|
53
|
+
<input type="text" size="16" name="prependedInput" id="prependedInput" class="medium">
|
54
|
+
|
55
|
+
<label for="prependedInput2">Prepended checkbox</label>
|
56
|
+
<label class="add-on"><input type="checkbox" value="" id="" name=""></label>
|
57
|
+
<input type="text" size="16" name="prependedInput2" id="prependedInput2" class="mini">
|
58
|
+
|
59
|
+
<label for="appendedInput">Appended checkbox</label>
|
60
|
+
<input type="text" size="16" name="appendedInput" id="appendedInput" class="mini">
|
61
|
+
<label class="add-on active"><input type="checkbox" checked="checked" value="" id="" name=""></label>
|
62
|
+
|
63
|
+
<label for="fileInput">File input</label>
|
64
|
+
<input type="file" name="fileInput" id="fileInput" class="input-file">
|
65
|
+
</fieldset>
|
66
|
+
|
67
|
+
<fieldset>
|
68
|
+
<label id="optionsCheckboxes">List of options</label>
|
69
|
+
|
70
|
+
<label>
|
71
|
+
<input type="checkbox" value="option1" name="optionsCheckboxes">
|
72
|
+
<span>Option one is this and that—be sure to include why it's great</span>
|
73
|
+
</label>
|
74
|
+
|
75
|
+
<label>
|
76
|
+
<input type="checkbox" value="option2" name="optionsCheckboxes">
|
77
|
+
<span>Option two can also be checked and included in form results</span>
|
78
|
+
</label>
|
79
|
+
|
80
|
+
<label>
|
81
|
+
<input type="checkbox" value="option2" name="optionsCheckboxes">
|
82
|
+
<span>Option three can—yes, you guessed it—also be checked and included in form results. Let's make it super long so that everyone can see how it wraps, too.</span>
|
83
|
+
</label>
|
84
|
+
|
85
|
+
<label class="disabled">
|
86
|
+
<input type="checkbox" disabled="" value="option2" name="optionsCheckboxes">
|
87
|
+
<span>Option four cannot be checked as it is disabled.</span>
|
88
|
+
</label>
|
89
|
+
|
90
|
+
<label>Date range</label>
|
91
|
+
<div class="inline-inputs">
|
92
|
+
<input type="text" value="May 1, 2011" class="small">
|
93
|
+
<input type="text" value="12:00am" class="mini">
|
94
|
+
to
|
95
|
+
<input type="text" value="May 8, 2011" class="small">
|
96
|
+
<input type="text" value="11:59pm" class="mini">
|
97
|
+
<span class="help-block">All times are shown as Pacific Standard Time (GMT -08:00).</span>
|
98
|
+
</div>
|
99
|
+
|
100
|
+
<label for="textarea">Textarea</label>
|
101
|
+
<textarea rows="3" name="textarea2" id="textarea2" class="xxlarge"></textarea>
|
102
|
+
|
103
|
+
<label id="optionsRadio">List of options</label>
|
104
|
+
<div class="input">
|
105
|
+
<label>
|
106
|
+
<input type="radio" value="option1" name="optionsRadios" checked="">
|
107
|
+
<span>Option one is this and that—be sure to include why it's great</span>
|
108
|
+
</label>
|
109
|
+
|
110
|
+
<label>
|
111
|
+
<input type="radio" value="option2" name="optionsRadios">
|
112
|
+
<span>Option two can is something else and selecting it will deselect options 1</span>
|
113
|
+
</label>
|
114
|
+
</div>
|
115
|
+
|
116
|
+
<input type="submit" value="Save changes" class="btn primary"> <button class="btn" type="reset">Cancel</button>
|
117
|
+
|
118
|
+
</fieldset>
|
119
|
+
</form>
|
120
|
+
})
|
121
|
+
@user = Kameleon::User::Guest.new(self)
|
122
|
+
end
|
123
|
+
|
124
|
+
context "and can judge that there is no text on site" do
|
125
|
+
it "with single param" do
|
126
|
+
@user.not_see "cool rails app"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "with multiple params at once" do
|
130
|
+
@user.not_see "sinatra app",
|
131
|
+
"padrino app"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "it will fail if at least one text is visibile" do
|
135
|
+
lambda {
|
136
|
+
@user.not_see "sinatra app",
|
137
|
+
"This is simple app"
|
138
|
+
}.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "text in site" do
|
143
|
+
it "when single parameter" do
|
144
|
+
@user.see "This is simple app"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "when many strings" do
|
148
|
+
@user.see "This is simple app",
|
149
|
+
"and there is many lines",
|
150
|
+
"i that app"
|
151
|
+
end
|
152
|
+
|
153
|
+
it "when many strings should fail if there is at least one missing" do
|
154
|
+
lambda {
|
155
|
+
@user.see("sinatra app",
|
156
|
+
"and there is many lines",
|
157
|
+
"i that app")
|
158
|
+
}.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
159
|
+
end
|
160
|
+
|
161
|
+
context "that are value for form" do
|
162
|
+
it "by input id" do
|
163
|
+
@user.see 'this is great value' => 'xlInput'
|
164
|
+
end
|
165
|
+
|
166
|
+
it "by input label" do
|
167
|
+
@user.see 'this is great value' => 'X-Large input'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "that are not value for form" do
|
172
|
+
it "by input id" do
|
173
|
+
@user.not_see 'this is not such a great value' => 'xlInput'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kameleon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.pre
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michał Czyż [@cs3b]
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name:
|
16
|
+
- capybara
|
17
|
+
- rspec
|
18
|
+
requirement: &20156160 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *20156160
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: &20155400 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *20155400
|
38
|
+
description: kameleon - it's a polish word for chameleon
|
39
|
+
email: michalczyz@gmail.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- lib/kameleon/user/base.rb
|
45
|
+
- lib/kameleon/user/guest.rb
|
46
|
+
- lib/kameleon/user/abstract.rb
|
47
|
+
- lib/kameleon/session/capybara.rb
|
48
|
+
- lib/kameleon/dsl/act.rb
|
49
|
+
- lib/kameleon/dsl/see.rb
|
50
|
+
- lib/kameleon.rb
|
51
|
+
- spec/unit/guest_spec.rb
|
52
|
+
- spec/unit/see_spec.rb
|
53
|
+
- spec/unit/act_spec.rb
|
54
|
+
- spec/sample_rack_app/hey.rb
|
55
|
+
- spec/spec_helper.rb
|
56
|
+
- LICENCE
|
57
|
+
homepage: http://kameleon.cs3b.com
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>'
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.1
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.8.10
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: high abstraction dsl for end user perspective tests
|
82
|
+
test_files: []
|