wor-simple_crud 0.2.1 → 0.3.1

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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/CHANGELOG.md +46 -0
  4. data/Gemfile +1 -0
  5. data/README.md +200 -2
  6. data/lib/simple_crud/action_lambdas.rb +81 -0
  7. data/lib/simple_crud/authorization/adapter.rb +7 -0
  8. data/lib/simple_crud/authorization/pundit_adapter.rb +6 -0
  9. data/lib/simple_crud/config.rb +6 -1
  10. data/lib/simple_crud/controller_helpers.rb +128 -0
  11. data/lib/simple_crud/pagination/adapter.rb +7 -1
  12. data/lib/simple_crud/pagination/kaminari_adapter.rb +23 -2
  13. data/lib/simple_crud/pagination/pagy_adapter.rb +7 -2
  14. data/lib/simple_crud/pagination/will_paginate_adapter.rb +7 -3
  15. data/lib/simple_crud/pagination/wor_paginate_adapter.rb +7 -2
  16. data/lib/simple_crud/rspec/config.rb +74 -0
  17. data/lib/simple_crud/rspec/helpers/authentication.rb +32 -0
  18. data/lib/simple_crud/rspec/helpers/controller_options.rb +19 -0
  19. data/lib/simple_crud/rspec/helpers/models.rb +55 -0
  20. data/lib/simple_crud/rspec/helpers/policies.rb +25 -0
  21. data/lib/simple_crud/rspec/helpers/requests.rb +45 -0
  22. data/lib/simple_crud/rspec/helpers/settings.rb +49 -0
  23. data/lib/simple_crud/rspec/helpers.rb +25 -0
  24. data/lib/simple_crud/rspec.rb +35 -0
  25. data/lib/simple_crud/simple_crud_controller.rb +27 -75
  26. data/lib/simple_crud/version.rb +1 -1
  27. data/lib/spec/shared_contexts/authenticate_user.rb +1 -7
  28. data/lib/spec/shared_examples/authorization_adapter_authorize.rb +11 -0
  29. data/lib/spec/shared_examples/simple_crud_for_create.rb +46 -11
  30. data/lib/spec/shared_examples/simple_crud_for_create_with_block.rb +36 -0
  31. data/lib/spec/shared_examples/simple_crud_for_create_with_build.rb +15 -0
  32. data/lib/spec/shared_examples/simple_crud_for_destroy.rb +44 -8
  33. data/lib/spec/shared_examples/simple_crud_for_destroy_with_block.rb +21 -0
  34. data/lib/spec/shared_examples/simple_crud_for_destroy_with_finder.rb +35 -0
  35. data/lib/spec/shared_examples/simple_crud_for_edit.rb +79 -0
  36. data/lib/spec/shared_examples/simple_crud_for_index.rb +9 -24
  37. data/lib/spec/shared_examples/simple_crud_for_index_with_block.rb +22 -0
  38. data/lib/spec/shared_examples/simple_crud_for_index_with_scope.rb +33 -0
  39. data/lib/spec/shared_examples/simple_crud_for_new.rb +29 -0
  40. data/lib/spec/shared_examples/simple_crud_for_new_with_block.rb +20 -0
  41. data/lib/spec/shared_examples/simple_crud_for_new_with_build.rb +19 -0
  42. data/lib/spec/shared_examples/simple_crud_for_show.rb +14 -10
  43. data/lib/spec/shared_examples/simple_crud_for_show_with_block.rb +22 -0
  44. data/lib/spec/shared_examples/simple_crud_for_show_with_finder.rb +33 -0
  45. data/lib/spec/shared_examples/simple_crud_for_update.rb +61 -14
  46. data/lib/spec/shared_examples/simple_crud_for_update_with_finder.rb +39 -0
  47. data/lib/spec/shared_examples/simple_crud_not_found_with_finder.rb +14 -0
  48. data/lib/spec/shared_examples/simple_crud_renders_template.rb +8 -0
  49. data/lib/spec/shared_examples/simple_crud_when_not_authorized.rb +18 -0
  50. data/lib/spec/shared_examples/simple_crud_without_authenticated_user.rb +9 -0
  51. data/lib/spec/shared_examples/unauthorized_when_not_logged_in.rb +2 -2
  52. data/spec/block/dummy_models_controller_spec.rb +8 -0
  53. data/spec/block_create/dummy_models_controller_spec.rb +7 -0
  54. data/spec/block_destroy/dummy_models_controller_spec.rb +7 -0
  55. data/spec/block_finder/dummy_models_controller_spec.rb +10 -0
  56. data/spec/block_json/dummy_models_controller_spec.rb +9 -0
  57. data/spec/block_new/dummy_models_controller_spec.rb +7 -0
  58. data/spec/block_redirect/dummy_models_controller_spec.rb +7 -0
  59. data/spec/block_show/dummy_models_controller_spec.rb +7 -0
  60. data/spec/built/dummy_models_controller_spec.rb +8 -0
  61. data/spec/dummy/app/controllers/block/dummy_models_controller.rb +17 -0
  62. data/spec/dummy/app/controllers/block_create/dummy_models_controller.rb +13 -0
  63. data/spec/dummy/app/controllers/block_destroy/dummy_models_controller.rb +9 -0
  64. data/spec/dummy/app/controllers/block_finder/dummy_models_controller.rb +25 -0
  65. data/spec/dummy/app/controllers/block_json/dummy_models_controller.rb +17 -0
  66. data/spec/dummy/app/controllers/block_modes/base_controller.rb +11 -0
  67. data/spec/dummy/app/controllers/block_new/dummy_models_controller.rb +9 -0
  68. data/spec/dummy/app/controllers/block_redirect/dummy_models_controller.rb +13 -0
  69. data/spec/dummy/app/controllers/block_show/dummy_models_controller.rb +9 -0
  70. data/spec/dummy/app/controllers/built/dummy_models_controller.rb +21 -0
  71. data/spec/dummy/app/controllers/dummy_models_controller.rb +2 -1
  72. data/spec/dummy/app/controllers/finder/dummy_models_controller.rb +23 -0
  73. data/spec/dummy/app/controllers/html/dummy_models_controller.rb +7 -0
  74. data/spec/dummy/app/controllers/html_create/dummy_models_controller.rb +7 -0
  75. data/spec/dummy/app/controllers/html_destroy/dummy_models_controller.rb +7 -0
  76. data/spec/dummy/app/controllers/html_finder/dummy_models_controller.rb +17 -0
  77. data/spec/dummy/app/controllers/html_modes/base_controller.rb +17 -0
  78. data/spec/dummy/app/controllers/html_new/dummy_models_controller.rb +7 -0
  79. data/spec/dummy/app/controllers/html_scoped/dummy_models_controller.rb +8 -0
  80. data/spec/dummy/app/controllers/html_show/dummy_models_controller.rb +7 -0
  81. data/spec/dummy/app/controllers/html_update/dummy_models_controller.rb +7 -0
  82. data/spec/dummy/app/controllers/invalid_status/dummy_models_controller.rb +13 -0
  83. data/spec/dummy/app/controllers/nested/dummy_models_controller.rb +21 -0
  84. data/spec/dummy/app/controllers/nested_route/dummy_models_controller.rb +26 -0
  85. data/spec/dummy/app/controllers/redirect/dummy_models_controller.rb +10 -0
  86. data/spec/dummy/app/controllers/redirect_auth/dummy_models_controller.rb +28 -0
  87. data/spec/dummy/app/controllers/scoped/dummy_models_controller.rb +16 -0
  88. data/spec/dummy/app/controllers/scoped_params/dummy_models_controller.rb +16 -0
  89. data/spec/dummy/app/controllers/strict/dummy_models_controller.rb +21 -0
  90. data/spec/dummy/app/controllers/unpaginated_scoped/dummy_models_controller.rb +16 -0
  91. data/spec/dummy/app/models/dummy_model.rb +4 -0
  92. data/spec/dummy/app/models/dummy_model_policy.rb +9 -1
  93. data/spec/dummy/app/views/block/dummy_models/index.html.erb +3 -0
  94. data/spec/dummy/app/views/block_new/dummy_models/new.html.erb +1 -0
  95. data/spec/dummy/app/views/block_show/dummy_models/show.html.erb +1 -0
  96. data/spec/dummy/app/views/html/dummy_models/index.html.erb +3 -0
  97. data/spec/dummy/app/views/html_create/dummy_models/new.html.erb +1 -0
  98. data/spec/dummy/app/views/html_destroy/dummy_models/show.html.erb +1 -0
  99. data/spec/dummy/app/views/html_finder/dummy_models/edit.html.erb +1 -0
  100. data/spec/dummy/app/views/html_finder/dummy_models/new.html.erb +1 -0
  101. data/spec/dummy/app/views/html_finder/dummy_models/show.html.erb +1 -0
  102. data/spec/dummy/app/views/html_new/dummy_models/new.html.erb +1 -0
  103. data/spec/dummy/app/views/html_scoped/dummy_models/index.html.erb +3 -0
  104. data/spec/dummy/app/views/html_show/dummy_models/show.html.erb +1 -0
  105. data/spec/dummy/app/views/html_update/dummy_models/edit.html.erb +1 -0
  106. data/spec/dummy/app/views/invalid_status/dummy_models/new.html.erb +1 -0
  107. data/spec/dummy/app/views/layouts/application.html.erb +4 -0
  108. data/spec/dummy/app/views/redirect/dummy_models/new.html.erb +1 -0
  109. data/spec/dummy/config/routes.rb +110 -0
  110. data/spec/dummy/db/migrate/20260806000000_add_slug_to_dummy_models.rb +7 -0
  111. data/spec/dummy/db/migrate/20260807000000_add_classroom_slug_to_dummy_models.rb +7 -0
  112. data/spec/dummy/db/schema.rb +3 -1
  113. data/spec/dummy/spec/factories/dummy_models.rb +1 -0
  114. data/spec/dummy_controller_spec.rb +1 -0
  115. data/spec/dummy_model_policy_spec.rb +6 -4
  116. data/spec/finder/dummy_models_controller_spec.rb +13 -0
  117. data/spec/html/dummy_models_controller_spec.rb +7 -0
  118. data/spec/html_create/dummy_models_controller_spec.rb +7 -0
  119. data/spec/html_destroy/dummy_models_controller_spec.rb +7 -0
  120. data/spec/html_finder/dummy_models_controller_spec.rb +11 -0
  121. data/spec/html_new/dummy_models_controller_spec.rb +7 -0
  122. data/spec/html_scoped/dummy_models_controller_spec.rb +7 -0
  123. data/spec/html_show/dummy_models_controller_spec.rb +7 -0
  124. data/spec/html_update/dummy_models_controller_spec.rb +7 -0
  125. data/spec/invalid_status/dummy_models_controller_spec.rb +10 -0
  126. data/spec/nested/dummy_models_controller_spec.rb +12 -0
  127. data/spec/nested_route/dummy_models_controller_spec.rb +19 -0
  128. data/spec/redirect/dummy_models_controller_spec.rb +23 -0
  129. data/spec/redirect_auth/dummy_models_controller_spec.rb +11 -0
  130. data/spec/scoped/dummy_models_controller_spec.rb +7 -0
  131. data/spec/scoped_params/dummy_models_controller_spec.rb +12 -0
  132. data/spec/simple_crud/authorization/action_policy_adapter_spec.rb +1 -9
  133. data/spec/simple_crud/authorization/can_can_can_adapter_spec.rb +1 -7
  134. data/spec/simple_crud/authorization/pundit_adapter_spec.rb +41 -0
  135. data/spec/simple_crud/controller_helpers_spec.rb +49 -0
  136. data/spec/simple_crud/pagination/adapters_spec.rb +37 -13
  137. data/spec/simple_crud/rspec_config_spec.rb +100 -0
  138. data/spec/simple_crud_configuration_spec.rb +19 -16
  139. data/spec/simple_crud_controller_spec.rb +4 -4
  140. data/spec/spec_helper.rb +1 -0
  141. data/spec/strict/dummy_models_controller_spec.rb +23 -0
  142. data/spec/unpaginated_scoped/dummy_models_controller_spec.rb +7 -0
  143. metadata +108 -4
  144. data/lib/spec/shared_examples/helpers.rb +0 -50
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'helpers'
4
-
5
3
  shared_examples 'simple crud for create' do
