pundit 2.5.0 → 2.5.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +1 -1
  4. data/lib/pundit/authorization.rb +18 -0
  5. data/lib/pundit/cache_store/legacy_store.rb +3 -0
  6. data/lib/pundit/cache_store/null_store.rb +3 -0
  7. data/lib/pundit/cache_store.rb +2 -0
  8. data/lib/pundit/context.rb +13 -0
  9. data/lib/pundit/error.rb +71 -0
  10. data/lib/pundit/helper.rb +16 -0
  11. data/lib/pundit/policy_finder.rb +11 -0
  12. data/lib/pundit/railtie.rb +1 -0
  13. data/lib/pundit/rspec.rb +2 -0
  14. data/lib/pundit/version.rb +1 -1
  15. data/lib/pundit.rb +10 -69
  16. metadata +4 -68
  17. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -20
  18. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  19. data/.github/PULL_REQUEST_TEMPLATE/gem_release_template.md +0 -8
  20. data/.github/pull_request_template.md +0 -9
  21. data/.github/workflows/main.yml +0 -147
  22. data/.github/workflows/push_gem.yml +0 -33
  23. data/.gitignore +0 -19
  24. data/.rubocop.yml +0 -73
  25. data/.rubocop_ignore_git.yml +0 -7
  26. data/.yardopts +0 -1
  27. data/CODE_OF_CONDUCT.md +0 -28
  28. data/CONTRIBUTING.md +0 -31
  29. data/Gemfile +0 -28
  30. data/Rakefile +0 -21
  31. data/config/rubocop-rspec.yml +0 -5
  32. data/pundit.gemspec +0 -31
  33. data/spec/authorization_spec.rb +0 -331
  34. data/spec/generators_spec.rb +0 -43
  35. data/spec/policies/post_policy_spec.rb +0 -49
  36. data/spec/policy_finder_spec.rb +0 -191
  37. data/spec/pundit/helper_spec.rb +0 -18
  38. data/spec/pundit_spec.rb +0 -474
  39. data/spec/rspec_dsl_spec.rb +0 -81
  40. data/spec/simple_cov_check_action_formatter.rb +0 -79
  41. data/spec/spec_helper.rb +0 -35
  42. data/spec/support/lib/controller.rb +0 -38
  43. data/spec/support/lib/custom_cache.rb +0 -19
  44. data/spec/support/lib/instance_tracking.rb +0 -20
  45. data/spec/support/models/article.rb +0 -4
  46. data/spec/support/models/article_tag.rb +0 -7
  47. data/spec/support/models/artificial_blog.rb +0 -7
  48. data/spec/support/models/blog.rb +0 -4
  49. data/spec/support/models/comment.rb +0 -5
  50. data/spec/support/models/comment_four_five_six.rb +0 -5
  51. data/spec/support/models/comment_scope.rb +0 -13
  52. data/spec/support/models/comments_relation.rb +0 -15
  53. data/spec/support/models/customer/post.rb +0 -11
  54. data/spec/support/models/default_scope_contains_error.rb +0 -5
  55. data/spec/support/models/dummy_current_user.rb +0 -7
  56. data/spec/support/models/foo.rb +0 -4
  57. data/spec/support/models/post.rb +0 -25
  58. data/spec/support/models/post_four_five_six.rb +0 -9
  59. data/spec/support/models/project_one_two_three/avatar_four_five_six.rb +0 -7
  60. data/spec/support/models/project_one_two_three/tag_four_five_six.rb +0 -11
  61. data/spec/support/models/wiki.rb +0 -4
  62. data/spec/support/policies/article_tag_other_name_policy.rb +0 -13
  63. data/spec/support/policies/base_policy.rb +0 -23
  64. data/spec/support/policies/blog_policy.rb +0 -5
  65. data/spec/support/policies/comment_policy.rb +0 -11
  66. data/spec/support/policies/criteria_policy.rb +0 -5
  67. data/spec/support/policies/default_scope_contains_error_policy.rb +0 -10
  68. data/spec/support/policies/denier_policy.rb +0 -7
  69. data/spec/support/policies/dummy_current_user_policy.rb +0 -9
  70. data/spec/support/policies/nil_class_policy.rb +0 -17
  71. data/spec/support/policies/post_policy.rb +0 -36
  72. data/spec/support/policies/project/admin/comment_policy.rb +0 -15
  73. data/spec/support/policies/project/comment_policy.rb +0 -17
  74. data/spec/support/policies/project/criteria_policy.rb +0 -7
  75. data/spec/support/policies/project/post_policy.rb +0 -13
  76. data/spec/support/policies/project_one_two_three/avatar_four_five_six_policy.rb +0 -6
  77. data/spec/support/policies/project_one_two_three/comment_four_five_six_policy.rb +0 -6
  78. data/spec/support/policies/project_one_two_three/criteria_four_five_six_policy.rb +0 -6
  79. data/spec/support/policies/project_one_two_three/post_four_five_six_policy.rb +0 -6
  80. data/spec/support/policies/project_one_two_three/tag_four_five_six_policy.rb +0 -6
  81. data/spec/support/policies/publication_policy.rb +0 -13
  82. data/spec/support/policies/wiki_policy.rb +0 -8
