Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow enabling/disabling IronTrail in rspec #9

Merged
merged 8 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ jobs:
POSTGRES_HOST: localhost
POSTGRES_PORT: 5432
- name: Run specs
run: bundle exec rake install_database_yml spec
run:
bundle exec rake install_database_yml spec && bundle exec rake testing_spec
env:
BACKTRACE: 1
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,32 @@ RSpec.configure do |config|
end
```

You'll likely also want to require [lib/iron_trail/testing/rspec.rb](lib/iron_trail/testing/rspec.rb)
in your `rails_helper.rb`, then explicitly either disable or enable IronTrail in tests:

```ruby
require 'iron_trail/testing/rspec'
IronTrail::Testing.enable! # to have it enabled by default in specs
IronTrail::Testing.disable! # to have it disabled by default in specs
```

You you don't make it explicit, IronTrail will be enabled by default, which will
andrepiske marked this conversation as resolved.
Show resolved Hide resolved
likely impact your test suite performance slightly.

In case you disable it by default, you can enable it per rspec context with:

```ruby
describe 'in a "describe" block', iron_trail: true do
it 'or also in an "it" block', iron_trail: true do
# ...
end
end
```

Enabling/disabling IronTrail in specs works by replacing the trigger function in Postgres
with a dummy no-op function or with the real function and it won't add or drop triggers from
any tables.

## Rake tasks

IronTrail comes with a few handy rake tasks you can use in your dev, test and
Expand Down
10 changes: 9 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,12 @@ require 'rspec/core/rake_task'
task(:spec).clear
RSpec::Core::RakeTask.new(:spec)

task default: %i[prepare spec]
# Loading the testing/rspec file will affect RSpec globally. Because of that,
# we want to test it in a separate scope. We could also always require it,
# but that wouldn't be true in a real rails app and could make all tests
# farther apart from reality, thus less reliable.
RSpec::Core::RakeTask.new(:testing_spec).tap do |task|
task.pattern = 'spec/testing_itself.rb'
end

task default: %i[prepare spec testing_spec]
41 changes: 41 additions & 0 deletions lib/iron_trail/testing/rspec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
# frozen_string_literal: true

require 'iron_trail'

module IronTrail
module Testing
class << self
attr_accessor :enabled

def enable!
DbFunctions.new(ActiveRecord::Base.connection).install_functions
@enabled = true
end

def disable!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unlikely to happen since you need to require this, but one might do it in a rails console, I'd like iron_trail to protect me from doing this in production

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. I'll add a protection if ENV['RAILS_ENV'] == 'production'

# We "disable" it by replacing the trigger function by a no-op one.
# This should be faster than adding/removing triggers from several
# tables every time.
sql = <<~SQL
CREATE OR REPLACE FUNCTION irontrail_log_row()
RETURNS TRIGGER AS $$
BEGIN
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
SQL

ActiveRecord::Base.connection.execute(sql)
@enabled = false
end
end
end
end

RSpec.configure do |config|
config.around(:each, iron_trail: true) do |example|
enabled = IronTrail::Testing.enabled
IronTrail::Testing.enable! unless enabled

example.run
ensure
IronTrail::Testing.disable! unless enabled
end
end
30 changes: 30 additions & 0 deletions spec/testing_itself.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require 'iron_trail/testing/rspec'

IronTrail::Testing.disable!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: also add a test where it is enabled by default, to ensure that iron_trail: false is working properly

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


RSpec.describe 'lib/iron_trail/testing/rspec.rb' do
let(:person) { Person.create!(first_name: 'Arthur', last_name: 'Schopenhauer') }

subject(:do_some_changes!) do
person.update!(first_name: 'Jim')
person.update!(first_name: 'Jane')
end

context 'with IronTrail disabled' do
it 'does not track anything' do
do_some_changes!

expect(person.reload.iron_trails.length).to be(0)
end
end

context 'with IronTrail enabled through the helper', iron_trail: true do
it 'does not track anything' do
do_some_changes!

expect(person.reload.iron_trails.length).to be(3)
end
end
end
Loading