shared_examples_for "has options" do |object|
  if object.respond_to?(:call)
    subject { object.call }
  else
    subject { object }
  end

  describe "dump options" do
    before do
      subject.dump_options = nil
    end

    after do
      subject.dump_options = nil
    end

    it "returns default options if not set" do
      expect(subject.dump_options).to eq(subject.default_dump_options)
    end

    it "allows hashes" do
      subject.dump_options = {foo: "bar"}
      expect(subject.dump_options).to eq(foo: "bar")
    end

    it "allows objects that implement #to_hash" do
      value = Class.new do
        def to_hash
          {foo: "bar"}
        end
      end.new

      subject.dump_options = value
      expect(subject.dump_options).to eq(foo: "bar")
    end

    it "evaluates lambda returning options (with args)" do
      subject.dump_options = ->(a1, a2) { {a1 => a2} }
      expect(subject.dump_options("1", "2")).to eq("1" => "2")
    end

    it "evaluates lambda returning options (with no args)" do
      subject.dump_options = -> { {foo: "bar"} }
      expect(subject.dump_options).to eq(foo: "bar")
    end

    it "returns empty hash in all other cases" do
      subject.dump_options = true
      expect(subject.dump_options).to eq(subject.default_dump_options)

      subject.dump_options = false
      expect(subject.dump_options).to eq(subject.default_dump_options)

      subject.dump_options = 10
      expect(subject.dump_options).to eq(subject.default_dump_options)

      subject.dump_options = nil
      expect(subject.dump_options).to eq(subject.default_dump_options)
    end
  end

  describe "load options" do
    before do
      subject.load_options = nil
    end

    after do
      subject.load_options = nil
    end

    it "returns default options if not set" do
      expect(subject.load_options).to eq(subject.default_load_options)
    end

    it "allows hashes" do
      subject.load_options = {foo: "bar"}
      expect(subject.load_options).to eq(foo: "bar")
    end

    it "allows objects that implement #to_hash" do
      value = Class.new do
        def to_hash
          {foo: "bar"}
        end
      end.new

      subject.load_options = value
      expect(subject.load_options).to eq(foo: "bar")
    end

    it "evaluates lambda returning options (with args)" do
      subject.load_options = ->(a1, a2) { {a1 => a2} }
      expect(subject.load_options("1", "2")).to eq("1" => "2")
    end

    it "evaluates lambda returning options (with no args)" do
      subject.load_options = -> { {foo: "bar"} }
      expect(subject.load_options).to eq(foo: "bar")
    end

    it "returns empty hash in all other cases" do
      subject.load_options = true
      expect(subject.load_options).to eq(subject.default_load_options)

      subject.load_options = false
      expect(subject.load_options).to eq(subject.default_load_options)

      subject.load_options = 10
      expect(subject.load_options).to eq(subject.default_load_options)

      subject.load_options = nil
      expect(subject.load_options).to eq(subject.default_load_options)
    end
  end
end
