Lint: Improve RSpec/NestedGroups from infinity to 5

This commit is contained in:
Jared Beck 2017-04-01 02:28:55 -04:00
parent 0b016be756
commit f3e38a2ec8
4 changed files with 336 additions and 388 deletions

View File

@ -28,7 +28,7 @@ RSpec/NamedSubject:
Enabled: false
RSpec/NestedGroups:
Enabled: false
Max: 5 # goal: 3
Security/YAMLLoad:
Enabled: false

View File

@ -22,45 +22,41 @@ describe Gadget, type: :model do
end
end
describe "Methods" do
describe "Instance", versioning: true do
describe "private" do
describe "#changed_notably?" do
subject { Gadget.new(created_at: Time.now) }
describe "#changed_notably?", versioning: true do
subject { Gadget.new(created_at: Time.now) }
context "create events" do
it { expect(subject.paper_trail.changed_notably?).to be true }
end
context "create events" do
it "returns true" do
expect(subject.paper_trail.changed_notably?).to eq(true)
end
end
context "update events" do
before { subject.save! }
context "update events" do
before { subject.save! }
context "without update timestamps" do
it "only acknowledges non-ignored attrs" do
subject.name = "Wrench"
expect(subject.paper_trail.changed_notably?).to be true
end
context "without update timestamps" do
it "only acknowledges non-ignored attrs" do
subject.name = "Wrench"
expect(subject.paper_trail.changed_notably?).to be true
end
it "does not acknowledge ignored attr (brand)" do
subject.brand = "Acme"
expect(subject.paper_trail.changed_notably?).to be false
end
end
it "does not acknowledge ignored attr (brand)" do
subject.brand = "Acme"
expect(subject.paper_trail.changed_notably?).to be false
end
end
context "with update timestamps" do
it "only acknowledges non-ignored attrs" do
subject.name = "Wrench"
subject.updated_at = Time.now
expect(subject.paper_trail.changed_notably?).to be true
end
context "with update timestamps" do
it "only acknowledges non-ignored attrs" do
subject.name = "Wrench"
subject.updated_at = Time.now
expect(subject.paper_trail.changed_notably?).to be true
end
it "does not acknowledge ignored attrs and timestamps only" do
subject.brand = "Acme"
subject.updated_at = Time.now
expect(subject.paper_trail.changed_notably?).to be false
end
end
end
it "does not acknowledge ignored attrs and timestamps only" do
subject.brand = "Acme"
subject.updated_at = Time.now
expect(subject.paper_trail.changed_notably?).to be false
end
end
end

View File

