spec/unit/attribute_spec.rb in attr_masker-0.2.1 vs spec/unit/attribute_spec.rb in attr_masker-0.3.0
- old
+ new
@@ -14,21 +14,21 @@
expect(retval.model).to eq(:some_model)
expect(retval.options).to eq(opts)
end
end
- describe "#column_name" do
- subject { receiver.method :column_name }
+ describe "#column_names" do
+ subject { receiver.method :column_names }
let(:receiver) { described_class.new :some_attr, :some_model, options }
let(:options) { {} }
- it "defaults to attribute name" do
- expect(subject.call).to eq(:some_attr)
+ it "defaults to array containing attribute name only" do
+ expect(subject.call).to contain_exactly(:some_attr)
end
- it "can be overriden with :column_name option" do
- options[:column_name] = :some_column
+ it "can be overriden with :column_names option" do
+ options[:column_names] = :some_column
expect(subject.call).to eq(:some_column)
end
end
describe "#should_mask?" do
@@ -51,9 +51,91 @@
def retval_for_opts(opts)
receiver = described_class.new(:some_attr, :some_model, opts)
callable = subject.bind(receiver)
callable.(model_instance)
end
+ end
+
+ describe "mask" do
+ subject { described_class.instance_method :mask }
+ let(:receiver) { described_class.new :some_attr, :some_model, options }
+ let(:model_instance) { Struct.new(:some_attr).new("value") }
+ let(:options) { { masker: masker } }
+ let(:masker) { ->(**) { "masked_value" } }
+
+ it "takes the instance.options[:masker] and calls it" do
+ expect(masker).to receive(:call)
+ subject.bind(receiver).call(model_instance)
+ end
+
+ it "passes the unmarshalled attribute value to the masker" do
+ expect(receiver).to receive(:unmarshal_data).
+ with("value").and_return("unmarshalled_value")
+ expect(masker).to receive(:call).
+ with(hash_including(value: "unmarshalled_value"))
+ subject.bind(receiver).call(model_instance)
+ end
+
+ it "passes the model instance to the masker" do
+ expect(masker).to receive(:call).
+ with(hash_including(model: model_instance))
+ subject.bind(receiver).call(model_instance)
+ end
+
+ it "passes the attribute name to the masker" do
+ expect(masker).to receive(:call).
+ with(hash_including(attribute_name: :some_attr))
+ subject.bind(receiver).call(model_instance)
+ end
+
+ it "passes the masking options to the masker" do
+ expect(masker).to receive(:call).
+ with(hash_including(masking_options: options))
+ subject.bind(receiver).call(model_instance)
+ end
+
+ it "marshals the masked value, and assigns it to the attribute" do
+ expect(receiver).to receive(:marshal_data).
+ with("masked_value").and_return("marshalled_masked_value")
+ subject.bind(receiver).call(model_instance)
+ expect(model_instance.some_attr).to eq("marshalled_masked_value")
+ end
+ end
+
+ describe "#masked_attributes_new_values" do
+ subject { receiver.method :masked_attributes_new_values }
+ let(:receiver) { described_class.new :some_attr, :some_model, options }
+ let(:options) { {} }
+ let(:model_instance) { double } # Struct.new(:some_attr, :other_attr) }
+ let(:changes) { { some_attr: [nil, "new"], other_attr: [nil, "other"] } }
+
+ before { allow(model_instance).to receive(:changes).and_return(changes) }
+
+ # rubocop:disable Style/BracesAroundHashParameters
+ # We are comparing hashes here, and we want hash literals
+ it "returns a hash of required database updates which include masked field \
+ change, but ignores other attribute changes" do
+ expect(subject.(model_instance)).to eq({ some_attr: "new" })
+ end
+
+ it "returns an emtpy hash for an unchanged object" do
+ changes.clear
+ expect(subject.(model_instance)).to eq({})
+ end
+
+ it "allows overriding column/field name to be updated with column_name \
+ option" do
+ options[:column_names] = %i[other_attr]
+ expect(subject.(model_instance)).to eq({ other_attr: "other" })
+ end
+
+ it "allows specifying more than one column/field name to be updated \
+ with column_name option" do
+ options[:column_names] = %i[some_attr other_attr]
+ expect(subject.(model_instance)).
+ to eq({ some_attr: "new", other_attr: "other" })
+ end
+ # rubocop:enable Style/BracesAroundHashParameters
end
describe "#evaluate_option" do
subject { receiver.method :evaluate_option }
let(:receiver) { described_class.new :some_attr, model_instance, options }