paper_trail_manager 0.7.0 → 0.9.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +13 -47
  3. data/.gitignore +2 -2
  4. data/.ruby-version +1 -0
  5. data/Appraisals +9 -17
  6. data/CHANGES.md +29 -0
  7. data/README.md +130 -66
  8. data/Rakefile +5 -3
  9. data/app/controllers/paper_trail_manager/changes_controller.rb +24 -9
  10. data/app/helpers/paper_trail_manager/changes_helper.rb +2 -2
  11. data/app/views/paper_trail_manager/changes/_version.html.erb +5 -5
  12. data/app/views/paper_trail_manager/changes/index.html.erb +44 -30
  13. data/app/views/paper_trail_manager/changes/show.html.erb +10 -7
  14. data/config/locales/en.yml +30 -0
  15. data/gemfiles/rails_6.1_paper_trail_12.0_kaminari.gemfile +10 -0
  16. data/gemfiles/rails_6.1_paper_trail_12.0_will_paginate.gemfile +10 -0
  17. data/gemfiles/rails_7.0_paper_trail_12.0_kaminari.gemfile +10 -0
  18. data/gemfiles/rails_7.0_paper_trail_12.0_will_paginate.gemfile +10 -0
  19. data/gemfiles/rails_7.0_paper_trail_15.0_kaminari.gemfile +10 -0
  20. data/gemfiles/rails_7.0_paper_trail_15.0_will_paginate.gemfile +10 -0
  21. data/gemfiles/rails_7.1_paper_trail_15.0_kaminari.gemfile +10 -0
  22. data/gemfiles/rails_7.1_paper_trail_15.0_will_paginate.gemfile +10 -0
  23. data/lib/generators/paper_trail_manager/install/install_generator.rb +36 -0
  24. data/lib/generators/paper_trail_manager/install/templates/initializer.rb +35 -0
  25. data/lib/paper_trail_manager.rb +8 -2
  26. data/paper_trail_manager.gemspec +14 -14
  27. data/spec/app_template.rb +19 -10
  28. data/spec/integration/authorization_spec.rb +84 -0
  29. data/spec/integration/date_filter_spec.rb +84 -0
  30. data/spec/integration/navigation_spec.rb +1 -1
  31. data/spec/integration/paper_trail_manager_spec.rb +6 -6
  32. data/spec/integration/response_formats_spec.rb +73 -0
  33. data/spec/support/factories.rb +2 -2
  34. data/spec/unit/authorization_spec.rb +42 -0
  35. data/spec/unit/changes_helper_spec.rb +81 -0
  36. metadata +78 -59
  37. data/gemfiles/rails_4.2.2_paper_trail_3.0_kaminari.gemfile +0 -13
  38. data/gemfiles/rails_4.2.2_paper_trail_3.0_will_paginate.gemfile +0 -13
  39. data/gemfiles/rails_4.2.2_paper_trail_4.0_kaminari.gemfile +0 -13
  40. data/gemfiles/rails_4.2.2_paper_trail_4.0_will_paginate.gemfile +0 -13
  41. data/gemfiles/rails_4.2.2_paper_trail_5.0_kaminari.gemfile +0 -13
  42. data/gemfiles/rails_4.2.2_paper_trail_5.0_will_paginate.gemfile +0 -13
  43. data/gemfiles/rails_4.2.2_paper_trail_6.0_kaminari.gemfile +0 -13
  44. data/gemfiles/rails_4.2.2_paper_trail_6.0_will_paginate.gemfile +0 -13
  45. data/gemfiles/rails_4.2.2_paper_trail_7.0_kaminari.gemfile +0 -13
  46. data/gemfiles/rails_4.2.2_paper_trail_7.0_will_paginate.gemfile +0 -13
  47. data/gemfiles/rails_4.2.2_paper_trail_8.0_kaminari.gemfile +0 -13
  48. data/gemfiles/rails_4.2.2_paper_trail_8.0_will_paginate.gemfile +0 -13
  49. data/gemfiles/rails_5.0.0_paper_trail_5.0_kaminari.gemfile +0 -13
  50. data/gemfiles/rails_5.0.0_paper_trail_5.0_will_paginate.gemfile +0 -13
  51. data/gemfiles/rails_5.0.0_paper_trail_6.0_kaminari.gemfile +0 -13
  52. data/gemfiles/rails_5.0.0_paper_trail_6.0_will_paginate.gemfile +0 -13
  53. data/gemfiles/rails_5.0.0_paper_trail_7.0_kaminari.gemfile +0 -13
  54. data/gemfiles/rails_5.0.0_paper_trail_7.0_will_paginate.gemfile +0 -13
  55. data/gemfiles/rails_5.0.0_paper_trail_8.0_kaminari.gemfile +0 -13
  56. data/gemfiles/rails_5.0.0_paper_trail_8.0_will_paginate.gemfile +0 -13
  57. data/gemfiles/rails_5.1.0_paper_trail_10.0_kaminari.gemfile +0 -13
  58. data/gemfiles/rails_5.1.0_paper_trail_10.0_will_paginate.gemfile +0 -13
  59. data/gemfiles/rails_5.1.0_paper_trail_7.0_kaminari.gemfile +0 -13
  60. data/gemfiles/rails_5.1.0_paper_trail_7.0_will_paginate.gemfile +0 -13
  61. data/gemfiles/rails_5.1.0_paper_trail_8.0_kaminari.gemfile +0 -13
  62. data/gemfiles/rails_5.1.0_paper_trail_8.0_will_paginate.gemfile +0 -13
  63. data/gemfiles/rails_5.1.0_paper_trail_9.0_kaminari.gemfile +0 -13
  64. data/gemfiles/rails_5.1.0_paper_trail_9.0_will_paginate.gemfile +0 -13
  65. data/gemfiles/rails_5.2.0_paper_trail_10.0_kaminari.gemfile +0 -13
  66. data/gemfiles/rails_5.2.0_paper_trail_10.0_will_paginate.gemfile +0 -13
  67. data/gemfiles/rails_5.2.0_paper_trail_9.0_kaminari.gemfile +0 -13
  68. data/gemfiles/rails_5.2.0_paper_trail_9.0_will_paginate.gemfile +0 -13
  69. data/gemfiles/rails_6.0.0_paper_trail_10.0_kaminari.gemfile +0 -14
  70. data/gemfiles/rails_6.0.0_paper_trail_10.0_will_paginate.gemfile +0 -15
