kameleon 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -0,0 +1,7 @@
1
+ require 'kameleon/session/capybara'
2
+ require 'kameleon/dsl/see'
3
+ require 'kameleon/dsl/act'
4
+
5
+ require 'kameleon/user/abstract'
6
+ require 'kameleon/user/base'
7
+ require 'kameleon/user/guest'
@@ -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,7 @@
1
+ module Kameleon
2
+ module User
3
+ class Base < Abstract
4
+
5
+ end
6
+ end
7
+ 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
@@ -0,0 +1,10 @@
1
+ class Hey
2
+
3
+ def initialize(body)
4
+ @body = body
5
+ end
6
+
7
+ def call(env)
8
+ [200, {"Content-Type" => "text/plain"}, [@body]]
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ require 'kameleon'
2
+ require 'capybara/dsl'
3
+
4
+ require 'sample_rack_app/hey'
@@ -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&mdash;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&mdash;yes, you guessed it&mdash;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&mdash;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">&nbsp;<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: []