6
4
  describe 'POST #create' do
7
5
  context 'without authenticated user' do
8
- subject!(:req) { post :create, params: attributes_for(model_class) }
6
+ subject!(:req) do
7
+ post :create, params: with_route_params(body_params(params_for(model_class))), format: request_format(:create)
8
+ end
9
9
 
10
10
  include_examples 'unauthorized when not logged in' if check_authenticate(:create)
11
11
  end
@@ -16,7 +16,7 @@ shared_examples 'simple crud for create' do
16
16
 
17
17
  before do
18
18
  make_policies_fail(:create)
19
- post :create, params: model_params
19
+ post :create, params: with_route_params(body_params(model_params)), format: request_format(:create)
20
20
  end
21
21
 
22
22
  it 'fails with forbidden' do
@@ -27,22 +27,57 @@ shared_examples 'simple crud for create' do
27
27
 
28
28
  context 'when successfully creating an article' do
29
29
  include_context 'with authenticated user' if check_authenticate(:create)
30
- let(:create_params) { model_params.merge(user_id: current_user.id) }
30
+ let(:create_params) { model_params.merge(owner_params) }
31
31
 
32
32
  before do
33
- post :create, params: create_params
33
+ post :create, params: with_route_params(body_params(create_params)), format: request_format(:create)
34
34
  end
