Allow rewinding of sequences

This commit is contained in:
Daniel Colson 2017-09-30 23:06:14 -04:00 committed by Joshua Clayton
parent e083f4a904
commit 50eeb67241
No known key found for this signature in database
GPG Key ID: 5B6558F77E9A8118
4 changed files with 104 additions and 43 deletions

View File

@ -111,6 +111,10 @@ module FactoryBot
sequences.find(name)
end
def self.rewind_sequences
sequences.each(&:rewind)
end
def self.register_trait(trait)
trait.names.each do |name|
traits.register(name, trait)

View File

@ -35,6 +35,10 @@ module FactoryBot
[@name] + @aliases
end
def rewind
@value.rewind
end
private
def value
@ -47,6 +51,7 @@ module FactoryBot
class EnumeratorAdapter
def initialize(value)
@first_value = value
@value = value
end
@ -57,6 +62,10 @@ module FactoryBot
def next
@value = @value.next
end
def rewind
@value = @first_value
end
end
end
end

View File

@ -0,0 +1,25 @@
require "spec_helper"
describe "FactoryBot.rewind_sequences" do
include FactoryBot::Syntax::Methods
it "resets all sequences back to their starting values" do
FactoryBot.define do
sequence(:email) { |n| "somebody#{n}@example.com" }
sequence(:name, %w[Joe Josh].to_enum)
end
2.times do
generate(:email)
generate(:name)
end
FactoryBot.rewind_sequences
email = generate(:email)
name = generate(:name)
expect(email).to eq "somebody1@example.com"
expect(name).to eq "Joe"
end
end

View File

@ -1,4 +1,25 @@
require 'spec_helper'
require "spec_helper"
shared_examples "a sequence" do |options|
first_value = options[:first_value]
second_value = options[:second_value]
its(:next) { should eq first_value }
context "when incrementing" do
before { subject.next }
its(:next) { should eq second_value }
end
context "after rewinding" do
before do
subject.next
subject.rewind
end
its(:next) { should eq first_value }
end
end
describe FactoryBot::Sequence do
describe "a basic sequence" do
@ -7,88 +28,90 @@ describe FactoryBot::Sequence do
its(:name) { should eq name }
its(:names) { should eq [name] }
its(:next) { should eq "=1" }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq "=2" }
end
it_behaves_like "a sequence", first_value: "=1", second_value: "=2"
end
describe "a custom sequence" do
subject { FactoryBot::Sequence.new(:name, "A") { |n| "=#{n}" } }
its(:next) { should eq "=A" }
subject { FactoryBot::Sequence.new(:name, "A") { |n| "=#{n}" } }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq "=B" }
end
it_behaves_like "a sequence", first_value: "=A", second_value: "=B"
end
describe "a sequence with aliases using default value" do
subject { FactoryBot::Sequence.new(:test, aliases: [:alias, :other]) { |n| "=#{n}" } }
its(:next) { should eq "=1" }
subject do
FactoryBot::Sequence.new(:test, aliases: [:alias, :other]) do |n|
"=#{n}"
end
end
its(:names) { should eq [:test, :alias, :other] }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq "=2" }
end
it_behaves_like "a sequence", first_value: "=1", second_value: "=2"
end
describe "a sequence with custom value and aliases" do
subject { FactoryBot::Sequence.new(:test, 3, aliases: [:alias, :other]) { |n| "=#{n}" } }
its(:next) { should eq "=3" }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq "=4" }
subject do
FactoryBot::Sequence.new(:test, 3, aliases: [:alias, :other]) do |n|
"=#{n}"
end
end
its(:names) { should eq [:test, :alias, :other] }
it_behaves_like "a sequence", first_value: "=3", second_value: "=4"
end
describe "a basic sequence without a block" do
subject { FactoryBot::Sequence.new(:name) }
its(:next) { should eq 1 }
subject { FactoryBot::Sequence.new(:name) }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq 2 }
end
it_behaves_like "a sequence", first_value: 1, second_value: 2
end
describe "a custom sequence without a block" do
subject { FactoryBot::Sequence.new(:name, "A") }
its(:next) { should eq "A" }
subject { FactoryBot::Sequence.new(:name, "A") }
describe "when incrementing" do
before { subject.next }
its(:next) { should eq "B" }
end
it_behaves_like "a sequence", first_value: "A", second_value: "B"
end
describe "iterating over items in an enumerator" do
subject { FactoryBot::Sequence.new(:name, %w[foo bar].to_enum) { |n| "=#{n}" } }
subject do
FactoryBot::Sequence.new(:name, %w[foo bar].to_enum) { |n| "=#{n}" }
end
it "navigates to the next items until no items remain" do
expect(subject.next).to eq "=foo"
expect(subject.next).to eq "=bar"
expect { subject.next }.to raise_error(StopIteration)
end
it_behaves_like "a sequence", first_value: "=foo", second_value: "=bar"
end
describe "a custom sequence and scope" do
subject { FactoryBot::Sequence.new(:name, 'A') { |n| "=#{n}#{foo}" } }
subject { FactoryBot::Sequence.new(:name, "A") { |n| "=#{n}#{foo}" } }
let(:scope) { double("scope", foo: "attribute") }
it 'increments within the correct scope' do
expect(subject.next(scope)).to eq '=Aattribute'
it "increments within the correct scope" do
expect(subject.next(scope)).to eq "=Aattribute"
end
describe 'when incrementing' do
context "when incrementing" do
before { subject.next(scope) }
it 'increments within the correct scope' do
expect(subject.next(scope)).to eq '=Battribute'
it "increments within the correct scope" do
expect(subject.next(scope)).to eq "=Battribute"
end
end
context "after rewinding" do
before do
subject.next(scope)
subject.rewind
end
it "increments within the correct scope" do
expect(subject.next(scope)).to eq "=Aattribute"
end
end
end