ree_lib 1.0.39 → 1.0.40

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -1
  3. data/lib/ree_lib/.vscode-ree/templates/spec_template.rb +1 -1
  4. data/lib/ree_lib/Packages.schema.json +4 -0
  5. data/lib/ree_lib/packages/.vscode-ree/templates/spec_template.rb +1 -1
  6. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +28 -70
  7. data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +1 -2
  8. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +34 -65
  9. data/lib/ree_lib/packages/ree_array/spec/ree_array/functions/group_by_spec.rb +1 -1
  10. data/lib/ree_lib/packages/ree_array/spec/ree_array/functions/index_by_spec.rb +1 -1
  11. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +53 -0
  12. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +73 -0
  13. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/build_sqlite_connection_spec.rb +1 -1
  14. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/one_to_many_spec.rb +2 -2
  15. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/one_to_one_spec.rb +2 -2
  16. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/persist_assoc_spec.rb +2 -2
  17. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_array_spec.rb +64 -0
  18. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_jsonb_spec.rb +94 -0
  19. data/lib/ree_lib/packages/ree_datetime/spec/ree_datetime/functions/in_default_time_zone_spec.rb +1 -1
  20. data/lib/ree_lib/packages/ree_dto/spec/ree_dto/entity_dsl_spec.rb +1 -1
  21. data/lib/ree_lib/packages/ree_hash/spec/ree_hash/functions/transform_values_spec.rb +1 -1
  22. data/lib/ree_lib/packages/ree_json/spec/ree_json/functions/from_json_spec.rb +1 -1
  23. data/lib/ree_lib/packages/ree_json/spec/ree_json/functions/to_json_spec.rb +1 -1
  24. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/appenders/appender_spec.rb +1 -1
  25. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/appenders/file_appender_spec.rb +3 -3
  26. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/appenders/rollbar_appender_spec.rb +1 -1
  27. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/appenders/stdout_appender_spec.rb +1 -1
  28. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/beans/logger_spec.rb +2 -2
  29. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/formatters/colorized_formatter_spec.rb +10 -7
  30. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/formatters/default_formatter_spec.rb +1 -1
  31. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/formatters/formatter_spec.rb +1 -1
  32. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/multi_logger_spec.rb +1 -1
  33. data/lib/ree_lib/packages/ree_migrator/spec/ree_migrator/functions/apply_migration_spec.rb +1 -1
  34. data/lib/ree_lib/packages/ree_migrator/spec/ree_migrator/functions/apply_migrations_spec.rb +1 -1
  35. data/lib/ree_lib/packages/ree_migrator/spec/ree_migrator/functions/migrate_db_spec.rb +1 -1
  36. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/deep_dup_spec.rb +2 -2
  37. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/deep_freeze_spec.rb +1 -1
  38. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/dump_as_json_spec.rb +1 -1
  39. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/is_blank_spec.rb +1 -1
  40. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/not_blank_spec.rb +1 -1
  41. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/to_hash_spec.rb +1 -1
  42. data/lib/ree_lib/packages/ree_object/spec/ree_object/functions/to_obj_spec.rb +8 -8
  43. data/lib/ree_lib/packages/ree_roda/Package.schema.json +14 -7
  44. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_routes.rb +231 -0
  45. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/{build_action_errors.rb → build_route_errors.rb} +5 -5
  46. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_routing_tree.rb +144 -0
  47. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_routes.rb +54 -0
  48. data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +2 -2
  49. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/{build_action_errors.schema.json → build_route_errors.schema.json} +5 -5
  50. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_routing_tree.schema.json +28 -0
  51. data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/{build_swagger_from_actions.schema.json → build_swagger_from_routes.schema.json} +7 -7
  52. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +141 -7
  53. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/services/build_routing_tree_spec.rb +261 -0
  54. data/lib/ree_lib/packages/ree_routes/.gitignore +0 -0
  55. data/lib/ree_lib/packages/ree_routes/.rspec +2 -0
  56. data/lib/ree_lib/packages/ree_routes/Package.schema.json +20 -0
  57. data/lib/ree_lib/packages/ree_routes/bin/console +5 -0
  58. data/lib/ree_lib/packages/ree_routes/package/ree_routes/dsl.rb +102 -0
  59. data/lib/ree_lib/packages/ree_routes/package/ree_routes/route.rb +10 -0
  60. data/lib/ree_lib/packages/{ree_actions/package/ree_actions/action_builder.rb → ree_routes/package/ree_routes/route_builder.rb} +15 -15
  61. data/lib/ree_lib/packages/ree_routes/package/ree_routes.rb +9 -0
  62. data/lib/ree_lib/packages/ree_routes/spec/package_schema_spec.rb +14 -0
  63. data/lib/ree_lib/packages/ree_routes/spec/ree_routes/dsl_spec.rb +93 -0
  64. data/lib/ree_lib/packages/ree_routes/spec/spec_helper.rb +3 -0
  65. data/lib/ree_lib/packages/ree_text/spec/ree_text/functions/safe_join_spec.rb +1 -1
  66. data/lib/ree_lib/packages/ree_text/spec/ree_text/functions/to_sentence_spec.rb +1 -1
  67. data/lib/ree_lib/packages/ree_validator/spec/ree_validator/functions/validate_password_spec.rb +1 -1
  68. data/lib/ree_lib/version.rb +1 -1
  69. metadata +39 -11
  70. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action.rb +0 -10
  71. data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_dsl.rb +0 -60
  72. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/action_dsl_spec.rb +0 -62
  73. data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +0 -150
  74. data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +0 -55