35
35
 
36
- it 'response with 200 status code' do
37
- expect(response).to have_http_status(:created)
36
+ if check_html(:create)
37
+ it 'redirects to the created record' do
38
+ expect(response).to have_http_status(:found)
39
+ end
40
+ else
41
+ it 'response with 201 status code' do
42
+ expect(response).to have_http_status(:created)
43
+ end
44
+
45
+ it 'creates an article with valid attributes' do
46
+ expect(model_class_object.last).to have_attributes(create_params)
47
+ end
38
48
  end
39
49
 
40
- it 'creates an article' do
50
+ it 'creates the record', :aggregate_failures do
41
51
  expect(model_class_object.count).to be 1
52
+ instance_exec(model_class_object.last, &created_record_check) if created_record_check
42
53
  end
54
+ end
55
+
56
+ unless check_raise_on_invalid(:create)
57
+ context 'when creating with invalid attributes' do
58
+ include_context 'with authenticated user' if check_authenticate(:create)
59
+
60
+ before do
61
+ post :create, params: with_route_params(body_params(owner_params)), format: request_format(:create)
62
+ end
43
63
 
44
- it 'creates an article with valid attributes' do
45
- expect(model_class_object.last).to have_attributes(create_params)
64
+ unless check_block(:create)
65
+ if check_html(:create)
66
+ include_examples 'simple crud renders template', :new, -> { invalid_status }
67
+ else
68
+ it 'responds with unprocessable entity' do
69
+ expect(response).to have_http_status(unprocessable_status)
70
+ end
71
+
72
+ it 'returns the validation errors' do
73
+ expect(response_body['errors']).to include(required_error)
74
+ end
75
+ end
76
+ end
77
+
78
+ it 'does not create a model' do
79
+ expect(model_class_object.count).to be 0
80
+ end
46
81
  end