@@ -1,35 +1,49 @@
1
- <h1>Changes</h1>
2
-
3
- <p class='changes_feed'><%= link_to 'Changes feed', changes_path(:format => 'atom') %></p>
1
+ <h1><%= t('paper_trail_manager.changes.index.title') %></h1>
4
2
 
5
3
  <p>
6
- Show:
7
- <%= ([link_to('All', changes_path)] + change_item_types.map { |type| link_to(type.pluralize, changes_path(:type => type)) }).join(' | ').html_safe %>
4
+ <%= t('paper_trail_manager.changes.index.show_label') %>
5
+ <%= ([link_to(t('paper_trail_manager.changes.index.all'), changes_path)] + change_item_types.map { |type| link_to(type.pluralize, changes_path(type: type)) }).join(' | ').html_safe %>
8
6
  </p>
9
7
 
10
- <table class='changes_table'>
11
- <tfoot>
12
- <tr>
13
- <td colspan='2'>
14
- <%= paginate @versions %>
15
- </td>
16
- </tr>
17
- </tfoot>
18
- <thead>
19
- <tr class='changes_header'>
20
- <th class='change_time'>Time</th>
21
- <th class='change_details'>Attribute with previous and current values</th>
22
- </tr>
23
- </thead>
24
- <tbody>
25
- <% if @versions.any? %>
26
- <% @versions.each do |version| %>
27
- <% next unless change_show_allowed?(version) %>
28
- <%= render :partial => 'version', :object => version %>
29
- <% end %>
30
- <% else %>
31
- <td rowspan='2'> &mdash; No changes found &mdash; </td>
32
- <% end %>
33
- </tbody>
34
- </table>
8
+ <%= form_tag changes_path, method: :get, class: 'changes_date_filter' do %>
9
+ <%= hidden_field_tag :type, params[:type] if params[:type] %>
10
+ <%= hidden_field_tag :id, params[:id] if params[:id] %>
11
+ <label for="from"><%= t('paper_trail_manager.changes.filter.from') %></label>
12
+ <%= date_field_tag :from, params[:from], id: 'from' %>
13
+ <label for="to"><%= t('paper_trail_manager.changes.filter.to') %></label>
14
+ <%= date_field_tag :to, params[:to], id: 'to' %>
15
+ <%= submit_tag t('paper_trail_manager.changes.filter.submit'), name: nil %>
16
+ <% if params[:from].present? || params[:to].present? %>
17
+ <%= link_to t('paper_trail_manager.changes.filter.clear'), changes_path(type: params[:type], id: params[:id]), class: 'clear_filter' %>
18
+ <% end %>
19
+ <% end %>
35
20
 
