watir-webdriver 0.0.1.dev3 → 0.0.1.dev4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -1
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/watir-webdriver/base_element.rb +4 -0
- data/lib/watir-webdriver/browser.rb +25 -5
- data/lib/watir-webdriver/browserbot.js +14 -14
- data/lib/watir-webdriver/collections/buttons_collection.rb +2 -0
- data/lib/watir-webdriver/collections/element_collection.rb +21 -1
- data/lib/watir-webdriver/collections/table_rows_collection.rb +2 -0
- data/lib/watir-webdriver/collections/text_fields_collection.rb +2 -0
- data/lib/watir-webdriver/container.rb +5 -0
- data/lib/watir-webdriver/elements/generated.rb +9 -9
- data/lib/watir-webdriver/elements/select_list.rb +88 -14
- data/lib/watir-webdriver/elements/text_field.rb +0 -1
- data/support/yard_handlers.rb +87 -0
- metadata +3 -6
- data/spec/element_locator_spec.rb +0 -11
- data/spec/xpath_builder_spec.rb +0 -49
data/README.rdoc
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
Watir implementation built on WebDriver's Ruby bindings.
|
4
4
|
See http://rubyforge.org/pipermail/wtr-development/2009-October/001313.html.
|
5
5
|
|
6
|
+
= API docs
|
7
|
+
|
8
|
+
http://jarib.github.com/watir-webdriver/doc/
|
9
|
+
|
6
10
|
= Description
|
7
11
|
|
8
12
|
The file in lib/watir/elements/generated.rb is autogenerated from the HTML5 spec. This is done by extracting the IDL parts from the spec and processing them with the WebIDL gem (link below).
|
@@ -29,4 +33,4 @@ The file in lib/watir/elements/generated.rb is autogenerated from the HTML5 spec
|
|
29
33
|
|
30
34
|
== Copyright
|
31
35
|
|
32
|
-
Copyright (c) 2009 Jari Bakken. See LICENSE for details.
|
36
|
+
Copyright (c) 2009-2010 Jari Bakken. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -97,10 +97,10 @@ task :default => :spec
|
|
97
97
|
|
98
98
|
begin
|
99
99
|
require 'yard'
|
100
|
-
require 'support/
|
100
|
+
require 'support/yard_handlers'
|
101
101
|
YARD::Rake::YardocTask.new
|
102
102
|
rescue LoadError
|
103
|
-
task :
|
103
|
+
task :yard do
|
104
104
|
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
105
105
|
end
|
106
106
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.1.
|
1
|
+
0.0.1.dev4
|
@@ -15,6 +15,13 @@ module Watir
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
#
|
19
|
+
# Create a Watir::Browser instance
|
20
|
+
#
|
21
|
+
# @param [:firefox, :ie, :chrome, :remote] browser
|
22
|
+
# @param args Passed to the underlying driver
|
23
|
+
#
|
24
|
+
|
18
25
|
def initialize(browser, *args)
|
19
26
|
case browser
|
20
27
|
when Symbol, String
|
@@ -32,8 +39,15 @@ module Watir
|
|
32
39
|
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
|
33
40
|
end
|
34
41
|
|
42
|
+
#
|
43
|
+
# Goto the given URL
|
44
|
+
#
|
45
|
+
# @param [String] uri The url.
|
46
|
+
# @return [String] The url you end up at.
|
47
|
+
#
|
48
|
+
|
35
49
|
def goto(uri)
|
36
|
-
uri = "http://#{uri}" unless uri.include?("://")
|
50
|
+
uri = "http://#{uri}" unless uri.include?("://") || uri =~ /^\w+:/
|
37
51
|
|
38
52
|
@driver.navigate.to uri
|
39
53
|
run_checkers
|
@@ -82,10 +96,6 @@ module Watir
|
|
82
96
|
@driver.navigate.refresh
|
83
97
|
end
|
84
98
|
|
85
|
-
def exist?
|
86
|
-
true
|
87
|
-
end
|
88
|
-
|
89
99
|
def status
|
90
100
|
execute_script "return window.status;"
|
91
101
|
end
|
@@ -119,6 +129,8 @@ module Watir
|
|
119
129
|
@error_checkers.each { |e| e[self] }
|
120
130
|
end
|
121
131
|
|
132
|
+
#
|
133
|
+
# Protocol shared with BaseElement
|
122
134
|
#
|
123
135
|
# @api private
|
124
136
|
#
|
@@ -127,5 +139,13 @@ module Watir
|
|
127
139
|
true # TODO: assert browser is open
|
128
140
|
end
|
129
141
|
|
142
|
+
def exist?
|
143
|
+
true
|
144
|
+
end
|
145
|
+
|
146
|
+
def browser
|
147
|
+
self
|
148
|
+
end
|
149
|
+
|
130
150
|
end # Browser
|
131
151
|
end # Watir
|
@@ -1,10 +1,10 @@
|
|
1
1
|
// stolen from injectableSelenium.js in WebDriver
|
2
|
-
|
3
2
|
var browserbot = {
|
4
3
|
|
5
|
-
triggerEvent
|
6
|
-
canBubble = (typeof(canBubble) == undefined) ? true
|
7
|
-
if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) {
|
4
|
+
triggerEvent: function(element, eventType, canBubble, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
|
5
|
+
canBubble = (typeof(canBubble) == undefined) ? true: canBubble;
|
6
|
+
if (element.fireEvent && element.ownerDocument && element.ownerDocument.createEventObject) {
|
7
|
+
// IE
|
8
8
|
var evt = this.createEventObject(element, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown);
|
9
9
|
element.fireEvent('on' + eventType, evt);
|
10
10
|
} else {
|
@@ -15,16 +15,16 @@ var browserbot = {
|
|
15
15
|
evt.metaKey = metaKeyDown;
|
16
16
|
evt.altKey = altKeyDown;
|
17
17
|
evt.ctrlKey = controlKeyDown;
|
18
|
-
} catch
|
18
|
+
} catch(e) {
|
19
19
|
// Nothing sane to do
|
20
|
-
|
20
|
+
}
|
21
21
|
|
22
22
|
evt.initEvent(eventType, canBubble, true);
|
23
23
|
element.dispatchEvent(evt);
|
24
24
|
}
|
25
25
|
},
|
26
26
|
|
27
|
-
getVisibleText
|
27
|
+
getVisibleText: function() {
|
28
28
|
var selection = getSelection();
|
29
29
|
var range = document.createRange();
|
30
30
|
range.selectNodeContents(document.documentElement);
|
@@ -32,14 +32,14 @@ var browserbot = {
|
|
32
32
|
return selection.toString();
|
33
33
|
},
|
34
34
|
|
35
|
-
getOuterHTML
|
36
|
-
|
35
|
+
getOuterHTML: function(element) {
|
36
|
+
if (element.outerHTML) {
|
37
37
|
return element.outerHTML;
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
} else if (typeof(XMLSerializer) != undefined) {
|
39
|
+
return new XMLSerializer().serializeToString(element);
|
40
|
+
} else {
|
41
|
+
throw "can't get outerHTML in this browser";
|
42
|
+
}
|
43
43
|
}
|
44
44
|
|
45
45
|
|
@@ -12,7 +12,7 @@ module Watir
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def length
|
15
|
-
|
15
|
+
elements.length
|
16
16
|
end
|
17
17
|
alias_method :size, :length
|
18
18
|
|
@@ -20,19 +20,39 @@ module Watir
|
|
20
20
|
to_a[idx] || @element_class.new(@parent, :index, idx)
|
21
21
|
end
|
22
22
|
|
23
|
+
#
|
24
|
+
# First element of this collection
|
25
|
+
#
|
26
|
+
# @return Watir::BaseElement
|
27
|
+
#
|
28
|
+
|
23
29
|
def first
|
24
30
|
to_a[0] || @element_class.new(@parent, :index, 0)
|
25
31
|
end
|
26
32
|
|
33
|
+
#
|
34
|
+
# Last element of the collection
|
35
|
+
#
|
36
|
+
# @return Watir::BaseElement
|
37
|
+
#
|
38
|
+
|
27
39
|
def last
|
28
40
|
to_a[-1] || @element_class.new(@parent, :index, -1)
|
29
41
|
end
|
30
42
|
|
43
|
+
#
|
44
|
+
# This collection as an Array
|
45
|
+
#
|
46
|
+
# @return [Array<Watir::BaseElement>]
|
47
|
+
#
|
48
|
+
|
31
49
|
def to_a
|
32
50
|
# TODO: optimize - lazily @element_class instance
|
33
51
|
@to_a ||= elements.map { |e| @element_class.new(@parent, :element, e) }
|
34
52
|
end
|
35
53
|
|
54
|
+
private
|
55
|
+
|
36
56
|
def elements
|
37
57
|
@elements ||= ElementLocator.new(
|
38
58
|
@parent.wd,
|
@@ -52,15 +52,15 @@ module Watir
|
|
52
52
|
attributes(:html_collection => ([:options]))
|
53
53
|
end
|
54
54
|
|
55
|
-
class Object < HTMLElement
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
55
|
+
# class Object < HTMLElement
|
56
|
+
# identifier(:tag_name => "object")
|
57
|
+
#
|
58
|
+
# container_method(:object)
|
59
|
+
#
|
60
|
+
# collection_method(:objects)
|
61
|
+
#
|
62
|
+
# attributes(:string => ([:data, :type, :name, :use_map, :width, :height, :content_window, :validity, :validation_message]), :document => ([:content_document]), :html_element => ([:form]), :bool => ([:will_validate]))
|
63
|
+
# end
|
64
64
|
|
65
65
|
class DList < HTMLElement
|
66
66
|
identifier(:tag_name => "dl")
|
@@ -12,7 +12,9 @@ module Watir
|
|
12
12
|
|
13
13
|
def clear
|
14
14
|
assert_exists
|
15
|
-
|
15
|
+
|
16
|
+
raise Error, "you can only clear multi-selects" unless multiple?
|
17
|
+
|
16
18
|
options.each do |o|
|
17
19
|
o.toggle if o.selected?
|
18
20
|
end
|
@@ -24,17 +26,16 @@ module Watir
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def select(str_or_rx)
|
27
|
-
|
29
|
+
select_by :text, str_or_rx, multiple?
|
28
30
|
end
|
29
31
|
|
30
|
-
# TODO: deprecate?
|
31
32
|
def select_value(str_or_rx)
|
32
|
-
select_by :value, str_or_rx
|
33
|
+
select_by :value, str_or_rx, multiple?
|
33
34
|
end
|
34
35
|
|
35
36
|
def selected?(str_or_rx)
|
36
37
|
assert_exists
|
37
|
-
matches =
|
38
|
+
matches = @element.find_elements(:tag_name, 'option').select { |e| str_or_rx === e.text || str_or_rx === e.attribute(:label) }
|
38
39
|
|
39
40
|
if matches.empty?
|
40
41
|
raise UnknownObjectException, "Unable to locate option matching #{str_or_rx.inspect}"
|
@@ -57,17 +58,90 @@ module Watir
|
|
57
58
|
|
58
59
|
private
|
59
60
|
|
60
|
-
def select_by(how, str_or_rx)
|
61
|
-
|
62
|
-
|
61
|
+
def select_by(how, str_or_rx, multiple)
|
62
|
+
case str_or_rx
|
63
|
+
when String
|
64
|
+
select_by_string(how, str_or_rx, multiple)
|
65
|
+
when Regexp
|
66
|
+
select_by_regexp(how, str_or_rx, multiple)
|
67
|
+
else
|
68
|
+
raise ArgumentError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def select_by_string(how, string, multiple)
|
73
|
+
xpath = option_xpath_for(how, string)
|
74
|
+
if multiple
|
75
|
+
elements = @element.find_elements(:xpath, xpath)
|
76
|
+
|
77
|
+
if elements.empty?
|
78
|
+
raise NoValueFoundException, "#{string.inspect} not found in select list"
|
79
|
+
end
|
80
|
+
|
81
|
+
elements.each { |e| e.select unless e.selected? }
|
82
|
+
elements.first.text
|
83
|
+
else
|
84
|
+
begin
|
85
|
+
e = @element.find_element(:xpath, xpath)
|
86
|
+
rescue WebDriver::Error::WebDriverError # should be more specific
|
87
|
+
raise NoValueFoundException, "#{string.inspect} not found in select list"
|
88
|
+
end
|
89
|
+
|
90
|
+
e.select unless e.selected?
|
91
|
+
e.text
|
92
|
+
end
|
93
|
+
end
|
63
94
|
|
64
|
-
|
65
|
-
|
95
|
+
def select_by_regexp(how, exp, multiple)
|
96
|
+
elements = @element.find_elements(:tag_name, 'option')
|
97
|
+
if elements.empty?
|
98
|
+
raise NoValueFoundException, "no options in select list"
|
66
99
|
end
|
67
100
|
|
68
|
-
|
69
|
-
|
101
|
+
if multiple
|
102
|
+
found = elements.select do |e|
|
103
|
+
next unless matches_regexp?(how, e, exp)
|
104
|
+
e.select unless e.selected?
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
if found.empty?
|
109
|
+
raise NoValueFoundException, "#{exp.inspect} not found in select list"
|
110
|
+
end
|
111
|
+
|
112
|
+
found.first.text
|
113
|
+
else
|
114
|
+
element = elements.find { |e| matches_regexp?(how, e, exp) }
|
115
|
+
unless element
|
116
|
+
raise NoValueFoundException, "#{exp.inspect} not found in select list"
|
117
|
+
end
|
118
|
+
|
119
|
+
element.select unless element.selected?
|
120
|
+
element.text
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def option_xpath_for(how, string)
|
125
|
+
case how
|
126
|
+
when :text
|
127
|
+
"//option[normalize-space()=#{string.inspect} or @label=#{string.inspect}]"
|
128
|
+
when :value
|
129
|
+
"//option[@value=#{string.inspect}]"
|
130
|
+
else
|
131
|
+
raise Error, "unknown how: #{how.inspect}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def matches_regexp?(how, element, exp)
|
136
|
+
case how
|
137
|
+
when :text
|
138
|
+
element.text =~ exp || element.attribute(:label) =~ exp
|
139
|
+
when :value
|
140
|
+
element.attribute(:value) =~ exp
|
141
|
+
else
|
142
|
+
raise Error, "unknown how: #{how.inspect}"
|
143
|
+
end
|
70
144
|
end
|
71
145
|
|
72
|
-
end
|
73
|
-
end
|
146
|
+
end # SelectList
|
147
|
+
end # Watir
|
@@ -2,7 +2,6 @@
|
|
2
2
|
module Watir
|
3
3
|
class TextField < Input
|
4
4
|
|
5
|
-
# perhaps we'll need a custom locate(), since this should also cover textareas
|
6
5
|
attributes Watir::TextArea.typed_attributes
|
7
6
|
def type; super; end # hacky, but we want Input#type here, which was overriden by TextArea's attributes
|
8
7
|
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# require "ruby-debug"
|
2
|
+
require "#{File.dirname(__FILE__)}/../lib/watir-webdriver/core_ext/string"
|
3
|
+
|
4
|
+
module YARD
|
5
|
+
module Watir
|
6
|
+
class AttributesHandler < YARD::Handlers::Ruby::Base
|
7
|
+
handles method_call(:attributes)
|
8
|
+
|
9
|
+
TYPES = {
|
10
|
+
:string => "String",
|
11
|
+
:bool => "Boolean",
|
12
|
+
:int => "Integer"
|
13
|
+
}
|
14
|
+
|
15
|
+
def process
|
16
|
+
attributes = try_eval
|
17
|
+
|
18
|
+
if attributes.nil?
|
19
|
+
p :ignoring => statement.source, :in => namespace.to_s
|
20
|
+
return
|
21
|
+
end
|
22
|
+
|
23
|
+
TYPES.each do |type, return_type|
|
24
|
+
if attributes.member? type
|
25
|
+
create_attributes attributes[type], return_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def create_attributes(names, return_type)
|
33
|
+
names.each do |attribute_name|
|
34
|
+
p :adding => "#{namespace}##{attribute_name}"
|
35
|
+
attribute_name = "#{attribute_name}?".to_sym if return_type == "Boolean"
|
36
|
+
register MethodObject.new(namespace, attribute_name, scope) do |o|
|
37
|
+
o.visibility = :public
|
38
|
+
o.explicit = false
|
39
|
+
o.docstring.add_tag YARD::Tags::Tag.new(:return, "", return_type)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def try_eval
|
45
|
+
eval "{#{statement.parameters.source}}"
|
46
|
+
rescue SyntaxError, StandardError
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
end # AttributesHandler
|
51
|
+
|
52
|
+
class ContainerMethodHandler < YARD::Handlers::Ruby::Base
|
53
|
+
handles method_call(:container_method)
|
54
|
+
|
55
|
+
def process
|
56
|
+
name = statement.parameters.flatten.first
|
57
|
+
return_type = namespace.to_s
|
58
|
+
p :adding => "Watir::Container##{name}"
|
59
|
+
|
60
|
+
register MethodObject.new(P("Watir::Container"), name, :instance) do |o|
|
61
|
+
o.docstring.add_tag(YARD::Tags::Tag.new(:return, "", return_type))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end # ContainerMethodHandler
|
65
|
+
|
66
|
+
class CollectionMethodHandler < YARD::Handlers::Ruby::Base
|
67
|
+
handles method_call(:collection_method)
|
68
|
+
|
69
|
+
def process
|
70
|
+
name = statement.parameters.flatten.first
|
71
|
+
p :adding => "Watir::Container##{name}"
|
72
|
+
|
73
|
+
class_name = "#{name.to_s.camel_case}Collection"
|
74
|
+
return_type = "Watir::#{class_name}"
|
75
|
+
|
76
|
+
register MethodObject.new(P("Watir::Container"), name, :instance) do |o|
|
77
|
+
o.docstring.add_tag(YARD::Tags::Tag.new(:return, "", return_type))
|
78
|
+
end
|
79
|
+
|
80
|
+
register ClassObject.new(P("Watir"), class_name) do |o|
|
81
|
+
o.superclass = "Watir::ElementCollection"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end # CollectionMethodHandler
|
85
|
+
|
86
|
+
end # Watir
|
87
|
+
end # YARD
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: watir-webdriver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.dev4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jari Bakken
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-27 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -102,13 +102,12 @@ files:
|
|
102
102
|
- lib/watir-webdriver/locators/table_row_locator.rb
|
103
103
|
- lib/watir-webdriver/locators/text_field_locator.rb
|
104
104
|
- lib/watir-webdriver/xpath_support.rb
|
105
|
-
- spec/element_locator_spec.rb
|
106
105
|
- spec/spec_helper.rb
|
107
|
-
- spec/xpath_builder_spec.rb
|
108
106
|
- support/html5/html5.idl
|
109
107
|
- support/html5/html5_extras.idl
|
110
108
|
- support/html5/idl_extractor.rb
|
111
109
|
- support/html5/watir_visitor.rb
|
110
|
+
- support/yard_handlers.rb
|
112
111
|
has_rdoc: true
|
113
112
|
homepage: http://github.com/jarib/watir-webdriver
|
114
113
|
licenses: []
|
@@ -138,7 +137,6 @@ signing_key:
|
|
138
137
|
specification_version: 3
|
139
138
|
summary: Watir on WebDriver
|
140
139
|
test_files:
|
141
|
-
- spec/element_locator_spec.rb
|
142
140
|
- spec/spec_helper.rb
|
143
141
|
- spec/watirspec/area_spec.rb
|
144
142
|
- spec/watirspec/areas_spec.rb
|
@@ -216,4 +214,3 @@ test_files:
|
|
216
214
|
- spec/watirspec/text_fields_spec.rb
|
217
215
|
- spec/watirspec/ul_spec.rb
|
218
216
|
- spec/watirspec/uls_spec.rb
|
219
|
-
- spec/xpath_builder_spec.rb
|
data/spec/xpath_builder_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "#{File.dirname(__FILE__)}/spec_helper"
|
3
|
-
|
4
|
-
# describe Watir::XPathBuilder do
|
5
|
-
# def build(selector)
|
6
|
-
# XPathBuilder.build_from(selector)
|
7
|
-
# end
|
8
|
-
#
|
9
|
-
# it "builds an xpath from a tag name and a single attribute" do
|
10
|
-
# build(
|
11
|
-
# :tag_name => "div",
|
12
|
-
# :id => "foo"
|
13
|
-
# ).should == '//div[@id="foo"]'
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# it "builds an xpath from a tag name and multiple attributes" do
|
17
|
-
# build(
|
18
|
-
# :tag_name => "input",
|
19
|
-
# :type => "radio",
|
20
|
-
# :value => '1'
|
21
|
-
# ).should == '//input[@type="radio" and @value="1"]'
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# it "builds an xpath from a tag name, an attribute and an index" do
|
25
|
-
# build(
|
26
|
-
# :tag_name => "input",
|
27
|
-
# :type => "text",
|
28
|
-
# :index => 2
|
29
|
-
# ).should == '//input[@type="text"][3]'
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# it "builds an xpath from a single attribute" do
|
33
|
-
# build(
|
34
|
-
# :class => 'foo'
|
35
|
-
# ).should == '//*[@class="foo"]'
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# it "builds an xpath from a tag name and index" do
|
39
|
-
# build(
|
40
|
-
# :tag_name => 'span',
|
41
|
-
# :index => 3
|
42
|
-
# ).should == '//span[4]'
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# it "returns nil if any the selector contains a regexp" do
|
46
|
-
# build(:tag_name => /span|div/).should be_nil
|
47
|
-
# end
|
48
|
-
|
49
|
-
# end
|