@ -35,8 +35,6 @@ describe PaperTrail::Version, type: :model do
subject { PaperTrail::Version.new }
describe "#paper_trail_originator" do
it { is_expected.to respond_to(:paper_trail_originator) }
context "No previous versions" do
specify { expect(subject.previous).to be_nil }
@ -65,8 +63,6 @@ describe PaperTrail::Version, type: :model do
end
describe "#originator" do
it { is_expected.to respond_to(:originator) }
it "sets the invoke `paper_trail_originator`" do
allow(ActiveSupport::Deprecation).to receive(:warn)
is_expected.to receive(:paper_trail_originator)
@ -85,188 +81,173 @@ describe PaperTrail::Version, type: :model do
let(:attributes) { { whodunnit: FFaker::Name.first_name } }
it { is_expected.to respond_to(:terminator) }
it "is an alias for the `whodunnit` attribute" do
expect(subject.terminator).to eq(attributes[:whodunnit])
end
end
describe "#version_author" do
it { is_expected.to respond_to(:version_author) }
it "is an alias for the `terminator` method" do
expect(subject.method(:version_author)).to eq(subject.method(:terminator))
end
end
end
describe "Class" do
column_overrides = [false]
if ENV["DB"] == "postgres" && ::ActiveRecord::VERSION::MAJOR >= 4
column_overrides << "json"
# 'jsonb' column types are only supported for ActiveRecord 4.2+
column_overrides << "jsonb" if ::ActiveRecord::VERSION::STRING >= "4.2"
end
column_overrides = [false]
if ENV["DB"] == "postgres" && ::ActiveRecord::VERSION::MAJOR >= 4
column_overrides << "json"
# 'jsonb' column types are only supported for ActiveRecord 4.2+
column_overrides << "jsonb" if ::ActiveRecord::VERSION::STRING >= "4.2"
end
column_overrides.shuffle.each do |override|
context "with a #{override || 'text'} column" do
before do
if override
ActiveRecord::Base.connection.execute("SAVEPOINT pgtest;")
%w(object object_changes).each do |column|
ActiveRecord::Base.connection.execute(
"ALTER TABLE versions DROP COLUMN #{column};"
)
ActiveRecord::Base.connection.execute(
"ALTER TABLE versions ADD COLUMN #{column} #{override};"
)
end
PaperTrail::Version.reset_column_information
end
end
after do
if override
ActiveRecord::Base.connection.execute("ROLLBACK TO SAVEPOINT pgtest;")
PaperTrail::Version.reset_column_information
end
end
describe "#where_object", versioning: true do
let(:widget) { Widget.new }
let(:name) { FFaker::Name.first_name }
let(:int) { rand(10) + 1 }
column_overrides.shuffle.each do |override|
context "with a #{override || 'text'} column" do
before do
if override
ActiveRecord::Base.connection.execute("SAVEPOINT pgtest;")
%w(object object_changes).each do |column|
ActiveRecord::Base.connection.execute(
"ALTER TABLE versions DROP COLUMN #{column};"
)
ActiveRecord::Base.connection.execute(
"ALTER TABLE versions ADD COLUMN #{column} #{override};"
)
end
PaperTrail::Version.reset_column_information
end
widget.update_attributes!(name: name, an_integer: int)
widget.update_attributes!(name: "foobar", an_integer: 100)
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: 15)
end
after do
if override
ActiveRecord::Base.connection.execute("ROLLBACK TO SAVEPOINT pgtest;")
PaperTrail::Version.reset_column_information
it "requires its argument to be a Hash" do
expect {
PaperTrail::Version.where_object(:foo)
}.to raise_error(ArgumentError)
expect {
PaperTrail::Version.where_object([])
}.to raise_error(ArgumentError)
end
context "`serializer == YAML`" do
specify do
expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML
end
it "locates versions according to their `object` contents" do
expect(
PaperTrail::Version.where_object(name: name)
).to eq([widget.versions[1]])
expect(
PaperTrail::Version.where_object(an_integer: 100)
).to eq([widget.versions[2]])
end
end
describe "#where_object" do
it { expect(PaperTrail::Version).to respond_to(:where_object) }
context "invalid arguments" do
it "raises an error" do
expect {
PaperTrail::Version.where_object(:foo)
}.to raise_error(ArgumentError)
expect {
PaperTrail::Version.where_object([])
}.to raise_error(ArgumentError)
end
context "JSON serializer" do
before(:all) do
PaperTrail.serializer = PaperTrail::Serializers::JSON
end
context "valid arguments", versioning: true do
let(:widget) { Widget.new }
let(:name) { FFaker::Name.first_name }
let(:int) { rand(10) + 1 }
specify do
expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON
end
before do
widget.update_attributes!(name: name, an_integer: int)
widget.update_attributes!(name: "foobar", an_integer: 100)
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: 15)
end
it "locates versions according to their `object` contents" do
expect(
PaperTrail::Version.where_object(name: name)
).to eq([widget.versions[1]])
expect(
PaperTrail::Version.where_object(an_integer: 100)
).to eq([widget.versions[2]])
end
context "`serializer == YAML`" do
specify do
expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML
end
after(:all) do
PaperTrail.serializer = PaperTrail::Serializers::YAML
end
end
end
it "locates versions according to their `object` contents" do
expect(
PaperTrail::Version.where_object(name: name)
).to eq([widget.versions[1]])
expect(
PaperTrail::Version.where_object(an_integer: 100)
).to eq([widget.versions[2]])
end
end
describe "#where_object_changes", versioning: true do
let(:widget) { Widget.new }
let(:name) { FFaker::Name.first_name }
let(:int) { rand(5) + 2 }
context "JSON serializer" do
before(:all) do
PaperTrail.serializer = PaperTrail::Serializers::JSON
end
before do
widget.update_attributes!(name: name, an_integer: 0)
widget.update_attributes!(name: "foobar", an_integer: 77)
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: int)
end
specify do
expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON
end
it "requires its argument to be a Hash" do
expect {
PaperTrail::Version.where_object_changes(:foo)
}.to raise_error(ArgumentError)
expect {
PaperTrail::Version.where_object_changes([])
}.to raise_error(ArgumentError)
end
it "locates versions according to their `object` contents" do
expect(
PaperTrail::Version.where_object(name: name)
).to eq([widget.versions[1]])
expect(
PaperTrail::Version.where_object(an_integer: 100)
).to eq([widget.versions[2]])
end
context "YAML serializer" do
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML }
after(:all) do
PaperTrail.serializer = PaperTrail::Serializers::YAML
end
end
it "locates versions according to their `object_changes` contents" do
expect(
widget.versions.where_object_changes(name: name)
).to eq(widget.versions[0..1])
expect(
widget.versions.where_object_changes(an_integer: 77)
).to eq(widget.versions[1..2])
expect(
widget.versions.where_object_changes(an_integer: int)
).to eq([widget.versions.last])
end
it "handles queries for multiple attributes" do
expect(
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
).to eq(widget.versions[1..2])
end
end
describe "#where_object_changes" do
context "invalid arguments" do
it "raises an error" do
expect {
PaperTrail::Version.where_object_changes(:foo)
}.to raise_error(ArgumentError)
expect {
PaperTrail::Version.where_object_changes([])
}.to raise_error(ArgumentError)
end
context "JSON serializer" do
before(:all) { PaperTrail.serializer = PaperTrail::Serializers::JSON }
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON }
it "locates versions according to their `object_changes` contents" do
expect(
widget.versions.where_object_changes(name: name)
).to eq(widget.versions[0..1])
expect(
widget.versions.where_object_changes(an_integer: 77)
).to eq(widget.versions[1..2])
expect(
widget.versions.where_object_changes(an_integer: int)
).to eq([widget.versions.last])
end
context "valid arguments", versioning: true do
let(:widget) { Widget.new }
let(:name) { FFaker::Name.first_name }
let(:int) { rand(5) + 2 }
before do
widget.update_attributes!(name: name, an_integer: 0)
widget.update_attributes!(name: "foobar", an_integer: 77)
widget.update_attributes!(name: FFaker::Name.last_name, an_integer: int)
end
context "YAML serializer" do
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::YAML }
it "locates versions according to their `object_changes` contents" do
expect(
widget.versions.where_object_changes(name: name)
).to eq(widget.versions[0..1])
expect(
widget.versions.where_object_changes(an_integer: 77)
).to eq(widget.versions[1..2])
expect(
widget.versions.where_object_changes(an_integer: int)
).to eq([widget.versions.last])
end
it "handles queries for multiple attributes" do
expect(
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
).to eq(widget.versions[1..2])
end
end
context "JSON serializer" do
before(:all) { PaperTrail.serializer = PaperTrail::Serializers::JSON }
specify { expect(PaperTrail.serializer).to be PaperTrail::Serializers::JSON }
it "locates versions according to their `object_changes` contents" do
expect(
widget.versions.where_object_changes(name: name)
).to eq(widget.versions[0..1])
expect(
widget.versions.where_object_changes(an_integer: 77)
).to eq(widget.versions[1..2])
expect(
widget.versions.where_object_changes(an_integer: int)
).to eq([widget.versions.last])
end
it "handles queries for multiple attributes" do
expect(
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
).to eq(widget.versions[1..2])
end
after(:all) { PaperTrail.serializer = PaperTrail::Serializers::YAML }
end
it "handles queries for multiple attributes" do
expect(
widget.versions.where_object_changes(an_integer: 77, name: "foobar")
).to eq(widget.versions[1..2])
end
after(:all) { PaperTrail.serializer = PaperTrail::Serializers::YAML }
end
end
end