21
+ <div class="table-responsive">
22
+ <table class='changes_table table table-bordered'>
23
+ <tfoot>
24
+ <tr>
25
+ <td colspan='2'>
26
+ <%= paginate @versions %>
27
+ </td>
28
+ </tr>
29
+ </tfoot>
30
+ <thead>
31
+ <tr class='changes_header'>
32
+ <th class='change_time'><%= t('paper_trail_manager.changes.index.time') %></th>
33
+ <th class='change_details'><%= t('paper_trail_manager.changes.index.details') %></th>
34
+ </tr>
35
+ </thead>
36
+ <tbody>
37
+ <% if @versions.any? %>
38
+ <% @versions.each do |version| %>
39
+ <% next unless change_show_allowed?(version) %>
40
+ <%= render partial: 'version', object: version %>
41
+ <% end %>
42
+ <% else %>
43
+ <tr>
44
+ <td colspan='2'> &mdash; <%= t('paper_trail_manager.changes.index.no_changes') %> &mdash; </td>
45
+ </tr>
46
+ <% end %>
47
+ </tbody>
48
+ </table>
49
+ </div>
@@ -1,10 +1,13 @@
1
- <h1>Change <%= @version.id %></h1>
1
+ <h1><%= t('paper_trail_manager.changes.show.title', id: @version.id) %></h1>
2
2
 
3
3
  <table class='changes_table'>
4
- <tr class='changes_header'>
5
- <th class='change_time'>Time</th>
6
- <th class='change_details'>Attribute with previous and current values</th>
7
- <%= render :partial => 'version', :object => @version %>
8
- </tr>
4
+ <thead>
5
+ <tr class='changes_header'>
6
+ <th class='change_time'><%= t('paper_trail_manager.changes.index.time') %></th>
7
+ <th class='change_details'><%= t('paper_trail_manager.changes.index.details') %></th>
8
+ </tr>
9
+ </thead>
10
+ <tbody>
11
+ <%= render partial: 'version', object: @version %>
12
+ </tbody>
9
13
  </table>
