factory_manager 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/factory_manager/generator.rb +142 -0
- data/lib/factory_manager.rb +12 -124
- metadata +40 -38
- data/spec/lib/factory_manager_spec.rb +0 -223
- data/spec/spec_helper.rb +0 -30
- data/spec/support/database/connection.rb +0 -11
- data/spec/support/database/factories.rb +0 -23
- data/spec/support/database/models.rb +0 -26
- data/spec/support/database/schema.rb +0 -23
- data/spec/support/database.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 001756b2357e09a0b523eb4b788531cf5d0bf5bc5ebd3f0eb2776e1c0a865225
|
4
|
+
data.tar.gz: f7a7190a1c5d732a17d1e9fadd0c1c3940e84bbc480eef4e4b8201e0e5e4d95b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94f5d3f67f5243c3a79336edc072e15d489b1a96042ab42f81c4fc22a09950a2bd0e624824c69b0c2e45dcfdaadaf86292489cd37384236532ea01fdf8564887
|
7
|
+
data.tar.gz: c697beeff0a385ed5f1ad556dc2bc98f213069bece4d07876f1c7e5572bd8fb60c9cb8c42b622895aa038ba48fc0a54ce9a9529bb9a0d836fb71a6bb8a9f7807
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FactoryManager
|
4
|
+
# The factory manager generator.
|
5
|
+
class Generator
|
6
|
+
# Initializes a new factory generator.
|
7
|
+
def initialize(strategy:)
|
8
|
+
@associations = {}
|
9
|
+
@results = {}
|
10
|
+
@strategy = strategy
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generates the factory.
|
14
|
+
#
|
15
|
+
# @yield Instance executes the block to generate the factory.
|
16
|
+
# @return [OpenStruct] An object containing the generator results.
|
17
|
+
def generate(&block)
|
18
|
+
OpenStruct.new.tap do |locals| # rubocop:disable Style/OpenStructUse
|
19
|
+
instance_exec(locals, &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Adds a record to a new or existing association.
|
26
|
+
#
|
27
|
+
# @param [ActiveRecord::Base] The record to add to the associations.
|
28
|
+
# @param [Symbol] name The name of the association.
|
29
|
+
# @return [ActiveRecord::Base] The record.
|
30
|
+
def _add_association(record, name:)
|
31
|
+
_factory_names(name).each do |factory_name|
|
32
|
+
@associations[factory_name] ||= []
|
33
|
+
@associations[factory_name] << record
|
34
|
+
end
|
35
|
+
|
36
|
+
yield
|
37
|
+
|
38
|
+
_factory_names(name).each do |factory_name|
|
39
|
+
@associations[factory_name].pop
|
40
|
+
end
|
41
|
+
|
42
|
+
record
|
43
|
+
end
|
44
|
+
|
45
|
+
# Finds the matching associations for a specific factory.
|
46
|
+
#
|
47
|
+
# @param [String] name The factory name.
|
48
|
+
# @return [Hash] The current associations for the factory.
|
49
|
+
def _associations_for(name)
|
50
|
+
@associations
|
51
|
+
.slice(*_factory_attributes(name))
|
52
|
+
.transform_values(&:last)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrieves all attribute names for a factory.
|
56
|
+
#
|
57
|
+
# @param [String] name The factory name.
|
58
|
+
# @return [Array] The attribute names for the factory.
|
59
|
+
def _factory_attributes(name)
|
60
|
+
@_factory_attributes ||= {}
|
61
|
+
@_factory_attributes[name] ||= FactoryBot.factories.find(name).definition.attributes.names
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the factory names up the nested tree.
|
65
|
+
#
|
66
|
+
# @param [String] name The factory name.
|
67
|
+
# @return [Array] The names the factory can be referred to as.
|
68
|
+
def _factory_names(name)
|
69
|
+
factory = FactoryBot.factories.find(name)
|
70
|
+
names = []
|
71
|
+
|
72
|
+
while factory.respond_to?(:names)
|
73
|
+
names.push(*factory.names)
|
74
|
+
|
75
|
+
factory = factory.__send__(:parent)
|
76
|
+
end
|
77
|
+
|
78
|
+
names
|
79
|
+
end
|
80
|
+
|
81
|
+
# Generates a factory record with associations and custom attributes.
|
82
|
+
#
|
83
|
+
# @param [String] name The factory name.
|
84
|
+
# @param [Hash] arguments The factory arguments.
|
85
|
+
# @return [ActiveRecord::Base] The built or created factory record.
|
86
|
+
def _generate_factory(name, *arguments)
|
87
|
+
arguments.push(
|
88
|
+
_associations_for(name).merge(arguments.extract_options!)
|
89
|
+
)
|
90
|
+
|
91
|
+
method = arguments.first.is_a?(Integer) ? "#{@strategy}_list" : @strategy
|
92
|
+
|
93
|
+
FactoryBot.public_send(method, name, *arguments)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Generate a sequence.
|
97
|
+
#
|
98
|
+
# @param [String] name The name of the sequence to generate.
|
99
|
+
# @return [...] The generated sequence.
|
100
|
+
def _generate_sequence(name)
|
101
|
+
FactoryBot.generate(name)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Determine if the method is attempt to generate a valid sequence.
|
105
|
+
#
|
106
|
+
# @return [Boolean] Whether or not the sequence exists.
|
107
|
+
def _sequence?(method, argument)
|
108
|
+
method == :sequence &&
|
109
|
+
!FactoryBot::Internal.sequences.find(argument).nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
# Attempts to generate a factory record for the missing method.
|
113
|
+
#
|
114
|
+
# @param [Symbol] method The name of the method.
|
115
|
+
# @param [Hash] arguments The factory arguments.
|
116
|
+
# @return [ActiveRecord::Base] The built factory record.
|
117
|
+
def method_missing(method, *arguments, &block)
|
118
|
+
super unless respond_to_missing?(method)
|
119
|
+
|
120
|
+
if _sequence?(method, arguments.first)
|
121
|
+
_generate_sequence(*arguments)
|
122
|
+
else
|
123
|
+
record = _generate_factory(method, *arguments)
|
124
|
+
|
125
|
+
_add_association(record, name: method) do
|
126
|
+
generate(&block) if block
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Determines if a factory exists for the missing method.
|
132
|
+
#
|
133
|
+
# @param [Symbol] method The name of the method.
|
134
|
+
# @return [Boolean] Whether or not the factory exists.
|
135
|
+
def respond_to_missing?(method)
|
136
|
+
method == :sequence ||
|
137
|
+
!FactoryBot.factories.find(method).nil?
|
138
|
+
rescue KeyError
|
139
|
+
false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/factory_manager.rb
CHANGED
@@ -1,136 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# A factory manager of factory bots.
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(strategy:)
|
7
|
-
@locals = {}
|
8
|
-
@results = {}
|
9
|
-
@scopes = {}
|
10
|
-
@strategy = strategy
|
11
|
-
end
|
4
|
+
module FactoryManager
|
5
|
+
autoload :Generator, "factory_manager/generator"
|
12
6
|
|
13
|
-
# Initializes and builds a new
|
7
|
+
# Initializes and builds a new build generator.
|
14
8
|
#
|
15
|
-
# @yield Invokes the block to build the
|
9
|
+
# @yield Invokes the block to build the generator.
|
16
10
|
def self.build(&block)
|
17
|
-
|
18
|
-
|
11
|
+
Generator
|
12
|
+
.new(strategy: :build)
|
13
|
+
.generate(&block)
|
19
14
|
end
|
20
15
|
|
21
|
-
# Initializes and creates a new
|
16
|
+
# Initializes and creates a new create generator.
|
22
17
|
#
|
23
|
-
# @yield Invokes the block to create the
|
18
|
+
# @yield Invokes the block to create the generator.
|
24
19
|
def self.create(&block)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# Generate the factory.
|
30
|
-
#
|
31
|
-
# @yield Invokes the block to generate the factory.
|
32
|
-
# @return [OpenStruct] An object containing the record results.
|
33
|
-
def generate(&block)
|
34
|
-
instance_eval(&block)
|
35
|
-
|
36
|
-
OpenStruct.new(@locals)
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
# Add a record to a new or existing scope.
|
42
|
-
#
|
43
|
-
# @param [ActiveRecord::Base] The record to add to the scope.
|
44
|
-
# @param [Symbol] scope The name of the scope.
|
45
|
-
# @return [ActiveRecord::Base] The record.
|
46
|
-
def _add_to_scope(record, scope:)
|
47
|
-
@scopes[scope] ||= []
|
48
|
-
@scopes[scope] << record
|
49
|
-
|
50
|
-
yield
|
51
|
-
|
52
|
-
@scopes[scope].pop
|
53
|
-
end
|
54
|
-
|
55
|
-
# Assign a local variable.
|
56
|
-
#
|
57
|
-
# @param [Symbol] method The method name for the local.
|
58
|
-
# @param [*] value The value of the local.
|
59
|
-
def _assign_local(method, value)
|
60
|
-
@locals[method.to_s.tr("=", "")] = value
|
61
|
-
end
|
62
|
-
|
63
|
-
# Determine if a name is an assignment method.
|
64
|
-
#
|
65
|
-
# @param [Symbol] name The assignment method name.
|
66
|
-
# @return [Boolean] Whether or not the name is an assignment method.
|
67
|
-
def _assignment_method?(name)
|
68
|
-
name.to_s.end_with?("=")
|
69
|
-
end
|
70
|
-
|
71
|
-
# Find the associations for a specific factory.
|
72
|
-
#
|
73
|
-
# @param [String] name The factory name.
|
74
|
-
# @return [Hash] The associations for the factory.
|
75
|
-
def _associations_for(name)
|
76
|
-
@scopes
|
77
|
-
.slice(*_factory_attributes(name))
|
78
|
-
.transform_values(&:last)
|
79
|
-
end
|
80
|
-
|
81
|
-
# Determine all attribute names for a factory.
|
82
|
-
#
|
83
|
-
# @param [String] name The factory name.
|
84
|
-
# @return [Array] The attributes for the factory.
|
85
|
-
def _factory_attributes(name)
|
86
|
-
@_factory_attributes ||= {}
|
87
|
-
@_factory_attributes[name] ||= FactoryBot.factories.find(name).definition.attributes.names
|
88
|
-
end
|
89
|
-
|
90
|
-
# Generate a factory record with associations and custom attributes.
|
91
|
-
#
|
92
|
-
# @param [String] name The factory name.
|
93
|
-
# @param [Hash] arguments The factory arguments.
|
94
|
-
# @return [ActiveRecord::Base] The built factory record.
|
95
|
-
def _generate_factory(name, *arguments)
|
96
|
-
arguments.push(
|
97
|
-
_associations_for(name).merge(arguments.extract_options!)
|
98
|
-
)
|
99
|
-
|
100
|
-
method = arguments.first.is_a?(Integer) ? "#{@strategy}_list" : @strategy
|
101
|
-
|
102
|
-
FactoryBot.public_send(method, name, *arguments)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Generate a factory record for the missing method.
|
106
|
-
#
|
107
|
-
# @param [Symbol] method The name of the method.
|
108
|
-
# @param [Hash] arguments The factory arguments.
|
109
|
-
# @return [ActiveRecord::Base] The built factory record.
|
110
|
-
def method_missing(method, *arguments, &block)
|
111
|
-
super unless respond_to_missing?(method)
|
112
|
-
|
113
|
-
if _assignment_method?(method)
|
114
|
-
_assign_local(method, arguments.first)
|
115
|
-
else
|
116
|
-
record = _generate_factory(method, *arguments)
|
117
|
-
|
118
|
-
_add_to_scope(record, scope: method) do
|
119
|
-
generate(&block) if block
|
120
|
-
end
|
121
|
-
|
122
|
-
record
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Determine if a factory exists for the missing method, or if a local
|
127
|
-
# variable is being assigned.
|
128
|
-
#
|
129
|
-
# @param [Symbol] method The name of the method.
|
130
|
-
# @return [Boolean] Whether or not the factory exists.
|
131
|
-
def respond_to_missing?(method)
|
132
|
-
!FactoryBot.factories.find(method).nil?
|
133
|
-
rescue KeyError
|
134
|
-
_assignment_method?(method)
|
20
|
+
Generator
|
21
|
+
.new(strategy: :create)
|
22
|
+
.generate(&block)
|
135
23
|
end
|
136
24
|
end
|
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factory_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tristan Dunn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: factory_bot
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 7.0.3.1
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 7.0.3.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: appraisal
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.4.1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.4.1
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,42 +72,42 @@ dependencies:
|
|
58
72
|
requirements:
|
59
73
|
- - '='
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: 3.
|
75
|
+
version: 3.11.0
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - '='
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: 3.
|
82
|
+
version: 3.11.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rubocop
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - '='
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.
|
89
|
+
version: 1.31.2
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - '='
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.
|
96
|
+
version: 1.31.2
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rubocop-performance
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - '='
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
103
|
+
version: 1.14.2
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - '='
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
110
|
+
version: 1.14.2
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rubocop-rake
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +128,14 @@ dependencies:
|
|
114
128
|
requirements:
|
115
129
|
- - '='
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: 2.
|
131
|
+
version: 2.12.1
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - '='
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: 2.
|
138
|
+
version: 2.12.1
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: simplecov-console
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,28 +156,28 @@ dependencies:
|
|
142
156
|
requirements:
|
143
157
|
- - '='
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: 1.4.
|
159
|
+
version: 1.4.4
|
146
160
|
type: :development
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
164
|
- - '='
|
151
165
|
- !ruby/object:Gem::Version
|
152
|
-
version: 1.4.
|
166
|
+
version: 1.4.4
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: yard
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
156
170
|
requirements:
|
157
171
|
- - '='
|
158
172
|
- !ruby/object:Gem::Version
|
159
|
-
version: 0.9.
|
173
|
+
version: 0.9.28
|
160
174
|
type: :development
|
161
175
|
prerelease: false
|
162
176
|
version_requirements: !ruby/object:Gem::Requirement
|
163
177
|
requirements:
|
164
178
|
- - '='
|
165
179
|
- !ruby/object:Gem::Version
|
166
|
-
version: 0.9.
|
180
|
+
version: 0.9.28
|
167
181
|
description: A factory manager of factory bots.
|
168
182
|
email: hello@tristandunn.com
|
169
183
|
executables: []
|
@@ -171,17 +185,12 @@ extensions: []
|
|
171
185
|
extra_rdoc_files: []
|
172
186
|
files:
|
173
187
|
- lib/factory_manager.rb
|
174
|
-
-
|
175
|
-
- spec/spec_helper.rb
|
176
|
-
- spec/support/database.rb
|
177
|
-
- spec/support/database/connection.rb
|
178
|
-
- spec/support/database/factories.rb
|
179
|
-
- spec/support/database/models.rb
|
180
|
-
- spec/support/database/schema.rb
|
188
|
+
- lib/factory_manager/generator.rb
|
181
189
|
homepage: https://github.com/tristandunn/factory_manager
|
182
190
|
licenses:
|
183
191
|
- MIT
|
184
|
-
metadata:
|
192
|
+
metadata:
|
193
|
+
rubygems_mfa_required: 'true'
|
185
194
|
post_install_message:
|
186
195
|
rdoc_options: []
|
187
196
|
require_paths:
|
@@ -190,22 +199,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
190
199
|
requirements:
|
191
200
|
- - ">="
|
192
201
|
- !ruby/object:Gem::Version
|
193
|
-
version: '2.
|
202
|
+
version: '2.7'
|
194
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
204
|
requirements:
|
196
205
|
- - ">="
|
197
206
|
- !ruby/object:Gem::Version
|
198
207
|
version: '0'
|
199
208
|
requirements: []
|
200
|
-
rubygems_version: 3.
|
209
|
+
rubygems_version: 3.3.7
|
201
210
|
signing_key:
|
202
211
|
specification_version: 4
|
203
212
|
summary: A factory manager of factory bots.
|
204
|
-
test_files:
|
205
|
-
- spec/lib/factory_manager_spec.rb
|
206
|
-
- spec/spec_helper.rb
|
207
|
-
- spec/support/database/connection.rb
|
208
|
-
- spec/support/database/factories.rb
|
209
|
-
- spec/support/database/models.rb
|
210
|
-
- spec/support/database/schema.rb
|
211
|
-
- spec/support/database.rb
|
213
|
+
test_files: []
|
@@ -1,223 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe FactoryManager do
|
6
|
-
describe ".build" do
|
7
|
-
context "with a valid factory" do
|
8
|
-
it "builds a record" do
|
9
|
-
result = build do
|
10
|
-
self.user = user
|
11
|
-
end
|
12
|
-
|
13
|
-
expect(result.user).to be_a(User)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "does not persist the record" do
|
17
|
-
result = build do
|
18
|
-
self.user = user
|
19
|
-
end
|
20
|
-
|
21
|
-
expect(result.user).not_to be_persisted
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context "with a factory trait" do
|
26
|
-
it "builds a record using the trait" do
|
27
|
-
result = build do
|
28
|
-
self.user = user(:admin, name: "Admin")
|
29
|
-
end
|
30
|
-
|
31
|
-
expect(result.user).to have_attributes(name: "Admin", admin: true)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context "with a number" do
|
36
|
-
it "builds multiple records" do
|
37
|
-
result = build do
|
38
|
-
self.users = user(2, :admin, name: "Admin")
|
39
|
-
end
|
40
|
-
|
41
|
-
expect(result.users).to contain_exactly(
|
42
|
-
an_object_having_attributes(name: "Admin", admin: true),
|
43
|
-
an_object_having_attributes(name: "Admin", admin: true)
|
44
|
-
)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context "with custom attributes" do
|
49
|
-
it "forwards the custom attributes to the factory" do
|
50
|
-
result = build do
|
51
|
-
self.user = user(name: "Tester")
|
52
|
-
end
|
53
|
-
|
54
|
-
expect(result.user).to have_attributes(name: "Tester")
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "with associations" do
|
59
|
-
it "allows nesting of associated records" do
|
60
|
-
result = build do
|
61
|
-
self.user = user do
|
62
|
-
self.post = post(title: "User's Post")
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
expect(result.post).to have_attributes(
|
67
|
-
user: result.user,
|
68
|
-
title: "User's Post"
|
69
|
-
)
|
70
|
-
end
|
71
|
-
|
72
|
-
it "allows multiple level nesting of associated records" do
|
73
|
-
result = build do
|
74
|
-
self.user_1 = user do
|
75
|
-
self.user_2 = user do
|
76
|
-
self.post = post(title: "User's Post")
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
expect(result).to have_attributes(
|
82
|
-
user_1: an_instance_of(User),
|
83
|
-
user_2: an_instance_of(User),
|
84
|
-
post: an_object_having_attributes(
|
85
|
-
user: result.user_2,
|
86
|
-
title: "User's Post"
|
87
|
-
)
|
88
|
-
)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context "with an invalid factory" do
|
93
|
-
it "raises a no method error" do
|
94
|
-
expect do
|
95
|
-
build { fake }
|
96
|
-
end.to raise_error(NoMethodError)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def build(&block)
|
101
|
-
described_class.build(&block)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe ".create" do
|
106
|
-
context "with a valid factory" do
|
107
|
-
it "creates a record" do
|
108
|
-
create do
|
109
|
-
user
|
110
|
-
end
|
111
|
-
|
112
|
-
expect(User.count).to eq(1)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context "with a factory trait" do
|
117
|
-
it "creates a record using the trait" do
|
118
|
-
create do
|
119
|
-
user(:admin, name: "Admin")
|
120
|
-
end
|
121
|
-
|
122
|
-
expect(User.all).to contain_exactly(
|
123
|
-
an_object_having_attributes(name: "Admin", admin: true)
|
124
|
-
)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
context "with a number" do
|
129
|
-
it "creates multiple records" do
|
130
|
-
create do
|
131
|
-
user(2, :admin, name: "Admin")
|
132
|
-
end
|
133
|
-
|
134
|
-
expect(User.all).to contain_exactly(
|
135
|
-
an_object_having_attributes(name: "Admin", admin: true),
|
136
|
-
an_object_having_attributes(name: "Admin", admin: true)
|
137
|
-
)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context "with custom attributes" do
|
142
|
-
it "forwards the custom attributes to the factory" do
|
143
|
-
create do
|
144
|
-
user(name: "Tester")
|
145
|
-
end
|
146
|
-
|
147
|
-
expect(User.all).to contain_exactly(
|
148
|
-
an_object_having_attributes(name: "Tester")
|
149
|
-
)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
context "with associations" do
|
154
|
-
it "allows nesting of associated records" do
|
155
|
-
create do
|
156
|
-
user do
|
157
|
-
post(title: "User's Post")
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
expect(User.all).to contain_exactly(
|
162
|
-
an_object_having_attributes(
|
163
|
-
posts: [an_object_having_attributes(title: "User's Post")]
|
164
|
-
)
|
165
|
-
)
|
166
|
-
end
|
167
|
-
|
168
|
-
it "allows multiple level nesting of associated records" do
|
169
|
-
create do
|
170
|
-
user do
|
171
|
-
user do
|
172
|
-
post(title: "User's Post")
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
expect(User.all).to contain_exactly(
|
178
|
-
an_object_having_attributes(
|
179
|
-
posts: []
|
180
|
-
),
|
181
|
-
an_object_having_attributes(
|
182
|
-
posts: [an_object_having_attributes(title: "User's Post")]
|
183
|
-
)
|
184
|
-
)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
context "with local variables" do
|
189
|
-
it "returns an object with local variable assignments" do
|
190
|
-
result = create do
|
191
|
-
user do
|
192
|
-
self.admin = admin = user(:admin)
|
193
|
-
|
194
|
-
self.user = user(name: "Local User") do
|
195
|
-
self.post = post(title: "User's Post")
|
196
|
-
end
|
197
|
-
|
198
|
-
self.announcement = post(user: admin)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
expect(result).to have_attributes(
|
203
|
-
admin: an_object_having_attributes(admin: true),
|
204
|
-
announcement: an_object_having_attributes(user: result.admin),
|
205
|
-
post: an_object_having_attributes(title: "User's Post"),
|
206
|
-
user: an_object_having_attributes(name: "Local User")
|
207
|
-
)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
context "with an invalid factory" do
|
212
|
-
it "raises a no method error" do
|
213
|
-
expect do
|
214
|
-
create { fake }
|
215
|
-
end.to raise_error(NoMethodError)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
def create(&block)
|
220
|
-
described_class.create(&block)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
|
5
|
-
if ENV["CI"] || ENV["COVERAGE"]
|
6
|
-
require "simplecov"
|
7
|
-
require "simplecov-console"
|
8
|
-
|
9
|
-
SimpleCov.formatter = SimpleCov::Formatter::Console
|
10
|
-
SimpleCov.start("rails") do
|
11
|
-
coverage_dir "./tmp/cache/coverage"
|
12
|
-
enable_coverage :branch
|
13
|
-
minimum_coverage line: 100, branch: 100
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
Bundler.require(:default, :development)
|
18
|
-
|
19
|
-
Dir[File.expand_path("support/**/*.rb", __dir__)].sort.each do |file|
|
20
|
-
require file
|
21
|
-
end
|
22
|
-
|
23
|
-
RSpec.configure do |config|
|
24
|
-
config.expect_with :rspec do |rspec|
|
25
|
-
rspec.syntax = :expect
|
26
|
-
end
|
27
|
-
|
28
|
-
# Raise errors for any deprecations.
|
29
|
-
config.raise_errors_for_deprecations!
|
30
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.configure do |config|
|
4
|
-
config.before(:suite) do
|
5
|
-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
6
|
-
end
|
7
|
-
|
8
|
-
config.after do
|
9
|
-
ApplicationRecord.subclasses.each(&:delete_all)
|
10
|
-
end
|
11
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "factory_bot"
|
4
|
-
|
5
|
-
RSpec.configure do |config|
|
6
|
-
config.before(:suite) do
|
7
|
-
FactoryBot.define do
|
8
|
-
factory :post do
|
9
|
-
user
|
10
|
-
|
11
|
-
sequence(:title) { |n| "Post ##{n}" }
|
12
|
-
end
|
13
|
-
|
14
|
-
factory :user do
|
15
|
-
sequence(:name) { |n| "User ##{n}" }
|
16
|
-
|
17
|
-
trait :admin do
|
18
|
-
admin { true }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Lint/ConstantDefinitionInBlock
|
4
|
-
RSpec.configure do |config|
|
5
|
-
config.before(:suite) do
|
6
|
-
# The base ActiveRecord class.
|
7
|
-
class ApplicationRecord < ActiveRecord::Base
|
8
|
-
self.abstract_class = true
|
9
|
-
end
|
10
|
-
|
11
|
-
# A post record.
|
12
|
-
class Post < ApplicationRecord
|
13
|
-
belongs_to :user, required: true
|
14
|
-
|
15
|
-
validates :title, presence: true
|
16
|
-
end
|
17
|
-
|
18
|
-
# A user record.
|
19
|
-
class User < ApplicationRecord
|
20
|
-
has_many :posts
|
21
|
-
|
22
|
-
validates :name, presence: true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
# rubocop:enable Lint/ConstantDefinitionInBlock
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.configure do |config|
|
4
|
-
config.before(:suite) do
|
5
|
-
ActiveRecord::Schema.define do
|
6
|
-
self.verbose = false
|
7
|
-
|
8
|
-
create_table :users, force: true do |t|
|
9
|
-
t.string :name, null: false
|
10
|
-
t.boolean :admin, null: false, default: false
|
11
|
-
|
12
|
-
t.timestamps null: false
|
13
|
-
end
|
14
|
-
|
15
|
-
create_table :posts, force: true do |t|
|
16
|
-
t.references :user, null: false
|
17
|
-
t.string :title, null: false
|
18
|
-
|
19
|
-
t.timestamps null: false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|