diff --git a/spec/factory_bot/factory_spec.rb b/spec/factory_bot/factory_spec.rb index f7fa560..247d24e 100644 --- a/spec/factory_bot/factory_spec.rb +++ b/spec/factory_bot/factory_spec.rb @@ -1,17 +1,19 @@ describe FactoryBot::Factory do - before do - @name = :user - @class = define_class("User") - @factory = FactoryBot::Factory.new(@name) - FactoryBot::Internal.register_factory(@factory) - end - it "has a factory name" do - expect(@factory.name).to eq @name + name = :user + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + + expect(factory.name).to eq name end it "has a build class" do - expect(@factory.build_class).to eq @class + name = :user + klass = define_class("User") + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + + expect(factory.build_class).to eq klass end it "returns associations" do @@ -41,214 +43,284 @@ describe FactoryBot::Factory do end describe "when overriding generated attributes with a hash" do - before do - @name = :name - @value = "The price is right!" - @hash = { @name => @value } - end - it "returns the overridden value in the generated attributes" do + name = :name + value = "The price is right!" + hash = { name => value } + define_class("Name") + factory = FactoryBot::Factory.new(name) declaration = - FactoryBot::Declaration::Dynamic.new(@name, false, -> { flunk }) - @factory.declare_attribute(declaration) - result = @factory.run(FactoryBot::Strategy::AttributesFor, @hash) - expect(result[@name]).to eq @value + FactoryBot::Declaration::Dynamic.new(name, false, -> { flunk }) + factory.declare_attribute(declaration) + result = factory.run(FactoryBot::Strategy::AttributesFor, hash) + expect(result[name]).to eq value end it "overrides a symbol parameter with a string parameter" do + name = :name + define_class("Name") + value = "The price is right!" + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) declaration = - FactoryBot::Declaration::Dynamic.new(@name, false, -> { flunk }) - @factory.declare_attribute(declaration) - @hash = { @name.to_s => @value } - result = @factory.run(FactoryBot::Strategy::AttributesFor, @hash) - expect(result[@name]).to eq @value + FactoryBot::Declaration::Dynamic.new(name, false, -> { flunk }) + factory.declare_attribute(declaration) + hash = { name.to_s => value } + result = factory.run(FactoryBot::Strategy::AttributesFor, hash) + + expect(result[name]).to eq value end end describe "overriding an attribute with an alias" do - before do + it "uses the passed in value for the alias" do + name = :user + define_class("User") + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) attribute = FactoryBot::Declaration::Dynamic.new( :test, false, -> { "original" } ) - @factory.declare_attribute(attribute) + factory.declare_attribute(attribute) FactoryBot.aliases << [/(.*)_alias/, '\1'] - @result = @factory.run( + result = factory.run( FactoryBot::Strategy::AttributesFor, test_alias: "new", ) - end - it "uses the passed in value for the alias" do - expect(@result[:test_alias]).to eq "new" + expect(result[:test_alias]).to eq "new" end it "discards the predefined value for the attribute" do - expect(@result[:test]).to be_nil + name = :user + define_class("User") + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + attribute = FactoryBot::Declaration::Dynamic.new( + :test, + false, -> { "original" } + ) + factory.declare_attribute(attribute) + FactoryBot.aliases << [/(.*)_alias/, '\1'] + result = factory.run( + FactoryBot::Strategy::AttributesFor, + test_alias: "new", + ) + + expect(result[:test]).to be_nil end end it "guesses the build class from the factory name" do - expect(@factory.build_class).to eq User + name = :user + define_class("User") + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + + expect(factory.build_class).to eq User end it "creates a new factory using the class of the parent" do - child = FactoryBot::Factory.new(:child, parent: @factory.name) + name = :user + define_class("User") + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + + child = FactoryBot::Factory.new(:child, parent: factory.name) child.compile - expect(child.build_class).to eq @factory.build_class + expect(child.build_class).to eq factory.build_class end it "creates a new factory while overriding the parent class" do - child = FactoryBot::Factory.new(:child, class: String, parent: @factory.name) + name = :user + factory = FactoryBot::Factory.new(name) + FactoryBot::Internal.register_factory(factory) + + child = FactoryBot::Factory.new(:child, class: String, parent: factory.name) child.compile expect(child.build_class).to eq String end end describe FactoryBot::Factory, "when defined with a custom class" do - subject { FactoryBot::Factory.new(:author, class: Float) } - its(:build_class) { should eq Float } + it "is an instance of that custom class" do + factory = FactoryBot::Factory.new(:author, class: Float) + expect(factory.build_class).to eq Float + end end describe FactoryBot::Factory, "when given a class that overrides #to_s" do - let(:overriding_class) { Overriding::Class } - - before do + it "sets build_class correctly" do define_class("Overriding") define_class("Overriding::Class") do def self.to_s "Overriding" end end - end + overriding_class = Overriding::Class + factory = FactoryBot::Factory.new(:overriding_class, class: Overriding::Class) - subject { FactoryBot::Factory.new(:overriding_class, class: Overriding::Class) } - - it "sets build_class correctly" do - expect(subject.build_class).to eq overriding_class + expect(factory.build_class).to eq overriding_class end end describe FactoryBot::Factory, "when defined with a class instead of a name" do - let(:factory_class) { ArgumentError } - let(:name) { :argument_error } + it "has a name" do + klass = ArgumentError + name = :argument_error + factory = FactoryBot::Factory.new(klass) - subject { FactoryBot::Factory.new(factory_class) } + expect(factory.name).to eq name + end - its(:name) { should eq name } - its(:build_class) { should eq factory_class } + it "has a build_class" do + klass = ArgumentError + factory = FactoryBot::Factory.new(klass) + + expect(factory.build_class).to eq klass + end end describe FactoryBot::Factory, "when defined with a custom class name" do - subject { FactoryBot::Factory.new(:author, class: :argument_error) } - its(:build_class) { should eq ArgumentError } + it "has a build_class equal to its custom class name" do + factory = FactoryBot::Factory.new(:author, class: :argument_error) + + expect(factory.build_class).to eq ArgumentError + end end describe FactoryBot::Factory, "with a name ending in s" do - let(:name) { :business } - let(:business_class) { Business } + it "has a name" do + factory = FactoryBot::Factory.new(:business) - before { define_class("Business") } - subject { FactoryBot::Factory.new(name) } + expect(factory.name).to eq :business + end - its(:name) { should eq name } - its(:build_class) { should eq business_class } + it "has a build class" do + define_class("Business") + factory = FactoryBot::Factory.new(:business) + + expect(factory.build_class).to eq Business + end end describe FactoryBot::Factory, "with a string for a name" do - let(:name) { :string } - subject { FactoryBot::Factory.new(name.to_s) } - its(:name) { should eq name } + it "has a name" do + name = :string + factory = FactoryBot::Factory.new(name.to_s) + + expect(factory.name).to eq name + end end describe FactoryBot::Factory, "for namespaced class" do - let(:name) { :settings } - let(:settings_class) { Admin::Settings } - - before do + it "sets build_class correctly with a namespaced class with Namespace::Class syntax" do + name = :settings define_class("Admin") define_class("Admin::Settings") + settings_class = Admin::Settings + factory = FactoryBot::Factory.new(name, class: "Admin::Settings") + + expect(factory.build_class).to eq settings_class end - context "with a namespaced class with Namespace::Class syntax" do - subject { FactoryBot::Factory.new(name, class: "Admin::Settings") } + it "sets build_class correctly with a namespaced class with namespace/class syntax" do + name = :settings + define_class("Admin") + define_class("Admin::Settings") + settings_class = Admin::Settings + factory = FactoryBot::Factory.new(name, class: "admin/settings") - it "sets build_class correctly" do - expect(subject.build_class).to eq settings_class - end - end - - context "with a namespaced class with namespace/class syntax" do - subject { FactoryBot::Factory.new(name, class: "admin/settings") } - - it "sets build_class correctly" do - expect(subject.build_class).to eq settings_class - end + expect(factory.build_class).to eq settings_class end end describe FactoryBot::Factory, "human names" do - context "factory name without underscores" do - subject { FactoryBot::Factory.new(:user) } - its(:names) { should eq [:user] } - its(:human_names) { should eq ["user"] } + it "parses names without underscores" do + factory = FactoryBot::Factory.new(:user) + + expect(factory.names).to eq [:user] end - context "factory name with underscores" do - subject { FactoryBot::Factory.new(:happy_user) } - its(:names) { should eq [:happy_user] } - its(:human_names) { should eq ["happy user"] } + it "parses human names without underscores" do + factory = FactoryBot::Factory.new(:user) + + expect(factory.human_names).to eq ["user"] end - context "factory name with big letters" do - subject { FactoryBot::Factory.new(:LoL) } - its(:names) { should eq [:LoL] } - its(:human_names) { should eq ["lol"] } + it "parses names with underscores" do + factory = FactoryBot::Factory.new(:happy_user) + + expect(factory.names).to eq [:happy_user] end - context "factory name with aliases" do - subject { FactoryBot::Factory.new(:happy_user, aliases: [:gleeful_user, :person]) } - its(:names) { should eq [:happy_user, :gleeful_user, :person] } - its(:human_names) { should eq ["happy user", "gleeful user", "person"] } + it "parses human names with underscores" do + factory = FactoryBot::Factory.new(:happy_user) + + expect(factory.human_names).to eq ["happy user"] + end + + it "parses names with big letters" do + factory = FactoryBot::Factory.new(:LoL) + + expect(factory.names).to eq [:LoL] + end + + it "parses human names with big letters" do + factory = FactoryBot::Factory.new(:LoL) + + expect(factory.human_names).to eq ["lol"] + end + + it "parses names with aliases" do + factory = FactoryBot::Factory.new(:happy_user, aliases: [:gleeful_user, :person]) + + expect(factory.names).to eq [:happy_user, :gleeful_user, :person] + end + + it "parses human names with aliases" do + factory = FactoryBot::Factory.new(:happy_user, aliases: [:gleeful_user, :person]) + + expect(factory.human_names).to eq ["happy user", "gleeful user", "person"] end end describe FactoryBot::Factory, "running a factory" do - subject { FactoryBot::Factory.new(:user) } - let(:attribute) do - FactoryBot::Attribute::Dynamic.new(:name, false, -> { "value" }) - end - let(:declaration) do - FactoryBot::Declaration::Dynamic.new(:name, false, -> { "value" }) - end - let(:strategy) { double("strategy", result: "result", add_observer: true) } - let(:attributes) { [attribute] } - let(:attribute_list) do - double("attribute-list", declarations: [declaration], to_a: attributes) - end - - before do + def build_factory + attribute = FactoryBot::Attribute::Dynamic.new(:name, false, -> { "value" }) + attributes = [attribute] + declaration = FactoryBot::Declaration::Dynamic.new(:name, false, -> { "value" }) + strategy = double("strategy", result: "result", add_observer: true) define_model("User", name: :string) allow(FactoryBot::Declaration::Dynamic).to receive(:new). and_return declaration allow(declaration).to receive(:to_attributes).and_return attributes allow(FactoryBot::Strategy::Build).to receive(:new).and_return strategy - subject.declare_attribute(declaration) + factory = FactoryBot::Factory.new(:user) + factory.declare_attribute(declaration) + factory end it "creates the right strategy using the build class when running" do - subject.run(FactoryBot::Strategy::Build, {}) + factory = build_factory + factory.run(FactoryBot::Strategy::Build, {}) + expect(FactoryBot::Strategy::Build).to have_received(:new).once end it "returns the result from the strategy when running" do - expect(subject.run(FactoryBot::Strategy::Build, {})).to eq "result" + factory = build_factory + + expect(factory.run(FactoryBot::Strategy::Build, {})).to eq "result" end it "calls the block and returns the result" do + factory = build_factory + block_run = nil block = ->(_result) { block_run = "changed" } - subject.run(FactoryBot::Strategy::Build, {}, &block) + factory.run(FactoryBot::Strategy::Build, {}, &block) expect(block_run).to eq "changed" end end