data/spec/pundit_spec.rb DELETED
@@ -1,474 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Pundit do
6
- let(:user) { double }
7
- let(:post) { Post.new(user) }
8
- let(:customer_post) { Customer::Post.new(user) }
9
- let(:post_four_five_six) { PostFourFiveSix.new(user) }
10
- let(:comment) { Comment.new }
11
- let(:comment_four_five_six) { CommentFourFiveSix.new }
12
- let(:article) { Article.new }
13
- let(:artificial_blog) { ArtificialBlog.new }
14
- let(:article_tag) { ArticleTag.new }
15
- let(:comments_relation) { CommentsRelation.new(empty: false) }
16
- let(:empty_comments_relation) { CommentsRelation.new(empty: true) }
17
- let(:tag_four_five_six) { ProjectOneTwoThree::TagFourFiveSix.new(user) }
18
- let(:avatar_four_five_six) { ProjectOneTwoThree::AvatarFourFiveSix.new }
19
- let(:wiki) { Wiki.new }
20
-
21
- describe ".authorize" do
22
- it "infers the policy and authorizes based on it" do
23
- expect(Pundit.authorize(user, post, :update?)).to be_truthy
24
- end
25
-
26
- it "returns the record on successful authorization" do
27
- expect(Pundit.authorize(user, post, :update?)).to eq(post)
28
- end
29
-
30
- it "returns the record when passed record with namespace " do
31
- expect(Pundit.authorize(user, [:project, comment], :update?)).to eq(comment)
32
- end
33
-
34
- it "returns the record when passed record with nested namespace " do
35
- expect(Pundit.authorize(user, [:project, :admin, comment], :update?)).to eq(comment)
36
- end
37
-
38
- it "returns the policy name symbol when passed record with headless policy" do
39
- expect(Pundit.authorize(user, :publication, :create?)).to eq(:publication)
40
- end
41
-
42
- it "returns the class when passed record not a particular instance" do
43
- expect(Pundit.authorize(user, Post, :show?)).to eq(Post)
44
- end
45
-
46
- it "works with anonymous class policies" do
47
- expect(Pundit.authorize(user, article_tag, :show?)).to be_truthy
48
- expect { Pundit.authorize(user, article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)
49
- end
50
-
51
- it "raises an error with the policy, query and record" do
52
- # rubocop:disable Style/MultilineBlockChain
53
- expect do
54
- Pundit.authorize(user, post, :destroy?)
55
- end.to raise_error(Pundit::NotAuthorizedError, "not allowed to PostPolicy#destroy? this Post") do |error|
56
- expect(error.query).to eq :destroy?
57
- expect(error.record).to eq post
58
- expect(error.policy).to have_attributes(
59
- user: user,
60
- record: post
61
- )
62
- expect(error.policy).to be_a(PostPolicy)
63
- end
64
- # rubocop:enable Style/MultilineBlockChain
65
- end
66
-
67
- it "raises an error with the policy, query and record when the record is namespaced" do
68
- # rubocop:disable Style/MultilineBlockChain
69
- expect do
70
- Pundit.authorize(user, [:project, :admin, comment], :destroy?)
71
- end.to raise_error(Pundit::NotAuthorizedError,
72
- "not allowed to Project::Admin::CommentPolicy#destroy? this Comment") do |error|
73
- expect(error.query).to eq :destroy?
74
- expect(error.record).to eq comment
75
- expect(error.policy).to have_attributes(
76
- user: user,
77
- record: comment
78
- )
79
- expect(error.policy).to be_a(Project::Admin::CommentPolicy)
80
- end
81
- # rubocop:enable Style/MultilineBlockChain
82
- end
83
-
84
- it "raises an error with the policy, query and the class name when a Class is given" do
85
- # rubocop:disable Style/MultilineBlockChain
86
- expect do
87
- Pundit.authorize(user, Post, :destroy?)
88
- end.to raise_error(Pundit::NotAuthorizedError, "not allowed to PostPolicy#destroy? Post") do |error|
89
- expect(error.query).to eq :destroy?
90
- expect(error.record).to eq Post
91
- expect(error.policy).to have_attributes(
92
- user: user,
93
- record: Post
94
- )
95
- expect(error.policy).to be_a(PostPolicy)
96
- end
97
- # rubocop:enable Style/MultilineBlockChain
98
- end
99
-
100
- it "raises an error with a invalid policy constructor" do
101
- expect do
102
- Pundit.authorize(user, wiki, :update?)
103
- end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
104
- end
105
-
106
- context "when passed a policy class" do
107
- it "uses the passed policy class" do
108
- expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy
109
- end
110
-
111
- # This is documenting past behaviour.
112
- it "doesn't cache the policy class" do
113
- cache = {}
114
-
115
- expect do
116
- Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)
117
- Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)
118
- end.to change { PublicationPolicy.instances }.by(2)
119
- end
120
- end
121
-
122
- context "when passed a policy class while simultaenously passing a namespace" do
123
- it "uses the passed policy class" do
124
- expect(PublicationPolicy).to receive(:new).with(user, comment).and_call_original
125
- expect(Pundit.authorize(user, [:project, comment], :create?, policy_class: PublicationPolicy)).to be_truthy
126
- end
127
- end
128
-
129
- context "when passed an explicit cache" do
130
- it "uses the hash assignment interface on the cache" do
131
- custom_cache = CustomCache.new
132
-
133
- Pundit.authorize(user, post, :update?, cache: custom_cache)
134
-
135
- expect(custom_cache.to_h).to match({
136
- post => kind_of(PostPolicy)
137
- })
138
- end
139
- end
140
- end
141
-
142
- describe ".policy_scope" do
143
- it "returns an instantiated policy scope given a plain model class" do
144
- expect(Pundit.policy_scope(user, Post)).to eq :published
145
- end
146
-
147
- it "returns an instantiated policy scope given an active model class" do
148
- expect(Pundit.policy_scope(user, Comment)).to eq CommentScope.new(Comment)
149
- end
150
-
151
- it "returns an instantiated policy scope given an active record relation" do
152
- expect(Pundit.policy_scope(user, comments_relation)).to eq CommentScope.new(comments_relation)
153
- end
154
-
155
- it "returns an instantiated policy scope given an empty active record relation" do
156
- expect(Pundit.policy_scope(user, empty_comments_relation)).to eq CommentScope.new(empty_comments_relation)
157
- end
158
-
159
- it "returns an instantiated policy scope given an array of a symbol and plain model class" do
160
- expect(Pundit.policy_scope(user, [:project, Post])).to eq :read
161
- end
162
-
163
- it "returns an instantiated policy scope given an array of a symbol and active model class" do
164
- expect(Pundit.policy_scope(user, [:project, Comment])).to eq Comment
165
- end
166
-
167
- it "returns nil if the given policy scope can't be found" do
168
- expect(Pundit.policy_scope(user, Article)).to be_nil
169
- end
170
-
171
- it "raises an exception if nil object given" do
172
- expect { Pundit.policy_scope(user, nil) }.to raise_error(Pundit::NotDefinedError)
173
- end
174
-
175
- it "raises an error with a invalid policy scope constructor" do
176
- expect do
177
- Pundit.policy_scope(user, Wiki)
178
- end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy::Scope> constructor is called")
179
- end
180
-
181
- it "raises an original error with a policy scope that contains error" do
182
- expect do
183
- Pundit.policy_scope(user, DefaultScopeContainsError)
184
- end.to raise_error(RuntimeError, "This is an arbitrary error that should bubble up")
185
- end
186
- end
187
-
188
- describe ".policy_scope!" do
189
- it "returns an instantiated policy scope given a plain model class" do
190
- expect(Pundit.policy_scope!(user, Post)).to eq :published
191
- end
192
-
193
- it "returns an instantiated policy scope given an active model class" do
194
- expect(Pundit.policy_scope!(user, Comment)).to eq CommentScope.new(Comment)
195
- end
196
-
197
- it "throws an exception if the given policy scope can't be found" do
198
- expect { Pundit.policy_scope!(user, Article) }.to raise_error(Pundit::NotDefinedError)
199
- end
200
-
201
- it "throws an exception if the given policy scope can't be found" do
202
- expect { Pundit.policy_scope!(user, ArticleTag) }.to raise_error(Pundit::NotDefinedError)
203
- end
204
-
205
- it "throws an exception if the given policy scope is nil" do
206
- expect do
207
- Pundit.policy_scope!(user, nil)
208
- end.to raise_error(Pundit::NotDefinedError, "Cannot scope NilClass")
209
- end
210
-
211
- it "returns an instantiated policy scope given an array of a symbol and plain model class" do
212
- expect(Pundit.policy_scope!(user, [:project, Post])).to eq :read
213
- end
214
-
215
- it "returns an instantiated policy scope given an array of a symbol and active model class" do
216
- expect(Pundit.policy_scope!(user, [:project, Comment])).to eq Comment
217
- end
218
-
219
- it "raises an error with a invalid policy scope constructor" do
220
- expect do
221
- Pundit.policy_scope(user, Wiki)
222
- end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy::Scope> constructor is called")
223
- end
224
- end
225
-
226
- describe ".policy" do
227
- it "returns an instantiated policy given a plain model instance" do
228
- policy = Pundit.policy(user, post)
229
- expect(policy.user).to eq user
230
- expect(policy.post).to eq post
231
- end
232
-
233
- it "returns an instantiated policy given an active model instance" do
234
- policy = Pundit.policy(user, comment)
235
- expect(policy.user).to eq user
236
- expect(policy.comment).to eq comment
237
- end
238
-
239
- it "returns an instantiated policy given a plain model class" do
240
- policy = Pundit.policy(user, Post)
241
- expect(policy.user).to eq user
242
- expect(policy.post).to eq Post
243
- end
244
-
245
- it "returns an instantiated policy given an active model class" do
246
- policy = Pundit.policy(user, Comment)
247
- expect(policy.user).to eq user
248
- expect(policy.comment).to eq Comment
249
- end
250
-
251
- it "returns an instantiated policy given a symbol" do
252
- policy = Pundit.policy(user, :criteria)
253
- expect(policy.class).to eq CriteriaPolicy
254
- expect(policy.user).to eq user
255
- expect(policy.criteria).to eq :criteria
256
- end
257
-
258
- it "returns an instantiated policy given an array of symbols" do
259
- policy = Pundit.policy(user, %i[project criteria])
260
- expect(policy.class).to eq Project::CriteriaPolicy
261
- expect(policy.user).to eq user
262
- expect(policy.criteria).to eq :criteria
263
- end
264
-
265
- it "returns an instantiated policy given an array of a symbol and plain model instance" do
266
- policy = Pundit.policy(user, [:project, post])
267
- expect(policy.class).to eq Project::PostPolicy
268
- expect(policy.user).to eq user
269
- expect(policy.post).to eq post
270
- end
271
-
272
- it "returns an instantiated policy given an array of a symbol and a model instance with policy_class override" do
273
- policy = Pundit.policy(user, [:project, customer_post])
274
- expect(policy.class).to eq Project::PostPolicy
275
- expect(policy.user).to eq user
276
- expect(policy.post).to eq customer_post
277
- end
278
-
279
- it "returns an instantiated policy given an array of a symbol and an active model instance" do
280
- policy = Pundit.policy(user, [:project, comment])
281
- expect(policy.class).to eq Project::CommentPolicy
282
- expect(policy.user).to eq user
283
- expect(policy.comment).to eq comment
284
- end
285
-
286
- it "returns an instantiated policy given an array of a symbol and a plain model class" do
287
- policy = Pundit.policy(user, [:project, Post])
288
- expect(policy.class).to eq Project::PostPolicy
289
- expect(policy.user).to eq user
290
- expect(policy.post).to eq Post
291
- end
292
-
293
- it "raises an error with a invalid policy constructor" do
294
- expect do
295
- Pundit.policy(user, Wiki)
296
- end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
297
- end
298
-
299
- it "returns an instantiated policy given an array of a symbol and an active model class" do
300
- policy = Pundit.policy(user, [:project, Comment])
301
- expect(policy.class).to eq Project::CommentPolicy
302
- expect(policy.user).to eq user
303
- expect(policy.comment).to eq Comment
304
- end
305
-
306
- it "returns an instantiated policy given an array of a symbol and a class with policy_class override" do
307
- policy = Pundit.policy(user, [:project, Customer::Post])
308
- expect(policy.class).to eq Project::PostPolicy
309
- expect(policy.user).to eq user
310
- expect(policy.post).to eq Customer::Post
311
- end
312
-
313
- it "returns correct policy class for an array of a multi-word symbols" do
314
- policy = Pundit.policy(user, %i[project_one_two_three criteria_four_five_six])
315
- expect(policy.class).to eq ProjectOneTwoThree::CriteriaFourFiveSixPolicy
316
- end
317
-
318
- it "returns correct policy class for an array of a multi-word symbol and a multi-word plain model instance" do
319
- policy = Pundit.policy(user, [:project_one_two_three, post_four_five_six])
320
- expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy
321
- end
322
-
323
- it "returns correct policy class for an array of a multi-word symbol and a multi-word active model instance" do
324
- policy = Pundit.policy(user, [:project_one_two_three, comment_four_five_six])
325
- expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy
326
- end
327
-
328
- it "returns correct policy class for an array of a multi-word symbol and a multi-word plain model class" do
329
- policy = Pundit.policy(user, [:project_one_two_three, PostFourFiveSix])
330
- expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy
331
- end
332
-
333
- it "returns correct policy class for an array of a multi-word symbol and a multi-word active model class" do
334
- policy = Pundit.policy(user, [:project_one_two_three, CommentFourFiveSix])
335
- expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy
336
- end
337
-
338
- it "returns correct policy class for a multi-word scoped plain model class" do
339
- policy = Pundit.policy(user, ProjectOneTwoThree::TagFourFiveSix)
340
- expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy
341
- end
342
-
343
- it "returns correct policy class for a multi-word scoped plain model instance" do
344
- policy = Pundit.policy(user, tag_four_five_six)
345
- expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy
346
- end
347
-
348
- it "returns correct policy class for a multi-word scoped active model class" do
349
- policy = Pundit.policy(user, ProjectOneTwoThree::AvatarFourFiveSix)
350
- expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy
351
- end
352
-
353
- it "returns correct policy class for a multi-word scoped active model instance" do
354
- policy = Pundit.policy(user, avatar_four_five_six)
355
- expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy
356
- end
357
-
358
- it "returns nil if the given policy can't be found" do
359
- expect(Pundit.policy(user, article)).to be_nil
360
- expect(Pundit.policy(user, Article)).to be_nil
361
- end
362
-
363
- it "returns the specified NilClassPolicy for nil" do
364
- expect(Pundit.policy(user, nil)).to be_a NilClassPolicy
365
- end
366
-
367
- describe "with .policy_class set on the model" do
368
- it "returns an instantiated policy given a plain model instance" do
369
- policy = Pundit.policy(user, artificial_blog)
370
- expect(policy.user).to eq user
371
- expect(policy.blog).to eq artificial_blog
372
- end
373
-
374
- it "returns an instantiated policy given a plain model class" do
375
- policy = Pundit.policy(user, ArtificialBlog)
376
- expect(policy.user).to eq user
377
- expect(policy.blog).to eq ArtificialBlog
378
- end
379
-
380
- it "returns an instantiated policy given a plain model instance providing an anonymous class" do
381
- policy = Pundit.policy(user, article_tag)
382
- expect(policy.user).to eq user
383
- expect(policy.tag).to eq article_tag
384
- end
385
-
386
- it "returns an instantiated policy given a plain model class providing an anonymous class" do
387
- policy = Pundit.policy(user, ArticleTag)
388
- expect(policy.user).to eq user
389
- expect(policy.tag).to eq ArticleTag
390
- end
391
- end
392
- end
393
-
394
- describe ".policy!" do
395
- it "returns an instantiated policy given a plain model instance" do
396
- policy = Pundit.policy!(user, post)
397
- expect(policy.user).to eq user
398
- expect(policy.post).to eq post
399
- end
400
-
401
- it "returns an instantiated policy given an active model instance" do
402
- policy = Pundit.policy!(user, comment)
403
- expect(policy.user).to eq user
404
- expect(policy.comment).to eq comment
405
- end
406
-
407
- it "returns an instantiated policy given a plain model class" do
408
- policy = Pundit.policy!(user, Post)
409
- expect(policy.user).to eq user
410
- expect(policy.post).to eq Post
411
- end
412
-
413
- it "returns an instantiated policy given an active model class" do
414
- policy = Pundit.policy!(user, Comment)
415
- expect(policy.user).to eq user
416
- expect(policy.comment).to eq Comment
417
- end
418
-
419
- it "returns an instantiated policy given a symbol" do
420
- policy = Pundit.policy!(user, :criteria)
421
- expect(policy.class).to eq CriteriaPolicy
422
- expect(policy.user).to eq user
423
- expect(policy.criteria).to eq :criteria
424
- end
425
-
426
- it "returns an instantiated policy given an array of symbols" do
427
- policy = Pundit.policy!(user, %i[project criteria])
428
- expect(policy.class).to eq Project::CriteriaPolicy
429
- expect(policy.user).to eq user
430
- expect(policy.criteria).to eq :criteria
431
- end
432
-
433
- it "throws an exception if the given policy can't be found" do
434
- expect { Pundit.policy!(user, article) }.to raise_error(Pundit::NotDefinedError)
435
- expect { Pundit.policy!(user, Article) }.to raise_error(Pundit::NotDefinedError)
436
- end
437
-
438
- it "returns the specified NilClassPolicy for nil" do
439
- expect(Pundit.policy!(user, nil)).to be_a NilClassPolicy
440
- end
441
-
442
- it "raises an error with a invalid policy constructor" do
443
- expect do
444
- Pundit.policy(user, Wiki)
445
- end.to raise_error(Pundit::InvalidConstructorError, "Invalid #<WikiPolicy> constructor is called")
446
- end
447
- end
448
-
449
- describe ".included" do
450
- it "includes Authorization module" do
451
- klass = Class.new
452
-
453
- expect do
454
- klass.include Pundit
455
- end.to output.to_stderr
456
-
457
- expect(klass).to include Pundit::Authorization
458
- end
459
-
460
- it "warns about deprecation" do
461
- klass = Class.new
462
- expect do
463
- klass.include Pundit
464
- end.to output(a_string_starting_with("'include Pundit' is deprecated")).to_stderr
465
- end
466
- end
467
-
468
- describe "Pundit::NotAuthorizedError" do
469
- it "can be initialized with a string as message" do
470
- error = Pundit::NotAuthorizedError.new("must be logged in")
471
- expect(error.message).to eq "must be logged in"
472
- end
473
- end
474
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe "Pundit RSpec DSL" do
6
- include Pundit::RSpec::PolicyExampleGroup
7
-
8
- let(:fake_rspec) do
9
- double = class_double(RSpec::ExampleGroups)
10
- double.extend(::Pundit::RSpec::DSL)
11
- double
12
- end
13
- let(:block) { proc { "block content" } }
14
-
15
- let(:user) { double }
16
- let(:other_user) { double }
17
- let(:post) { Post.new(user) }
18
- let(:policy) { PostPolicy }
19
-
20
- it "calls describe with the correct metadata and without :focus" do
21
- expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array) }
22
- expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block|
23
- expect(block.call).to eq("block content")
24
- end
25
-
26
- fake_rspec.permissions(:item1, :item2, &block)
27
- end
28
-
29
- it "calls describe with the correct metadata and with :focus" do
30
- expected_metadata = { permissions: %i[item1 item2], caller: instance_of(Array), focus: true }
31
- expect(fake_rspec).to receive(:describe).with("item1 and item2", match(expected_metadata)) do |&block|
32
- expect(block.call).to eq("block content")
33
- end
34
-
35
- fake_rspec.permissions(:item1, :item2, :focus, &block)
36
- end
37
-
38
- describe "#permit" do
39
- context "when not appropriately wrapped in permissions" do
40
- it "raises a descriptive error" do
41
- expect do
42
- expect(policy).to permit(user, post)
43
- end.to raise_error(KeyError, <<~MSG.strip)
44
- No permissions in example metadata, did you forget to wrap with `permissions :show?, ...`?
45
- MSG
46
- end
47
- end
48
-
49
- permissions :edit?, :update? do
50
- it "succeeds when action is permitted" do
51
- expect(policy).to permit(user, post)
52
- end
53
-
54
- context "when it fails" do
55
- it "fails with a descriptive error message" do
56
- expect do
57
- expect(policy).to permit(other_user, post)
58
- end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)
59
- Expected PostPolicy to grant edit? and update? on Post but edit? and update? were not granted
60
- MSG
61
- end
62
- end
63
-
64
- context "when negated" do
65
- it "succeeds when action is not permitted" do
66
- expect(policy).not_to permit(other_user, post)
67
- end
68
-
69
- context "when it fails" do
70
- it "fails with a descriptive error message" do
71
- expect do
72
- expect(policy).not_to permit(user, post)
73
- end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)
74
- Expected PostPolicy not to grant edit? and update? on Post but edit? and update? were granted
75
- MSG
76
- end
77
- end
78
- end
79
- end
80
- end
81
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "simplecov"
4
- require "json"
5
-
6
- class SimpleCovCheckActionFormatter
7
- SourceFile = Data.define(:source_file) do
8
- def covered_strength = source_file.covered_strength
9
- def covered_percent = source_file.covered_percent
10
-
11
- def to_json(*args)
12
- {
13
- filename: source_file.filename,
14
- covered_percent: covered_percent.nan? ? 0.0 : covered_percent,
15
- coverage: source_file.coverage_data,
16
- covered_strength: covered_strength.nan? ? 0.0 : covered_strength,
17
- covered_lines: source_file.covered_lines.count,
18
- lines_of_code: source_file.lines_of_code
19
- }.to_json(*args)
20
- end
21
- end
22
-
23
- Result = Data.define(:result) do
24
- def included?(source_file) = result.filenames.include?(source_file.filename)
25
-
26
- def files
27
- result.files.filter_map do |source_file|
28
- next unless result.filenames.include? source_file.filename
29
-
30
- SourceFile.new(source_file)
31
- end
32
- end
33
-
34
- def to_json(*args) # rubocop:disable Metrics/AbcSize
35
- {
36
- timestamp: result.created_at.to_i,
37
- command_name: result.command_name,
38
- files: files,
39
- metrics: {
40
- covered_percent: result.covered_percent,
41
- covered_strength: result.covered_strength.nan? ? 0.0 : result.covered_strength,
42
- covered_lines: result.covered_lines,
43
- total_lines: result.total_lines
44
- }
45
- }.to_json(*args)
46
- end
47
- end
48
-
49
- FormatterWithOptions = Data.define(:formatter) do
50
- def new = formatter
51
- end
52
-
53
- class << self
54
- def with_options(...)
55
- FormatterWithOptions.new(new(...))
56
- end
57
- end
58
-
59
- def initialize(output_filename: "coverage.json", output_directory: SimpleCov.coverage_path)
60
- @output_filename = output_filename
61
- @output_directory = output_directory
62
- end
63
-
64
- attr_reader :output_filename, :output_directory
65
-
66
- def output_filepath = File.join(output_directory, output_filename)
67
-
68
- def format(result_data)
69
- result = Result.new(result_data)
70
- json = JSON.generate(result)
71
- File.write(output_filepath, json)
72
- puts output_message(result_data)
73
- json
74
- end
75
-
76
- def output_message(result)
77
- "Coverage report generated for #{result.command_name} to #{output_filepath}. #{result.covered_lines} / #{result.total_lines} LOC (#{result.covered_percent.round(2)}%) covered." # rubocop:disable Layout/LineLength
78
- end
79
- end
data/spec/spec_helper.rb DELETED
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- if ENV["COVERAGE"]
4
- require "simplecov"
5
- require "simplecov_json_formatter"
6
- require_relative "simple_cov_check_action_formatter"
7
- SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
8
- SimpleCov::Formatter::HTMLFormatter,
9
- SimpleCov::Formatter::JSONFormatter,
10
- SimpleCovCheckActionFormatter.with_options(
11
- output_filename: "simplecov-check-action.json"
12
- )
13
- ])
14
- SimpleCov.start do
15
- add_filter "/spec/"
16
- enable_coverage :branch
17
- primary_coverage :branch
18
- end
19
- end
20
-
21
- # @see https://github.com/rails/rails/issues/54260
22
- require "logger" if RUBY_ENGINE == "jruby" && RUBY_ENGINE_VERSION.start_with?("9.3")
23
-
24
- require "pundit"
25
- require "pundit/rspec"
26
- require "active_model/naming"
27
-
28
- # Load all supporting files: models, policies, etc.
29
- require "zeitwerk"
30
- loader = Zeitwerk::Loader.new
31
- loader.push_dir(File.expand_path("support/models", __dir__))
32
- loader.push_dir(File.expand_path("support/policies", __dir__))
33
- loader.push_dir(File.expand_path("support/lib", __dir__))
34
- loader.setup
35
- loader.eager_load