10
-
@@ -0,0 +1,30 @@
1
+ en:
2
+ paper_trail_manager:
3
+ changes:
4
+ index:
5
+ title: "Changes"
6
+ show_label: "Show:"
7
+ all: "All"
8
+ no_changes: "No changes found"
9
+ time: "Time"
10
+ details: "Attribute with previous and current values"
11
+ show:
12
+ title: "Change %{id}"
13
+ filter:
14
+ from: "From:"
15
+ to: "To:"
16
+ submit: "Filter"
17
+ clear: "Clear"
18
+ version:
19
+ change_id: "Change #%{id}"
20
+ roll_back: "Roll back"
21
+ confirm_rollback: "Are you sure?"
22
+ by: "by"
23
+ flash:
24
+ index_denied: "You do not have permission to list changes."
25
+ show_denied: "You do not have permission to show that change."
26
+ revert_denied: "You do not have permission to revert this change."
27
+ not_found: "No such version."
28
+ rollback_create: "Rolled back newly-created record by destroying it."
29
+ rollback_update: "Rolled back changes to this record."
30
+ rollback_failed: "Couldn't rollback. Sorry."
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.1.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 12.0"
8
+ gem "kaminari", ">= 1.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 6.1.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 12.0"
8
+ gem "will_paginate", "~> 4.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.0.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 12.0"
8
+ gem "kaminari", ">= 1.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.0.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 12.0"
8
+ gem "will_paginate", "~> 4.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.0.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 15.0"
8
+ gem "kaminari", ">= 1.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.0.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 15.0"
8
+ gem "will_paginate", "~> 4.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.1.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 15.0"
8
+ gem "kaminari", ">= 1.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 7.1.0"
6
+ gem "sqlite3", "~> 1.7"
7
+ gem "paper_trail", "~> 15.0"
8
+ gem "will_paginate", "~> 4.0"
9
+
10
+ gemspec path: "../"
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ class PaperTrailManager
6
+ class InstallGenerator < Rails::Generators::Base
7
+ source_root File.expand_path('templates', __dir__)
8
+ desc 'Install PaperTrailManager: add route and create initializer'
9
+
10
+ def add_route
11
+ route_string = "resources :changes, controller: 'paper_trail_manager/changes'"
12
+ routes_file = File.join(destination_root, 'config/routes.rb')
13
+
14
+ if File.exist?(routes_file) && File.read(routes_file).include?(route_string)
15
+ say_status :skip, 'Route already exists', :yellow
16
+ else
17
+ route route_string
18
+ end
19
+ end
20
+
21
+ def create_initializer
22
+ template 'initializer.rb', 'config/initializers/paper_trail_manager.rb'
23
+ end
24
+
25
+ def show_post_install
26
+ say ''
27
+ say '✅ PaperTrailManager installed!', :green
28
+ say ''
29
+ say 'Next steps:'
30
+ say ' 1. Restart your Rails server'
31
+ say ' 2. Visit /changes to browse your PaperTrail version history'
32
+ say ' 3. Edit config/initializers/paper_trail_manager.rb to customize authorization'
33
+ say ''
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PaperTrailManager configuration
4
+ # See: https://github.com/DamageLabs/paper_trail_manager
5
+
6
+ # Control who can view the changes index.
7
+ # PaperTrailManager.allow_index_when do |controller|
8
+ # controller.current_user.present?
9
+ # end
10
+
11
+ # Control who can view individual change details.
12
+ # Defaults to the allow_index rules if not set separately.
13
+ # PaperTrailManager.allow_show_when do |controller, version|
14
+ # controller.current_user.present?
15
+ # end
16
+
17
+ # Control who can revert changes.
18
+ # PaperTrailManager.allow_revert_when do |controller, version|
19
+ # controller.current_user&.admin?
20
+ # end
21
+
22
+ # Configure how to look up users referenced in PaperTrail's whodunnit column.
23
+ # PaperTrailManager.whodunnit_class = User
24
+ # PaperTrailManager.whodunnit_name_method = :name
25
+
26
+ # Specify a method to identify items on the index page.
27
+ # PaperTrailManager.item_name_method = :name
28
+
29
+ # Customize the user path helper (set to nil to disable user links).
30
+ # PaperTrailManager.user_path_method = :user_path
31
+
32
+ # When embedding inside another Rails engine:
33
+ # PaperTrailManager.base_controller = 'MyEngine::ApplicationController'
34
+ # PaperTrailManager.route_helpers = MyEngine::Engine.routes.url_helpers
35
+ # PaperTrailManager.layout = 'my_engine/application'
@@ -14,8 +14,14 @@ rescue LoadError
14
14
  end
15
15
 
16
16
  class PaperTrailManager < Rails::Engine
17
+ initializer 'paper_trail_manager.i18n' do
18
+ config.i18n.load_path += Dir[root.join('config', 'locales', '*.yml')]
19
+ end
20
+
17
21
  initializer 'paper_trail_manager.pagination' do
18
- ::ActionView::Base.send(:alias_method, :paginate, :will_paginate) if defined?(WillPaginate)
22
+ if defined?(WillPaginate)
23
+ ::ActionView::Base.define_method(:paginate) { |*args, **kwargs, &block| will_paginate(*args, **kwargs, &block) }
24
+ end
19
25
  end
20
26
 
21
27
  @@whodunnit_name_method = :name
@@ -50,7 +56,7 @@ class PaperTrailManager < Rails::Engine
50
56
  end
51
57
 
52
58
  def self.allow_show?(controller, version)
53
- allow_index_block.call controller, version
59
+ allow_show_block.call controller, version
54
60
  end
55
61
 
56
62
  # Describe when to allow reverts. Call this with a block that accepts
@@ -5,28 +5,28 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'paper_trail_manager'
8
- spec.version = '0.7.0'
8
+ spec.version = '0.9.0'
9
9
  spec.authors = ['Igal Koshevoy', 'Reid Beels']
10
- spec.authors = ['mail@reidbeels.com']
10
+ spec.email = ['mail@reidbeels.com']
11
11
  spec.summary = 'A user interface for `paper_trail` versioning data in Rails applications.'
12
12
  spec.description = 'Browse, subscribe, view and revert changes to records when using Rails and the `paper_trail` gem.'
