waw 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE.rdoc +25 -0
- data/README.rdoc +32 -0
- data/bin/waw +32 -0
- data/bin/waw-profile +26 -0
- data/bin/waw-start +26 -0
- data/bin/wspec +33 -0
- data/layouts/empty/Rakefile +14 -0
- data/layouts/empty/config.ru +5 -0
- data/layouts/empty/config/commons.cfg +31 -0
- data/layouts/empty/config/devel.cfg +21 -0
- data/layouts/empty/ignore +7 -0
- data/layouts/empty/logs/dontforgetme +0 -0
- data/layouts/empty/resources/messages.rs +1 -0
- data/layouts/empty/test/wspec/site_respond.wspec +3 -0
- data/layouts/empty/test/wspec/test_all.rb +13 -0
- data/layouts/empty/waw.deploy +1 -0
- data/layouts/empty/waw.routing +6 -0
- data/layouts/static/dependencies +1 -0
- data/layouts/static/public/.wawaccess +18 -0
- data/layouts/static/public/css/style.css +0 -0
- data/layouts/static/public/images/dontforgetme +0 -0
- data/layouts/static/public/js/project.js +0 -0
- data/layouts/static/public/pages/.wawaccess +30 -0
- data/layouts/static/public/pages/404.wtpl +1 -0
- data/layouts/static/public/pages/index.wtpl +5 -0
- data/layouts/static/public/templates/.wawaccess +9 -0
- data/layouts/static/public/templates/layout.wtpl +17 -0
- data/layouts/static/test/wspec/static_pages_are_served.wspec +21 -0
- data/layouts/static/waw.routing +8 -0
- data/lib/waw.rb +99 -0
- data/lib/waw/commands/command.rb +115 -0
- data/lib/waw/commands/profile_command.rb +66 -0
- data/lib/waw/commands/start_command.rb +59 -0
- data/lib/waw/config.rb +110 -0
- data/lib/waw/controller.rb +25 -0
- data/lib/waw/controllers/action/action.rb +91 -0
- data/lib/waw/controllers/action/action_utils.rb +30 -0
- data/lib/waw/controllers/action/js_generation.rb +116 -0
- data/lib/waw/controllers/action_controller.rb +133 -0
- data/lib/waw/controllers/error/backtrace.rb +54 -0
- data/lib/waw/controllers/error_handler.rb +62 -0
- data/lib/waw/controllers/json_controller.rb +31 -0
- data/lib/waw/controllers/no_cache.rb +22 -0
- data/lib/waw/controllers/static/match.rb +80 -0
- data/lib/waw/controllers/static/waw_access.rb +235 -0
- data/lib/waw/controllers/static/waw_access_dsl.rb +48 -0
- data/lib/waw/controllers/static_controller.rb +37 -0
- data/lib/waw/default_config.cfg +14 -0
- data/lib/waw/environment_utils.rb +57 -0
- data/lib/waw/errors.rb +4 -0
- data/lib/waw/ext.rb +3 -0
- data/lib/waw/ext/core.rb +4 -0
- data/lib/waw/ext/core/hash.rb +47 -0
- data/lib/waw/ext/core/logger.rb +10 -0
- data/lib/waw/ext/core/module.rb +20 -0
- data/lib/waw/ext/core/object.rb +29 -0
- data/lib/waw/ext/rack.rb +19 -0
- data/lib/waw/ext/rack/builder.rb +43 -0
- data/lib/waw/ext/rack/delegator.rb +51 -0
- data/lib/waw/ext/rack/urlmap.rb +55 -0
- data/lib/waw/ext/wlang.rb +1 -0
- data/lib/waw/ext/wlang/hosted_language.rb +21 -0
- data/lib/waw/fullstate.rb +8 -0
- data/lib/waw/fullstate/on_class.rb +37 -0
- data/lib/waw/fullstate/on_instance.rb +27 -0
- data/lib/waw/fullstate/variable.rb +36 -0
- data/lib/waw/kern.rb +6 -0
- data/lib/waw/kern/app.rb +48 -0
- data/lib/waw/kern/empty/waw.deploy +0 -0
- data/lib/waw/kern/empty/waw.routing +1 -0
- data/lib/waw/kern/freezed_state.rb +32 -0
- data/lib/waw/kern/hooks.rb +53 -0
- data/lib/waw/kern/lifecycle.rb +248 -0
- data/lib/waw/kern/living_state.rb +87 -0
- data/lib/waw/kern/utils.rb +27 -0
- data/lib/waw/resource_collection.rb +100 -0
- data/lib/waw/restart.rb +32 -0
- data/lib/waw/routing.rb +43 -0
- data/lib/waw/routing/action_routing.rb +78 -0
- data/lib/waw/routing/dsl.rb +45 -0
- data/lib/waw/routing/feedback.rb +23 -0
- data/lib/waw/routing/form_validation_feedback.rb +36 -0
- data/lib/waw/routing/javascript.rb +17 -0
- data/lib/waw/routing/redirect.rb +26 -0
- data/lib/waw/routing/refresh.rb +17 -0
- data/lib/waw/routing/routing_rule.rb +16 -0
- data/lib/waw/scope_utils.rb +69 -0
- data/lib/waw/session.rb +51 -0
- data/lib/waw/testing.rb +1 -0
- data/lib/waw/tools/mail.rb +4 -0
- data/lib/waw/tools/mail/mail.rb +119 -0
- data/lib/waw/tools/mail/mail_agent.rb +123 -0
- data/lib/waw/tools/mail/mailbox.rb +62 -0
- data/lib/waw/tools/mail/template.rb +38 -0
- data/lib/waw/utils/dsl_helper.rb +116 -0
- data/lib/waw/validation.rb +175 -0
- data/lib/waw/validation/and_validator.rb +27 -0
- data/lib/waw/validation/array_validations.rb +38 -0
- data/lib/waw/validation/boolean_validator.rb +32 -0
- data/lib/waw/validation/comparison_validations.rb +45 -0
- data/lib/waw/validation/date_validator.rb +31 -0
- data/lib/waw/validation/default_validator.rb +30 -0
- data/lib/waw/validation/dsl_ruby_extensions.rb +11 -0
- data/lib/waw/validation/errors.rb +17 -0
- data/lib/waw/validation/ext.rb +3 -0
- data/lib/waw/validation/file_validator.rb +30 -0
- data/lib/waw/validation/float_validator.rb +19 -0
- data/lib/waw/validation/helpers.rb +67 -0
- data/lib/waw/validation/integer_validator.rb +16 -0
- data/lib/waw/validation/isin_validator.rb +24 -0
- data/lib/waw/validation/mandatory_validator.rb +17 -0
- data/lib/waw/validation/missing_validator.rb +17 -0
- data/lib/waw/validation/not_validator.rb +20 -0
- data/lib/waw/validation/or_validator.rb +34 -0
- data/lib/waw/validation/regexp_validator.rb +29 -0
- data/lib/waw/validation/same_validator.rb +16 -0
- data/lib/waw/validation/signature.rb +157 -0
- data/lib/waw/validation/size_validations.rb +44 -0
- data/lib/waw/validation/string_validator.rb +15 -0
- data/lib/waw/validation/validator.rb +48 -0
- data/lib/waw/wawgen.rb +2 -0
- data/lib/waw/wawgen/create.rb +166 -0
- data/lib/waw/wawgen/project.rb +25 -0
- data/lib/waw/wspec.rb +5 -0
- data/lib/waw/wspec/browser.rb +240 -0
- data/lib/waw/wspec/dsl.rb +201 -0
- data/lib/waw/wspec/html_analysis.rb +136 -0
- data/lib/waw/wspec/html_analysis/tag.rb +56 -0
- data/lib/waw/wspec/runner.rb +70 -0
- data/lib/waw/wspec/scenario.rb +35 -0
- data/lib/waw/wspec/suite.rb +54 -0
- data/test/bricks/error_handler/config/test.cfg +2 -0
- data/test/bricks/error_handler/logs/webapp.log +1411 -0
- data/test/bricks/error_handler/test/error_handler.wspec +16 -0
- data/test/bricks/error_handler/waw.deploy +1 -0
- data/test/bricks/error_handler/waw.routing +27 -0
- data/test/integration/waw_create_integration_test.rb +24 -0
- data/test/spec/assumptions_spec.rb +30 -0
- data/test/spec/controllers/action_controller_spec.rb +14 -0
- data/test/spec/controllers/static/waw_access_spec.rb +112 -0
- data/test/spec/environment_utils_spec.rb +15 -0
- data/test/spec/ext/core/hash_spec.rb +58 -0
- data/test/spec/fixtures.rb +41 -0
- data/test/spec/fixtures/action/config/default.cfg +2 -0
- data/test/spec/fixtures/action/lib/action_controller_test.rb +12 -0
- data/test/spec/fixtures/action/waw.deploy +1 -0
- data/test/spec/fixtures/action/waw.routing +6 -0
- data/test/spec/fixtures/empty/waw.deploy +0 -0
- data/test/spec/fixtures/empty/waw.routing +0 -0
- data/test/spec/fullstate/on_class_spec.rb +59 -0
- data/test/spec/fullstate/on_instance_spec.rb +59 -0
- data/test/spec/fullstate/session_spec.rb +43 -0
- data/test/spec/fullstate/variable_spec.rb +55 -0
- data/test/spec/resource_collection_spec.rb +50 -0
- data/test/spec/test_all.rb +9 -0
- data/test/spec/tools/mail/mail_agent_spec.rb +116 -0
- data/test/spec/tools/mail/mail_spec.rb +56 -0
- data/test/spec/tools/mail/mailbox_spec.rb +57 -0
- data/test/spec/tools/mail/template_spec.rb +47 -0
- data/test/spec/validation/array_validation_spec.rb +63 -0
- data/test/spec/validation/array_validator_spec.rb +17 -0
- data/test/spec/validation/date_validation_spec.rb +35 -0
- data/test/spec/validation/default_validation_spec.rb +37 -0
- data/test/spec/validation/disjuctive_validation_spec.rb +33 -0
- data/test/spec/validation/errors_spec.rb +37 -0
- data/test/spec/validation/file_validator_spec.rb +34 -0
- data/test/spec/validation/mail_validation_spec.rb +51 -0
- data/test/spec/validation/missing_validation_spec.rb +43 -0
- data/test/spec/validation/same_validation_spec.rb +24 -0
- data/test/spec/validation/signature_intuition_spec.rb +37 -0
- data/test/spec/validation/signature_spec.rb +164 -0
- data/test/spec/validation/validation_spec.rb +28 -0
- data/test/spec/wspec/html_analysis/tag_spec.rb +38 -0
- data/test/spec/wspec/html_analysis_spec.rb +170 -0
- data/test/unit/test_all.rb +8 -0
- data/test/unit/waw/app_test.rb +126 -0
- data/test/unit/waw/app_test/config/commons.cfg +2 -0
- data/test/unit/waw/app_test/config/devel.cfg +1 -0
- data/test/unit/waw/config_test.rb +54 -0
- data/test/unit/waw/controllers/action_controller_test.rb +76 -0
- data/test/unit/waw/controllers/action_test.rb +35 -0
- data/test/unit/waw/controllers/example_action_controller_test.rb +24 -0
- data/test/unit/waw/controllers/multiple_action_controller_test.rb +78 -0
- data/test/unit/waw/controllers/static/example/css/example.css +1 -0
- data/test/unit/waw/controllers/static/example/index.html +1 -0
- data/test/unit/waw/controllers/static/example/js/example.js +1 -0
- data/test/unit/waw/controllers/static/example/pages/hello.wtpl +1 -0
- data/test/unit/waw/controllers/static/waw_access_test.rb +76 -0
- data/test/unit/waw/ext/rack_test.rb +74 -0
- data/test/unit/waw/resource_collection_test.rb +49 -0
- data/test/unit/waw/resources.txt +4 -0
- data/test/unit/waw/routing/routing_test.rb +26 -0
- data/test/unit/waw/utils/dsl_helper_test.rb +79 -0
- data/test/unit/waw/utils/dsl_helper_test_extensions1.rb +4 -0
- data/test/unit/waw/validation/signature_test.rb +193 -0
- data/test/unit/waw/validation_test.rb +319 -0
- data/test/unit/waw/wspec/html_analysis_test.html +81 -0
- data/test/unit/waw/wspec/html_analysis_test.rb +26 -0
- metadata +272 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'test/unit/assertions'
|
2
|
+
module Waw
|
3
|
+
module WSpec
|
4
|
+
#
|
5
|
+
# Provides the DSL of the .wspec scenario language.
|
6
|
+
#
|
7
|
+
class DSL
|
8
|
+
include ::Waw::ScopeUtils
|
9
|
+
include ::Test::Unit::Assertions
|
10
|
+
include HTMLAnalysis
|
11
|
+
|
12
|
+
# Creates a DSL instance for a given scenario
|
13
|
+
def initialize(waw_kernel, scenario)
|
14
|
+
@waw_kernel = waw_kernel
|
15
|
+
@scenario = scenario
|
16
|
+
@browser = Browser.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns waw kernel
|
20
|
+
def waw_kernel
|
21
|
+
@waw_kernel
|
22
|
+
end
|
23
|
+
|
24
|
+
#################################################################### Semi-private utilities
|
25
|
+
|
26
|
+
# Executes some code
|
27
|
+
def __execute(&block)
|
28
|
+
self.instance_eval(&block)
|
29
|
+
end
|
30
|
+
alias :by_the_way :__execute
|
31
|
+
|
32
|
+
# A stack of execution context
|
33
|
+
def __stack
|
34
|
+
@stack ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the last because clause
|
38
|
+
def __last_because
|
39
|
+
__stack.last || @scenario.name
|
40
|
+
end
|
41
|
+
|
42
|
+
# Adds an assertion
|
43
|
+
def add_assertion
|
44
|
+
@scenario.add_assertion
|
45
|
+
end
|
46
|
+
|
47
|
+
#################################################################### About scoping
|
48
|
+
|
49
|
+
# Delegates to waw ressources
|
50
|
+
def method_missing(name, *args, &block)
|
51
|
+
if args.empty? and resources and resources.has_resource?(name)
|
52
|
+
resources[name]
|
53
|
+
else
|
54
|
+
super(name, *args, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#################################################################### About browser
|
59
|
+
|
60
|
+
# Returns the current browser instance
|
61
|
+
def browser
|
62
|
+
@browser
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns current browser contents (used by HTMLAnalysis)
|
66
|
+
def browser_contents
|
67
|
+
browser.contents
|
68
|
+
end
|
69
|
+
alias :contents :browser_contents
|
70
|
+
|
71
|
+
# Returns the URL of the index page (the web_base actually)
|
72
|
+
# This method returns nil unless the Waw application has been loaded
|
73
|
+
def index_page
|
74
|
+
config && config.web_base
|
75
|
+
end
|
76
|
+
|
77
|
+
# Goes to a given location and returns the HTTPResponse object
|
78
|
+
def go(location)
|
79
|
+
browser.location = location
|
80
|
+
browser.response
|
81
|
+
end
|
82
|
+
|
83
|
+
# Simply returns args
|
84
|
+
def with(args = {})
|
85
|
+
args
|
86
|
+
end
|
87
|
+
|
88
|
+
#################################################################### About scenario execution
|
89
|
+
|
90
|
+
# Because some condition holds...
|
91
|
+
def because(msg="Unknown cause", &block)
|
92
|
+
raise ArgumentError, "WSpec because/therefore expects a block" unless block
|
93
|
+
__stack.push(msg)
|
94
|
+
yield(browser)
|
95
|
+
__stack.pop
|
96
|
+
end
|
97
|
+
alias :therefore :because
|
98
|
+
|
99
|
+
#################################################################### About reaching pages
|
100
|
+
|
101
|
+
# Asserts that a page can be reached, leading to a Net::HTTPSuccess result
|
102
|
+
def i_reach(which_page)
|
103
|
+
result = go(which_page)
|
104
|
+
assert Net::HTTPSuccess===result, __last_because + " (cannot actually reach #{which_page}: #{result})"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Asserts that a page could be reached (requesting headers leads to a Net::HTTPSucess result)
|
108
|
+
def i_could_reach(which_page)
|
109
|
+
return if which_page.nil? or '#'==which_page
|
110
|
+
case which_page
|
111
|
+
when Tag
|
112
|
+
i_could_reach(which_page[:href])
|
113
|
+
when Array
|
114
|
+
which_page.each{|link| i_could_reach(link)}
|
115
|
+
when String
|
116
|
+
result = browser.headers_fetch(which_page)
|
117
|
+
assert Net::HTTPSuccess===result, __last_because + " (could not reach #{which_page}: #{result})"
|
118
|
+
else
|
119
|
+
raise ArgumentError, "Unable to use #{which_page} for i_could_reach"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Asserts that a page cannot be reached, leading to a Net::HTTPNotFound or a Net::HTTPForbidden (403)
|
124
|
+
# result
|
125
|
+
def i_dont_reach(which_page)
|
126
|
+
result = go(which_page)
|
127
|
+
assert (Net::HTTPNotFound===result or Net::HTTPForbidden===result), __last_because + " (can reach #{which_page}: #{result})"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Asserts that a page may not be reached, leading to a Net::HTTPForbidden (403) result.
|
131
|
+
def i_may_not_reach(which_page)
|
132
|
+
result = go(which_page)
|
133
|
+
assert (Net::HTTPForbidden===result or Net::HTTPBadRequest===result), __last_because + " (may actually reach #{which_page}: #{result})"
|
134
|
+
end
|
135
|
+
|
136
|
+
#################################################################### About seeing something on the page
|
137
|
+
|
138
|
+
# Asserts that something can be seen on the current page
|
139
|
+
def i_see(what)
|
140
|
+
assert i_see?(what), __last_because + " (don't see #{what})"
|
141
|
+
end
|
142
|
+
|
143
|
+
# Asserts that something is not present on the current page
|
144
|
+
def i_dont_see(what)
|
145
|
+
assert !i_see?(what), __last_because + " (actually see #{what})"
|
146
|
+
end
|
147
|
+
|
148
|
+
# Asserts that I see a particular tag (see HTMLAnalysis.tag)
|
149
|
+
def i_see_tag(name, opts = nil)
|
150
|
+
assert has_tag?(name, opts), __last_because + " (don't see tag <#{name} #{opts.inspect})"
|
151
|
+
end
|
152
|
+
|
153
|
+
# Asserts that I see a particular link (see HTMLAnalysis.link)
|
154
|
+
def i_see_link(opts = nil)
|
155
|
+
assert has_link?(opts), __last_because + " (dont see link <a #{opts.inspect})"
|
156
|
+
end
|
157
|
+
|
158
|
+
#################################################################### About link-based navigation
|
159
|
+
|
160
|
+
# Following a link
|
161
|
+
def i_follow(link)
|
162
|
+
link = case link
|
163
|
+
when String
|
164
|
+
link
|
165
|
+
when Tag
|
166
|
+
link[:href]
|
167
|
+
when ::Waw::ActionController::Action
|
168
|
+
link.href
|
169
|
+
else
|
170
|
+
raise ArgumentError, "Unable to apply i_follow to #{link.inspect}"
|
171
|
+
end
|
172
|
+
i_reach(link)
|
173
|
+
end
|
174
|
+
|
175
|
+
#################################################################### About forms and action
|
176
|
+
|
177
|
+
# Submits some form with optional arguments
|
178
|
+
def i_submit(form, args = {})
|
179
|
+
assert_not_nil form, __last_because + "(form has not been found)"
|
180
|
+
raise ArgumentError, "i_submit requires a Tag instance, #{form.inspect} received" unless Tag===form
|
181
|
+
i_invoke(form[:action], args)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Directly invoke an action or service server side, bypassing
|
185
|
+
# form lookup and so on.
|
186
|
+
def i_invoke(action, args = {})
|
187
|
+
result = case action
|
188
|
+
when String
|
189
|
+
browser.invoke_service(action, args)
|
190
|
+
when ::Waw::ActionController::Action
|
191
|
+
browser.invoke_action(action, args)
|
192
|
+
else
|
193
|
+
raise ArgumentError, "Unable to apply i_invoke on #{action.inspect}, unable to catch the associated action"
|
194
|
+
end
|
195
|
+
assert Net::HTTPSuccess===result, __last_because + " (invoking #{action.inspect} led to: #{result})"
|
196
|
+
result
|
197
|
+
end
|
198
|
+
|
199
|
+
end # class DSL
|
200
|
+
end # module WSpec
|
201
|
+
end # module Waw
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'waw/wspec/html_analysis/tag'
|
2
|
+
module Waw
|
3
|
+
module WSpec
|
4
|
+
#
|
5
|
+
# Provides utility methods for analysis of XML/HTML contents.
|
6
|
+
#
|
7
|
+
# This module expects an accessor to a browser instance. Otherwise,
|
8
|
+
# the browser_contents method may be overrided.
|
9
|
+
#
|
10
|
+
module HTMLAnalysis
|
11
|
+
|
12
|
+
# Yields the block passing browser contents as first argument
|
13
|
+
def browser_contents
|
14
|
+
browser.contents
|
15
|
+
end
|
16
|
+
|
17
|
+
# Decodes a string of HTML attributes as a hash with symbols as keys
|
18
|
+
def decode_attributes_string(str)
|
19
|
+
attrs = {}
|
20
|
+
str.scan(/([a-z]+)=["'](.*?)["']/) do |match|
|
21
|
+
attrs[match[0].to_sym] = match[1]
|
22
|
+
end
|
23
|
+
attrs
|
24
|
+
end
|
25
|
+
|
26
|
+
#################################################################### Tag helpers
|
27
|
+
|
28
|
+
# Find tags inside the browser contents. If a block is given, yield it with
|
29
|
+
# each tag information. Otherwise, returns an array of found tags, that can be
|
30
|
+
# empty.
|
31
|
+
def all_tags(name, opts = nil, contents = browser_contents)
|
32
|
+
found = [] unless block_given?
|
33
|
+
contents.scan(/(<\s*#{name}\s*(.*?)\/?>)/) do |match|
|
34
|
+
tag = Tag.new(match[0], name, decode_attributes_string(match[1]))
|
35
|
+
next unless tag.matches?(opts)
|
36
|
+
block_given? ? yield(tag) : (found << tag)
|
37
|
+
end
|
38
|
+
found
|
39
|
+
end
|
40
|
+
alias :tags :all_tags
|
41
|
+
|
42
|
+
# Iterates over a tag specification
|
43
|
+
def each_tag(name, opts = nil, contents = browser_contents, &block)
|
44
|
+
tags(name, opts, contents, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Shortcut for <code>tags(name, opts, contents)[0]</code>. Returns nil if no such
|
48
|
+
# tag can be found
|
49
|
+
def first_tag(name, opts = nil, contents = browser_contents)
|
50
|
+
tags(name, opts, contents)[0]
|
51
|
+
end
|
52
|
+
alias :tag :first_tag
|
53
|
+
|
54
|
+
# Look for some html tag
|
55
|
+
def has_tag?(name, opts = nil, contents = browser_contents)
|
56
|
+
return tags(name, opts, contents).size != 0
|
57
|
+
end
|
58
|
+
|
59
|
+
#################################################################### Links helpers
|
60
|
+
|
61
|
+
# Shortcut for <code>tags('a', {:href => /^(.*?)$/}.merge(opts), contents, &block)</code>
|
62
|
+
def all_links(opts = nil, contents = browser_contents, &block)
|
63
|
+
tags('a', {:href => /^(.*?)$/}.merge(opts || {}), contents, &block)
|
64
|
+
end
|
65
|
+
alias :links :all_links
|
66
|
+
|
67
|
+
# Same as all_links, but retains internal links only (i.e. <code>not(URI::Generic.absolute?)</code>)
|
68
|
+
def all_internal_links(opts = nil, contents = browser_contents, &block)
|
69
|
+
if block
|
70
|
+
all_links(opts, contents).each do |link|
|
71
|
+
yield(link) unless URI.parse(link[:href]).absolute?
|
72
|
+
end
|
73
|
+
else
|
74
|
+
all_links(opts, contents).reject{|link| URI.parse(link[:href]).absolute?}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias :internal_links :all_internal_links
|
78
|
+
|
79
|
+
# Same as all_links, but retains external links only (i.e. <code>URI::Generic.absolute?</code>)
|
80
|
+
def all_external_links(opts = nil, contents = browser_contents, &block)
|
81
|
+
if block
|
82
|
+
all_links(opts, contents).each do |link|
|
83
|
+
yield(link) if URI.parse(link[:href]).absolute?
|
84
|
+
end
|
85
|
+
else
|
86
|
+
all_links(opts, contents).select{|link| URI.parse(link[:href]).absolute?}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
alias :external_links :all_external_links
|
90
|
+
|
91
|
+
# Shortcut for <code>links(name, opts, contents)[0]</code>. Returns nil if no such
|
92
|
+
# link can be found
|
93
|
+
def first_link(opts = nil, contents = browser_contents)
|
94
|
+
links(opts, contents)[0]
|
95
|
+
end
|
96
|
+
alias :link :first_link
|
97
|
+
|
98
|
+
# Checks if some link can be found
|
99
|
+
def has_link?(opts = nil, contents = browser_contents)
|
100
|
+
return links(opts, contents).size != 0
|
101
|
+
end
|
102
|
+
|
103
|
+
#################################################################### Form helpers
|
104
|
+
|
105
|
+
# Shortcut for <code>tag('form', opts, contents)</code>
|
106
|
+
def form(opts = nil, contents = browser_contents)
|
107
|
+
if opts[:action] and ::Waw::ActionController::Action===opts[:action]
|
108
|
+
action = opts[:action]
|
109
|
+
opts = {:id => action.id}.merge(opts || {}).forget(:action)
|
110
|
+
form = tag('form', opts, contents)
|
111
|
+
form[:action] = action if form
|
112
|
+
form
|
113
|
+
else
|
114
|
+
tag('form', opts, contents)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#################################################################### Text helpers
|
119
|
+
|
120
|
+
# Assert that the user sees something in the browser contents
|
121
|
+
def i_see?(what, contents = browser_contents)
|
122
|
+
case what
|
123
|
+
when NilClass
|
124
|
+
false
|
125
|
+
when String, Regexp
|
126
|
+
not(contents.index(what).nil?)
|
127
|
+
when Tag
|
128
|
+
true
|
129
|
+
else
|
130
|
+
raise ArgumentError, "Unable to see #{what}, not understood"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end # module HTMLAnalysis
|
135
|
+
end # module WSpec
|
136
|
+
end # module Waw
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Waw
|
2
|
+
module WSpec
|
3
|
+
module HTMLAnalysis
|
4
|
+
|
5
|
+
# A tag helper class
|
6
|
+
class Tag
|
7
|
+
|
8
|
+
# Result of the regexp matching applied to get this tag
|
9
|
+
attr_reader :match
|
10
|
+
|
11
|
+
# Name of the tag
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# Tag attributes
|
15
|
+
attr_reader :attributes
|
16
|
+
|
17
|
+
# Creates a Tag instance
|
18
|
+
def initialize(match, name, attributes)
|
19
|
+
@match, @name, @attributes = match, name, attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the value of an attribute
|
23
|
+
def [](key)
|
24
|
+
attributes[key]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Forces the value of an attribute
|
28
|
+
def []=(key, value)
|
29
|
+
attributes[key] = value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Checks if this tags has a given attribute
|
33
|
+
def has_attribute?(name)
|
34
|
+
attributes.has_key?(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Checks if this tag matches a given attributes specification
|
38
|
+
def matches?(opts = {})
|
39
|
+
return true if (opts.nil? or opts.empty?)
|
40
|
+
opts.each_pair do |name, value|
|
41
|
+
return false unless self.has_attribute?(name)
|
42
|
+
case value
|
43
|
+
when Regexp
|
44
|
+
return false unless value =~ self[name]
|
45
|
+
else
|
46
|
+
return false unless value.to_s == self[name]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
end # class Tag
|
53
|
+
|
54
|
+
end # module HTMLAnalysis
|
55
|
+
end # module WSpec
|
56
|
+
end # module Waw
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'waw'
|
2
|
+
require 'waw/wspec'
|
3
|
+
|
4
|
+
if RUBY_VERSION >= "1.9"
|
5
|
+
# These classes don't seem to exist in some Ruby 1.9 installations
|
6
|
+
module Test
|
7
|
+
module Unit
|
8
|
+
class AssertionFailedError < StandardError
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
else
|
13
|
+
# These classes don't seem to exist in some Ruby 1.8 installations
|
14
|
+
module MiniTest
|
15
|
+
class Assertion < StandardError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# The autoloaded scenarios
|
21
|
+
$scenarios = []
|
22
|
+
def scenario(name, &block)
|
23
|
+
$scenarios << Waw::WSpec::Scenario.new(name, &block)
|
24
|
+
end
|
25
|
+
alias :requirement :scenario
|
26
|
+
|
27
|
+
# We run the whole suite at end
|
28
|
+
at_exit {
|
29
|
+
begin
|
30
|
+
puts "Running wspec test suite now"
|
31
|
+
|
32
|
+
# Load waw through rack in a different thread
|
33
|
+
puts "Loading waw application and web server"
|
34
|
+
t = Thread.new(Waw.kernel) do |app|
|
35
|
+
begin
|
36
|
+
server = Rack::Handler::Mongrel
|
37
|
+
rescue LoadError => e
|
38
|
+
server = Rack::Handler::WEBrick
|
39
|
+
end
|
40
|
+
options = {:Port => Waw.config.web_port, :Host => "0.0.0.0", :AccessLog => []}
|
41
|
+
server.run app, options
|
42
|
+
end
|
43
|
+
|
44
|
+
# Wait until the server is loaded
|
45
|
+
try, ok = 0, false
|
46
|
+
begin
|
47
|
+
puts "Attempting to reach the web server..."
|
48
|
+
Net::HTTP.get(URI.parse(Waw.config.web_base))
|
49
|
+
ok = true
|
50
|
+
rescue Errno::ECONNREFUSED => ex
|
51
|
+
sleep 0.1
|
52
|
+
end until (ok or (try += 1)>10)
|
53
|
+
|
54
|
+
# Create the suite and run it
|
55
|
+
if ok
|
56
|
+
s = ::Waw::WSpec::Suite.new($scenarios)
|
57
|
+
t1 = Time.now
|
58
|
+
s.run(Waw.kernel)
|
59
|
+
t2 = Time.now
|
60
|
+
puts "\nFinished in #{Time.now - t1} seconds.\n"
|
61
|
+
puts "#{s.scenario_count} high-level requirements, #{s.assertion_count} assertions, #{s.failure_count} failures, #{s.error_count} errors"
|
62
|
+
else
|
63
|
+
raise WawError, "Unable to reach the local web server... sorry!"
|
64
|
+
end
|
65
|
+
|
66
|
+
ensure
|
67
|
+
# Kill the web server thread
|
68
|
+
t.kill if t
|
69
|
+
end
|
70
|
+
}
|