47
82
  end
48
83
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for create with block' do
4
+ describe 'POST #create with a render block' do
5
+ context 'when successfully creating a record' do
6
+ include_context 'with authenticated user' if check_authenticate(:create)
7
+ let(:create_params) { model_params.merge(owner_params) }
8
+
9
+ before do
10
+ post :create, params: with_route_params(body_params(create_params)), format: request_format(:create)
11
+ end
12
+
13
+ it 'passes the saved record to the block' do
14
+ expect(response).to be_successful
15
+ end
16
+
17
+ it 'creates the record' do
18
+ expect(model_class_object.count).to be 1
19
+ end
20
+ end
21
+
22
+ unless check_raise_on_invalid(:create)
23
+ context 'when creating with invalid attributes' do
24
+ include_context 'with authenticated user' if check_authenticate(:create)
25
+
26
+ before do
27
+ post :create, params: with_route_params(body_params(owner_params)), format: request_format(:create)
28
+ end
29
+
30
+ it 'does not create a model' do
31
+ expect(model_class_object.count).to be 0
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for create with build' do
4
+ describe 'POST #create with a build hook' do
5
+ include_context 'with authenticated user' if check_authenticate(:create)
6
+
7
+ before do
8
+ post :create, params: with_route_params(body_params(params_for(model_class))), format: request_format(:create)
9
+ end
10
+
11
+ it 'creates the record owned by the current user' do
12
+ expect(model_class_object.last.public_send(owner_association)).to eq(current_user)
13
+ end
14
+ end
15
+ end
@@ -3,7 +3,10 @@
3
3
  shared_examples 'simple crud for destroy' do
