File: build_stubbed_spec.rb

package info (click to toggle)
ruby-factory-bot 6.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,372 kB
  • sloc: ruby: 7,827; makefile: 6
file content (299 lines) | stat: -rw-r--r-- 7,470 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
describe "a generated stub instance" do
  include FactoryBot::Syntax::Methods

  before do
    define_model("User")

    define_model("Post", title: :string,
      body: :string,
      age: :integer,
      user_id: :integer,
      draft: :boolean) do
      belongs_to :user
    end

    FactoryBot.define do
      factory :user

      factory :post do
        title { "default title" }
        body { "default body" }
        user
      end
    end
  end

  subject { build_stubbed(:post, title: "overridden title") }

  it "assigns a default attribute" do
    expect(subject.body).to eq "default body"
  end

  it "assigns an overridden attribute" do
    expect(subject.title).to eq "overridden title"
  end

  it "assigns associations" do
    expect(subject.user).to be_kind_of(User)
  end

  it "has an id" do
    expect(subject.id).to be > 0
  end

  it "generates unique ids" do
    other_stub = build_stubbed(:post)
    expect(subject.id).not_to eq other_stub.id
  end

  it "isn't a new record" do
    expect(subject).not_to be_new_record
  end

  it "assigns associations that aren't new records" do
    expect(subject.user).not_to be_new_record
  end

  it "isn't changed" do
    expect(subject).not_to be_changed
  end

  it "disables connection" do
    expect { subject.connection }.to raise_error(RuntimeError)
  end

  it "disables update_attribute" do
    expect { subject.update_attribute(:title, "value") }.to raise_error(RuntimeError)
  end

  it "disables reload" do
    expect { subject.reload }.to raise_error(RuntimeError)
  end

  it "disables destroy" do
    expect { subject.destroy }.to raise_error(RuntimeError)
  end

  it "disables save" do
    expect { subject.save }.to raise_error(RuntimeError)
  end

  it "disables increment!" do
    expect { subject.increment!(:age) }.to raise_error(RuntimeError)
  end

  it "disables decrement!" do
    expect { subject.decrement!(:age) }.to raise_error(RuntimeError)
  end

  it "disables toggle!" do
    expect { subject.toggle!(:draft) }.to raise_error(RuntimeError)
  end

  it "allows increment" do
    subject.age = 1
    subject.increment(:age)
    expect(subject.age).to eq(2)
  end

  it "allows decrement" do
    subject.age = 1
    subject.decrement(:age)
    expect(subject.age).to eq(0)
  end

  it "allows toggle" do
    subject.draft = true
    subject.toggle(:draft)
    expect(subject).not_to be_draft
  end
end

describe "calling `build_stubbed` with a block" do
  include FactoryBot::Syntax::Methods

  before do
    define_model("Company", name: :string)

    FactoryBot.define do
      factory :company
    end
  end

  it "passes the stub instance" do
    build_stubbed(:company, name: "thoughtbot") do |company|
      expect(company.name).to eq("thoughtbot")
      expect { company.save }.to raise_error(RuntimeError)
    end
  end

  it "returns the stub instance" do
    expected = nil
    result = build_stubbed(:company) { |company|
      expected = company
      "hello!"
    }
    expect(result).to eq expected
  end
end

