waw 0.2.2
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.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,44 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Validation
|
|
3
|
+
# Validation linked to the length of the string
|
|
4
|
+
module SizeValidations
|
|
5
|
+
module Methods
|
|
6
|
+
|
|
7
|
+
# Checks that it has a size
|
|
8
|
+
def has_size?(val) val.respond_to?(:size) end
|
|
9
|
+
|
|
10
|
+
# Builds a validator that verifies that the length is greater than
|
|
11
|
+
# a specified value
|
|
12
|
+
def >(value)
|
|
13
|
+
Validator.new {|*vals| Validation.argument_safe{ vals.all?{|val| has_size?(val) and (val.size > value)} }}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Builds a validator that verifies that the length is greater-or-equal to
|
|
17
|
+
# a specified value
|
|
18
|
+
def >=(value)
|
|
19
|
+
Validator.new {|*vals| Validation.argument_safe{ vals.all?{|val| has_size?(val) and (val.size >= value)} }}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Builds a validator that verifies that the length is less than
|
|
23
|
+
# a specified value
|
|
24
|
+
def <(value)
|
|
25
|
+
Validator.new {|*vals| Validation.argument_safe{ vals.all?{|val| has_size?(val) and (val.size < value)} }}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Builds a validator that verifies that the length is less-or-equal to
|
|
29
|
+
# a specified value
|
|
30
|
+
def <=(value)
|
|
31
|
+
Validator.new {|*vals| Validation.argument_safe{ vals.all?{|val| has_size?(val) and (val.size <= value)} }}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Builds a validator that verifies that the length is equal to a
|
|
35
|
+
# specified value
|
|
36
|
+
def ==(value)
|
|
37
|
+
Validator.new {|*vals| Validation.argument_safe{ vals.all?{|val| has_size?(val) and (val.size == value)} }}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
extend Methods
|
|
42
|
+
end # module SizeValidations
|
|
43
|
+
end # module Validation
|
|
44
|
+
end # module Waw
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Validation
|
|
3
|
+
class StringValidator < Validator
|
|
4
|
+
|
|
5
|
+
def validate(*values)
|
|
6
|
+
values.all?{|v| String===v}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def convert_and_validate(*values)
|
|
10
|
+
[validate(*values), values]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end # module Validation
|
|
15
|
+
end # module Waw
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Validation
|
|
3
|
+
#
|
|
4
|
+
# A validator reusable class.
|
|
5
|
+
#
|
|
6
|
+
class Validator
|
|
7
|
+
include ::Waw::Validation::Helpers
|
|
8
|
+
|
|
9
|
+
# Creates a validator instance that takes a block as validation code
|
|
10
|
+
def initialize(&block)
|
|
11
|
+
@block = block
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Calls the block installed at initialization time
|
|
15
|
+
def validate(*values)
|
|
16
|
+
raise "Missing validation block on #{self}" unless @block
|
|
17
|
+
@block.call(*values)
|
|
18
|
+
end
|
|
19
|
+
def ===(*args)
|
|
20
|
+
validate(*args)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Converts and validate
|
|
24
|
+
def convert_and_validate(*values)
|
|
25
|
+
validate(*values) ? [true, values] : [false, values]
|
|
26
|
+
end
|
|
27
|
+
def =~(*args)
|
|
28
|
+
convert_and_validate(*args)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Negates this validator
|
|
32
|
+
def not
|
|
33
|
+
NotValidator.new(self)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Creates a validator by disjunction
|
|
37
|
+
def |(validator)
|
|
38
|
+
OrValidator.new(self, Waw::Validation.to_validator(validator))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Creates a validator by conjunction
|
|
42
|
+
def &(validator)
|
|
43
|
+
AndValidator.new(self, Waw::Validation.to_validator(validator))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end # class Validator
|
|
47
|
+
end # module Validation
|
|
48
|
+
end # module Waw
|
data/lib/waw/wawgen.rb
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
module Waw
|
|
4
|
+
module Wawgen
|
|
5
|
+
# Implementation of 'waw create'
|
|
6
|
+
class Create
|
|
7
|
+
|
|
8
|
+
# Which layout
|
|
9
|
+
attr_reader :layout
|
|
10
|
+
|
|
11
|
+
# Force overrides?
|
|
12
|
+
attr_reader :force
|
|
13
|
+
|
|
14
|
+
# Creates a command instance
|
|
15
|
+
def initialize
|
|
16
|
+
@layout = 'empty'
|
|
17
|
+
@force = false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Parses commandline options provided as an array of Strings.
|
|
21
|
+
def options
|
|
22
|
+
@options ||= OptionParser.new do |opt|
|
|
23
|
+
opt.program_name = File.basename $0
|
|
24
|
+
opt.version = WLang::VERSION
|
|
25
|
+
opt.release = nil
|
|
26
|
+
opt.summary_indent = ' ' * 4
|
|
27
|
+
banner = <<-EOF
|
|
28
|
+
# Usage waw create [options] ProjectName
|
|
29
|
+
|
|
30
|
+
# Creates an initial waw project structure
|
|
31
|
+
EOF
|
|
32
|
+
opt.banner = banner.gsub(/[ \t]+# /, "")
|
|
33
|
+
|
|
34
|
+
opt.separator nil
|
|
35
|
+
opt.separator "Options:"
|
|
36
|
+
|
|
37
|
+
opt.on("--force", "-f", "Erase any exsting file on conflict") do |value|
|
|
38
|
+
@force = true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
opt.on("--layout=LAYOUT", "-l", "Use a specific waw layout (default empty)") do |value|
|
|
42
|
+
@layout = value
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
opt.on("--verbose", "-v", "Display extra progress as we parse.") do |value|
|
|
46
|
+
@verbosity = 2
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# No argument, shows at tail. This will print an options summary.
|
|
50
|
+
# Try it and see!
|
|
51
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
|
52
|
+
puts options
|
|
53
|
+
exit
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Another typical switch to print the version.
|
|
57
|
+
opt.on_tail("--version", "Show version") do
|
|
58
|
+
puts "waw version " << Waw::VERSION << " (c) University of Louvain, Bernard & Louis Lambeau"
|
|
59
|
+
exit
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
opt.separator nil
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Runs the command
|
|
67
|
+
def run(argv)
|
|
68
|
+
# parse options
|
|
69
|
+
rest = options.parse!(argv)
|
|
70
|
+
if rest.length != 1
|
|
71
|
+
puts options
|
|
72
|
+
exit(-1)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# check project name
|
|
76
|
+
project_name = rest[0]
|
|
77
|
+
exit("Invalid project name #{project_name}, must start with [a-zA-Z]") unless /^[a-zA-Z]/ =~ project_name
|
|
78
|
+
if project_name =~ /^[a-z]/
|
|
79
|
+
project_name = (project_name[0...1].upcase + project_name[1..-1])
|
|
80
|
+
puts "Warning: using #{project_name} as project name for ruby needs..."
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# create project
|
|
84
|
+
project = ::Waw::Wawgen::Project.new(project_name)
|
|
85
|
+
begin
|
|
86
|
+
generate(project)
|
|
87
|
+
rescue WLang::Error => ex
|
|
88
|
+
puts ex.message
|
|
89
|
+
puts ex.wlang_backtrace.join("\n")
|
|
90
|
+
puts ex.backtrace.join("\n")
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Puts an error message and exits
|
|
95
|
+
def exit(msg)
|
|
96
|
+
puts msg
|
|
97
|
+
Kernel.exit(-1)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def generate_recursively(project, layout_folder, target_folder)
|
|
101
|
+
# Generate files now
|
|
102
|
+
Dir.new(layout_folder).each do |file|
|
|
103
|
+
next if ['.', '..', 'dontforgetme'].include?(file)
|
|
104
|
+
next if 'dependencies'==file
|
|
105
|
+
target = File.join(target_folder, file.gsub('project', project.lowname))
|
|
106
|
+
puts "Generating #{target} from #{layout}/#{file}"
|
|
107
|
+
|
|
108
|
+
if File.directory?(source=File.join(layout_folder, file))
|
|
109
|
+
FileUtils.mkdir_p target unless File.exists?(target)
|
|
110
|
+
generate_recursively(project, source, target)
|
|
111
|
+
else
|
|
112
|
+
File.open(target, 'w') do |io|
|
|
113
|
+
if /jquery/ =~ file
|
|
114
|
+
io << File.read(File.join(layout_folder, file))
|
|
115
|
+
else
|
|
116
|
+
context = {"project" => project}
|
|
117
|
+
io << WLang.file_instantiate(File.join(layout_folder, file), context, 'wlang/active-string', :parentheses).to_s
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Generates a given layout for a specific project
|
|
125
|
+
def generate_layout(project, layout)
|
|
126
|
+
# Locate the layout folder
|
|
127
|
+
layout_folder = File.join(File.dirname(__FILE__), '..', '..', '..', 'layouts', layout)
|
|
128
|
+
puts File.expand_path(layout_folder)
|
|
129
|
+
exit("Unknown layout #{layout}") unless File.exists?(layout_folder)
|
|
130
|
+
|
|
131
|
+
# Handle dependencies
|
|
132
|
+
dependencies_file = File.join(layout_folder, 'dependencies')
|
|
133
|
+
if File.exists?(dependencies_file)
|
|
134
|
+
File.readlines(dependencies_file).each do |line|
|
|
135
|
+
next if /^#/ =~ (line = line.strip)
|
|
136
|
+
line.split(/\s/).each do |word|
|
|
137
|
+
generate_layout(project, word)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Let recursive generation occur
|
|
143
|
+
puts "Generating recursively project, #{layout_folder}, #{project.folder}"
|
|
144
|
+
generate_recursively(project, layout_folder, project.folder)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Generates the project
|
|
148
|
+
def generate(project)
|
|
149
|
+
# A small debug message and we start
|
|
150
|
+
puts "Generating project with names #{project.upname} inside #{project.lowname} using layout #{layout}"
|
|
151
|
+
|
|
152
|
+
# 1) Create the output folder if it not exists
|
|
153
|
+
if File.exists?(project.folder) and not(force)
|
|
154
|
+
exit("The project folder #{project.lowname} already exists. Remove it first")
|
|
155
|
+
else
|
|
156
|
+
FileUtils.rm_rf project.folder if File.exists?(project.folder)
|
|
157
|
+
FileUtils.mkdir_p project.folder
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
generate_layout(project, layout)
|
|
161
|
+
FileUtils.chmod 0755, File.join(project.root, 'config.ru')
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
end # class Create
|
|
165
|
+
end # module Wawgen
|
|
166
|
+
end # module Waw
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Waw
|
|
2
|
+
module Wawgen
|
|
3
|
+
class Project
|
|
4
|
+
|
|
5
|
+
# Upper case name of the project
|
|
6
|
+
attr_reader :upname
|
|
7
|
+
|
|
8
|
+
# Lower case name of the project
|
|
9
|
+
attr_reader :lowname
|
|
10
|
+
|
|
11
|
+
# Creates a project instance
|
|
12
|
+
def initialize(name, folder=nil)
|
|
13
|
+
@upname, @lowname = name, WLang::encode(name, 'ruby/method-case')
|
|
14
|
+
@folder = folder
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns root folder
|
|
18
|
+
def root
|
|
19
|
+
@folder ||= lowname
|
|
20
|
+
end
|
|
21
|
+
alias :folder :root
|
|
22
|
+
|
|
23
|
+
end # class Project
|
|
24
|
+
end # module Wawgen
|
|
25
|
+
end # module Waw
|
data/lib/waw/wspec.rb
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'uri'
|
|
3
|
+
module Waw
|
|
4
|
+
module WSpec
|
|
5
|
+
# A fake browser for waw application testing
|
|
6
|
+
class Browser
|
|
7
|
+
include Waw::WSpec::HTMLAnalysis
|
|
8
|
+
|
|
9
|
+
# Current browser location
|
|
10
|
+
attr_reader :location
|
|
11
|
+
|
|
12
|
+
# Current server response
|
|
13
|
+
attr_reader :response
|
|
14
|
+
|
|
15
|
+
# The last action result
|
|
16
|
+
attr_reader :last_action_result
|
|
17
|
+
|
|
18
|
+
# Creates a browser instance
|
|
19
|
+
def initialize(location = nil)
|
|
20
|
+
self.location = location if location
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#################################################################### URI utilities
|
|
24
|
+
|
|
25
|
+
# Checks if something is an URI
|
|
26
|
+
def is_uri?(uri)
|
|
27
|
+
URI::Generic===uri
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Ensures that something is an uri or convert it.
|
|
31
|
+
def ensure_uri(uri)
|
|
32
|
+
raise ArgumentError, "ensure_uri: uri may not be nil" if uri.nil?
|
|
33
|
+
is_uri?(uri) ? uri : URI.parse(uri)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Extracts the base of an URI
|
|
37
|
+
def extract_base(uri)
|
|
38
|
+
raise ArgumentError, "extract_base: uri may not be nil" if uri.nil?
|
|
39
|
+
ensure_uri("#{uri.scheme}://#{uri.host}#{uri.port ? (':' + uri.port.to_s) : ''}/")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Computes the new location if a relative uri is followed
|
|
43
|
+
def relative_uri(uri)
|
|
44
|
+
raise ArgumentError, "relative_uri: uri may not be nil" if uri.nil?
|
|
45
|
+
uri = ensure_uri(uri)
|
|
46
|
+
if uri.path[0...1] == '/'
|
|
47
|
+
new_location = base.dup
|
|
48
|
+
new_location.path = uri.path
|
|
49
|
+
new_location.query = uri.query
|
|
50
|
+
new_location
|
|
51
|
+
else
|
|
52
|
+
new_location = base.dup
|
|
53
|
+
new_location.path = '/' + uri.path
|
|
54
|
+
new_location.query = uri.query
|
|
55
|
+
new_location
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#################################################################### Query utilities
|
|
60
|
+
|
|
61
|
+
# Looks for the base of the website
|
|
62
|
+
def base
|
|
63
|
+
@base ||= find_base
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Finds the base of the current location
|
|
67
|
+
def find_base
|
|
68
|
+
if contents and (found = tag("base", {:href => /.*/}, contents))
|
|
69
|
+
ensure_uri(found[:href])
|
|
70
|
+
else
|
|
71
|
+
extract_base(location)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Checks if the last request waw answered by a 404 not found
|
|
76
|
+
def is404
|
|
77
|
+
(Net::HTTPNotFound === response)
|
|
78
|
+
end
|
|
79
|
+
alias :is404? :is404
|
|
80
|
+
|
|
81
|
+
# Checks if the last request waw answered by a 200 OK
|
|
82
|
+
def is200
|
|
83
|
+
(Net::HTTPSuccess === response)
|
|
84
|
+
end
|
|
85
|
+
alias :is200? :is200
|
|
86
|
+
|
|
87
|
+
# Returns the current shown contents
|
|
88
|
+
def contents
|
|
89
|
+
response ? response.read_body : nil
|
|
90
|
+
end
|
|
91
|
+
alias :browser_contents :contents
|
|
92
|
+
|
|
93
|
+
#################################################################### Location set
|
|
94
|
+
|
|
95
|
+
# Go to a relative position
|
|
96
|
+
def go_relative(uri)
|
|
97
|
+
self.location = relative_uri(uri)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Sets the current location
|
|
101
|
+
def location=(loc)
|
|
102
|
+
if (loc = ensure_uri(loc)).relative?
|
|
103
|
+
go_relative(loc)
|
|
104
|
+
else
|
|
105
|
+
@location, @response = fetch(loc)
|
|
106
|
+
@location
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Fetches the headers only and returns it without keeping the result in browser
|
|
111
|
+
# state
|
|
112
|
+
def headers_fetch(uri)
|
|
113
|
+
# Fetch the result at that location
|
|
114
|
+
if (loc = ensure_uri(uri)).relative?
|
|
115
|
+
headers_fetch(relative_uri(uri))
|
|
116
|
+
else
|
|
117
|
+
response = Net::HTTP.start(loc.host, loc.port) do |http|
|
|
118
|
+
headers = @cookie ? {'Cookie' => @cookie} : {}
|
|
119
|
+
http.head(loc.path, headers)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Refreshes the browser
|
|
125
|
+
def refresh
|
|
126
|
+
self.location = location
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Simulates a click. Support relative as well as absolute paths.
|
|
130
|
+
# Raises a URI::InvalidURIError if the given href seems invalid.
|
|
131
|
+
def click_href(href)
|
|
132
|
+
uri = URI.parse(href)
|
|
133
|
+
if uri.relative?
|
|
134
|
+
go_relative(uri)
|
|
135
|
+
else
|
|
136
|
+
case uri.scheme
|
|
137
|
+
when "http"
|
|
138
|
+
self.location = href
|
|
139
|
+
else
|
|
140
|
+
raise ArgumentError, "This browser does not support #{href} location"
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
#################################################################### Server invocation utilities
|
|
146
|
+
|
|
147
|
+
# Applies the action routing for a given action
|
|
148
|
+
def apply_action_routing(action, result)
|
|
149
|
+
@last_action_result = result
|
|
150
|
+
action.routing.apply_on_browser(result, self) if action.routing
|
|
151
|
+
result.extend(Waw::Routing::Methods)
|
|
152
|
+
result
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Invokes an action server side, decodes json response an applies action routing.
|
|
156
|
+
# Returns the action result.
|
|
157
|
+
def invoke_action(action, args = {})
|
|
158
|
+
raise ArgumentError, "Browser.invoke_action expects an ActionController::Action as first parameter"\
|
|
159
|
+
unless ::Waw::ActionController::Action===action
|
|
160
|
+
location, response = fetch(relative_uri(action.uri), :post, args)
|
|
161
|
+
apply_action_routing(action, JSON.parse(response.body))
|
|
162
|
+
self.response
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Invokes a service server side and returns HTTP response
|
|
166
|
+
def invoke_service(service, args = {})
|
|
167
|
+
raise ArgumentError, "Browser.invoke_service expects a String as first parameter"\
|
|
168
|
+
unless String===service
|
|
169
|
+
location, response = fetch(relative_uri(service), :post, args)
|
|
170
|
+
self.response
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Invokes a server service with arguments and decoding method
|
|
174
|
+
def server_invoke(service, args, decode_method = nil)
|
|
175
|
+
location, response = fetch(relative_uri(service), :post, args)
|
|
176
|
+
response
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
#################################################################### Private section
|
|
180
|
+
# Clean cache after fetch
|
|
181
|
+
def clean_post_fetch
|
|
182
|
+
@base = nil
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Fetchs a given location
|
|
186
|
+
def fetch(uri, method = :get, data = {}, limit = 10)
|
|
187
|
+
# You should choose better exception.
|
|
188
|
+
raise 'HTTP redirect too deep' if limit == 0
|
|
189
|
+
|
|
190
|
+
# Fetch the result at that location
|
|
191
|
+
location = ensure_uri(uri)
|
|
192
|
+
response = Net::HTTP.start(location.host, location.port) do |http|
|
|
193
|
+
headers = @cookie ? {'Cookie' => @cookie} : {}
|
|
194
|
+
case method
|
|
195
|
+
when :get
|
|
196
|
+
path = location.path
|
|
197
|
+
path += '?' + location.query if location.query
|
|
198
|
+
http.request_get(path, headers)
|
|
199
|
+
when :post
|
|
200
|
+
req = Net::HTTP::Post.new(location.path, headers)
|
|
201
|
+
req.form_data = data.unsymbolize_keys
|
|
202
|
+
http.request(req)
|
|
203
|
+
else
|
|
204
|
+
raise ArgumentError, "Invalid fetch method #{method}"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# If a cookie is requested save it
|
|
209
|
+
@cookie = response['set-cookie']
|
|
210
|
+
|
|
211
|
+
# Catch the response, following redirections
|
|
212
|
+
result = case response
|
|
213
|
+
when Net::HTTPRedirection
|
|
214
|
+
fetch(response['location'] || response['Location'], :get, {}, limit - 1)
|
|
215
|
+
else
|
|
216
|
+
[location, response]
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Cleans cache and returns result
|
|
220
|
+
clean_post_fetch
|
|
221
|
+
result
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
#################################################################### Helpers to save context
|
|
225
|
+
|
|
226
|
+
# Installs the browser context
|
|
227
|
+
def install_context(location, response, cookie)
|
|
228
|
+
@location, @response, @cookie = location, response, cookie
|
|
229
|
+
self
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Duplicates this browser instance, with internal state
|
|
233
|
+
def dup
|
|
234
|
+
Browser.new.install_context(@location, @response, @cookie)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
end # class Browser
|
|
238
|
+
class ServerError < StandardError; end
|
|
239
|
+
end # module WSpec
|
|
240
|
+
end # module Waw
|