power_api 0.1.0

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 (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