-
Notifications
You must be signed in to change notification settings - Fork 145
/
ex_machina_test.exs
234 lines (185 loc) · 6.26 KB
/
ex_machina_test.exs
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
defmodule ExMachinaTest do
use ExUnit.Case
defmodule FooBar do
defstruct [:name]
end
defmodule Factory do
use ExMachina
def user_factory do
%{
id: 3,
name: "John Doe",
admin: false
}
end
def profile_factory do
%{
username: sequence("username"),
user: build(:user)
}
end
def account_factory do
%{
private: true,
profile: fn -> build(:profile) end
}
end
def admin_account_factory do
%{
admin: true,
profile: fn account -> build(:profile, admin: account.admin) end
}
end
def email_factory do
%{
email: sequence(:email, &"me-#{&1}@foo.com")
}
end
def article_factory do
%{
title: sequence("Post Title")
}
end
def foo_bar_factory do
%FooBar{}
end
def comment_factory(attrs) do
%{name: name} = attrs
username = sequence(:username, &"#{name}-#{&1}")
comment = %{
author: "#{name} Doe",
username: username
}
merge_attributes(comment, attrs)
end
def room_number_factory(attrs) do
%{floor: floor_number} = attrs
sequence(:room_number, &"#{floor_number}0#{&1}")
end
end
describe "sequence" do
test "sequence/2 sequences a value" do
assert "me-0@foo.com" == Factory.build(:email).email
assert "me-1@foo.com" == Factory.build(:email).email
end
test "sequence/1 shortcut for creating sequences" do
assert "Post Title0" == Factory.build(:article).title
assert "Post Title1" == Factory.build(:article).title
end
end
describe "build/2" do
test "raises a helpful error if the factory is not defined" do
assert_raise ExMachina.UndefinedFactoryError, fn ->
Factory.build(:foo)
end
end
test "build/2 returns the matching factory" do
assert Factory.build(:user) == %{
id: 3,
name: "John Doe",
admin: false
}
end
test "build/2 merges passed in options as keyword list" do
assert Factory.build(:user, admin: true) == %{
id: 3,
name: "John Doe",
admin: true
}
end
test "build/2 merges passed in options as a map" do
assert Factory.build(:user, %{admin: true}) == %{
id: 3,
name: "John Doe",
admin: true
}
end
test "build/2 raises if passing invalid keys to a struct factory" do
assert_raise KeyError, fn ->
Factory.build(:foo_bar, doesnt_exist: true)
end
end
test "build/2 allows factories to have full control of provided arguments" do
comment = Factory.build(:comment, name: "James")
assert %{author: "James Doe", name: "James"} = comment
assert String.starts_with?(comment[:username], "James-")
end
test "build/2 allows custom (non-map) factories to be built" do
assert Factory.build(:room_number, floor: 5) == "500"
assert Factory.build(:room_number, floor: 5) == "501"
end
test "build/2 accepts anonymous functions for a factory's attributes" do
account = Factory.build(:account)
assert %{username: _} = account.profile
end
test "build/2 accepts anonymous functions that use parent record in factory's definition" do
assert %{profile: %{admin: true}} = Factory.build(:admin_account, admin: true)
assert %{profile: %{admin: false}} = Factory.build(:admin_account, admin: false)
end
test "build/2 can take anonymous functions for attributes" do
user = Factory.build(:user, foo_bar: fn -> Factory.build(:foo_bar) end)
assert %FooBar{} = user.foo_bar
end
test "build/2 does not evaluate lazy attributes when factory definition has full control" do
comment = Factory.build(:comment, name: "James", user: fn -> Factory.build(:user) end)
assert is_function(comment.user)
assert %{id: 3, name: "John Doe", admin: false} = comment.user.()
end
test "build/2 recursively builds nested lazy attributes" do
lazy_profile = fn -> Factory.build(:profile, user: fn -> Factory.build(:user) end) end
account = Factory.build(:account, profile: lazy_profile)
assert %{username: _} = account.profile
assert %{name: "John Doe", admin: false} = account.profile.user
end
test "build/2 lazily evaluates an attribute that is a list" do
user = Factory.build(:user, profiles: fn -> [Factory.build(:profile)] end)
profile = hd(user.profiles)
assert Map.has_key?(profile, :username)
assert Map.has_key?(profile, :user)
end
end
describe "build_pair/2" do
test "build_pair/2 builds 2 factories" do
records = Factory.build_pair(:user, admin: true)
expected_record = %{
id: 3,
name: "John Doe",
admin: true
}
assert records == [expected_record, expected_record]
end
test "build_pair/2 recursively builds many nested lazy attributes" do
lazy_profile = fn -> Factory.build(:profile, user: fn -> Factory.build(:user) end) end
[account1, account2] = Factory.build_pair(:account, profile: lazy_profile)
assert account1.profile.username != account2.profile.username
end
end
describe "build_list/3" do
test "build_list/3 builds the factory the passed in number of times" do
records = Factory.build_list(3, :user, admin: true)
expected_record = %{
id: 3,
name: "John Doe",
admin: true
}
assert records == [expected_record, expected_record, expected_record]
end
test "build_list/3 handles the number 0" do
assert [] = Factory.build_list(0, :user)
end
test "raises helpful error when using old create functions" do
assert_raise RuntimeError, ~r/create\/1 has been removed/, fn ->
Factory.create(:user)
end
assert_raise RuntimeError, ~r/create\/2 has been removed/, fn ->
Factory.create(:user, admin: true)
end
assert_raise RuntimeError, ~r/create_pair\/2 has been removed/, fn ->
Factory.create_pair(:user, admin: true)
end
assert_raise RuntimeError, ~r/create_list\/3 has been removed/, fn ->
Factory.create_list(3, :user, admin: true)
end
end
end
end