4
4
  describe 'DELETE #destroy' do
5
5
  context 'without authenticated user' do
6
- subject!(:req) { delete :destroy, params: { id: 1 } }
6
+ subject!(:req) do
7
+ delete :destroy, params: with_route_params(record_param(:destroy, nil, not_found: true)),
8
+ format: request_format(:destroy)
9
+ end
7
10
 
8
11
  include_examples 'unauthorized when not logged in' if check_authenticate(:destroy)
9
12
  end
@@ -14,7 +17,7 @@ shared_examples 'simple crud for destroy' do
14
17
 
15
18
  before do
16
19
  make_policies_fail(:destroy)
17
- delete :destroy, params: { id: model.id }
20
+ delete :destroy, params: with_route_params(record_param(:destroy, model)), format: request_format(:destroy)
18
21
  end
19
22
 
20
23
  it 'fails with forbidden' do
@@ -28,11 +31,43 @@ shared_examples 'simple crud for destroy' do
28
31
 
29
32
  before do
30
33
  model
31
- delete :destroy, params: { id: model.id }
34
+ delete :destroy, params: with_route_params(record_param(:destroy, model)), format: request_format(:destroy)
32
35
  end
33
36
 
34
- it 'response with 200 status code' do
35
- expect(response).to have_http_status(:ok)
37
+ if check_html(:destroy)
38
+ it 'redirects to the collection and destroys the record', :aggregate_failures do
39
+ expect(response).to have_http_status(:found)
40
+ expect(model_class_object.exists?(model.id)).to be false
41
+ end
42
+ else
43
+ it 'response with 200 status code' do
44
+ expect(response).to have_http_status(:ok)
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'when destroying fails' do
50
+ include_context 'with authenticated user' if check_authenticate(:destroy)
51
+
52
+ before do
53
+ model
54
+ allow(model).to receive(:destroy).and_return(false)
55
+ allow(SimpleCrudController).to receive(:find_record).and_return(model)
56
+ delete :destroy, params: with_route_params(record_param(:destroy, model)), format: request_format(:destroy)
57
+ end
58
+
59
+ it 'keeps the record' do
60
+ expect(model_class_object.exists?(model.id)).to be true
61
+ end
62
+
63
+ unless check_block(:destroy) || check_raise_on_invalid(:destroy)
64
+ if check_html(:destroy)
65
+ include_examples 'simple crud renders template', :show
66
+ else
67
+ it 'responds with unprocessable entity' do
68
+ expect(response).to have_http_status(unprocessable_status)
69
+ end
70
+ end
36
71
  end
37
72
  end
38
73
 
@@ -41,7 +76,8 @@ shared_examples 'simple crud for destroy' do
41
76
 
42
77
  before do
43
78
  model
44
- delete :destroy, params: { id: model.id + 13 }
79
+ delete :destroy, params: with_route_params(record_param(:destroy, nil, not_found: true)),
80
+ format: request_format(:destroy)
45
81
  end
46
82
 
47
83
  it 'responds with not found status' do
@@ -56,10 +92,10 @@ shared_examples 'simple crud for destroy' do
56
92
  before do
57
93
  model
58
94
  make_policies_fail(:destroy)
59
- delete :destroy, params: { id: model.id }
95
+ delete :destroy, params: with_route_params(record_param(:destroy, model)), format: request_format(:destroy)
60
96
  end
61
97
 
62
- it 'response with 200 status code' do
98
+ it 'responds with forbidden status' do
63
99
  expect(response).to have_http_status(:forbidden)
64
100
  end