@@ -0,0 +1,144 @@
1
+ class ReeRoda::BuildRoutingTree
2
+ include Ree::FnDSL
3
+
4
+ fn :build_routing_tree
5
+
6
+ class RoutingTree
7
+ attr_accessor :children, :value, :depth, :routes, :type, :parent
8
+
9
+ def initialize(value, depth, type, parent = nil, routes = [])
10
+ @value = value
11
+ @depth = depth
12
+ @parent = parent
13
+ @type = type
14
+ @routes = []
15
+ @children = []
16
+ end
17
+
18
+ def find_by_value(
19
+ tree: self,
20
+ value: nil,
21
+ type: :param,
22
+ depth: 0
23
+ )
24
+ return tree if tree.depth == depth && tree.value == value
25
+ if tree.depth < depth
26
+ res = tree.children.map do |c|
27
+ find_by_value(tree: c, value: value, type: type, depth: depth)
28
+ end.flatten.compact
29
+
30
+ return res.size > 1 ? res : res.first
31
+ end
32
+ end
33
+
34
+ def children_have_value?(value)
35
+ !!self.children.find { |c| c.value == value }
36
+ end
37
+
38
+ def add_child(value, depth, type)
39
+ new_child = self.class.new(value, depth, type, self.value)
40
+ self.children << new_child
41
+ self.children = self.children.sort { _1.value.match?(/\:/) ? 1 : 0 }
42
+
43
+ return new_child
44
+ end
45
+
46
+ def add_route(route)
47
+ self.routes << route
48
+ end
49
+
50
+ def print_tree(tree = self)
51
+ puts "#{get_offset(tree.depth)}#{tree.value} - #{tree.depth}"
52
+ if tree.children.length > 0
53
+ tree.children.each do |child|
54
+ print_tree(child)
55
+ end
56
+ end
57
+
58
+ nil
59
+ end
60
+
61
+ def print_proc_tree(tree = self)
62
+ param_value = tree.value.start_with?(":") ? String : "\"#{tree.value}\""
63
+ if tree.routes.length == 0
64
+ if tree.children.length > 0
65
+ puts "#{get_offset(tree.depth)}r.on #{param_value} do"
66
+ tree.children.each do |child|
67
+ print_proc_tree(child)
68
+ end
69
+ puts "#{get_offset(tree.depth)}end"
70
+ end
71
+
72
+ nil
73
+ else
74
+ if tree.children.length > 0
75
+ puts "#{get_offset(tree.depth)}r.on #{param_value} do"
76
+ tree.children.each do |child|
77
+ print_proc_tree(child)
78
+ end
79
+ tree.routes.each do |route|
80
+ puts "#{get_offset(tree.depth + 1)}r.#{route.request_method} do"
81
+ puts "#{get_offset(tree.depth + 1)}end"
82
+ end
83
+ puts "#{get_offset(tree.depth)}end"
84
+ else
85
+ puts "#{get_offset(tree.depth)}r.is #{param_value} do"
86
+ tree.routes.each do |route|
87
+ puts "#{get_offset(tree.depth + 1)}r.#{route.request_method} do"
88
+ puts "#{get_offset(tree.depth + 1)}end"
89
+ end
90
+ puts "#{get_offset(tree.depth)}end"
91
+ end
92
+ end
93
+
94
+ nil
95
+ end
96
+
97
+ private
98
+
99
+ def get_offset(depth)
100
+ " " * (depth + 1) * 2
101
+ end
102
+ end
103
+
104
+ contract(ArrayOf[ReeRoutes::Route] => Nilor[RoutingTree])
105
+ def call(routes)
106
+ tree = nil
107
+ routes.each do |route|
108
+ splitted = route.path.split("/")
109
+
110
+ parent_tree = tree
111
+ splitted.each_with_index do |v, j|
112
+ if tree.nil?
113
+ tree = RoutingTree.new(v, j, :string)
114
+ parent_tree = tree
115
+ next
116
+ end
117
+
118
+ current = parent_tree.find_by_value(value: v, depth: j)
119
+ if current
120
+ parent_tree = current
121
+
122
+ current.add_route(route) if j == (splitted.length - 1)
123
+ else
124
+ if !parent_tree.children_have_value?(v)
125
+ if parent_tree.children.any? { |c| c.type == :param } && v.start_with?(":")
126
+ param_child = parent_tree.children.find { |c| c.type == :param }
127
+ param_child.add_route(route) if j == (splitted.length - 1)
128
+ parent_tree = param_child
129
+
130
+ next
131
+ end
132
+
133
+ new_tree = parent_tree.add_child(v, j, v.start_with?(":") ? :param : :string)
134
+ parent_tree = new_tree
135
+ end
136
+
137
+ parent_tree.add_route(route) if j == (splitted.length - 1)
138
+ end
139
+ end
140
+ end
141
+
142
+ tree
143
+ end
144
+ end
@@ -0,0 +1,54 @@
1
+ class ReeRoda::BuildSwaggerFromRoutes
2
+ include Ree::FnDSL
3
+
4
+ fn :build_swagger_from_routes do
5
+ link :build_route_errors
6
+ link :build_schema, from: :ree_swagger
7
+ link "ree_swagger/dto/endpoint_dto", -> { EndpointDto }
8
+ end
9
+
10
+ contract(ArrayOf[ReeRoutes::Route], String, String, String, String => Hash)
11
+ def call(routes, title, description, version, api_url)
12
+ endpoints = routes.map do |route|
13
+ method_decorator = Ree::Contracts.get_method_decorator(
14
+ route.action.klass, :call, scope: :instance
15
+ )
16
+
17
+ response_status = case route.request_method
18
+ when :post
19
+ 201
20
+ when :put, :delete, :patch
21
+ 204
22
+ else
23
+ 200
24
+ end
25
+
26
+ caster = if route.action.klass.const_defined?(:ActionCaster)
27
+ route.action.klass.const_get(:ActionCaster)
28
+ end
29
+
30
+ EndpointDto.new(
31
+ method: route.request_method,
32
+ sections: route.sections,
33
+ respond_to: route.respond_to,
34
+ path: route.path.start_with?("/") ? route.path : "/#{route.path}",
35
+ caster: caster,
36
+ serializer: route.serializer&.klass&.new,
37
+ summary: route.summary,
38
+ authenticate: route.warden_scope != :visitor,
39
+ description: method_decorator&.doc || "",
40
+ response_status: response_status,
41
+ response_description: nil,
42
+ errors: build_route_errors(route)
43
+ )
44
+ end
45
+
46
+ build_schema(
47
+ title: title,
48
+ description: description,
49
+ version: version,
50
+ api_url: api_url,
51
+ endpoints: endpoints
52
+ )
53
+ end
54
+ end
@@ -4,7 +4,7 @@ module ReeRoda
4
4
  include Ree::PackageDSL
