power_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +9 -0
  4. data/.hound.yml +4 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +479 -0
  7. data/.ruby-version +1 -0
  8. data/.travis.yml +15 -0
  9. data/CHANGELOG.md +7 -0
  10. data/Gemfile +18 -0
  11. data/Gemfile.lock +310 -0
  12. data/Guardfile +15 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +904 -0
  15. data/Rakefile +10 -0
  16. data/app/assets/config/power_api_manifest.js +2 -0
  17. data/app/assets/images/power_api/.keep +0 -0
  18. data/app/assets/javascripts/power_api/application.js +13 -0
  19. data/app/assets/stylesheets/power_api/application.css +15 -0
  20. data/app/controllers/concerns/api/deprecated.rb +23 -0
  21. data/app/controllers/concerns/api/error.rb +37 -0
  22. data/app/controllers/concerns/api/filtered.rb +15 -0
  23. data/app/controllers/concerns/api/versioned.rb +36 -0
  24. data/app/controllers/power_api/base_controller.rb +14 -0
  25. data/app/helpers/power_api/application_helper.rb +4 -0
  26. data/app/jobs/power_api/application_job.rb +4 -0
  27. data/app/mailers/power_api/application_mailer.rb +6 -0
  28. data/app/models/power_api/application_record.rb +5 -0
  29. data/app/responders/api_responder.rb +13 -0
  30. data/app/views/layouts/power_api/application.html.erb +14 -0
  31. data/bin/rails +14 -0
  32. data/config/routes.rb +2 -0
  33. data/lib/generators/power_api/controller/USAGE +5 -0
  34. data/lib/generators/power_api/controller/controller_generator.rb +152 -0
  35. data/lib/generators/power_api/install/USAGE +5 -0
  36. data/lib/generators/power_api/install/install_generator.rb +67 -0
  37. data/lib/generators/power_api/version/USAGE +5 -0
  38. data/lib/generators/power_api/version/version_generator.rb +54 -0
  39. data/lib/power_api.rb +35 -0
  40. data/lib/power_api/engine.rb +28 -0
  41. data/lib/power_api/errors.rb +4 -0
  42. data/lib/power_api/generator_helper/active_record_resource.rb +192 -0
  43. data/lib/power_api/generator_helper/ams_helper.rb +43 -0
  44. data/lib/power_api/generator_helper/controller_helper.rb +184 -0
  45. data/lib/power_api/generator_helper/pagination_helper.rb +48 -0
  46. data/lib/power_api/generator_helper/resource_helper.rb +33 -0
  47. data/lib/power_api/generator_helper/routes_helper.rb +91 -0
  48. data/lib/power_api/generator_helper/rubocop_helper.rb +11 -0
  49. data/lib/power_api/generator_helper/simple_token_auth_helper.rb +124 -0
  50. data/lib/power_api/generator_helper/swagger_helper.rb +463 -0
  51. data/lib/power_api/generator_helper/template_builder_helper.rb +23 -0
  52. data/lib/power_api/generator_helper/version_helper.rb +16 -0
  53. data/lib/power_api/generator_helpers.rb +25 -0
  54. data/lib/power_api/version.rb +3 -0
  55. data/lib/tasks/power_api_tasks.rake +4 -0
  56. data/power_api.gemspec +44 -0
  57. data/spec/dummy/Rakefile +6 -0
  58. data/spec/dummy/app/assets/config/manifest.js +5 -0
  59. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  60. data/spec/dummy/app/assets/javascripts/cable.js +13 -0
  61. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  62. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  63. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  64. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  65. data/spec/dummy/app/controllers/concerns/api/deprecated_spec.rb +37 -0
  66. data/spec/dummy/app/controllers/concerns/api/error_spec.rb +97 -0
  67. data/spec/dummy/app/controllers/concerns/api/filtered_spec.rb +42 -0
  68. data/spec/dummy/app/controllers/concerns/api/versioned_spec.rb +64 -0
  69. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  70. data/spec/dummy/app/jobs/application_job.rb +2 -0
  71. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  72. data/spec/dummy/app/models/application_record.rb +3 -0
  73. data/spec/dummy/app/models/blog.rb +5 -0
  74. data/spec/dummy/app/models/portfolio.rb +5 -0
  75. data/spec/dummy/app/models/user.rb +3 -0
  76. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  77. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  78. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  79. data/spec/dummy/bin/bundle +3 -0
  80. data/spec/dummy/bin/rails +4 -0
  81. data/spec/dummy/bin/rake +4 -0
  82. data/spec/dummy/bin/setup +38 -0
  83. data/spec/dummy/bin/update +29 -0
  84. data/spec/dummy/bin/yarn +11 -0
  85. data/spec/dummy/config.ru +5 -0
  86. data/spec/dummy/config/application.rb +26 -0
  87. data/spec/dummy/config/boot.rb +5 -0
  88. data/spec/dummy/config/cable.yml +10 -0
  89. data/spec/dummy/config/database.yml +25 -0
  90. data/spec/dummy/config/environment.rb +5 -0
  91. data/spec/dummy/config/environments/development.rb +54 -0
  92. data/spec/dummy/config/environments/production.rb +91 -0
  93. data/spec/dummy/config/environments/test.rb +42 -0
  94. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  95. data/spec/dummy/config/initializers/assets.rb +14 -0
  96. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  97. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  98. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  99. data/spec/dummy/config/initializers/inflections.rb +16 -0
  100. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  101. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  102. data/spec/dummy/config/locales/en.yml +33 -0
  103. data/spec/dummy/config/puma.rb +56 -0
  104. data/spec/dummy/config/routes.rb +12 -0
  105. data/spec/dummy/config/secrets.yml +32 -0
  106. data/spec/dummy/config/spring.rb +6 -0
  107. data/spec/dummy/db/migrate/20190322205209_create_blogs.rb +10 -0
  108. data/spec/dummy/db/migrate/20200215225917_create_users.rb +9 -0
  109. data/spec/dummy/db/migrate/20200227150449_create_portfolios.rb +10 -0
  110. data/spec/dummy/db/migrate/20200227150548_add_portfolio_id_blogs.rb +5 -0
  111. data/spec/dummy/db/schema.rb +38 -0
  112. data/spec/dummy/package.json +5 -0
  113. data/spec/dummy/public/404.html +67 -0
  114. data/spec/dummy/public/422.html +67 -0
  115. data/spec/dummy/public/500.html +66 -0
  116. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  117. data/spec/dummy/public/apple-touch-icon.png +0 -0
  118. data/spec/dummy/public/favicon.ico +0 -0
  119. data/spec/dummy/spec/assets/image.png +0 -0
  120. data/spec/dummy/spec/assets/video.mp4 +0 -0
  121. data/spec/dummy/spec/factories/blogs.rb +7 -0
  122. data/spec/dummy/spec/factories/portfolios.rb +6 -0
  123. data/spec/dummy/spec/factories/users.rb +5 -0
  124. data/spec/dummy/spec/lib/power_api/generator_helper/ams_helper_spec.rb +87 -0
  125. data/spec/dummy/spec/lib/power_api/generator_helper/controller_helper_spec.rb +361 -0
  126. data/spec/dummy/spec/lib/power_api/generator_helper/pagination_helper_spec.rb +56 -0
  127. data/spec/dummy/spec/lib/power_api/generator_helper/resource_helper_spec.rb +31 -0
  128. data/spec/dummy/spec/lib/power_api/generator_helper/routes_helper_spec.rb +179 -0
  129. data/spec/dummy/spec/lib/power_api/generator_helper/simple_token_auth_helper_spec.rb +164 -0
  130. data/spec/dummy/spec/lib/power_api/generator_helper/swagger_helper_spec.rb +451 -0
  131. data/spec/dummy/spec/lib/power_api/generator_helper/version_helper_spec.rb +55 -0
  132. data/spec/dummy/spec/support/shared_examples/active_record_resource.rb +101 -0
  133. data/spec/dummy/spec/support/shared_examples/active_record_resource_atrributes.rb +164 -0
  134. data/spec/dummy/spec/support/test_generator_helpers.rb +29 -0
  135. data/spec/dummy/spec/support/test_helpers.rb +11 -0
  136. data/spec/rails_helper.rb +49 -0
  137. data/spec/spec_helper.rb +9 -0
  138. metadata +602 -0