65
101
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for destroy with block' do
4
+ describe 'DELETE #destroy with a render block' do
5
+ include_context 'with authenticated user' if check_authenticate(:destroy)
6
+
7
+ let!(:record) { model }
8
+
9
+ before do
10
+ delete :destroy, params: with_route_params(record_param(:destroy, record)), format: request_format(:destroy)
11
+ end
12
+
13
+ it 'passes the destroyed record to the block' do
14
+ expect(response).to be_successful
15
+ end
16
+
17
+ it 'destroys the record' do
18
+ expect(model_class_object.exists?(record.id)).to be false
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for destroy with finder' do
4
+ describe 'DELETE #destroy with a custom finder' do
5
+ include_context 'with authenticated user' if check_authenticate(:destroy)
6
+
7
+ context 'when the model exists' do
8
+ before do
9
+ model
10
+ delete :destroy, params: with_route_params(finder_key => model.public_send(finder_key)),
11
+ format: request_format(:destroy)
12
+ end
13
+
14
+ it 'destroys the model' do
15
+ expect(model_class_object.exists?(model.id)).to be false
16
+ end
17
+
18
+ if check_block(:destroy)
19
+ it 'passes the destroyed record to the block' do
20
+ expect(rendered_record.id).to eq(model.id)
21
+ end
22
+ elsif check_html(:destroy)
23
+ it 'redirects to the collection' do
24
+ expect(response).to have_http_status(:found)
25
+ end
26
+ else
27
+ it 'responds with ok status' do
28
+ expect(response).to have_http_status(:ok)
29
+ end
30
+ end
31
+ end
32
+
33
+ include_examples 'simple crud not found with finder', :delete, :destroy
34
+ end
35
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for edit' do
4
+ describe 'GET #edit' do
5
+ subject(:edit_request) { get :edit, params: with_route_params(edit_params), format: request_format(:edit) }
6
+
7
+ before do
8
+ model
9
+ end
10
+
11
+ context 'without authenticated user' do
12
+ subject!(:req) do
13
+ get :edit, params: with_route_params(record_param(:edit, model)), format: request_format(:edit)
14
+ end
15
+
16
+ include_examples 'unauthorized when not logged in' if check_authenticate(:edit)
17
+ end
18
+
19
+ if check_authorize(:edit)
20
+ context 'when the user is not authorized' do
21
+ include_context 'with authenticated user' if check_authenticate(:edit)
22
+
23
+ let(:edit_params) { record_param(:edit, model) }
24
+
25
+ before do
26
+ model
27
+ make_policies_fail(:edit)
28
+ edit_request
29
+ end
30
+
31
+ it 'responds with forbidden status' do
32
+ expect(response).to have_http_status(:forbidden)
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'when the model exists' do
38
+ include_context 'with authenticated user' if check_authenticate(:edit)
39
+
40
+ let(:edit_params) { record_param(:edit, model) }
41
+
42
+ before do
43
+ model
44
+ make_policies_succeed(:edit) if check_authorize(:edit)
45
+ edit_request
46
+ end
47
+
48
+ it 'responds with ok status' do
49
+ expect(response).to have_http_status(:ok)
50
+ end
51
+
52
+ if check_block(:edit)
53
+ it 'renders the asked model through the block' do
54
+ expect(response).to be_successful
55
+ end
56
+ elsif check_html(:edit)
57
+ include_examples 'simple crud renders template', :edit
58
+ else
59
+ it 'returns the asked model' do
60
+ expect(response_body['id']).to eq(model.id)
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when the model does not exist' do
66
+ include_context 'with authenticated user'
67
+
68
+ let(:edit_params) { record_param(:edit, nil, not_found: true) }
69
+
70
+ before do
71
+ edit_request
72
+ end
73
+
74
+ it 'responds with not found status' do
75
+ expect(response).to have_http_status(:not_found)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -2,39 +2,24 @@
2
2
 
3
3
  shared_examples 'simple crud for index' do
4
4
  describe 'GET #index' do
5
- let(:created_models) { create_list(model_class, 10) }
5
+ let(:created_models) { create_records(model_class, 10, model_attributes) }
6
6
 
7
7
  before { created_models }
8
8
 
9
- context 'without authenticated user' do
10
- subject!(:req) { get :index }
11
-
12
- include_examples 'unauthorized when not logged in' if check_authenticate(:index)
13
- end
14
-
15
- if check_authorize(:index)
16
- context 'when not authorized' do
17
- include_context 'with authenticated user' if check_authenticate(:index)
18
-
19
- before do
20
- make_policies_fail(:index)
21
- get :index
22
- end
23
-
24
- it 'fails with forbidden' do
25
- expect(response).to have_http_status(:forbidden)
26
- end
27
- end
28
- end
9
+ include_examples 'simple crud without authenticated user', :index
10
+ include_examples 'simple crud when not authorized', :index, :get
29
11
 