describe "defaulting `created_at`" do
  include FactoryBot::Syntax::Methods

  before do
    define_model("ThingWithTimestamp", created_at: :datetime)
    define_model("ThingWithoutTimestamp")

    FactoryBot.define do
      factory :thing_with_timestamp
      factory :thing_without_timestamp
    end
  end

  it "defaults created_at for objects with created_at" do
    expect(build_stubbed(:thing_with_timestamp).created_at).to be_about_now
  end

  it "is doesn't mark the object as changed" do
    stub = build_stubbed(:thing_with_timestamp)
    expect(stub).not_to be_changed
  end

  it "doesn't add created_at to objects who don't have the method" do
    expect(build_stubbed(:thing_without_timestamp))
      .not_to respond_to(:created_at)
  end

  it "allows overriding created_at for objects with created_at" do
    created_at = 3.days.ago
    stubbed = build_stubbed(:thing_with_timestamp, created_at: created_at)
    expect(stubbed.created_at).to be_within(1.second).of created_at
  end

  it "doesn't allow setting created_at on an object that doesn't define it" do
    expect { build_stubbed(:thing_without_timestamp, created_at: Time.now) }
      .to raise_error(NoMethodError, /created_at=/)
  end

  it "allows assignment of created_at" do
    stub = build_stubbed(:thing_with_timestamp)
    expect(stub.created_at).to be_about_now
    past_time = 3.days.ago
    stub.created_at = past_time
    expect(stub.created_at).to be_within(1.second).of past_time
  end

  it "behaves the same as a non-stubbed created_at" do
    define_model("ThingWithCreatedAt", created_at: :datetime) do
      def created_at
        :the_real_created_at
      end
    end

    FactoryBot.define do
      factory :thing_with_created_at
    end

    stub = build_stubbed(:thing_with_created_at)
    persisted = create(:thing_with_created_at)

    expect(stub.created_at).to eq(persisted.created_at)
  end
end

describe "defaulting `updated_at`" do
  include FactoryBot::Syntax::Methods

  before do
    define_model("ThingWithTimestamp", updated_at: :datetime)
    define_model("ThingWithoutTimestamp")

    FactoryBot.define do
      factory :thing_with_timestamp
      factory :thing_without_timestamp
    end
  end

  it "defaults updated_at for objects with updated_at" do
    expect(build_stubbed(:thing_with_timestamp).updated_at).to be_about_now
  end

  it "is doesn't mark the object as changed" do
    stub = build_stubbed(:thing_with_timestamp)
    expect(stub).not_to be_changed
  end

  it "doesn't add updated_at to objects who don't have the method" do
    expect(build_stubbed(:thing_without_timestamp))
      .not_to respond_to(:updated_at)
  end

  it "allows overriding updated_at for objects with updated_at" do
    past_time = 3.days.ago
    stubbed = build_stubbed(:thing_with_timestamp, updated_at: past_time)
    expect(stubbed.updated_at).to be_within(1.second).of past_time
  end

  it "doesn't allow setting updated_at on an object that doesn't define it" do
    expect {
      build_stubbed(:thing_without_timestamp, updated_at: Time.now)
    }.to raise_error(NoMethodError, /updated_at=/)
  end

  it "allows assignment of updated_at" do
    stub = build_stubbed(:thing_with_timestamp)
    expect(stub.updated_at).to be_about_now
    past_time = 3.days.ago
    stub.updated_at = past_time
    expect(stub.updated_at).to be_within(1.second).of past_time
  end

  it "behaves the same as a non-stubbed updated_at" do
    define_model("ThingWithUpdatedAt", updated_at: :datetime) do
      def updated_at
        :the_real_updated_at
      end
    end

    FactoryBot.define do
      factory :thing_with_updated_at
    end

    stub = build_stubbed(:thing_with_updated_at)
    persisted = create(:thing_with_updated_at)

    expect(stub.updated_at).to eq(persisted.updated_at)
  end
end

describe "defaulting `id`" do
  before do
    define_model("Post")

    FactoryBot.define do
      factory :post
    end
  end

  it "allows overriding id" do
    expect(FactoryBot.build_stubbed(:post, id: 12).id).to eq 12
  end
end

describe "configuring the starting id" do
  it "defines which id build_stubbed instances start with" do
    define_model("Post")

    FactoryBot.define do
      factory :post
    end

    FactoryBot.build_stubbed_starting_id = 1000

    expect(FactoryBot.build_stubbed(:post).id).to eq 1000

    FactoryBot.build_stubbed_starting_id = 3000

    expect(FactoryBot.build_stubbed(:post).id).to eq 3000
  end
end