5
5
 
6
6
  package do
7
- depends_on :ree_actions
7
+ depends_on :ree_routes
8
8
  depends_on :ree_logger
9
9
  depends_on :ree_json
10
10
  depends_on :ree_hash
@@ -15,5 +15,5 @@ module ReeRoda
15
15
  end
16
16
 
17
17
  package_require "ree_roda/plugins/ree_logger"
18
- package_require "ree_roda/plugins/ree_actions"
18
+ package_require "ree_roda/plugins/ree_routes"
19
19
  package_require "ree_roda/app"
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schema_type": "object",
3
3
  "schema_version": "1.1",
4
- "name": "build_action_errors",
5
- "path": "packages/ree_roda/package/ree_roda/services/build_action_errors.rb",
4
+ "name": "build_route_errors",
5
+ "path": "packages/ree_roda/package/ree_roda/services/build_route_errors.rb",
6
6
  "mount_as": "fn",
7
- "class": "ReeRoda::BuildActionErrors",
7
+ "class": "ReeRoda::BuildRouteErrors",
8
8
  "factory": null,
9
9
  "methods": [
10
10
  {
@@ -15,9 +15,9 @@
15
15
  "return": "ArrayOf[ReeSwagger::ErrorDto]",
16
16
  "args": [
17
17
  {
18
- "arg": "action",
18
+ "arg": "route",
19
19
  "arg_type": "req",
20
- "type": "ReeActions::Action"
20
+ "type": "ReeRoutes::Route"
21
21
  }
22
22
  ]
23
23
  }
@@ -0,0 +1,28 @@
1
+ {
2
+ "schema_type": "object",
3
+ "schema_version": "1.1",
4
+ "name": "build_routing_tree",
5
+ "path": "packages/ree_roda/package/ree_roda/services/build_routing_tree.rb",
6
+ "mount_as": "fn",
7
+ "class": "ReeRoda::BuildRoutingTree",
8
+ "factory": null,
9
+ "methods": [
10
+ {
11
+ "doc": "",
12
+ "throws": [
13
+
14
+ ],
15
+ "return": "Nilor[ReeRoda::BuildRoutingTree::RoutingTree]",
16
+ "args": [
17
+ {
18
+ "arg": "routes",
19
+ "arg_type": "req",
20
+ "type": "ArrayOf[ReeRoutes::Route]"
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "links": [
26
+
27
+ ]
28
+ }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schema_type": "object",
3
3
  "schema_version": "1.1",
4
- "name": "build_swagger_from_actions",
5
- "path": "packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb",
4
+ "name": "build_swagger_from_routes",
5
+ "path": "packages/ree_roda/package/ree_roda/services/build_swagger_from_routes.rb",
6
6
  "mount_as": "fn",
7
- "class": "ReeRoda::BuildSwaggerFromActions",
7
+ "class": "ReeRoda::BuildSwaggerFromRoutes",
8
8
  "factory": null,
9
9
  "methods": [
10
10
  {
@@ -15,9 +15,9 @@
15
15
  "return": "Hash",
16
16
  "args": [
17
17
  {
18
- "arg": "actions",
18
+ "arg": "routes",
19
19
  "arg_type": "req",
20
- "type": "ArrayOf[ReeActions::Action]"
20
+ "type": "ArrayOf[ReeRoutes::Route]"
21
21
  },
22
22
  {
23
23
  "arg": "title",
@@ -44,9 +44,9 @@
44
44
  ],
45
45
  "links": [
46
46
  {
47
- "target": "build_action_errors",
47
+ "target": "build_route_errors",
48
48
  "package_name": "ree_roda",
49
- "as": "build_action_errors",
49
+ "as": "build_route_errors",
50
50
  "imports": [
51
51
 
52
52
  ]
@@ -2,7 +2,10 @@ require "rack/test"
2
2
 
3
3
  package_require("ree_roda/app")
4
4
  package_require("ree_actions/dsl")
5
- package_require("ree_roda/plugins/ree_actions")
5
+ package_require("ree_routes/dsl")
6
+ package_require("ree_roda/plugins/ree_routes")
7
+
8
+ require "warden"
6
9
 
7
10
  RSpec.describe ReeRoda::App do
8
11
  include Rack::Test::Methods
@@ -17,7 +20,7 @@ RSpec.describe ReeRoda::App do
17
20
  end
18
21
 
19
22
  class ReeRodaTest::Cmd
20
- include ReeActions::ActionDSL
23
+ include ReeActions::DSL
21
24
 
22
25
  action :cmd
23
26
 
@@ -26,13 +29,57 @@ RSpec.describe ReeRoda::App do
26
29
  end
27
30
 
28
31
  def call(access, attrs)
32
+ {result: "result"}
33
+ end
34
+ end
35
+
36
+ class ReeRodaTest::AnotherCmd
37
+ include ReeActions::DSL
38
+
39
+ action :another_cmd
40
+
41
+ ActionCaster = build_mapper.use(:cast) do
42
+ integer :id
43
+ end
44
+
45
+ def call(access, attrs)
46
+ {result: "another_result"}
29
47
  end
30
48
  end
31
49
 
32
- class ReeRodaTest::TestActions
50
+ class ReeRodaTest::SubCmd
33
51
  include ReeActions::DSL
34
52
 
35
- actions :test_actions do
53
+ action :sub_cmd
54
+
55
+ ActionCaster = build_mapper.use(:cast) do
56
+ integer :id
57
+ integer :sub_id
58
+ end
59
+
60
+ def call(access, attrs)
61
+ {result: "another_result"}
62
+ end
63
+ end
64
+
65
+ class ReeRodaTest::Serializer
66
+ include ReeMapper::DSL
67
+
68
+ mapper :serializer
69
+
70
+ build_mapper.use(:serialize) do
71
+ string :result
72
+ end
73
+
74
+ def call(access, attrs)
75
+ {result: "result"}
76
+ end
77
+ end
78
+
79
+ class ReeRodaTest::TestRoutes
80
+ include ReeRoutes::DSL
81
+
82
+ routes :test_routes do
36
83
  default_warden_scope :identity
37
84
  opts = {from: :ree_roda_test}
38
85
 
@@ -41,14 +88,83 @@ RSpec.describe ReeRoda::App do
41
88
  warden_scope :visitor
42
89
  sections "some_action"
43
90
  action :cmd, **opts
91
+ serializer :serializer, **opts
92
+ end
93
+
94
+ get "api/action/:id/subaction" do
95
+ summary "Subaction"
96
+ warden_scope :visitor
97
+ sections "some_action"
98
+ action :cmd, **opts
99
+ serializer :serializer, **opts
100
+ end
101
+
102
+ post "api/action/:id/subaction" do
103
+ summary "Some action"
104
+ warden_scope :visitor
105
+ sections "some_action"
106
+ action :cmd, **opts
107
+ serializer :serializer, **opts
108
+ end
109
+
110
+ post "api/action/:id/anotheraction" do
111
+ summary "Some action"
112
+ warden_scope :visitor
113
+ sections "some_action"
114
+ action :another_cmd, **opts
115
+ serializer :serializer, **opts
116
+ end
117
+
118
+ post "api/action/:id/subaction/:sub_id" do
119
+ summary "Some action"
120
+ warden_scope :visitor
121
+ sections "some_action"
122
+ action :sub_cmd, **opts
123
+ serializer :serializer, **opts
124
+ end
125
+
126
+ post "api/action/:id" do
127
+ summary "Some action"
128
+ warden_scope :visitor
129
+ sections "some_action"
130
+ action :cmd, **opts
131
+ serializer :serializer, **opts
44
132
  end
45
133
  end
46
134
  end
47
135
 
136
+ class VisitorStrategy < Warden::Strategies::Base
137
+ include Ree::LinkDSL
138
+
139
+ def valid?
140
+ true
141
+ end
142
+
143
+ def authenticate!
144
+ success!({user: "visitor"})
145
+ end
146
+ end
147
+
148
+ Warden::Strategies.add(:visitor, VisitorStrategy)
149
+
48
150
  class TestApp < ReeRoda::App
49
- plugin :ree_actions
151
+ use Warden::Manager do |config|
152
+ config.default_strategies :visitor
153
+ config.default_scope = :visitor
154
+ config.scope_defaults :visitor, strategies: [:visitor], store: false
155
+
156
+ config.failure_app = -> (env) {
157
+ [
158
+ 401,
159
+ {"Content-Type" => "text/plain"},
160
+ ["requires authentication"]
161
+ ]
162
+ }
163
+ end
50
164
 
51
- ree_actions ReeRodaTest::TestActions.new,
165
+ plugin :ree_routes
166
+
167
+ ree_routes ReeRodaTest::TestRoutes.new,
52
168
  api_url: "http://some.api.url:1337",
53
169
  swagger_url: "swagger"
54
170
 
@@ -57,7 +173,7 @@ RSpec.describe ReeRoda::App do
57
173
  "success"
58
174
  end
59
175
 
60
- r.ree_actions
176
+ r.ree_routes
61
177
  end
62
178
  end
63
179
  end
@@ -81,4 +197,22 @@ RSpec.describe ReeRoda::App do
81
197
  get "api/v1/swagger"
82
198
  expect(last_response.status).to eq(404)
83
199
  }
200
+
201
+ it {
202
+ get "api/action/1/subaction"
203
+ expect(last_response.status).to eq(200)
204
+ expect(last_response.body).to eq("{\"result\":\"result\"}")
205
+ }
206
+
207
+ it {
208
+ post "api/action/1/subaction/2"
209
+ expect(last_response.status).to eq(201)
210
+ expect(last_response.body).to eq("{\"result\":\"another_result\"}")
211
+ }
212
+
213
+ it {
214
+ post "api/action/1/anotheraction"
215
+ expect(last_response.status).to eq(201)
216
+ expect(last_response.body).to eq("{\"result\":\"another_result\"}")
217
+ }
84
218
  end