30
12
  context 'with authenticated user' do
31
13
  include_context 'with authenticated user' if check_authenticate(:index)
14
+
32
15
  before do
33
- make_policies_succeed(:index)
34
- get :index
16
+ make_policies_succeed(:index) if check_authorize(:index)
17
+ get :index, params: with_route_params({}), format: request_format(:index)
35
18
  end
36
19
 
37
- if check_paginate(:index)
20
+ if check_html(:index)
21
+ include_examples 'simple crud renders template', :index
22
+ elsif check_paginate(:index)
38
23
  it 'renders paginated models correctly serialized' do
39
24
  expect(response_body['page']).to have_been_serialized_with(model_serializer)
40
25
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for index with block' do
4
+ describe 'GET #index with a render block' do
5
+ let(:created_models) { create_records(model_class, 2, model_attributes) }
6
+
7
+ include_context 'with authenticated user' if check_authenticate(:index)
8
+
9
+ before do
10
+ created_models
11
+ get :index, params: with_route_params({}), format: request_format(:index)
12
+ end
13
+
14
+ if check_html(:index)
15
+ include_examples 'simple crud renders template', :index
16
+ else
17
+ it 'renders the records through the block' do
18
+ expect(response).to be_successful
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for index with scope' do
4
+ let(:request_params) { {} }
5
+ let(:my_models) { create_records(model_class, 2, scoped_attributes) }
6
+ let(:other_models) { create_records(model_class, 3, other_scoped_attributes) }
7
+
8
+ # Hooks stay inside this context so co-including the example never
9
+ # authenticates or stubs policies for sibling examples.
10
+ context 'when listing the scoped records' do
11
+ before do
12
+ authenticate_request if check_authenticate(:index)
13
+ make_policies_succeed(:index) if check_authorize(:index)
14
+ my_models
15
+ other_models
16
+ get :index, params: with_route_params(request_params), format: request_format(:index)
17
+ end
18
+
19
+ if check_html(:index)
20
+ it 'returns only the assigned scoped records' do
21
+ expect(rendered_records.map(&:id)).to match_array(my_models.map(&:id))
22
+ end
23
+ elsif check_paginate(:index)
24
+ it 'returns only the paginated scoped records' do
25
+ expect(response_body['page'].map { |m| m['id'] }).to match_array(my_models.map(&:id))
26
+ end
27
+ else
28
+ it 'returns only the unpaginated scoped records' do
29
+ expect(response_body.map { |m| m['id'] }).to match_array(my_models.map(&:id))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for new' do
4
+ describe 'GET #new' do
5
+ include_examples 'simple crud without authenticated user', :new
6
+ include_examples 'simple crud when not authorized', :new, :get
7
+
8
+ context 'when building a new record' do
9
+ include_context 'with authenticated user' if check_authenticate(:new)
10
+
11
+ before do
12
+ make_policies_succeed(:new) if check_authorize(:new)
13
+ get :new, params: with_route_params({}), format: request_format(:new)
14
+ end
15
+
16
+ it 'responds with ok status' do
17
+ expect(response).to have_http_status(:ok)
18
+ end
19
+
20
+ if check_html(:new)
21
+ include_examples 'simple crud renders template', :new
22
+ else
23
+ it 'returns a blank record as json' do
24
+ expect(response_body['id']).to be_nil
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for new with block' do
4
+ describe 'GET #new with a render block' do
5
+ include_context 'with authenticated user' if check_authenticate(:new)
6
+
7
+ before do
8
+ make_policies_succeed(:new) if check_authorize(:new)
9
+ get :new, params: with_route_params({}), format: request_format(:new)
10
+ end
11
+
12
+ if check_html(:new)
13
+ include_examples 'simple crud renders template', :new
14
+ else
15
+ it 'renders the built record through the block' do
16
+ expect(response).to be_successful
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for new with build' do
4
+ describe 'GET #new with a build hook' do
5
+ include_context 'with authenticated user' if check_authenticate(:new)
6
+
7
+ before do
8
+ get :new, params: with_route_params({}), format: request_format(:new)
9
+ end
10
+
11
+ it 'builds the record owned by the current user', :aggregate_failures do
12
+ if check_html(:new) || check_block(:new)
13
+ expect(rendered_record.public_send(owner_foreign_key)).to eq(current_user.id)
14
+ else
15
+ expect(response_body[owner_foreign_key.to_s]).to eq(current_user.id)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,21 +2,21 @@
2
2
 