View File

@ -52,16 +52,14 @@ describe Widget, type: :model do
describe "Callbacks", versioning: true do
describe "before_save" do
context ":on => :update" do
before { widget.update_attributes!(name: "Foobar") }
before { widget.update_attributes!(name: "Foobar") }
subject { widget.versions.last.reify }
subject { widget.versions.last.reify }
it "resets value for timestamp attrs for update so that value gets updated properly" do
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
expect { subject.save! }.to change(subject, :updated_at)
end
it "resets value for timestamp attrs for update so that value gets updated properly" do
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
expect { subject.save! }.to change(subject, :updated_at)
end
end
end
@ -153,207 +151,180 @@ describe Widget, type: :model do
end
end
describe "Methods" do
describe "Instance", versioning: true do
describe "#create" do
it "creates a version record" do
wordget = Widget.create
assert_equal 1, wordget.versions.length
end
end
describe "#create", versioning: true do
it "creates a version record" do
wordget = Widget.create
assert_equal 1, wordget.versions.length
end
end
describe "#destroy" do
it "creates a version record" do
widget = Widget.create
assert_equal 1, widget.versions.length
widget.destroy
versions_for_widget = PaperTrail::Version.with_item_keys("Widget", widget.id)
assert_equal 2, versions_for_widget.length
end
it "can have multiple destruction records" do
versions = lambda { |widget|
# Workaround for AR 3. When we drop AR 3 support, we can simply use
# the `widget.versions` association, instead of `with_item_keys`.
PaperTrail::Version.with_item_keys("Widget", widget.id)
}
widget = Widget.create
assert_equal 1, widget.versions.length
widget.destroy
assert_equal 2, versions.call(widget).length
widget = widget.version.reify
widget.save
assert_equal 3, versions.call(widget).length
widget.destroy
assert_equal 4, versions.call(widget).length
assert_equal 2, versions.call(widget).where(event: "destroy").length
end
end
describe "#paper_trail.originator" do
describe "return value" do
let(:orig_name) { FFaker::Name.name }
let(:new_name) { FFaker::Name.name }
before do
PaperTrail.whodunnit = orig_name
end
context "accessed from live model instance" do
specify { expect(widget.paper_trail).to be_live }
it "returns the originator for the model at a given state" do
expect(widget.paper_trail.originator).to eq(orig_name)
widget.paper_trail.whodunnit(new_name) { |w|
w.update_attributes(name: "Elizabeth")
}
expect(widget.paper_trail.originator).to eq(new_name)
end
end
context "accessed from a reified model instance" do
before do
widget.update_attributes(name: "Andy")
PaperTrail.whodunnit = new_name
widget.update_attributes(name: "Elizabeth")
end
context "default behavior (no `options[:dup]` option passed in)" do
let(:reified_widget) { widget.versions[1].reify }
it "returns the appropriate originator" do
expect(reified_widget.paper_trail.originator).to eq(orig_name)
end
it "does not create a new model instance" do
expect(reified_widget).not_to be_new_record
end
end
context "creating a new instance (`options[:dup] == true`)" do
let(:reified_widget) { widget.versions[1].reify(dup: true) }
it "returns the appropriate originator" do
expect(reified_widget.paper_trail.originator).to eq(orig_name)
end
it "does not create a new model instance" do
expect(reified_widget).to be_new_record
end
end
end
end
end
describe "#version_at" do
context "Timestamp argument is AFTER object has been destroyed" do
it "returns nil" do
widget.update_attribute(:name, "foobar")
widget.destroy
expect(widget.paper_trail.version_at(Time.now)).to be_nil
end
end
end
describe "#whodunnit" do
context "no block given" do
it "raises an error" do
expect {
widget.paper_trail.whodunnit("Ben")
}.to raise_error(ArgumentError, "expected to receive a block")
end
end
context "block given" do
let(:orig_name) { FFaker::Name.name }
let(:new_name) { FFaker::Name.name }
before do
PaperTrail.whodunnit = orig_name
expect(widget.versions.last.whodunnit).to eq(orig_name) # persist `widget`
end
it "modifies value of `PaperTrail.whodunnit` while executing the block" do
widget.paper_trail.whodunnit(new_name) do
expect(PaperTrail.whodunnit).to eq(new_name)
widget.update_attributes(name: "Elizabeth")
end
expect(widget.versions.last.whodunnit).to eq(new_name)
end
context "after executing the block" do
it "reverts value of whodunnit to previous value" do
widget.paper_trail.whodunnit(new_name) { |w|
w.update_attributes(name: "Elizabeth")
}
expect(PaperTrail.whodunnit).to eq(orig_name)
end
end
context "error within block" do
it "still reverts the whodunnit value to previous value" do
expect {
widget.paper_trail.whodunnit(new_name) { raise }
}.to raise_error(RuntimeError)
expect(PaperTrail.whodunnit).to eq(orig_name)
end
end
end
end
describe "#touch_with_version" do
it "creates a version" do
count = widget.versions.size
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
widget.paper_trail.touch_with_version
end
expect(widget.versions.size).to eq(count + 1)
end
it "increments the `:updated_at` timestamp" do
time_was = widget.updated_at
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
widget.paper_trail.touch_with_version
end
expect(widget.updated_at).to be > time_was
end
end
describe "#update" do
it "creates a version record" do
widget = Widget.create
assert_equal 1, widget.versions.length
widget.update_attributes(name: "Bugle")
assert_equal 2, widget.versions.length
end
end
describe "#destroy", versioning: true do
it "creates a version record" do
widget = Widget.create
assert_equal 1, widget.versions.length
widget.destroy
versions_for_widget = PaperTrail::Version.with_item_keys("Widget", widget.id)
assert_equal 2, versions_for_widget.length
end
describe "Class" do
describe ".paper_trail.enabled?" do
it "returns true" do
expect(Widget.paper_trail.enabled?).to eq(true)
end
it "can have multiple destruction records" do
versions = lambda { |widget|
# Workaround for AR 3. When we drop AR 3 support, we can simply use
# the `widget.versions` association, instead of `with_item_keys`.
PaperTrail::Version.with_item_keys("Widget", widget.id)
}
widget = Widget.create
assert_equal 1, widget.versions.length
widget.destroy
assert_equal 2, versions.call(widget).length
widget = widget.version.reify
widget.save
assert_equal 3, versions.call(widget).length
widget.destroy
assert_equal 4, versions.call(widget).length
assert_equal 2, versions.call(widget).where(event: "destroy").length
end
end
describe "#paper_trail.originator", versioning: true do
describe "return value" do
let(:orig_name) { FFaker::Name.name }
let(:new_name) { FFaker::Name.name }
before do
PaperTrail.whodunnit = orig_name
end
describe ".disable" do
it "sets the `paper_trail.enabled?` to `false`" do
expect(Widget.paper_trail.enabled?).to eq(true)
Widget.paper_trail.disable
expect(Widget.paper_trail.enabled?).to eq(false)
end
it "returns the originator for the model at a given state" do
expect(widget.paper_trail).to be_live
expect(widget.paper_trail.originator).to eq(orig_name)
widget.paper_trail.whodunnit(new_name) { |w|
w.update_attributes(name: "Elizabeth")
}
expect(widget.paper_trail.originator).to eq(new_name)
end
describe ".enable" do
it "sets the `paper_trail.enabled?` to `true`" do
Widget.paper_trail.disable
expect(Widget.paper_trail.enabled?).to eq(false)
Widget.paper_trail.enable
expect(Widget.paper_trail.enabled?).to eq(true)
end
it "returns the appropriate originator" do
widget.update_attributes(name: "Andy")
PaperTrail.whodunnit = new_name
widget.update_attributes(name: "Elizabeth")
reified_widget = widget.versions[1].reify
expect(reified_widget.paper_trail.originator).to eq(orig_name)
expect(reified_widget).not_to be_new_record
end
it "can create a new instance with options[:dup]" do
widget.update_attributes(name: "Andy")
PaperTrail.whodunnit = new_name
widget.update_attributes(name: "Elizabeth")
reified_widget = widget.versions[1].reify(dup: true)
expect(reified_widget.paper_trail.originator).to eq(orig_name)
expect(reified_widget).to be_new_record
end
end
end
describe "#version_at", versioning: true do
context "Timestamp argument is AFTER object has been destroyed" do
it "returns nil" do
widget.update_attribute(:name, "foobar")
widget.destroy
expect(widget.paper_trail.version_at(Time.now)).to be_nil
end
end
end
describe "#whodunnit", versioning: true do
context "no block given" do
it "raises an error" do
expect {
widget.paper_trail.whodunnit("Ben")
}.to raise_error(ArgumentError, "expected to receive a block")
end
end
context "block given" do
let(:orig_name) { FFaker::Name.name }
let(:new_name) { FFaker::Name.name }
before do
PaperTrail.whodunnit = orig_name
expect(widget.versions.last.whodunnit).to eq(orig_name) # persist `widget`
end
it "modifies value of `PaperTrail.whodunnit` while executing the block" do
widget.paper_trail.whodunnit(new_name) do
expect(PaperTrail.whodunnit).to eq(new_name)
widget.update_attributes(name: "Elizabeth")
end
expect(widget.versions.last.whodunnit).to eq(new_name)
end
it "reverts value of whodunnit to previous value after executing the block" do
widget.paper_trail.whodunnit(new_name) { |w|
w.update_attributes(name: "Elizabeth")
}
expect(PaperTrail.whodunnit).to eq(orig_name)
end
it "reverts to previous value, even if error within block" do
expect {
widget.paper_trail.whodunnit(new_name) { raise }
}.to raise_error(RuntimeError)
expect(PaperTrail.whodunnit).to eq(orig_name)
end
end
end
describe "#touch_with_version", versioning: true do
it "creates a version" do
count = widget.versions.size
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
widget.paper_trail.touch_with_version
end
expect(widget.versions.size).to eq(count + 1)
end
it "increments the `:updated_at` timestamp" do
time_was = widget.updated_at
# Travel 1 second because MySQL lacks sub-second resolution
Timecop.travel(1) do
widget.paper_trail.touch_with_version
end
expect(widget.updated_at).to be > time_was
end
end
describe "#update", versioning: true do
it "creates a version record" do
widget = Widget.create
assert_equal 1, widget.versions.length
widget.update_attributes(name: "Bugle")
assert_equal 2, widget.versions.length
end
end
describe ".paper_trail.enabled?" do
it "returns true" do
expect(Widget.paper_trail.enabled?).to eq(true)
end
end
describe ".disable" do
it "sets the `paper_trail.enabled?` to `false`" do
expect(Widget.paper_trail.enabled?).to eq(true)
Widget.paper_trail.disable
expect(Widget.paper_trail.enabled?).to eq(false)
end
end
describe ".enable" do
it "sets the `paper_trail.enabled?` to `true`" do
Widget.paper_trail.disable
expect(Widget.paper_trail.enabled?).to eq(false)
Widget.paper_trail.enable
expect(Widget.paper_trail.enabled?).to eq(true)
end
end
end