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 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: []