weasel_diesel 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ruby-head
11
+ - jruby-head
12
+ - ree
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in weasel_diesel.gemspec
4
4
  gemspec
5
+
6
+ gem "json", :platform => :jruby
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Web Service DSL
2
2
 
3
+ [![CI Build Status](https://secure.travis-ci.org/mattetti/Weasel-Diesel.png?branch=master)](http://travis-ci.org/mattetti/Weasel-Diesel)
4
+
3
5
  Weasel Diesel is a DSL to describe and document your web API.
4
6
 
5
7
  To get you going quickly, see the [generator for sinatra apps](https://github.com/mattetti/wd-sinatra).
@@ -20,7 +22,7 @@ describe_service "hello_world" do |service|
20
22
  service.disable_auth # on by default
21
23
 
22
24
  # INPUT
23
- service.param.string :name, :default => 'World'
25
+ service.param.string :name, :default => 'World', :doc => "The name of the person to greet."
24
26
 
25
27
  # OUTPUT
26
28
  service.response do |response|
@@ -33,7 +35,6 @@ describe_service "hello_world" do |service|
33
35
  # DOCUMENTATION
34
36
  service.documentation do |doc|
35
37
  doc.overall "This service provides a simple hello world implementation example."
36
- doc.param :name, "The name of the person to greet."
37
38
  doc.example "<code>curl -I 'http://localhost:9292/hello_world?name=Matt'</code>"
38
39
  end
39
40
 
@@ -59,9 +60,15 @@ Or a more complex example using XML:
59
60
  service.params do |p|
60
61
  p.string :framework, :in => SpecOptions, :null => false, :required => true
61
62
 
62
- p.datetime :timestamp, :default => Time.now
63
+ p.datetime :timestamp,
64
+ :default => Time.now,
65
+ :doc => "The test framework used, could be one of the two following: #{SpecOptions.join(", ")}."
66
+
63
67
  p.string :alpha, :in => ['a', 'b', 'c']
64
- p.string :version, :null => false
68
+ p.string :version,
69
+ :null => false,
70
+ :doc => "The version of the framework to use."
71
+
65
72
  p.integer :num, :minvalue => 42
66
73
  p.namespace :user do |user|
67
74
  user.integer :id, :required => :true
@@ -92,10 +99,6 @@ Or a more complex example using XML:
92
99
  This is a test service used to test the framework.
93
100
  DOC
94
101
 
95
- # doc.params <name>, <definition>
96
- doc.params :framework, "The test framework used, could be one of the two following: #{SpecOptions.join(", ")}."
97
- doc.params :version, "The version of the framework to use."
98
-
99
102
  # doc.example <markdown text>
100
103
  doc.example <<-DOC
101
104
  The most common way to use this service looks like that:
@@ -119,6 +119,7 @@ class WeaselDiesel
119
119
  end
120
120
  @namespaced_params << new_ns_param
121
121
  end
122
+ alias :object :namespace
122
123
 
123
124
  def response
124
125
  @response ||= Documentation.new
@@ -24,10 +24,10 @@ class WeaselDiesel
24
24
  # @option options [Symbol] :default The default value of the param.
25
25
  # @option options [Symbol] :minvalue The minimum acceptable value.
26
26
  # @option options [Symbol] :maxvalue The maximim acceptable value.
27
+ # @option options [Symbol] :doc Documentation for the param.
27
28
  # @api public
28
29
  attr_reader :options
29
30
 
30
-
31
31
  # @param [Symbol, String] name
32
32
  # The param's name
33
33
  # @param [Hash] opts The rule options
@@ -36,6 +36,7 @@ class WeaselDiesel
36
36
  # @option opts [Symbol] :default The default value of the param.
37
37
  # @option opts [Symbol] :minvalue The minimum acceptable value.
38
38
  # @option opts [Symbol] :maxvalue The maximim acceptable value.
39
+ # @option opts [Symbol] :doc Documentation for the param.
39
40
  # @api public
40
41
  def initialize(name, opts = {})
41
42
  @name = name
@@ -50,6 +51,14 @@ class WeaselDiesel
50
51
  @options[:space_name]
51
52
  end
52
53
 
54
+ # The documentation of this Rule
55
+ #
56
+ # @return [NilClass, String]
57
+ # api public
58
+ def doc
59
+ @options[:doc]
60
+ end
61
+
53
62
  # Converts the rule into a hash with its name and options.
54
63
  #
55
64
  # @return [Hash]
@@ -351,6 +360,7 @@ class WeaselDiesel
351
360
  yield(params) if block_given?
352
361
  namespaced_params << params unless namespaced_params.include?(params)
353
362
  end
363
+ alias :object :namespace
354
364
 
355
365
  # Returns the namespaced params
356
366
  #
@@ -79,7 +79,7 @@ module ParamsVerification
79
79
  params.each_pair do |key, value|
80
80
  if value.is_a?(Hash)
81
81
  namespaced = service_params.namespaced_params.find{|np| np.space_name.to_s == key.to_s}
82
- raise UnexpectedParam, "Request included unexpected parameter: #{key}" if namespaced.nil?
82
+ raise UnexpectedParam, "Request included unexpected parameter: #{ERB::Util.html_escape(key)}" if namespaced.nil?
83
83
  unexpected_params?(params[key], namespaced.param_names)
84
84
  end
85
85
  end
@@ -123,7 +123,7 @@ module ParamsVerification
123
123
  verify_cast(param_name, param_value, rule.options[:type])
124
124
  end
125
125
 
126
- if rule.options[:options] || rule.options[:in]
126
+ if rule.options[:options] || rule.options[:in.inspect]
127
127
  choices = rule.options[:options] || rule.options[:in]
128
128
  if rule.options[:type]
129
129
  # Force the cast so we can compare properly
@@ -348,6 +348,13 @@ class WeaselDiesel
348
348
  end
349
349
  end
350
350
 
351
+ # Converts an element into a json representation
352
+ #
353
+ # @return [String] the element attributes formated in a json structure
354
+ def to_json
355
+ to_hash.to_json
356
+ end
357
+
351
358
  def to_html
352
359
  output = ""
353
360
  if name
@@ -408,7 +408,17 @@ module Kernel
408
408
  def describe_service(url, &block)
409
409
  service = WeaselDiesel.new(url)
410
410
  yield service
411
+
412
+ service.defined_params.list_optional.each do |rule|
413
+ service.doc.param(rule.name, rule.options[:doc]) if rule.options[:doc]
414
+ end
415
+
416
+ service.defined_params.list_required.each do |rule|
417
+ service.doc.param(rule.name, rule.options[:doc]) if rule.options[:doc]
418
+ end
419
+
411
420
  WSList.add(service)
421
+
412
422
  service
413
423
  end
414
424
 
@@ -1,3 +1,3 @@
1
1
  class WeaselDiesel
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
@@ -5,12 +5,16 @@ describe_service "services/test.xml" do |service|
5
5
  service.http_verb :get
6
6
 
7
7
  service.params do |p|
8
- p.string :framework, :in => WeaselDieselSpecOptions, :null => false, :required => true
8
+ p.string :framework,
9
+ :in => WeaselDieselSpecOptions,
10
+ :null => false,
11
+ :required => true,
12
+ :doc => "The test framework used, could be one of the two following: #{WeaselDieselSpecOptions.join(", ")}."
9
13
 
10
14
  p.datetime :timestamp, :default => Time.now
11
15
  p.string :alpha, :in => ['a', 'b', 'c']
12
- p.string :version, :null => false
13
- p.integer :num, :minvalue => 42
16
+ p.string :version, :null => false, :doc => "The version of the framework to use."
17
+ p.integer :num, :minvalue => 42, :doc => "The number to test"
14
18
 
15
19
  end
16
20
 
@@ -66,10 +70,6 @@ describe_service "services/test.xml" do |service|
66
70
  This is a test service used to test the framework.
67
71
  DOC
68
72
 
69
- # doc.params <name>, <definition>
70
- doc.param :framework, "The test framework used, could be one of the two following: #{WeaselDieselSpecOptions.join(", ")}."
71
- doc.param :version, "The version of the framework to use."
72
-
73
73
  # doc.example <markdown text>
74
74
  doc.example <<-DOC
75
75
  The most common way to use this service looks like that:
@@ -0,0 +1,161 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe "WeaselDiesel #controller_dispatch" do
4
+
5
+ before :all do
6
+ @service = WSList.all.find{|s| s.url == 'services/test.xml'}
7
+ @service.should_not be_nil
8
+ end
9
+
10
+ describe "#controller_dispatch" do
11
+
12
+ class ProjectsController
13
+ def initialize(app, service)
14
+ @app = app
15
+ @service = service.name
16
+ end
17
+
18
+ def send(action)
19
+ [@app, @service, action]
20
+ end
21
+ end
22
+
23
+ module Projects
24
+ class TasksController < ProjectsController
25
+ end
26
+ end
27
+
28
+ module Projects
29
+ module Tasks
30
+ class ItemsController < ProjectsController
31
+ end
32
+ end
33
+ end
34
+
35
+ before :all do
36
+ @original_use_controller_dispatch = WeaselDiesel.use_controller_dispatch
37
+ WeaselDiesel.use_controller_dispatch = true
38
+ @original_services = WSList.all.dup
39
+ WSList.all.clear
40
+ end
41
+
42
+ after :all do
43
+ WeaselDiesel.use_controller_dispatch = @original_use_controller_dispatch
44
+ WSList.all.replace @original_services
45
+ end
46
+
47
+ it "should be able to dispatch controller" do
48
+ describe_service("projects.xml") { |s| }
49
+ service = WSList["projects.xml"]
50
+ service.controller_dispatch("application").
51
+ should == ["application", "projects", "list"]
52
+ end
53
+
54
+ it "should be able to dispatch namespaced controller" do
55
+ describe_service("project/:project_id/tasks.xml") do |service|
56
+ service.controller_name = "Projects::TasksController"
57
+ service.action = "list"
58
+ end
59
+
60
+ describe_service("project/:project_id/task/:task_id/items.xml") do |service|
61
+ service.controller_name = "Projects::Tasks::ItemsController"
62
+ service.action = "list"
63
+ end
64
+
65
+ service = WSList["project/:project_id/tasks.xml"]
66
+ service.controller_dispatch("application").should == ["application", "project", "list"]
67
+
68
+ service = WSList["project/:project_id/task/:task_id/items.xml"]
69
+ service.controller_dispatch("application").should == ["application", "project", "list"]
70
+ end
71
+
72
+ it "should raise exception when controller class is not found" do
73
+ describe_service("unknown.xml") do |service|
74
+ service.controller_name = "UnknownController"
75
+ service.action = "list"
76
+ end
77
+ service = WSList["unknown.xml"]
78
+ lambda { service.controller_dispatch("application") }.
79
+ should raise_error("The UnknownController class was not found")
80
+ end
81
+
82
+ end
83
+
84
+ describe "With controller dispatch on" do
85
+ before :all do
86
+ @original_services = WSList.all.dup
87
+ WSList.all.clear
88
+ WeaselDiesel.use_controller_dispatch = true
89
+ load File.expand_path('test_services.rb', File.dirname(__FILE__))
90
+ @c_service = WSList.all.find{|s| s.url == 'services/test.xml'}
91
+ @c_service.should_not be_nil
92
+ end
93
+ after :all do
94
+ WeaselDiesel.use_controller_dispatch = false
95
+ WSList.all.replace @original_services
96
+ end
97
+
98
+ it "should set the controller accordingly" do
99
+ @c_service.controller_name.should_not be_nil
100
+ @c_service.controller_name.should == 'ServicesController'
101
+ service = WeaselDiesel.new("preferences.xml")
102
+ service.name.should == 'preferences'
103
+ ExtlibCopy.classify('preferences').should == 'Preferences'
104
+ service.controller_name.should == 'PreferencesController'
105
+ end
106
+
107
+ it "should set the action accordingly" do
108
+ @c_service.action.should_not be_nil
109
+ @c_service.action.should == 'test'
110
+ end
111
+
112
+ it "should support restful routes based on the HTTP verb" do
113
+ service = WSList.all.find{|s| s.url == "services.xml"}
114
+ service.should_not be_nil
115
+ service.http_verb.should == :put
116
+ service.action.should_not be_nil
117
+ service.controller_name.should == 'ServicesController'
118
+ service.action.should == 'update'
119
+ end
120
+
121
+ it "should have a default action" do
122
+ service = WeaselDiesel.new('spec_test.xml')
123
+ service.action.should == 'list'
124
+ end
125
+
126
+ it "should route to show when an id is the last passed param" do
127
+ service = WeaselDiesel.new("players/:id.xml")
128
+ service.action.should == 'show'
129
+ end
130
+
131
+ it "should support some extra attributes" do
132
+ service = WeaselDiesel.new("players/:id.xml")
133
+ service.extra[:custom_name] = 'fooBar'
134
+ service.extra[:custom_name].should == 'fooBar'
135
+ end
136
+
137
+ it "should respect the global controller pluralization flag" do
138
+ WeaselDiesel.use_pluralized_controllers = true
139
+ service = WeaselDiesel.new("player/:id.xml")
140
+ service.controller_name.should == "PlayersController"
141
+ service = WeaselDiesel.new("players/:id.xml")
142
+ service.controller_name.should == "PlayersController"
143
+ WeaselDiesel.use_pluralized_controllers = false
144
+ service = WeaselDiesel.new("player/:id.xml")
145
+ service.controller_name.should == "PlayerController"
146
+ end
147
+
148
+
149
+ it "should let overwrite the controller name and action after initialization" do
150
+ describe_service "players/:id.xml" do |service|
151
+ service.controller_name = "CustomController"
152
+ service.action = "foo"
153
+ end
154
+ service = WSList.all.find{|s| s.url == "players/:id.xml"}
155
+ service.controller_name.should == "CustomController"
156
+ service.action.should == "foo"
157
+ end
158
+
159
+ end
160
+
161
+ end
@@ -0,0 +1,149 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe WeaselDiesel::Documentation do
4
+
5
+ before :all do
6
+ @service = WSList.all.find{|s| s.url == 'services/test.xml'}
7
+ @service.should_not be_nil
8
+ @doc = @service.doc
9
+ @doc.should_not be_nil
10
+ end
11
+
12
+ it "should have an overall description" do
13
+ @doc.desc.strip.should == "This is a test service used to test the framework."
14
+ end
15
+
16
+ it "should have a list of params doc" do
17
+ @doc.params_doc.should be_an_instance_of(Hash)
18
+ @doc.params_doc.keys.sort.should == [:framework, :num, :version]
19
+ @doc.params_doc[:framework].should == "The test framework used, could be one of the two following: #{WeaselDieselSpecOptions.join(", ")}."
20
+ @doc.params_doc[:num].should == 'The number to test'
21
+ end
22
+
23
+ it "should allow to define namespaced params doc" do
24
+ service = WSList.all.find{|s| s.url == "services.xml"}
25
+ service.documentation do |doc|
26
+ doc.namespace :preference do |ns|
27
+ ns.param :id, "Ze id."
28
+ end
29
+ end
30
+ service.doc.namespaced_params.should_not be_empty
31
+ ns = service.doc.namespaced_params.find{|ns| ns.name == :preference}
32
+ ns.should_not be_nil
33
+ ns.params[:id].should == "Ze id."
34
+ end
35
+
36
+ it "should allow object to be an alias for namespace params" do
37
+ service = WSList.all.find{|s| s.url == "services.xml"}
38
+ service.documentation do |doc|
39
+ doc.object :preference do |ns|
40
+ ns.param :id, "Ze id."
41
+ end
42
+ end
43
+ service.doc.namespaced_params.should_not be_empty
44
+ ns = service.doc.namespaced_params.find{|ns| ns.name == :preference}
45
+ ns.should_not be_nil
46
+ ns.params[:id].should == "Ze id."
47
+ end
48
+
49
+ it "should have an optional list of examples" do
50
+ @doc.examples.should be_an_instance_of(Array)
51
+ @doc.examples.first.should == <<-DOC
52
+ The most common way to use this service looks like that:
53
+ http://example.com/services/test.xml?framework=rspec&version=2.0.0
54
+ DOC
55
+ end
56
+
57
+ it "should have the service response documented" do
58
+ @doc.response.should_not be_nil
59
+ end
60
+
61
+ it "should have documentation for the response elements via the response itself" do
62
+ @service.response.elements.first.should_not be_nil
63
+ @service.response.elements.first.doc.should_not be_nil
64
+ @service.response.elements.first.doc.name.should == "player_creation_ratings"
65
+ end
66
+
67
+ it "should have a json representation of an response element" do
68
+ json = @service.response.elements.first.to_json
69
+ loaded_json = JSON.load(json)
70
+ loaded_json[@service.response.elements.first.doc.name].should_not be_empty
71
+ end
72
+
73
+ it "should have documentation for a response element attribute" do
74
+ @service.response.elements.first.doc.attributes.should_not be_empty
75
+ @service.response.elements.first.doc.attributes[:id].should == "id doc"
76
+ end
77
+
78
+ it "should have documentation for a response element array" do
79
+ element = @service.response.elements.first
80
+ element.arrays.should_not be_empty
81
+ element.arrays.first.name.should == :player_creation_rating
82
+ element.arrays.first.type.should == "PlayerCreationRating"
83
+ element.arrays.first.attributes.should_not be_empty
84
+ end
85
+
86
+ it "should have documentation for the attributes of an response element array" do
87
+ element = @service.response.elements.first
88
+ array = element.arrays.first
89
+ attribute = array.attributes.find{|att| att.name == :comments }
90
+ attribute.should_not be_nil
91
+ attribute.name.should == :comments # just in case we change the way to find the attribute
92
+ attribute.doc.should == "comments doc"
93
+ end
94
+
95
+ it "should emit html documention for elements" do
96
+ @service.response.elements.first.to_html.should be_a(String)
97
+ end
98
+
99
+ describe "legacy param documentation" do
100
+
101
+ before :all do
102
+ @original_services = WSList.all.dup
103
+ WSList.all.clear
104
+ define_service
105
+ end
106
+
107
+ after :all do
108
+ WSList.all.replace @original_services
109
+ end
110
+
111
+ def define_service
112
+ describe_service "legacy_param_doc" do |service|
113
+ service.formats :xml, :json
114
+
115
+ service.params do |p|
116
+ p.string :framework, :in => WeaselDieselSpecOptions, :null => false, :required => true
117
+
118
+ p.datetime :timestamp, :default => Time.now
119
+ p.string :alpha, :in => ['a', 'b', 'c']
120
+ p.string :version, :null => false
121
+ p.integer :num, :minvalue => 42
122
+
123
+ end
124
+
125
+ service.params.namespace :user do |user|
126
+ user.integer :id, :required => :true
127
+ user.string :sex, :in => %Q{female, male}
128
+ user.boolean :mailing_list, :default => true
129
+ end
130
+
131
+ service.documentation do |doc|
132
+ # doc.overall <markdown description text>
133
+ doc.overall "This is a test service used to test the framework."
134
+ # doc.params <name>, <definition>
135
+ doc.param :framework, "The test framework used, could be one of the two following: #{WeaselDieselSpecOptions.join(", ")}."
136
+ doc.param :version, "The version of the framework to use."
137
+ end
138
+ end
139
+ end
140
+
141
+ it "should have the param documented" do
142
+ service = WSList["legacy_param_doc"]
143
+ service.doc.params_doc.keys.sort.should == [:framework, :version]
144
+ service.doc.params_doc[service.doc.params_doc.keys.first].should_not be_nil
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,76 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe WeaselDiesel::Params do
4
+
5
+ before :all do
6
+ @service = WSList.all.find{|s| s.url == 'services/test.xml'}
7
+ @service.should_not be_nil
8
+ @sparams = @service.params
9
+ end
10
+
11
+ it "should have the possibility to have a space name" do
12
+ @sparams.should respond_to(:space_name)
13
+ service_params = WeaselDiesel::Params.new(:space_name => 'spec_test')
14
+ service_params.space_name.should == 'spec_test'
15
+ end
16
+
17
+ it "should have a list of required param rules" do
18
+ @sparams.list_required.should be_an_instance_of(Array)
19
+ @sparams.list_required.length.should == 1
20
+ end
21
+
22
+ it "should have a list of optional param rules" do
23
+ @sparams.list_optional.should be_an_instance_of(Array)
24
+ @sparams.list_optional.length.should == 4
25
+ end
26
+
27
+ it "should have a list of namespaced param rules" do
28
+ @sparams.namespaced_params.should be_an_instance_of(Array)
29
+ @sparams.namespaced_params.length.should == 1
30
+ @sparams.namespaced_params.first.space_name.should == :user
31
+ end
32
+
33
+ it "should allow to define namespaced param" do
34
+ service = WSList.all.find{|s| s.url == "services.xml"}
35
+ service.params do |params|
36
+ params.namespace :preference do |ns|
37
+ ns.param :id, "Ze id."
38
+ end
39
+ end
40
+ service.params.namespaced_params.should_not be_empty
41
+ ns = service.params.namespaced_params.find{|ns| ns.space_name == :preference}
42
+ ns.should_not be_nil
43
+ ns.list_optional.first.name.should == "Ze id."
44
+ end
45
+
46
+ it "should allow object as an alias to namespaced param" do
47
+ service = WSList.all.find{|s| s.url == "services.xml"}
48
+ service.params do |params|
49
+ params.object :preference do |ns|
50
+ ns.param :id, "Ze id."
51
+ end
52
+ end
53
+ service.params.namespaced_params.should_not be_empty
54
+ ns = service.params.namespaced_params.find{|ns| ns.space_name == :preference}
55
+ ns.should_not be_nil
56
+ ns.list_optional.first.name.should == "Ze id."
57
+ end
58
+
59
+ describe WeaselDiesel::Params::Rule do
60
+ before :all do
61
+ @rule = @sparams.list_required.first
62
+ @rule.should_not be_nil
63
+ end
64
+
65
+ it "should have a name" do
66
+ @rule.name.should == :framework
67
+ end
68
+
69
+ it "should have options" do
70
+ @rule.options[:type].should == :string
71
+ @rule.options[:in].should == WeaselDieselSpecOptions
72
+ @rule.options[:null].should be_false
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ describe WeaselDiesel do
4
+
5
+ before :all do
6
+ @service = WSList.all.find{|s| s.url == 'services/test.xml'}
7
+ @service.should_not be_nil
8
+ end
9
+
10
+ it "should have an url" do
11
+ # dummy test since that's how we found the service, but oh well
12
+ @service.url.should == 'services/test.xml'
13
+ end
14
+
15
+ it "should have some http verbs defined" do
16
+ @service.verb.should == :get
17
+ end
18
+
19
+ it "should have supported formats defined" do
20
+ @service.formats.should == [:xml, :json]
21
+ end
22
+
23
+ it "should have params info" do
24
+ @service.params.should be_an_instance_of(WeaselDiesel::Params)
25
+ end
26
+
27
+ it "should have direct access to the required params" do
28
+ @service.required_rules.should == @service.params.list_required
29
+ end
30
+
31
+ it "should have direct access to the optional params" do
32
+ @service.optional_rules.should == @service.params.list_optional
33
+ end
34
+
35
+ it "should have direct access to the nested params" do
36
+ @service.nested_params.should == @service.params.namespaced_params
37
+ end
38
+
39
+ it "should have some documentation" do
40
+ @service.doc.should be_an_instance_of(WeaselDiesel::Documentation)
41
+ end
42
+
43
+ end
@@ -4,20 +4,30 @@ require File.expand_path("./../lib/framework_ext/sinatra.rb", File.dirname(__FIL
4
4
  WeaselDiesel.send(:include, WeaselDieselSinatraExtension)
5
5
 
6
6
  describe "Hello World example" do
7
- require_relative "hello_world_service"
8
- require_relative "hello_world_controller"
9
7
 
10
- def app
11
- Sinatra::Application
8
+ before :all do
9
+ @original_use_controller_dispatch = WeaselDiesel.use_controller_dispatch
10
+ WeaselDiesel.use_controller_dispatch = true
11
+ @original_services = WSList.all.dup
12
+ WSList.all.clear
13
+ require "hello_world_service"
14
+ require "hello_world_controller"
15
+ @service = WSList.all.find{|s| s.url == 'hello_world.xml'}
16
+ @service.should_not be_nil
17
+ @service.load_sinatra_route
18
+ end
19
+
20
+ after :all do
21
+ WeaselDiesel.use_controller_dispatch = @original_use_controller_dispatch
22
+ WSList.all.replace @original_services
12
23
  end
13
24
 
14
- before(:all) do
15
- service = WSList.all.find{|s| s.url == 'hello_world.xml'}
16
- service.should_not be_nil
17
- service.load_sinatra_route
25
+ def app
26
+ Sinatra::Application
18
27
  end
19
28
 
20
29
  it "should dispatch the hello world service properly" do
30
+ @service.controller_name.should == "HelloWorldController"
21
31
  get "/hello_world.xml"
22
32
  last_response.body.should include("Hello World")
23
33
  end
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency "rack-test"
24
24
  s.add_development_dependency "yard"
25
25
  s.add_development_dependency "sinatra"
26
+ s.add_development_dependency "rake"
26
27
  if RUBY_VERSION =~ /1.8/
27
28
  s.add_runtime_dependency "backports"
28
29
  s.add_runtime_dependency "json"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weasel_diesel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-11 00:00:00.000000000 Z
12
+ date: 2012-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70245501824860 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70245501824860
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rack-test
27
- requirement: &70245501824280 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70245501824280
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: yard
38
- requirement: &70245501823640 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70245501823640
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: sinatra
49
- requirement: &70245501823060 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,7 +69,28 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *70245501823060
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
58
94
  description: Ruby DSL describing Web Services without implementation details.
59
95
  email:
60
96
  - mattaimonetti@gmail.com
@@ -63,6 +99,7 @@ extensions: []
63
99
  extra_rdoc_files: []
64
100
  files:
65
101
  - .gitignore
102
+ - .travis.yml
66
103
  - Gemfile
67
104
  - LICENSE
68
105
  - README.md
@@ -86,8 +123,11 @@ files:
86
123
  - spec/preferences_service.rb
87
124
  - spec/spec_helper.rb
88
125
  - spec/test_services.rb
126
+ - spec/wd_controller_dispatch_spec.rb
127
+ - spec/wd_documentation_spec.rb
128
+ - spec/wd_params_spec.rb
129
+ - spec/wd_spec.rb
89
130
  - spec/wsdsl_sinatra_ext_spec.rb
90
- - spec/wsdsl_spec.rb
91
131
  - weasel_diesel.gemspec
92
132
  homepage: https://github.com/mattetti/Weasel-Diesel
93
133
  licenses: []
@@ -109,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
149
  version: '0'
110
150
  requirements: []
111
151
  rubyforge_project: wsdsl
112
- rubygems_version: 1.8.16
152
+ rubygems_version: 1.8.24
113
153
  signing_key:
114
154
  specification_version: 3
115
155
  summary: Web Service DSL
@@ -122,6 +162,9 @@ test_files:
122
162
  - spec/preferences_service.rb
123
163
  - spec/spec_helper.rb
124
164
  - spec/test_services.rb
165
+ - spec/wd_controller_dispatch_spec.rb
166
+ - spec/wd_documentation_spec.rb
167
+ - spec/wd_params_spec.rb
168
+ - spec/wd_spec.rb
125
169
  - spec/wsdsl_sinatra_ext_spec.rb
126
- - spec/wsdsl_spec.rb
127
170
  has_rdoc:
@@ -1,317 +0,0 @@
1
- require File.expand_path("spec_helper", File.dirname(__FILE__))
2
-
3
- describe WeaselDiesel do
4
-
5
- before :all do
6
- @service = WSList.all.find{|s| s.url == 'services/test.xml'}
7
- @service.should_not be_nil
8
- end
9
-
10
- it "should have an url" do
11
- # dummy test since that's how we found the service, but oh well
12
- @service.url.should == 'services/test.xml'
13
- end
14
-
15
- it "should have some http verbs defined" do
16
- @service.verb.should == :get
17
- end
18
-
19
- it "should have supported formats defined" do
20
- @service.formats.should == [:xml, :json]
21
- end
22
-
23
- it "should have params info" do
24
- @service.params.should be_an_instance_of(WeaselDiesel::Params)
25
- end
26
-
27
- it "should have direct access to the required params" do
28
- @service.required_rules.should == @service.params.list_required
29
- end
30
-
31
- it "should have direct access to the optional params" do
32
- @service.optional_rules.should == @service.params.list_optional
33
- end
34
-
35
- it "should have direct access to the nested params" do
36
- @service.nested_params.should == @service.params.namespaced_params
37
- end
38
-
39
- describe "#controller_dispatch" do
40
-
41
- class ProjectsController
42
- def initialize(app, service)
43
- @app = app
44
- @service = service.name
45
- end
46
-
47
- def send(action)
48
- [@app, @service, action]
49
- end
50
- end
51
-
52
- module Projects
53
- class TasksController < ProjectsController
54
- end
55
- end
56
-
57
- module Projects
58
- module Tasks
59
- class ItemsController < ProjectsController
60
- end
61
- end
62
- end
63
-
64
- before :all do
65
- @original_use_controller_dispatch = WeaselDiesel.use_controller_dispatch
66
- WeaselDiesel.use_controller_dispatch = true
67
- @original_services = WSList.all.dup
68
- WSList.all.clear
69
- end
70
-
71
- after :all do
72
- WeaselDiesel.use_controller_dispatch = @original_use_controller_dispatch
73
- WSList.all.replace @original_services
74
- end
75
-
76
- it "should be able to dispatch controller" do
77
- describe_service("projects.xml") { |s| }
78
- service = WSList["projects.xml"]
79
- service.controller_dispatch("application").
80
- should == ["application", "projects", "list"]
81
- end
82
-
83
- it "should be able to dispatch namespaced controller" do
84
- describe_service("project/:project_id/tasks.xml") do |service|
85
- service.controller_name = "Projects::TasksController"
86
- service.action = "list"
87
- end
88
-
89
- describe_service("project/:project_id/task/:task_id/items.xml") do |service|
90
- service.controller_name = "Projects::Tasks::ItemsController"
91
- service.action = "list"
92
- end
93
-
94
- service = WSList["project/:project_id/tasks.xml"]
95
- service.controller_dispatch("application").should == ["application", "project", "list"]
96
-
97
- service = WSList["project/:project_id/task/:task_id/items.xml"]
98
- service.controller_dispatch("application").should == ["application", "project", "list"]
99
- end
100
-
101
- it "should raise exception when controller class is not found" do
102
- describe_service("unknown.xml") do |service|
103
- service.controller_name = "UnknownController"
104
- service.action = "list"
105
- end
106
- service = WSList["unknown.xml"]
107
- lambda { service.controller_dispatch("application") }.
108
- should raise_error("The UnknownController class was not found")
109
- end
110
-
111
- end
112
-
113
- describe "With controller dispatch on" do
114
- before :all do
115
- @original_services = WSList.all.dup
116
- WSList.all.clear
117
- WeaselDiesel.use_controller_dispatch = true
118
- load File.expand_path('test_services.rb', File.dirname(__FILE__))
119
- @c_service = WSList.all.find{|s| s.url == 'services/test.xml'}
120
- @c_service.should_not be_nil
121
- end
122
- after :all do
123
- WeaselDiesel.use_controller_dispatch = false
124
- WSList.all.replace @original_services
125
- end
126
-
127
- it "should set the controller accordingly" do
128
- @c_service.controller_name.should_not be_nil
129
- @c_service.controller_name.should == 'ServicesController'
130
- service = WeaselDiesel.new("preferences.xml")
131
- service.name.should == 'preferences'
132
- ExtlibCopy.classify('preferences').should == 'Preferences'
133
- service.controller_name.should == 'PreferencesController'
134
- end
135
-
136
- it "should set the action accordingly" do
137
- @c_service.action.should_not be_nil
138
- @c_service.action.should == 'test'
139
- end
140
-
141
- it "should support restful routes based on the HTTP verb" do
142
- service = WSList.all.find{|s| s.url == "services.xml"}
143
- service.should_not be_nil
144
- service.http_verb.should == :put
145
- service.action.should_not be_nil
146
- service.controller_name.should == 'ServicesController'
147
- service.action.should == 'update'
148
- end
149
-
150
- it "should have a default action" do
151
- service = WeaselDiesel.new('spec_test.xml')
152
- service.action.should == 'list'
153
- end
154
-
155
- it "should route to show when an id is the last passed param" do
156
- service = WeaselDiesel.new("players/:id.xml")
157
- service.action.should == 'show'
158
- end
159
-
160
- it "should support some extra attributes" do
161
- service = WeaselDiesel.new("players/:id.xml")
162
- service.extra[:custom_name] = 'fooBar'
163
- service.extra[:custom_name].should == 'fooBar'
164
- end
165
-
166
- it "should respect the global controller pluralization flag" do
167
- WeaselDiesel.use_pluralized_controllers = true
168
- service = WeaselDiesel.new("player/:id.xml")
169
- service.controller_name.should == "PlayersController"
170
- service = WeaselDiesel.new("players/:id.xml")
171
- service.controller_name.should == "PlayersController"
172
- WeaselDiesel.use_pluralized_controllers = false
173
- service = WeaselDiesel.new("player/:id.xml")
174
- service.controller_name.should == "PlayerController"
175
- end
176
-
177
-
178
- it "should let overwrite the controller name and action after initialization" do
179
- describe_service "players/:id.xml" do |service|
180
- service.controller_name = "CustomController"
181
- service.action = "foo"
182
- end
183
- service = WSList.all.find{|s| s.url == "players/:id.xml"}
184
- service.controller_name.should == "CustomController"
185
- service.action.should == "foo"
186
- end
187
-
188
- end
189
-
190
-
191
- describe WeaselDiesel::Params do
192
-
193
- before(:all) do
194
- @sparams = @service.params
195
- end
196
-
197
- it "should have the possibility to have a space name" do
198
- @sparams.should respond_to(:space_name)
199
- service_params = WeaselDiesel::Params.new(:space_name => 'spec_test')
200
- service_params.space_name.should == 'spec_test'
201
- end
202
-
203
- it "should have a list of required param rules" do
204
- @sparams.list_required.should be_an_instance_of(Array)
205
- @sparams.list_required.length.should == 1
206
- end
207
-
208
- it "should have a list of optional param rules" do
209
- @sparams.list_optional.should be_an_instance_of(Array)
210
- @sparams.list_optional.length.should == 4
211
- end
212
-
213
- it "should have a list of namespaced param rules" do
214
- @sparams.namespaced_params.should be_an_instance_of(Array)
215
- @sparams.namespaced_params.length.should == 1
216
- @sparams.namespaced_params.first.space_name.should == :user
217
- end
218
-
219
- describe WeaselDiesel::Params::Rule do
220
- before :all do
221
- @rule = @sparams.list_required.first
222
- @rule.should_not be_nil
223
- end
224
-
225
- it "should have a name" do
226
- @rule.name.should == :framework
227
- end
228
-
229
- it "should have options" do
230
- @rule.options[:type].should == :string
231
- @rule.options[:in].should == WeaselDieselSpecOptions
232
- @rule.options[:null].should be_false
233
- end
234
- end
235
-
236
- end
237
-
238
- it "should have some documentation" do
239
- @service.doc.should be_an_instance_of(WeaselDiesel::Documentation)
240
- end
241
-
242
- describe WeaselDiesel::Documentation do
243
- before(:all) do
244
- @doc = @service.doc
245
- @doc.should_not be_nil
246
- end
247
-
248
- it "should have an overall description" do
249
- @doc.desc.strip.should == "This is a test service used to test the framework."
250
- end
251
-
252
- it "should have a list of params doc" do
253
- @doc.params_doc.should be_an_instance_of(Hash)
254
- @doc.params_doc.keys.sort.should == [:framework, :version]
255
- @doc.params_doc[:framework].should == "The test framework used, could be one of the two following: #{WeaselDieselSpecOptions.join(", ")}."
256
- end
257
-
258
- it "should allow to define namespaced params doc" do
259
- service = WSList.all.find{|s| s.url == "services.xml"}
260
- service.documentation do |doc|
261
- doc.namespace :preference do |ns|
262
- ns.param :id, "Ze id."
263
- end
264
- end
265
- service.doc.namespaced_params.should_not be_empty
266
- ns = service.doc.namespaced_params.find{|ns| ns.name == :preference}
267
- ns.should_not be_nil
268
- ns.params[:id].should == "Ze id."
269
- end
270
-
271
- it "should have an optional list of examples" do
272
- @doc.examples.should be_an_instance_of(Array)
273
- @doc.examples.first.should == <<-DOC
274
- The most common way to use this service looks like that:
275
- http://example.com/services/test.xml?framework=rspec&version=2.0.0
276
- DOC
277
- end
278
-
279
- it "should have the service response documented" do
280
- @doc.response.should_not be_nil
281
- end
282
-
283
- it "should have documentation for the response elements via the response itself" do
284
- @service.response.elements.first.should_not be_nil
285
- @service.response.elements.first.doc.should_not be_nil
286
- @service.response.elements.first.doc.name.should == "player_creation_ratings"
287
- end
288
-
289
- it "should have documentation for a response element attribute" do
290
- p @service.response.elements.first.doc.inspect
291
- @service.response.elements.first.doc.attributes.should_not be_empty
292
- @service.response.elements.first.doc.attributes[:id].should == "id doc"
293
- end
294
-
295
- it "should have documentation for a response element array" do
296
- element = @service.response.elements.first
297
- element.arrays.should_not be_empty
298
- element.arrays.first.name.should == :player_creation_rating
299
- element.arrays.first.type.should == "PlayerCreationRating"
300
- element.arrays.first.attributes.should_not be_empty
301
- end
302
-
303
- it "should have documentation for the attributes of an response element array" do
304
- element = @service.response.elements.first
305
- array = element.arrays.first
306
- attribute = array.attributes.find{|att| att.name == :comments }
307
- attribute.should_not be_nil
308
- attribute.name.should == :comments # just in case we change the way to find the attribute
309
- attribute.doc.should == "comments doc"
310
- end
311
-
312
- it "should emit html documention for elements" do
313
- @service.response.elements.first.to_html.should be_a(String)
314
- end
315
-
316
- end
317
- end