13
- spec.homepage = 'https://github.com/fusion94/paper_trail_manager'
13
+ spec.homepage = 'https://github.com/DamageLabs/paper_trail_manager'
14
14
  spec.license = 'MIT'
15
-
16
15
  spec.files = `git ls-files -z`.split("\x0")
17
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
18
  spec.require_paths = ['lib']
20
-
21
- spec.add_dependency 'paper_trail', ['>= 3.0']
22
- spec.add_dependency 'rails', ['>= 3.0', '< 7.0']
23
-
24
- spec.add_development_dependency 'appraisal', '~> 1.0'
25
- spec.add_development_dependency 'factory_girl_rails', '~> 4.0'
26
- spec.add_development_dependency 'rake', '~> 10.4'
19
+ spec.required_ruby_version = '>= 3.1'
20
+ spec.add_dependency 'paper_trail', ['>= 12.0']
21
+ spec.add_dependency 'rails', ['>= 6.1', '< 8.0']
22
+ spec.add_dependency 'nokogiri', ['>= 1.18.3']
23
+ spec.add_dependency 'rails-html-sanitizer', ['>= 1.6.1']
24
+ spec.add_development_dependency 'appraisal', '~> 2.0'
25
+ spec.add_development_dependency 'factory_bot_rails', '~> 6.0'
26
+ spec.add_development_dependency 'rake', '~> 13.0'
27
27
  spec.add_development_dependency 'rspec-activemodel-mocks', '~> 1.0'
28
- spec.add_development_dependency 'rspec-html-matchers', '~> 0.9.2'
28
+ spec.add_development_dependency 'rspec-html-matchers', '~> 0.10'
29
29
  spec.add_development_dependency 'rspec-its', '~> 1.0'
30
- spec.add_development_dependency 'rspec-rails', '~> 3.0'
31
- spec.add_development_dependency 'sqlite3', '>= 1.3.6'
30
+ spec.add_development_dependency 'rspec-rails', '~> 6.0'
31
+ spec.add_development_dependency 'sqlite3', '~> 1.7'
32
32
  end
data/spec/app_template.rb CHANGED
@@ -2,29 +2,38 @@
2
2
 
3
3
  gem 'paper_trail_manager', path: __FILE__ + '/../../../'
4
4
 
5
- unless File.exist?('app/assets/config/manifest.js')
6
- create_file 'app/assets/config/manifest.js'
7
- append_to_file 'app/assets/config/manifest.js', "//= link application.css\n"
8
- append_to_file 'app/assets/config/manifest.js', "//= link application.js\n"
9
- end
5
+ # Remove auto-generated request specs from dummy app
6
+ remove_file 'spec/requests/entities_spec.rb' if File.exist?('spec/requests/entities_spec.rb')
7
+ remove_file 'spec/requests/platforms_spec.rb' if File.exist?('spec/requests/platforms_spec.rb')
10
8
 
11
9
  generate 'paper_trail:install'
12
10
  generate 'resource', 'entity name:string status:string --no-controller-specs --no-helper-specs'
13
11
  generate 'resource', 'platform name:string status:string --no-controller-specs --no-helper-specs'
14
12
 
15
- remove_file 'spec/models/entity_spec.rb'
16
- remove_file 'spec/models/platform_spec.rb'
13
+ # Remove auto-generated spec files that conflict with our factories
14
+ remove_file 'spec/models/entity_spec.rb' if File.exist?('spec/models/entity_spec.rb')
15
+ remove_file 'spec/models/platform_spec.rb' if File.exist?('spec/models/platform_spec.rb')
17
16
 
18
17
  model_body = <<-MODEL
19
18
  has_paper_trail
20
19
 
21
- validates_presence_of :name
22
- validates_presence_of :status
20
+ validates :name, presence: true
21
+ validates :status, presence: true
23
22
  MODEL
24
23
 
25
24
  inject_into_class 'app/models/entity.rb', 'Entity', model_body
26
25
  inject_into_class 'app/models/platform.rb', 'Platform', model_body
27
26
 
