wrapybara 0.1.0

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.
@@ -0,0 +1,22 @@
1
+ module Wrapybara
2
+ class TextArea
3
+ include Element
4
+ include FillableField
5
+
6
+ def initialize(identifier, scope = default_scope, how = default_how)
7
+ @identifier = identifier
8
+ @how = how
9
+ @scope = scope
10
+ xpath = XPath::HTML.send(:locate_field, XPath.descendant(:textarea), identifier)
11
+ @element = get_element(xpath, scope)
12
+ end
13
+
14
+ def should_exist
15
+ super "Expected a text area #{self.element_identifier} to exist"
16
+ end
17
+
18
+ def should_not_exist
19
+ super "Did not expect a text area #{self.element_identifier}' to exist"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Wrapybara
2
+ class TextField
3
+ include Element
4
+ include FillableField
5
+
6
+ def initialize(identifier, scope = default_scope, how = default_how)
7
+ @identifier = identifier
8
+ @how = how
9
+ @scope = scope
10
+ xpath = XPath::HTML.send(:locate_field, XPath.descendant(:input)[XPath.attr(:type).equals('text')], identifier)
11
+ @element = get_element(xpath, scope)
12
+ end
13
+
14
+ def should_exist
15
+ super "Expected a text field #{self.element_identifier} to exist"
16
+ end
17
+
18
+ def should_not_exist
19
+ super "Did not expect a text field #{self.element_identifier}' to exist"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,68 @@
1
+ /*
2
+ This script facilitates tracking whether or not an element has focus. It is not an ideal solution,
3
+ but it does work across browsers and test environments. The need for such a solution was prompted
4
+ by HtmlUnit not supporting document.activeElement, which all major browsers now support. HtmlUnit
5
+ being the underlying technology used by Akephalos (in Cucumber via Capybara), this was a problem.
6
+
7
+ Focus Tracking can be used by calling FocusTracking.initialize once the dom is loaded and then by
8
+ calling $(element_id).has_focus().
9
+
10
+ This script is currently dependent on Prototype, but could be easily adapted for any JavaScript library.
11
+ */
12
+
13
+ var FocusTracking = {};
14
+
15
+ FocusTracking.attribute = 'has-focus';
16
+ FocusTracking.auto_focus_class_name = 'auto-focus';
17
+
18
+ FocusTracking.focusable_elements = function ()
19
+ {
20
+ return $$('input[type=text], input[type=password], input[type=submit], input[type=button], input[type=checkbox], input[type=radio], textarea, button, select');
21
+ }
22
+
23
+ FocusTracking.initialize = function ()
24
+ {
25
+ var elements = FocusTracking.focusable_elements();
26
+ elements.each(
27
+ function (element)
28
+ {
29
+ if (element.readAttribute(FocusTracking.attribute) == null)
30
+ {
31
+ // if the element already has the focus tracking pieces, leave it alone...only initialize it if
32
+ // it isn't there so we don't miss saving some changes.
33
+ Object.extend(element, FocusTracking.Element);
34
+ element.writeAttribute(FocusTracking.attribute, 'false');
35
+ element.observe('focus', element.got_focus);
36
+ element.observe('blur', element.lost_focus);
37
+ }
38
+ }
39
+ );
40
+ }
41
+
42
+ FocusTracking.auto_focus = function (class_name)
43
+ {
44
+ class_name = class_name == undefined || class_name == null ? FocusTracking.auto_focus_class_name : class_name;
45
+ var elements = $$('.' + class_name);
46
+ if (elements.length > 0)
47
+ {
48
+ element = elements.first();
49
+ element.activate();
50
+ }
51
+ }
52
+
53
+ FocusTracking.Element = {};
54
+
55
+ FocusTracking.Element.has_focus = function ()
56
+ {
57
+ return this.readAttribute(FocusTracking.attribute) == 'true';
58
+ }
59
+
60
+ FocusTracking.Element.got_focus = function ()
61
+ {
62
+ this.writeAttribute(FocusTracking.attribute, 'true');
63
+ }
64
+
65
+ FocusTracking.Element.lost_focus = function ()
66
+ {
67
+ this.writeAttribute(FocusTracking.attribute, 'false');
68
+ }
@@ -0,0 +1,45 @@
1
+ # This module is, admittedly, something of a hack. In order to reliably (across browsers and testing libraries) test for
2
+ # an element having focus, I resorted to adding some JavaScript event handling to read/write an attribute on focus/blur.
3
+ # Not pretty, but HtmlUnit, which Akephalos uses, did not recognize document.activeElement, so I had to roll my own
4
+ # solution. To make it easier for you to use this module, the corresponding JavaScript is included in focus_tracking.js.
5
+ # See it for usage notes.
6
+
7
+ # To use Wrapybara's focus handling capabilities, require wrapybara/ext/focus_handling in some file that gets loaded (I use
8
+ # support/extras.rb so I don't pollute env.rb) and then optionally set Wrapybara.focus_attribute to whatever the element
9
+ # attribute will be. As you can see below, Wrapybara checks the value of the attribute against what you say it should be
10
+ # when the element has focus.
11
+
12
+ module Wrapybara
13
+ def self.focus_attribute=(attribute)
14
+ @focus_attribute = attribute
15
+ end
16
+
17
+ def self.focus_attribute
18
+ @focus_attribute || 'has-focus'
19
+ end
20
+
21
+ def self.focus_value=(value)
22
+ @focus_value = value
23
+ end
24
+
25
+ def self.focus_value
26
+ @focus_value || 'true'
27
+ end
28
+
29
+ module Element
30
+ def focused?
31
+ self.should_exist
32
+ element[Wrapybara.focus_attribute] == Wrapybara.focus_value
33
+ end
34
+
35
+ def should_be_focused
36
+ message = "Expected element #{self.element_identifier} to be focused"
37
+ raise UnmetExpectation, message unless self.focused?
38
+ end
39
+
40
+ def should_not_be_focused
41
+ message = "Did not expect element #{self.element_identifier} to be focused"
42
+ raise UnmetExpectation, message if self.focused?
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ # add this directory to the load path if it's not already included
2
+ this_dir = File.expand_path(File.dirname(__FILE__))
3
+ $: << this_dir unless $:.include?(this_dir)
4
+
5
+ module Wrapybara
6
+ class UnmetExpectation < Exception; end
7
+
8
+ def host
9
+ Capybara.app_host
10
+ end
11
+
12
+ def current_path
13
+ Capybara.current_path
14
+ end
15
+
16
+ def current_url
17
+ Capybara.current_url
18
+ end
19
+
20
+ def current_path_is?(path)
21
+ path = path.gsub('/', '\/').gsub('?', '\?')
22
+ (current_url || current_path) =~ /#{path}/
23
+ end
24
+
25
+ def current_path_should_be(path)
26
+ raise UnmetExpectation, "Expected the current path to be '#{path}'" unless current_path_is?(path)
27
+ end
28
+
29
+ def current_path_should_not_be(path)
30
+ raise UnmetExpectation, "Did not expect the current path to be '#{path}'" if current_path_is?(path)
31
+ end
32
+ end
33
+
34
+ require 'xpath'
35
+ require 'element'
36
+ require 'elements/attribute'
37
+ require 'elements/button'
38
+ require 'elements/checkbox'
39
+ require 'elements/content'
40
+ require 'elements/form'
41
+ require 'elements/image'
42
+ require 'elements/label'
43
+ require 'elements/link'
44
+ require 'elements/file_field'
45
+ require 'elements/fillable_field'
46
+ require 'elements/option'
47
+ require 'elements/password_field'
48
+ require 'elements/radio_button'
49
+ require 'elements/select'
50
+ require 'elements/table'
51
+ require 'elements/table_body'
52
+ require 'elements/table_cell'
53
+ require 'elements/table_head'
54
+ require 'elements/text_area'
55
+ require 'elements/text_field'
56
+
57
+ World(Wrapybara)
@@ -0,0 +1,139 @@
1
+ Given /^(?:I )?debug$/ do
2
+ require 'ruby-debug'
3
+ debugger
4
+ puts "\n\nDEBUGGER\n\n"
5
+ end
6
+
7
+ Given /^(?:I )?reload(?: the page)?$/ do
8
+ visit current_path
9
+ end
10
+
11
+ Given /^(?:I )?display "([^"]+)"$/ do |something|
12
+ puts "\n\n#{something}\n\n"
13
+ end
14
+
15
+ Given /^(?:I )?wait(?: (?:for )?(\d+) seconds)?$/ do |seconds|
16
+ seconds ||= '2'
17
+ sleep(seconds.to_i)
18
+ end
19
+
20
+ Given /^there (should|should not) be a[n]? (.+) (labeled|identified by|for|titled) "([^"]+)"(?: (?:in|within) "([^"]+)")?$/ do |expectation, element, how, identifier, scope|
21
+ element.gsub!(' ', '_')
22
+ expectation.gsub!(' ', '_')
23
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).send("#{expectation}_exist")
24
+ end
25
+
26
+ Given /^the table (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) have column[s]?(?: "([^"]+)")?$/ do |how, identifier, scope, expectation, column, table|
27
+ columns = column ? [column] : (table.hashes.collect { |row| row['label'] || '' })
28
+ Wrapybara::Table.new(identifier, scope, how).send("#{expectation}_have_columns", columns)
29
+ end
30
+
31
+ Given /^the select (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) have option[s]?(?: "([^"]+)")?(?: (selected))?$/ do |how, identifier, scope, expectation, option, selected, table|
32
+ options = option ? [option] : (table.hashes.collect { |row| row['label'] || '' })
33
+ expectation.gsub!(' ', '_')
34
+ if selected
35
+ options.each do |option|
36
+ Wrapybara::Select.new(identifier, scope, how).option(option).send("#{expectation}_be_selected")
37
+ end
38
+ else
39
+ Wrapybara::Select.new(identifier, scope, how).send("#{expectation}_have_options", options)
40
+ end
41
+ end
42
+
43
+ # In this step, the label capture must use an * to accept empty strings, ie, selecting the blank option typically at the top of the options
44
+ Given /^(?:I )?(choose|select|deselect) "([^"]*)" from the select (labeled|identified by) "([^"]+)"?(?: (?:in|within) "([^"]+)")?$/ do |action, option, how, identifier, scope|
45
+ Wrapybara::Select.new(identifier, scope, how).send(action.to_sym, option)
46
+ end
47
+
48
+ Given /^the select (labeled|identified by) "([^"]+)"?(?: (?:in|within) "([^"]+)")? (should|should not) have "([^"]*)" selected$/ do |how, identifier, scope, expectation, option|
49
+ expectation.gsub!(' ', '_')
50
+ Wrapybara::Select.new(identifier, scope, how).option(option).send("#{expectation}_be_selected")
51
+ end
52
+
53
+ Given /^the (.+) (labeled|identified by|titled) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) be (.+)$/ do |element, how, identifier, scope, expectation, state|
54
+ element.gsub!(' ', '_')
55
+ expectation.gsub!(' ', '_')
56
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).send("#{expectation}_be_#{state}")
57
+ end
58
+
59
+ Given /^the (.+) (labeled|identified by|titled) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) have attribute "([^"]+)" with value "([^"]+)"$/ do |element, how, identifier, scope, expectation, attribute, value|
60
+ element.gsub!(' ', '_')
61
+ expectation.gsub!(' ', '_')
62
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).send("#{expectation}_have_attribute", attribute, value)
63
+ end
64
+
65
+ Given /^(?:I )?(check|uncheck) the (checkbox|radio button) (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")?$/ do |action, element, how, identifier, scope|
66
+ element.gsub!(' ', '_')
67
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).send(action)
68
+ end
69
+
70
+ # In this step, the label capture must use an * to accept empty strings, so we can clear the field
71
+ Given /^(?:I )?fill in the (text field|password field|text area) (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? with "([^"]*)"$/ do |element, how, identifier, scope, content|
72
+ content ||= ''
73
+ element.gsub!(' ', '_')
74
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).fill_in(content)
75
+ end
76
+
77
+ Given /^(?:I )?click the (button|link) (labeled|identified by|titled) "([^"]+)"(?: (?:in|within) "([^"]+)")?$/ do |element, how, identifier, scope|
78
+ "Wrapybara::#{element.capitalize}".constantize.new(identifier, scope, how).click
79
+ end
80
+
81
+ # for finding unlabeled links
82
+ Given /^there (should|should not) be a link to "([^"]+)"(?: (?:in|within) "([^"]+)")?$/ do |expectation, destination, scope|
83
+ expectation.gsub!(' ', '_')
84
+ Wrapybara::Link.new(destination, scope, 'to').send("#{expectation}_exist")
85
+ end
86
+
87
+ Given /^there (should|should not) be a link to the "([^"]+)" page(?: (?:in|within) "([^"]+)")?$/ do |expectation, destination, scope|
88
+ expectation.gsub!(' ', '_')
89
+ destination = path_to(destination)
90
+ Wrapybara::Link.new(destination, scope, 'to').send("#{expectation}_exist")
91
+ end
92
+
93
+ # for clicking unlabeled links
94
+ Given /^(?:I )?click the link to the "([^"]+)" page(?: (?:in|within) "([^"]+)")?$/ do |destination, scope|
95
+ destination = path_to(destination)
96
+ Wrapybara::Link.new(destination, scope, 'to').click
97
+ end
98
+
99
+ # for clicking table column headers (as in sortable columns)
100
+ Given /^(?:I )?click column "([^"]+)" of the table (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")?$/ do |column, how, table, scope|
101
+ Wrapybara::Table.new(table, scope, how).click_column(column)
102
+ end
103
+
104
+ # content
105
+ Given /^(?:I )?(should|should not) see "([^"]+)"(?: within "([^"]+)")?$/ do |expectation, content, scope|
106
+ expectation.gsub!(' ', '_')
107
+ Wrapybara::Content.new(content, scope).send("#{expectation}_exist")
108
+ end
109
+
110
+ Given /^"([^"]+)"(?: within "([^"]+)")? (should|should not) be visible$/ do |content, scope, expectation|
111
+ expectation.gsub!(' ', '_')
112
+ Wrapybara::Content.new(content, scope).send("#{expectation}_be_visible")
113
+ end
114
+
115
+ # for clicking things like headers that have expandable detail below them
116
+ Given /^I click the text "([^"]+)"(?: within "([^"]+)")?$/ do |content, scope|
117
+ Wrapybara::Content.new(content, scope).click
118
+ end
119
+
120
+ # fillable fields (text field, password field, text area)
121
+ Given /^the (.+) (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) have content "([^"]+)"$/ do |element, how, identifier, scope, expectation, content|
122
+ element.gsub!(' ', '_')
123
+ expectation.gsub!(' ', '_')
124
+ "Wrapybara::#{element.camelize}".constantize.new(identifier, scope, how).send("#{expectation}_have_content", content)
125
+ end
126
+
127
+ # table content
128
+ Given /^(head|body)?\s?row (\d+) column (\d+) of the table (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) have content "([^"]+)"$/ do |element, row, column, how, identifier, scope, expectation, content|
129
+ element ||= 'body'
130
+ expectation.gsub!(' ', '_')
131
+ Wrapybara::Table.new(identifier, scope, how).send(element).cell(row, column).send("#{expectation}_have_content", content)
132
+ end
133
+
134
+ # other elements in table cells
135
+ Given /^(head|body)?\s?row (\d+) column (\d+) of the table (labeled|identified by) "([^"]+)"(?: (?:in|within) "([^"]+)")? (should|should not) contain a[n]? (.+) (labeled|identified by) "([^"]+)"$/ do |element, row, column, how, identifier, scope, expectation, child_element, child_how, child_identifier|
136
+ element ||= 'body'
137
+ expectation.gsub!(' ', '_')
138
+ Wrapybara::Table.new(identifier, scope, how).send(element).cell(row, column).send("#{expectation}_contain", child_element, child_identifier, child_how)
139
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wrapybara
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Phillip Koebbe
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-05-20 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Wrapybara creates objects that are based on Capybara.
22
+ email: phillipkoebbe@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - LICENSE.txt
29
+ - README.rdoc
30
+ files:
31
+ - lib/wrapybara.rb
32
+ - lib/wrapybara/element.rb
33
+ - lib/wrapybara/elements/attribute.rb
34
+ - lib/wrapybara/elements/button.rb
35
+ - lib/wrapybara/elements/checkbox.rb
36
+ - lib/wrapybara/elements/content.rb
37
+ - lib/wrapybara/elements/file_field.rb
38
+ - lib/wrapybara/elements/fillable_field.rb
39
+ - lib/wrapybara/elements/form.rb
40
+ - lib/wrapybara/elements/image.rb
41
+ - lib/wrapybara/elements/label.rb
42
+ - lib/wrapybara/elements/link.rb
43
+ - lib/wrapybara/elements/option.rb
44
+ - lib/wrapybara/elements/password_field.rb
45
+ - lib/wrapybara/elements/radio_button.rb
46
+ - lib/wrapybara/elements/select.rb
47
+ - lib/wrapybara/elements/table.rb
48
+ - lib/wrapybara/elements/table_body.rb
49
+ - lib/wrapybara/elements/table_cell.rb
50
+ - lib/wrapybara/elements/table_head.rb
51
+ - lib/wrapybara/elements/text_area.rb
52
+ - lib/wrapybara/elements/text_field.rb
53
+ - lib/wrapybara/ext/focus_tracking.js
54
+ - lib/wrapybara/ext/focus_tracking.rb
55
+ - lib/wrapybara/methods.rb
56
+ - lib/wrapybara/steps.rb
57
+ - LICENSE.txt
58
+ - README.rdoc
59
+ has_rdoc: true
60
+ homepage: http://github.com/phillipkoebbe/wrapybara
61
+ licenses:
62
+ - MIT
63
+ post_install_message:
64
+ rdoc_options: []
65
+
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ segments:
82
+ - 0
83
+ version: "0"
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.7
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: An object wrapper around Capybara.
91
+ test_files: []
92
+