3
3
  shared_examples 'simple crud for show' do
4
4
  describe 'GET #show' do
5
- subject(:show_request) { get :show, params: show_params }
5
+ subject(:show_request) { get :show, params: with_route_params(show_params), format: request_format(:show) }
6
6
 
7
7
  before do
8
8
  model
9
9
  end
10
10
 
11
11
  context 'without authenticated user' do
12
- subject!(:req) { get :show, params: { id: model.id } }
12
+ subject!(:req) { get :show, params: with_route_params(record_param(:show, model)), format: request_format(:show) }
13
13
 
14
- include_examples 'unauthorized when not logged in'
14
+ include_examples 'unauthorized when not logged in' if check_authenticate(:show)
15
15
  end
16
16
 
17
17
  describe 'when the model exists' do
18
18
  include_context 'with authenticated user'
19
- let(:show_params) { { id: model.id } }
19
+ let(:show_params) { record_param(:show, model) }
20
20
 
21
21
  before do
22
22
  show_request
@@ -26,18 +26,22 @@ shared_examples 'simple crud for show' do
26
26
  expect(response).to have_http_status(:ok)
27
27
  end
28
28
 
29
- it 'returns the asked model' do
30
- expect(response_body['id']).to eq(model.id)
31
- end
29
+ if check_html(:show)
30
+ include_examples 'simple crud renders template', :show
31
+ else
32
+ it 'returns the asked model' do
33
+ expect(response_body['id']).to eq(model.id)
34
+ end
32
35
 
33
- it 'have been serializer with model Serializer' do
34
- expect(response_body).to have_been_serialized_with(model_serializer)
36
+ it 'have been serializer with model Serializer' do
37
+ expect(response_body).to have_been_serialized_with(model_serializer)
38
+ end
35
39
  end
36
40
  end
37
41
 
38
42
  describe 'when the model does not exist' do
39
43
  include_context 'with authenticated user'
40
- let(:show_params) { { id: -1 } }
44
+ let(:show_params) { record_param(:show, nil, not_found: true) }
41
45
 
42
46
  before do
43
47
  show_request
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for show with block' do
4
+ describe 'GET #show with a render block' do
5
+ include_context 'with authenticated user' if check_authenticate(:show)
6
+
7
+ let!(:record) { model }
8
+
9
+ before do
10
+ make_policies_succeed(:show) if check_authorize(:show)
11
+ get :show, params: with_route_params(record_param(:show, record)), format: request_format(:show)
12
+ end
13
+
14
+ if check_html(:show)
15
+ include_examples 'simple crud renders template', :show
16
+ else
17
+ it 'renders the record through the block' do
18
+ expect(response).to be_successful
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'simple crud for show with finder' do
4
+ describe 'GET #show with a custom finder' do
5
+ include_context 'with authenticated user' if check_authenticate(:show)
6
+
7
+ context 'when the model exists' do
8
+ before do
9
+ model
10
+ get :show, params: with_route_params(finder_key => model.public_send(finder_key)),
11
+ format: request_format(:show)
12
+ end
13
+
14
+ if check_block(:show)
15
+ it 'finds the asked model' do
16
+ expect(rendered_record.id).to eq(model.id)
17
+ end
18
+ elsif check_html(:show)
19
+ include_examples 'simple crud renders template', :show
20
+ else
21
+ it 'responds with ok status' do
22
+ expect(response).to have_http_status(:ok)
23
+ end
24
+
25
+ it 'returns the asked model' do
26
+ expect(response_body['id']).to eq(model.id)
27
+ end
28
+ end
29
+ end
30
+
31
+ include_examples 'simple crud not found with finder', :get, :show
32
+ end
33
+ end