28
- route "resources :changes, :controller => 'paper_trail_manager/changes'"
27
+ route "resources :changes, controller: 'paper_trail_manager/changes'"
28
+ route "root to: 'paper_trail_manager/changes#index'"
29
+
30
+ # Allow YAML deserialization of ActiveSupport::TimeWithZone (Ruby 3.1+ Psych 4)
31
+ initializer 'permitted_classes.rb', <<~RUBY
32
+ Rails.application.config.active_record.yaml_column_permitted_classes = [
33
+ ActiveSupport::TimeWithZone,
34
+ ActiveSupport::TimeZone,
35
+ Time
36
+ ]
37
+ RUBY
29
38
 
30
39
  rake 'db:migrate db:test:prepare'
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PaperTrailManager, 'authorization integration', versioning: true do
6
+ let(:entity) { FactoryBot.create(:entity, name: 'Test Entity', status: 'Active') }
7
+
8
+ before do
9
+ entity
10
+ entity.update(status: 'Updated')
11
+ end
12
+
13
+ after do
14
+ default = proc { true }
15
+ PaperTrailManager.allow_index_block = default
16
+ PaperTrailManager.allow_show_block = default
17
+ PaperTrailManager.allow_revert_block = default
18
+ end
19
+
20
+ describe 'index' do
21
+ context 'when not authorized' do
22
+ before do
23
+ PaperTrailManager.allow_index_when { |_controller| false }
24
+ end
25
+
26
+ it 'redirects with an error flash' do
27
+ get changes_path
28
+ expect(response).to have_http_status(:redirect)
29
+ expect(flash[:error]).to eq('You do not have permission to list changes.')
30
+ end
31
+ end
32
+ end
33
+
34
+ describe 'show' do
35
+ context 'when not authorized' do
36
+ before do
37
+ PaperTrailManager.allow_show_when { |_controller, _version| false }
38
+ end
39
+
40
+ it 'redirects with an error flash' do
41
+ get change_path(entity.versions.last)
42
+ expect(response).to have_http_status(:redirect)
43
+ expect(flash[:error]).to eq('You do not have permission to show that change.')
44
+ end
45
+ end
46
+
47
+ context 'when change does not exist' do
48
+ it 'redirects with an error flash' do
49
+ get change_path(id: 999999)
50
+ expect(response).to have_http_status(:redirect)
51
+ expect(flash[:error]).to eq('No such version.')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe 'revert' do
57
+ context 'when not authorized' do
58
+ before do
59
+ PaperTrailManager.allow_revert_when { |_controller, _version| false }
60
+ end
61
+
62
+ it 'redirects with an error flash' do
63
+ put change_path(entity.versions.last)
64
+ expect(response).to have_http_status(:redirect)
65
+ expect(flash[:error]).to eq('You do not have permission to revert this change.')
66
+ end
67
+ end
68
+
69
+ context 'when change does not exist' do
70
+ it 'redirects with an error flash' do
71
+ put change_path(id: 999999)
72
+ expect(response).to have_http_status(:redirect)
73
+ expect(flash[:error]).to eq('No such version.')
74
+ end
75
+ end
76
+ end
77
+
78
+ describe 'filtering by non-existent type' do
79
+ it 'returns an empty changes list' do
80
+ get changes_path(type: 'NonExistentModel')
81
+ expect(response.body).to include('No changes found')
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PaperTrailManager, 'date range filtering', versioning: true do
6
+ let(:entity) { FactoryBot.create(:entity, name: 'Test Entity', status: 'Active') }
7
+
8
+ before do
9
+ entity
10
+ entity.update(status: 'Updated')
11
+ end
12
+
13
+ describe 'index with date filters' do
14
+ context 'with from parameter' do
15
+ it 'shows changes on or after the date' do
16
+ get changes_path(from: Date.today.to_s)
17
+ expect(response).to have_http_status(:ok)
18
+ expect(response.body).to have_tag('.change_row')
19
+ end
20
+
21
+ it 'returns no changes for future date' do
22
+ get changes_path(from: (Date.today + 1).to_s)
23
+ expect(response.body).to include('No changes found')
24
+ end
25
+ end
26
+
27
+ context 'with to parameter' do
28
+ it 'shows changes on or before the date' do
29
+ get changes_path(to: Date.today.to_s)
30
+ expect(response).to have_http_status(:ok)
31
+ expect(response.body).to have_tag('.change_row')
32
+ end
33
+
34
+ it 'returns no changes for past date' do
35
+ get changes_path(to: (Date.today - 1).to_s)
36
+ expect(response.body).to include('No changes found')
37
+ end
38
+ end
39
+
40
+ context 'with from and to combined' do
41
+ it 'shows changes within the range' do
42
+ get changes_path(from: Date.today.to_s, to: Date.today.to_s)
43
+ expect(response).to have_http_status(:ok)
44
+ expect(response.body).to have_tag('.change_row')
45
+ end
46
+ end
47
+
48
+ context 'combined with type filter' do
49
+ it 'respects both date and type filters' do
50
+ get changes_path(from: Date.today.to_s, type: 'Entity')
51
+ expect(response).to have_http_status(:ok)
52
+ expect(response.body).to have_tag('.change_item', text: /Entity/)
53
+ end
54
+ end
55
+
56
+ context 'with invalid date' do
57
+ it 'ignores invalid from date gracefully' do
58
+ get changes_path(from: 'not-a-date')
59
+ expect(response).to have_http_status(:ok)
60
+ expect(response.body).to have_tag('.change_row')
61
+ end
62
+
63
+ it 'ignores invalid to date gracefully' do
64
+ get changes_path(to: 'garbage')
65
+ expect(response).to have_http_status(:ok)
66
+ expect(response.body).to have_tag('.change_row')
67
+ end
68
+ end
69
+
70
+ context 'date filter form' do
71
+ it 'renders date inputs' do
72
+ get changes_path
73
+ expect(response.body).to have_tag('input[type="date"][name="from"]')
74
+ expect(response.body).to have_tag('input[type="date"][name="to"]')
75
+ end
76
+
77
+ it 'preserves date values in form' do
78
+ get changes_path(from: '2026-01-01', to: '2026-12-31')
79
+ expect(response.body).to have_tag('input[name="from"][value="2026-01-01"]')
80
+ expect(response.body).to have_tag('input[name="to"][value="2026-12-31"]')
81
+ end
82
+ end
83
+ end
84
+ end
@@ -4,6 +4,6 @@ require 'spec_helper'
4
4
 