@@ -0,0 +1,56 @@
1
+ RSpec.describe PowerApi::GeneratorHelper::PaginationHelper, type: :generator do
2
+ describe "#api_pagination_initializer_path" do
3
+ let(:expected_path) { "config/initializers/api_pagination.rb" }
4
+
5
+ def perform
6
+ generators_helper.api_pagination_initializer_path
7
+ end
8
+
9
+ it { expect(perform).to eq(expected_path) }
10
+ end
11
+
12
+ describe "api_pagination_initializer_tpl" do
13
+ let(:template) do
14
+ <<~API_PAGINATION
15
+ ApiPagination.configure do |config|
16
+ # If you have more than one gem included, you can choose a paginator.
17
+ config.paginator = :kaminari
18
+
19
+ # By default, this is set to 'Total'
20
+ config.total_header = 'X-Total'
21
+
22
+ # By default, this is set to 'Per-Page'
23
+ config.per_page_header = 'X-Per-Page'
24
+
25
+ # Optional: set this to add a header with the current page number.
26
+ config.page_header = 'X-Page'
27
+
28
+ # Optional: set this to add other response format. Useful with tools that define :jsonapi format
29
+ # config.response_formats = [:json, :xml, :jsonapi]
30
+ config.response_formats = [:jsonapi]
31
+
32
+ # Optional: what parameter should be used to set the page option
33
+ config.page_param do |params|
34
+ params[:page][:number] if params[:page].is_a?(ActionController::Parameters)
35
+ end
36
+
37
+ # Optional: what parameter should be used to set the per page option
38
+ config.per_page_param do |params|
39
+ params[:page][:size] if params[:page].is_a?(ActionController::Parameters)
40
+ end
41
+
42
+ # Optional: Include the total and last_page link header
43
+ # By default, this is set to true
44
+ # Note: When using kaminari, this prevents the count call to the database
45
+ config.include_total = true
46
+ end
47
+ API_PAGINATION
48
+ end
49
+
50
+ def perform
51
+ generators_helper.api_pagination_initializer_tpl
52
+ end
53
+
54
+ it { expect(perform).to eq(template) }
55
+ end
56
+ end
@@ -0,0 +1,31 @@
1
+ RSpec.describe PowerApi::GeneratorHelper::ResourceHelper, type: :generator do
2
+ describe "#resource" do
3
+ let(:resource) { generators_helper.resource }
4
+
5
+ it_behaves_like('ActiveRecord resource')
6
+ it_behaves_like('ActiveRecord resource attributes', :resource_attributes)
7
+ end
8
+
9
+ describe "#parent_resource" do
10
+ let(:parent_resource_name) { "blog" }
11
+ let(:resource) { generators_helper.parent_resource }
12
+
13
+ it_behaves_like('ActiveRecord resource')
14
+ end
15
+
16
+ describe "#parent_resource?" do
17
+ let(:parent_resource_name) { "blog" }
18
+
19
+ def perform
20
+ generators_helper.parent_resource?
21
+ end
22
+
23
+ it { expect(perform).to eq(true) }
24
+
25
+ context "with no parent resource name" do
26
+ let(:parent_resource_name) { nil }
27
+
28
+ it { expect(perform).to eq(false) }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,179 @@
1
+ RSpec.describe PowerApi::GeneratorHelper::RoutesHelper, type: :generator do
2
+ describe "#routes_path" do
3
+ let(:expected_path) { "config/routes.rb" }
4
+
5
+ def perform
6
+ generators_helper.routes_path
7
+ end
8
+
9
+ it { expect(perform).to eq(expected_path) }
10
+ end
11
+
12
+ describe "#api_version_routes_line_regex" do
13
+ let(:expected_regex) { /Api::V1[^\n]*/ }
14
+
15
+ def perform
16
+ generators_helper.api_version_routes_line_regex
17
+ end
18
+
19
+ it { expect(perform).to eq(expected_regex) }
20
+ end
21
+
22
+ describe "#parent_resource_routes_line_regex" do
23
+ def perform
24
+ generators_helper.parent_resource_routes_line_regex
25
+ end
26
+
27
+ it { expect { perform }.to raise_error("missing parent_resource") }
28
+
29
+ context "with parent_resource" do
30
+ let(:expected_regex) { /resources :users[^\n]*/ }
31
+ let(:parent_resource_name) { "user" }
32
+
33
+ it { expect(perform).to eq(expected_regex) }
34
+ end
35
+ end
36
+
37
+ describe "#resource_route_tpl" do
38
+ let(:actions) { [] }
39
+ let(:expected_tpl) { "resources :blogs" }
40
+ let(:parent_resource_name) { "user" }
41
+ let(:is_parent) { false }
42
+
43
+ def perform
44
+ generators_helper.resource_route_tpl(actions: actions, is_parent: is_parent)
45
+ end
46
+
47
+ it { expect(perform).to eq(expected_tpl) }
48
+
49
+ context "with specific actions" do
50
+ let(:actions) { ["index", "create"] }
51
+ let(:expected_tpl) { "resources :blogs, only: [:index, :create]" }
52
+
53
+ it { expect(perform).to eq(expected_tpl) }
54
+ end
55
+
56
+ context "with is_parent option actions" do
57
+ let(:is_parent) { true }
58
+ let(:expected_tpl) { "resources :users" }
59
+
60
+ it { expect(perform).to eq(expected_tpl) }
61
+ end
62
+ end
63
+
64
+ describe "routes_line_to_inject_new_version" do
65
+ let(:expected_line) do
66
+ "routes.draw do\n"
67
+ end
68
+
69
+ def perform
70
+ generators_helper.routes_line_to_inject_new_version
71
+ end
72
+
73
+ it { expect(perform).to eq(expected_line) }
74
+
75
+ context "when is not the first version" do
76
+ let(:version_number) { "2" }
77
+
78
+ let(:expected_line) do
79
+ "'/api' do\n"
80
+ end
81
+
82
+ it { expect(perform).to eq(expected_line) }
83
+ end
84
+ end
85
+
86
+ describe "#version_route_tpl" do
87
+ let(:expected_tpl) do
88
+ <<~ROUTE
89
+ scope path: '/api' do
90
+ api_version(module: 'Api::V1', path: { value: 'v1' }, defaults: { format: 'json' }) do
91
+ end
92
+ end
93
+ ROUTE
94
+ end
95
+
96
+ def perform
97
+ generators_helper.version_route_tpl
98
+ end
99
+
100
+ it { expect(perform).to eq(expected_tpl) }
101
+
102
+ context "when is not the first version" do
103
+ let(:version_number) { "2" }
104
+
105
+ let(:expected_tpl) do
106
+ <<~ROUTE
107
+ api_version(module: 'Api::V2', path: { value: 'v2' }, defaults: { format: 'json' }) do
108
+ end
109
+ ROUTE
110
+ end
111
+
112
+ it { expect(perform).to eq(expected_tpl.delete_suffix("\n")) }
113
+ end
114
+ end
115
+
116
+ describe "#parent_route_exist?" do
117
+ let(:parent_resource_name) { "user" }
118
+ let(:line) { nil }
119
+
120
+ def perform
121
+ generators_helper.parent_route_exist?
122
+ end
123
+
124
+ before { mock_file_content("config/routes.rb", [line]) }
125
+
126
+ context "with file line not matching regex" do
127
+ let(:line) { "X" }
128
+
129
+ it { expect(perform).to eq(false) }
130
+ end
131
+
132
+ context "with no parent_resource" do
133
+ let(:parent_resource_name) { nil }
134
+
135
+ it { expect { perform }.to raise_error("missing parent_resource") }
136
+ end
137
+
138
+ context "with file line matching regex" do
139
+ let(:line) { "resources :users" }
140
+
141
+ it { expect(perform).to eq(true) }
142
+ end
143
+ end
144
+
145
+ describe "#parent_route_already_have_children?" do
146
+ let(:parent_resource_name) { "user" }
147
+ let(:line) { nil }
148
+
149
+ def perform
150
+ generators_helper.parent_route_already_have_children?
151
+ end
152
+
153
+ before { mock_file_content("config/routes.rb", [line]) }
154
+
155
+ context "with file line not matching regex" do
156
+ let(:line) { "X" }
157
+
158
+ it { expect(perform).to eq(false) }
159
+ end
160
+
161
+ context "with no parent_resource" do
162
+ let(:parent_resource_name) { nil }
163
+
164
+ it { expect { perform }.to raise_error("missing parent_resource") }
165
+ end
166
+
167
+ context "with parent line found but with no children" do
168
+ let(:line) { "resources :users" }
169
+
170
+ it { expect(perform).to eq(false) }
171
+ end
172
+
173
+ context "with parent line found with children" do
174
+ let(:line) { "resources :users do" }
175
+
176
+ it { expect(perform).to eq(true) }
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,164 @@
1
+ RSpec.describe PowerApi::GeneratorHelper::SimpleTokenAuthHelper, type: :generator do
2
+ describe "#authenticated_resource" do
3
+ let(:authenticated_resource) { "blog" }
4
+ let(:resource) { generators_helper.authenticated_resource }
5
+
6
+ it_behaves_like('ActiveRecord resource') do
7
+ describe "#authenticated_resources_migrations" do
8
+ let(:expected) do
9
+ "migration add_authentication_token_to_blogs authentication_token:string{30}:uniq"
10
+ end
11
+
12
+ it { expect(resource.authenticated_resource_migration).to eq(expected) }
13
+ end
14
+
15
+ describe "current_authenticated_resource" do
16
+ it { expect(generators_helper.current_authenticated_resource).to eq("current_blog") }
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "#authenticated_resources=" do
22
+ let(:resources_names) { ["blog"] }
23
+ let(:resource) { resources.first }
24
+
25
+ def resources
26
+ generators_helper.authenticated_resources = resources_names
27
+ generators_helper.authenticated_resources
28
+ end
29
+
30
+ it { expect(resources.count).to eq(1) }
31
+ it { expect(resources.first).to be_a(described_class::SimpleTokenAuthResource) }
32
+
33
+ it_behaves_like('ActiveRecord resource') do
34
+ describe "#authenticated_resources_migrations" do
35
+ let(:expected) do
36
+ "migration add_authentication_token_to_blogs authentication_token:string{30}:uniq"
37
+ end
38
+
39
+ it { expect(resource.authenticated_resource_migration).to eq(expected) }
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#owned_by_authenticated_resource?" do
45
+ let(:authenticated_resource) { "user" }
46
+ let(:owned_by_authenticated_resource) { true }
47
+ let(:parent_resource_name) { nil }
48
+
49
+ def perform
50
+ generators_helper.owned_by_authenticated_resource?
51
+ end
52
+
53
+ it { expect(perform).to eq(true) }
54
+
55
+ context "with no authenticated_resource" do
56
+ let(:authenticated_resource) { nil }
57
+
58
+ it { expect(perform).to eq(false) }
59
+ end
60
+
61
+ context "with no owned_by_authenticated_resource" do
62
+ let(:owned_by_authenticated_resource) { false }
63
+
64
+ it { expect(perform).to eq(false) }
65
+ end
66
+
67
+ context "with no parent_resource_name" do
68
+ let(:parent_resource_name) { "portfolio" }
69
+
70
+ it { expect(perform).to eq(false) }
71
+ end
72
+ end
73
+
74
+ describe "#simple_token_auth_method" do
75
+ let(:expected) do
76
+ " acts_as_token_authenticatable\n\n"
77
+ end
78
+
79
+ it { expect(generators_helper.simple_token_auth_method).to eq(expected) }
80
+ end
81
+
82
+ describe "#simple_token_auth_initializer_path" do
83
+ let(:expected_path) { "spec/swagger/.gitkeep" }
84
+
85
+ def perform
86
+ generators_helper.simple_token_auth_initializer_path
87
+ end
88
+
89
+ it { expect(perform).to eq("config/initializers/simple_token_authentication.rb") }
90
+ end
91
+
92
+ describe "#simple_token_auth_initializer_tpl" do
93
+ let(:expected) do
94
+ <<~INITIALIZER
95
+ SimpleTokenAuthentication.configure do |config|
96
+ # Configure the session persistence policy after a successful sign in,
97
+ # in other words, if the authentication token acts as a signin token.
98
+ # If true, user is stored in the session and the authentication token and
99
+ # email may be provided only once.
100
+ # If false, users must provide their authentication token and email at every request.
101
+ # config.sign_in_token = false
102
+
103
+ # Configure the name of the HTTP headers watched for authentication.
104
+ #
105
+ # Default header names for a given token authenticatable entity follow the pattern:
106
+ # { entity: { authentication_token: 'X-Entity-Token', email: 'X-Entity-Email'} }
107
+ #
108
+ # When several token authenticatable models are defined, custom header names
109
+ # can be specified for none, any, or all of them.
110
+ #
111
+ # Note: when using the identifiers options, this option behaviour is modified.
112
+ # Please see the example below.
113
+ #
114
+ # Examples
115
+ #
116
+ # Given User and SuperAdmin are token authenticatable,
117
+ # When the following configuration is used:
118
+ # `config.header_names = { super_admin: { authentication_token: 'X-Admin-Auth-Token' } }`
119
+ # Then the token authentification handler for User watches the following headers:
120
+ # `X-User-Token, X-User-Email`
121
+ # And the token authentification handler for SuperAdmin watches the following headers:
122
+ # `X-Admin-Auth-Token, X-SuperAdmin-Email`
123
+ #
124
+ # When the identifiers option is set:
125
+ # `config.identifiers = { super_admin: :phone_number }`
126
+ # Then both the header names identifier key and default value are modified accordingly:
127
+ # `config.header_names = { super_admin: { phone_number: 'X-SuperAdmin-PhoneNumber' } }`
128
+ #
129
+ # config.header_names = { user: { authentication_token: 'X-User-Token', email: 'X-User-Email' } }
130
+
131
+ # Configure the name of the attribute used to identify the user for authentication.
132
+ # That attribute must exist in your model.
133
+ #
134
+ # The default identifiers follow the pattern:
135
+ # { entity: 'email' }
136
+ #
137
+ # Note: the identifer must match your Devise configuration,
138
+ # see https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address#tell-devise-to-use-username-in-the-authentication_keys
139
+ #
140
+ # Note: setting this option does modify the header_names behaviour,
141
+ # see the header_names section above.
142
+ #
143
+ # Example:
144
+ #
145
+ # `config.identifiers = { super_admin: 'phone_number', user: 'uuid' }`
146
+ #
147
+ # config.identifiers = { user: 'email' }
148
+
149
+ # Configure the Devise trackable strategy integration.
150
+ #
151
+ # If true, tracking is disabled for token authentication: signing in through
152
+ # token authentication won't modify the Devise trackable statistics.
153
+ #
154
+ # If false, given Devise trackable is configured for the relevant model,
155
+ # then signing in through token authentication will be tracked as any other sign in.
156
+ #
157
+ # config.skip_devise_trackable = true
158
+ end
159
+ INITIALIZER
160
+ end
161
+
162
+ it { expect(generators_helper.simple_token_auth_initializer_tpl).to eq(expected) }
163
+ end
164
+ end
@@ -0,0 +1,451 @@
1
+ RSpec.describe PowerApi::GeneratorHelper::SwaggerHelper, type: :generator do
2
+ describe "#swagger_helper_path" do
3
+ let(:expected_path) { "spec/swagger_helper.rb" }
4
+
5
+ def perform
6
+ generators_helper.swagger_helper_path
7
+ end
8
+
9
+ it { expect(perform).to eq(expected_path) }
10
+ end
11
+
12
+ describe "#spec_swagger_path" do
13
+ let(:expected_path) { "spec/swagger/.gitkeep" }
14
+
15
+ def perform
16
+ generators_helper.spec_swagger_path
17
+ end
18
+
19
+ it { expect(perform).to eq(expected_path) }
20
+ end
21
+
22
+ describe "#spec_integration_path" do
23
+ let(:expected_path) { "spec/integration/.gitkeep" }
24
+
25
+ def perform
26
+ generators_helper.spec_integration_path
27
+ end
28
+
29
+ it { expect(perform).to eq(expected_path) }
30
+ end
31
+
32
+ describe "#rswag_ui_initializer_path" do
33
+ let(:expected_path) { "config/initializers/rswag-ui.rb" }
34
+
35
+ def perform
36
+ generators_helper.rswag_ui_initializer_path
37
+ end
38
+
39
+ it { expect(perform).to eq(expected_path) }
40
+ end
41
+
42
+ describe "#swagger_resource_schema_path" do
43
+ let(:expected_path) { "spec/swagger/v1/schemas/blog_schema.rb" }
44
+
45
+ def perform
46
+ generators_helper.swagger_resource_schema_path
47
+ end
48
+
49
+ it { expect(perform).to eq(expected_path) }
50
+ end
51
+
52
+ describe "#swagger_version_definition_path" do
53
+ let(:expected_path) { "spec/swagger/v1/definition.rb" }
54
+
55
+ def perform
56
+ generators_helper.swagger_version_definition_path
57
+ end
58
+
59
+ it { expect(perform).to eq(expected_path) }
60
+ end
61
+
62
+ describe "#swagger_resource_spec_path" do
63
+ let(:expected_path) { "spec/integration/api/v1/blogs_spec.rb" }
64
+
65
+ def perform
66
+ generators_helper.swagger_resource_spec_path
67
+ end
68
+
69
+ it { expect(perform).to eq(expected_path) }
70
+ end
71
+
72
+ describe "#rswag_ui_configure_line" do
73
+ let(:expected_path) do
74
+ "Rswag::Ui.configure do |c|\n"
75
+ end
76
+
77
+ def perform
78
+ generators_helper.rswag_ui_configure_line
79
+ end
80
+
81
+ it { expect(perform).to eq(expected_path) }
82
+ end
83
+
84
+ describe "#swagger_helper_api_definition_line" do
85
+ let(:expected_line) do
86
+ "config.swagger_docs = {\n"
87
+ end
88
+
89
+ def perform
90
+ generators_helper.swagger_helper_api_definition_line
91
+ end
92
+
93
+ it { expect(perform).to eq(expected_line) }
94
+ end
95
+
96
+ describe "#swagger_definition_line_to_inject_schema" do
97
+ let(:expected_line) { /definitions: {/ }
98
+
99
+ def perform
100
+ generators_helper.swagger_definition_line_to_inject_schema
101
+ end
102
+
103
+ it { expect(perform).to eq(expected_line) }
104
+ end
105
+
106
+ describe "#swagger_helper_api_definition" do
107
+ let(:expected_tpl) do
108
+ <<-VERSION
109
+ 'v1/swagger.json' => API_V1
110
+ VERSION
111
+ end
112
+
113
+ def perform
114
+ generators_helper.swagger_helper_api_definition
115
+ end
116
+
117
+ it { expect(perform).to eq(expected_tpl) }
118
+
119
+ context "with another version" do
120
+ let(:version_number) { "2" }
121
+
122
+ let(:expected_tpl) do
123
+ <<-VERSION
124
+ 'v2/swagger.json' => API_V2,
125
+ VERSION
126
+ end
127
+
128
+ it { expect(perform).to eq(expected_tpl) }
129
+ end
130
+ end
131
+
132
+ describe "#rswag_ui_initializer_tpl" do
133
+ let(:expected_tpl) do
134
+ <<~INITIALIZER
135
+ Rswag::Ui.configure do |c|
136
+ end
137
+ INITIALIZER
138
+ end
139
+
140
+ def perform
141
+ generators_helper.rswag_ui_initializer_tpl
142
+ end
143
+
144
+ it { expect(perform).to eq(expected_tpl) }
145
+ end
146
+
147
+ describe "#swagger_definition_tpl" do
148
+ let(:expected_tpl) do
149
+ <<~DEFINITION
150
+ API_V1 = {
151
+ swagger: '2.0',
152
+ info: {
153
+ title: 'API V1',
154
+ version: 'v1'
155
+ },
156
+ basePath: '/api/v1',
157
+ definitions: {
158
+ }
159
+ }
160
+ DEFINITION
161
+ end
162
+
163
+ def perform
164
+ generators_helper.swagger_definition_tpl
165
+ end
166
+
167
+ it { expect(perform).to eq(expected_tpl) }
168
+ end
169
+
170
+ describe "swagger_helper_tpl" do
171
+ let(:template) do
172
+ <<~SWAGGER
173
+ require 'rails_helper'
174
+
175
+ Dir[::Rails.root.join("spec/swagger/**/schemas/*.rb")].each { |f| require f }
176
+ Dir[::Rails.root.join("spec/swagger/**/definition.rb")].each { |f| require f }
177
+
178
+ RSpec.configure do |config|
179
+ # Specify a root folder where Swagger JSON files are generated
180
+ # NOTE: If you're using the rswag-api to serve API descriptions, you'll need
181
+ # to ensure that it's confiugred to serve Swagger from the same folder
182
+ config.swagger_root = Rails.root.to_s + '/swagger'
183
+
184
+ # Define one or more Swagger documents and provide global metadata for each one
185
+ # When you run the 'rswag:specs:to_swagger' rake task, the complete Swagger will
186
+ # be generated at the provided relative path under swagger_root
187
+ # By default, the operations defined in spec files are added to the first
188
+ # document below. You can override this behavior by adding a swagger_doc tag to the
189
+ # the root example_group in your specs, e.g. describe '...', swagger_doc: 'v2/swagger.json'
190
+ config.swagger_docs = {
191
+ }
192
+ end
193
+ SWAGGER
194
+ end
195
+
196
+ def perform
197
+ generators_helper.swagger_helper_tpl
198
+ end
199
+
200
+ it { expect(perform).to eq(template) }
201
+ end
202
+
203
+ describe "#swagger_schema_tpl" do
204
+ let(:template) do
205
+ <<~SCHEMA
206
+ BLOG_SCHEMA = {
207
+ type: :object,
208
+ properties: {
209
+ id: { type: :string, example: '1' },
210
+ type: { type: :string, example: 'blog' },
211
+ attributes: {
212
+ type: :object,
213
+ properties: {
214
+ title: { type: :string, example: 'Some title' },
215
+ body: { type: :string, example: 'Some body' },
216
+ created_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true },
217
+ updated_at: { type: :string, example: '1984-06-04 09:00', 'x-nullable': true },
218
+ portfolio_id: { type: :integer, example: 666, 'x-nullable': true }
219
+ },
220
+ required: [
221
+ :title,
222
+ :body
223
+ ]
224
+ }
225
+ },
226
+ required: [
227
+ :id,
228
+ :type,
229
+ :attributes
230
+ ]
231
+ }
232
+
233
+ BLOGS_COLLECTION_SCHEMA = {
234
+ type: "object",
235
+ properties: {
236
+ data: {
237
+ type: "array",
238
+ items: { "$ref" => "#/definitions/blog" }
239
+ }
240
+ },
241
+ required: [
242
+ :data
243
+ ]
244
+ }
245
+
246
+ BLOG_RESOURCE_SCHEMA = {
247
+ type: "object",
248
+ properties: {
249
+ data: { "$ref" => "#/definitions/blog" }
250
+ },
251
+ required: [
252
+ :data
253
+ ]
254
+ }
255
+ SCHEMA
256
+ end
257
+
258
+ def perform
259
+ generators_helper.swagger_schema_tpl
260
+ end
261
+
262
+ it { expect(perform).to eq(template) }
263
+ end
264
+
265
+ describe "#swagger_resource_spec_tpl" do
266
+ let(:template) do
267
+ <<~SPEC
268
+ require 'swagger_helper'
269
+
270
+ describe 'API V1 Blogs', swagger_doc: 'v1/swagger.json' do
271
+ path '/blogs' do
272
+ get 'Retrieves Blogs' do
273
+ description 'Retrieves all the blogs'
274
+ produces 'application/json'
275
+
276
+ let(:collection_count) { 5 }
277
+ let(:expected_collection_count) { collection_count }
278
+
279
+ before { create_list(:blog, collection_count) }
280
+ response '200', 'Blogs retrieved' do
281
+ schema('$ref' => '#/definitions/blogs_collection')
282
+
283
+ run_test! do |response|
284
+ expect(JSON.parse(response.body)['data'].count).to eq(expected_collection_count)
285
+ end
286
+ end
287
+
288
+ end
289
+
290
+ post 'Creates Blog' do
291
+ description 'Creates Blog'
292
+ consumes 'application/json'
293
+ produces 'application/json'
294
+ parameter(name: :blog, in: :body)
295
+
296
+ response '201', 'blog created' do
297
+ let(:blog) do
298
+ {
299
+ title: 'Some title',
300
+ body: 'Some body'}
301
+ end
302
+
303
+ run_test!
304
+ end
305
+
306
+ response '400', 'invalid attributes' do
307
+ let(:blog) do
308
+ {
309
+ title: nil}
310
+ end
311
+
312
+ run_test!
313
+ end
314
+
315
+ end
316
+
317
+ end
318
+
319
+ path '/blogs/{id}' do
320
+ parameter name: :id, in: :path, type: :integer
321
+
322
+ let(:existent_blog) { create(:blog) }
323
+ let(:id) { existent_blog.id }
324
+
325
+ get 'Retrieves Blog' do
326
+ produces 'application/json'
327
+
328
+ response '200', 'blog retrieved' do
329
+ schema('$ref' => '#/definitions/blog_resource')
330
+
331
+ run_test!
332
+ end
333
+
334
+ response '404', 'invalid blog id' do
335
+ let(:id) { 'invalid' }
336
+ run_test!
337
+ end
338
+
339
+ end
340
+
341
+ put 'Updates Blog' do
342
+ description 'Updates Blog'
343
+ consumes 'application/json'
344
+ produces 'application/json'
345
+ parameter(name: :blog, in: :body)
346
+
347
+ response '200', 'blog updated' do
348
+ let(:blog) do
349
+ {
350
+ title: 'Some title',
351
+ body: 'Some body'}
352
+ end
353
+
354
+ run_test!
355
+ end
356
+
357
+ response '400', 'invalid attributes' do
358
+ let(:blog) do
359
+ {
360
+ title: nil}
361
+ end
362
+
363
+ run_test!
364
+ end
365
+
366
+ end
367
+
368
+ delete 'Deletes Blog' do
369
+ produces 'application/json'
370
+ description 'Deletes specific blog'
371
+
372
+ response '204', 'blog deleted' do
373
+ run_test!
374
+ end
375
+
376
+ response '404', 'blog not found' do
377
+ let(:id) { 'invalid' }
378
+
379
+ run_test!
380
+ end
381
+
382
+ end
383
+
384
+ end
385
+
386
+ end
387
+ SPEC
388
+ end
389
+
390
+ def perform
391
+ generators_helper.swagger_resource_spec_tpl
392
+ end
393
+
394
+ it { expect(perform).to eq(template) }
395
+
396
+ context "with authenticated_resource option" do
397
+ let(:authenticated_resource) { "user" }
398
+
399
+ it { expect(perform).to include("let(:user) { create(:user) }") }
400
+ it { expect(perform).to include("let(:user_email) { user.email }") }
401
+ it { expect(perform).to include("let(:user_token) { user.authentication_token }") }
402
+ it { expect(perform).to include("parameter name: :user_email, in: :query, type: :string") }
403
+ it { expect(perform).to include("parameter name: :user_token, in: :query, type: :string") }
404
+ it { expect(perform).to include("response '401', 'user unauthorized' do") }
405
+ end
406
+
407
+ context "with owned_by_authenticated_resource option" do
408
+ let(:authenticated_resource) { "user" }
409
+ let(:owned_by_authenticated_resource) { true }
410
+
411
+ it { expect(perform).to include("create_list(:blog, collection_count, user: user)") }
412
+ it { expect(perform).to include("(:existent_blog) { create(:blog, user: user) }") }
413
+ end
414
+
415
+ context "with parent_resource option" do
416
+ let(:parent_resource_name) { "portfolio" }
417
+
418
+ it { expect(perform).to include("/portfolios/{portfolio_id}/blogs") }
419
+ it { expect(perform).to include("parameter name: :portfolio_id, in: :path, type: :integer") }
420
+ it { expect(perform).to include("reate_list(:blog, collection_count, portfolio: portfolio)") }
421
+ it { expect(perform).to include("let(:portfolio) { create(:portfolio) }") }
422
+ it { expect(perform).to include("(:existent_blog) { create(:blog, portfolio: portfolio) }") }
423
+ end
424
+ end
425
+
426
+ describe "#rswag_ui_swagger_endpoint" do
427
+ let(:expected_entry) do
428
+ " c.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'\n"
429
+ end
430
+
431
+ def perform
432
+ generators_helper.rswag_ui_swagger_endpoint
433
+ end
434
+
435
+ it { expect(perform).to eq(expected_entry) }
436
+ end
437
+
438
+ describe "#swagger_definition_entry" do
439
+ let(:expected_entry) do
440
+ "\n blog: BLOG_SCHEMA,\
441
+ \n blogs_collection: BLOGS_COLLECTION_SCHEMA,\
442
+ \n blog_resource: BLOG_RESOURCE_SCHEMA,"
443
+ end
444
+
445
+ def perform
446
+ generators_helper.swagger_definition_entry
447
+ end
448
+
449
+ it { expect(perform).to eq(expected_entry) }
450
+ end
451
+ end