5
5
  describe 'Navigation' do
6
6
  it 'is a valid app' do
7
- ::Rails.application.should be_a_kind_of(Rails::Application)
7
+ expect(::Rails.application).to be_a_kind_of(Rails::Application)
8
8
  end
9
9
  end
@@ -14,11 +14,11 @@ describe PaperTrailManager, versioning: true do
14
14
  end
15
15
 
16
16
  context 'with changes' do
17
- let(:reimu) { FactoryGirl.create(:entity, name: 'Miko Hakurei Reimu', status: 'Highly Responsive to Prayers') }
18
- let(:flanchan) { FactoryGirl.create(:entity, name: 'Flandre Scarlet', status: 'The Embodiment of Scarlet Devil') }
19
- let(:sakuya) { FactoryGirl.create(:entity, name: 'Sakuya Izayoi', status: 'Flowering Night') }
20
- let(:kyuu_hachi) { FactoryGirl.create(:platform, name: 'PC-9801', status: 'SUGOI!!1!') }
21
- let!(:uinodouzu) { FactoryGirl.create(:platform, name: 'Mikorusofto Uinodouzu', status: 'o-O') }
17
+ let(:reimu) { FactoryBot.create(:entity, name: 'Miko Hakurei Reimu', status: 'Highly Responsive to Prayers') }
18
+ let(:flanchan) { FactoryBot.create(:entity, name: 'Flandre Scarlet', status: 'The Embodiment of Scarlet Devil') }
19
+ let(:sakuya) { FactoryBot.create(:entity, name: 'Sakuya Izayoi', status: 'Flowering Night') }
20
+ let(:kyuu_hachi) { FactoryBot.create(:platform, name: 'PC-9801', status: 'SUGOI!!1!') }
21
+ let!(:uinodouzu) { FactoryBot.create(:platform, name: 'Mikorusofto Uinodouzu', status: 'o-O') }
22
22
 
23
23
  let!(:flanchan_id) { flanchan.id }
24
24
 
@@ -161,7 +161,7 @@ describe PaperTrailManager, versioning: true do
161
161
  end
162
162
 
163
163
  it 'rollbacks a delete by restoring the record' do
164
- Entity.exists?(flanchan_id).should be_falsey
164
+ expect(Entity.exists?(flanchan_id)).to be_falsey
165
165
 
166
166
  put change_path(PaperTrail::Version.where(item_id: flanchan_id, item_type: 'Entity').last)
167
167