active-fixtures 0.0.1
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +175 -0
- data/lib/active-fixtures.rb +45 -0
- data/lib/active-fixtures/resource.rb +25 -0
- data/lib/active-fixtures/rspec.rb +19 -0
- data/lib/active-fixtures/session.rb +51 -0
- data/lib/active-fixtures/state.rb +47 -0
- data/lib/active-fixtures/state_builder.rb +37 -0
- data/lib/active-fixtures/state_dumper.rb +67 -0
- data/lib/active-fixtures/version.rb +3 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54bd0172edecb818492c68d1ee90d4c6c3fc855c
|
4
|
+
data.tar.gz: ba2b97ec7dc4c14a95765dfd98dc56e0e85cb017
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c41606271c058aa0e688c1aba385054eac7e68609d44ef8f8ebddba15caaf6755a7b1b57b33c848ff9c78a1b7f2938c4521f5560d0677a33387b91b49dfb90f3
|
7
|
+
data.tar.gz: 735065ee98e5e34df977c6a607067ea0465b611d89850534195ffdc94f15260cf63b70cca75ede71996d7b1ab85141d893baf5417de1a738e6c68cbdf619884c
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sergey Tokarenko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
ActiveFixtures
|
2
|
+
==============
|
3
|
+
[](http://badge.fury.io/rb/active-fixtures)
|
4
|
+
|
5
|
+
ActiveFixtures provides the way how to populate the server state (DB, sessions) as an application user but not as programmer.
|
6
|
+
|
7
|
+
## Why?
|
8
|
+
The correct question is `why we write the tests at all?`.
|
9
|
+
Or even better - `what does the green line means?`.
|
10
|
+
|
11
|
+
Typical legacy code contains a tons of tests in isolation aka Unit Tests.
|
12
|
+
Mocks, stubs, factories & terrible traits, fakers etc etc.
|
13
|
+
Many smart things, so called `best practices`, a lot of efforts and time spent to write all of these.
|
14
|
+
|
15
|
+
And, after all - application just can't run due to the simple misspelling in `routes.rb`.
|
16
|
+
|
17
|
+
So, what is a really valuable reason to write the tests?
|
18
|
+
|
19
|
+
We working on the project for somebody personal.
|
20
|
+
We creating the web application for web users, we write the new cool library for other programmers.
|
21
|
+
The primary goal of automatic tests is to be sure that `our code works right like the target user expects`.
|
22
|
+
|
23
|
+
Test web application as web user plays with it.
|
24
|
+
Test the public methods of your library just like other programmer will use them.
|
25
|
+
Test web service endpoints just like the third-party applications will call them.
|
26
|
+
|
27
|
+
Nobody interested how exactly working the private methods in `Product` class.
|
28
|
+
Even more, nobody interested to know that class `Product` exists, it mapped to some database table etc.
|
29
|
+
|
30
|
+
Single thing is matter - how the application's user thinking about your application,
|
31
|
+
which entities he understand, how he affects to such entities.
|
32
|
+
|
33
|
+
In general case, tests in isolation are at least useless, at max - hurtful.
|
34
|
+
Lets write acceptance tests instead!
|
35
|
+
|
36
|
+
## requirements
|
37
|
+
Currently works with Poltergeist and PostgreSQL.
|
38
|
+
|
39
|
+
## Getting started
|
40
|
+
|
41
|
+
Add to your Gemfile:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
gem 'ruby-features', group: :test
|
45
|
+
```
|
46
|
+
|
47
|
+
Add to your rspec helper:
|
48
|
+
```ruby
|
49
|
+
require 'active-fixtures/rspec'
|
50
|
+
```
|
51
|
+
|
52
|
+
Remove Database Cleaners from your project, ActiveFixtures will take care about database cleanup in additional.
|
53
|
+
|
54
|
+
## Usage
|
55
|
+
### Active factory definition
|
56
|
+
Lets add the active factory in `spec/active_fixtures/user.rb`:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class AFUser < ActiveFixtures::Resource
|
60
|
+
attribute :login, type: String, default: 'admin@lvh.me'
|
61
|
+
attribute :password, type: String, default: 'p@ssw0rd'
|
62
|
+
|
63
|
+
def self.create_initial(attrs = {})
|
64
|
+
new(attrs).tap { |user|
|
65
|
+
Rake::Task['user:create'].invoke(user.login, user.password)
|
66
|
+
Rake::Task['user:create'].reenable
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.create(attrs = {})
|
71
|
+
new(attrs).tap { |user|
|
72
|
+
af_session(:admin) do
|
73
|
+
click_on 'Admins'
|
74
|
+
|
75
|
+
click_on 'Invite'
|
76
|
+
fill_in 'Email', with: user.login
|
77
|
+
click_on 'Send an invitation'
|
78
|
+
end
|
79
|
+
|
80
|
+
af_session do
|
81
|
+
open_email(user.login)
|
82
|
+
|
83
|
+
current_email.click_on 'Accept invitation'
|
84
|
+
fill_in 'Password', with: user.password
|
85
|
+
fill_in 'Password confirmation', with: user.password
|
86
|
+
click_on 'Set my password'
|
87
|
+
assert_text 'Your password was set successfully. You are now signed in.'
|
88
|
+
end
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def sign_in
|
93
|
+
visit '/'
|
94
|
+
fill_in 'Email', with: login
|
95
|
+
fill_in 'Password', with: password
|
96
|
+
click_on 'Sign in'
|
97
|
+
assert_text 'Signed in successfully.'
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
Implement the resource factory just like the application user will do -
|
104
|
+
capybara steps, rake tasks invocation, API calls etc.
|
105
|
+
|
106
|
+
Any methods available in `it` rspec context will be available in the factory
|
107
|
+
(for example `open_email` helper from `capybara-email` gem).
|
108
|
+
|
109
|
+
`ActiveFixtures::Resource` includes the [ActiveAttr::Model](https://github.com/cgriego/active_attr),
|
110
|
+
feel free to use any it's features.
|
111
|
+
|
112
|
+
`af_session` helper called without parameter will provide the clean capybara session on each call.
|
113
|
+
Use it in factory to avoid the influence to rspec's example default session.
|
114
|
+
|
115
|
+
`af_session` with parameter is a bit tricky, lets recall it later.
|
116
|
+
|
117
|
+
Now you can use factory in your tests:
|
118
|
+
```ruby
|
119
|
+
describe 'Users' do
|
120
|
+
let(:admin) { AFUser.create_initial }
|
121
|
+
|
122
|
+
it 'should pass' do
|
123
|
+
admin.sing_in
|
124
|
+
end
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
### Fixtures definition
|
129
|
+
Lets define active fixture in `spec/active_fixtures/_fixtures.rb`:
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
ActiveFixtures.populate(:default) do
|
133
|
+
resource(:admin) { AFUser.create_initial }
|
134
|
+
session(:admin) { AFUser[:admin].sign_in }
|
135
|
+
resource(:invited_admin) { AFUser.create(login: 'new_user@lvh.me') }
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
`:default` fixture will be loaded before each rspec example. You can play with resources like that:
|
140
|
+
```ruby
|
141
|
+
it 'should pass' do
|
142
|
+
AFUser[:invited_admin].sign_in
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
### Active sessions
|
147
|
+
Once you defined the named session in factory, you can use it by `af_session` helper:
|
148
|
+
```ruby
|
149
|
+
it 'should pass' do
|
150
|
+
af_session(:admin) do
|
151
|
+
# already logged as admin
|
152
|
+
end
|
153
|
+
|
154
|
+
# some code
|
155
|
+
af_session(:admin) do
|
156
|
+
# second and any further `af_session` call within the same example
|
157
|
+
# will drop the session to the state reached right after the session initialization
|
158
|
+
# - same current URL, same cookies. This way you don't need to keep in mind
|
159
|
+
# what you did with named session before, but can expect the same session state each time.
|
160
|
+
end
|
161
|
+
|
162
|
+
af_session do
|
163
|
+
# always clean session, with blank current URL
|
164
|
+
end
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
### How it works
|
169
|
+
ActiveFixtures work fairly, but effectively.
|
170
|
+
|
171
|
+
Fixture will be populated on the first it's usage, by genuine application's user actions.
|
172
|
+
For the next example it will be loaded from cache - no sense to to the same work again.
|
173
|
+
|
174
|
+
## License
|
175
|
+
MIT License. Copyright (c) 2016 Sergey Tokarenko
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active-fixtures/version'
|
2
|
+
|
3
|
+
module ActiveFixtures
|
4
|
+
autoload :Resource, 'active-fixtures/resource'
|
5
|
+
|
6
|
+
autoload :Session, 'active-fixtures/session'
|
7
|
+
autoload :StateBuilder, 'active-fixtures/state_builder'
|
8
|
+
autoload :State, 'active-fixtures/state'
|
9
|
+
autoload :StateDumper, 'active-fixtures/state_dumper'
|
10
|
+
|
11
|
+
mattr_accessor :state_builders
|
12
|
+
self.state_builders = {}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def populate(name, &block)
|
16
|
+
state_builders[name] = StateBuilder.new(block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def init!
|
20
|
+
StateDumper.init!
|
21
|
+
end
|
22
|
+
|
23
|
+
def cleanup!
|
24
|
+
StateDumper.cleanup!
|
25
|
+
end
|
26
|
+
|
27
|
+
def prepare!(name)
|
28
|
+
self.current_state = State.new(name)
|
29
|
+
current_state.prepare!(state_builders[name])
|
30
|
+
end
|
31
|
+
|
32
|
+
def thread_storage
|
33
|
+
Thread.current[:__active_fixtures] ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def current_state
|
37
|
+
thread_storage[:current_state]
|
38
|
+
end
|
39
|
+
|
40
|
+
def current_state=(state)
|
41
|
+
thread_storage[:current_state] = state
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveFixtures
|
2
|
+
class Resource
|
3
|
+
include ActiveAttr::Model
|
4
|
+
|
5
|
+
delegate :context, to: :class
|
6
|
+
|
7
|
+
def self.[](name)
|
8
|
+
ActiveFixtures.current_state.read_entity(name, self)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def self.context
|
14
|
+
RSpec.current_example.example_group_instance
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.method_missing(method, *args, &block)
|
18
|
+
context.respond_to?(method) ?
|
19
|
+
context.public_send(method, *args, &block) :
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
define_method(:method_missing, &method(:method_missing))
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Dir[Rails.root.join('spec/active_fixtures/**/*.rb')].each { |f| require f }
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.include ActiveFixtures::Session::Helper
|
5
|
+
|
6
|
+
config.around(:each) do |example|
|
7
|
+
ActiveFixtures.prepare!(:default)
|
8
|
+
example.run
|
9
|
+
end
|
10
|
+
|
11
|
+
config.before(:suite) do
|
12
|
+
ActiveFixtures.init!
|
13
|
+
end
|
14
|
+
|
15
|
+
config.after(:suite) do
|
16
|
+
ActiveFixtures.cleanup!
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActiveFixtures
|
2
|
+
class Session < Resource
|
3
|
+
CLEAN_NAME = :__clean
|
4
|
+
|
5
|
+
module Helper
|
6
|
+
def af_session(name = CLEAN_NAME, &block)
|
7
|
+
Session[name].perform(block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
attribute :name, type: String, default: CLEAN_NAME
|
12
|
+
attribute :url, type: String
|
13
|
+
attribute :cookies, type: Object, default: []
|
14
|
+
|
15
|
+
def initialize(attrs = {})
|
16
|
+
super
|
17
|
+
|
18
|
+
cookies.map!(&:symbolize_keys!)
|
19
|
+
|
20
|
+
if attrs[:block]
|
21
|
+
using_session do
|
22
|
+
attrs[:block].call
|
23
|
+
|
24
|
+
self.url = context.current_url
|
25
|
+
self.cookies = context.page.driver.cookies.values.map{ |c| c.instance_variable_get(:@attributes).symbolize_keys}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def perform(block)
|
31
|
+
res = nil
|
32
|
+
|
33
|
+
using_session do
|
34
|
+
context.reset_session!
|
35
|
+
cookies.each do |cookie|
|
36
|
+
context.page.driver.set_cookie(nil, nil, cookie)
|
37
|
+
end
|
38
|
+
context.visit(url) if url
|
39
|
+
res = block.call
|
40
|
+
end
|
41
|
+
|
42
|
+
res
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def using_session(&block)
|
48
|
+
context.using_session("__af::#{name}", &block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveFixtures
|
2
|
+
class State
|
3
|
+
attr_accessor :name
|
4
|
+
|
5
|
+
def initialize(_name)
|
6
|
+
self.name = _name
|
7
|
+
end
|
8
|
+
|
9
|
+
def prepare!(state_builder)
|
10
|
+
entities.clear
|
11
|
+
|
12
|
+
if StateDumper.exists?(name)
|
13
|
+
entities.merge!(StateDumper.load(name))
|
14
|
+
else
|
15
|
+
StateDumper.load_clean
|
16
|
+
|
17
|
+
clean_session = Session.new
|
18
|
+
write_entity(clean_session.name, clean_session)
|
19
|
+
|
20
|
+
state_builder.prepare_each do |name, resource|
|
21
|
+
write_entity(name, resource)
|
22
|
+
end
|
23
|
+
|
24
|
+
StateDumper.dump(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_entity(name, resource_class)
|
29
|
+
entities[normalize_name(name, resource_class)]
|
30
|
+
end
|
31
|
+
|
32
|
+
def entities
|
33
|
+
ActiveFixtures.thread_storage[:entities] ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def write_entity(name, resource)
|
39
|
+
entities[normalize_name(name, resource.class)] = resource
|
40
|
+
end
|
41
|
+
|
42
|
+
def normalize_name(name, resource_class)
|
43
|
+
"#{resource_class.name}::#{name}"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActiveFixtures
|
2
|
+
class StateBuilder
|
3
|
+
attr_accessor :steps
|
4
|
+
|
5
|
+
def initialize(block)
|
6
|
+
self.steps = []
|
7
|
+
instance_eval(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def prepare_each
|
11
|
+
steps.each do |build_step|
|
12
|
+
yield(
|
13
|
+
build_step[:name],
|
14
|
+
send("build_#{build_step[:type]}", build_step)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def resource(name, &block)
|
22
|
+
steps << {type: :resource, name: name, block: block}
|
23
|
+
end
|
24
|
+
|
25
|
+
def session(name, &block)
|
26
|
+
steps << {type: :session, name: name, block: block}
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_resource(build_step)
|
30
|
+
build_step[:block].call
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_session(build_step)
|
34
|
+
Session.new(build_step)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ActiveFixtures
|
2
|
+
module StateDumper
|
3
|
+
FIXTURES_PATH = Rails.root.join('spec/fixtures/active').freeze
|
4
|
+
DB_NAME = ApplicationRecord.connection_config[:database].freeze
|
5
|
+
CLEAN_STATE_NAME = :__clean
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def init!
|
9
|
+
FileUtils.mkdir_p(FIXTURES_PATH)
|
10
|
+
dump_db(CLEAN_STATE_NAME)
|
11
|
+
end
|
12
|
+
|
13
|
+
def cleanup!
|
14
|
+
load_clean
|
15
|
+
FileUtils.rm_rf(FIXTURES_PATH) if File.exist?(FIXTURES_PATH)
|
16
|
+
end
|
17
|
+
|
18
|
+
def exists?(state_name)
|
19
|
+
File.exists?(dump_db_file(state_name))
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_clean
|
23
|
+
load_db(CLEAN_STATE_NAME)
|
24
|
+
end
|
25
|
+
|
26
|
+
def load(state_name)
|
27
|
+
load_db(state_name)
|
28
|
+
|
29
|
+
Hash[*JSON.parse(File.read(dump_entities_file(state_name))).flat_map{ |name, attrs|
|
30
|
+
[name, name.gsub(/::[^:]*\z/, '').constantize.new(attrs)]
|
31
|
+
}]
|
32
|
+
end
|
33
|
+
|
34
|
+
def dump(state)
|
35
|
+
dump_db(state.name)
|
36
|
+
File.write(
|
37
|
+
dump_entities_file(state.name),
|
38
|
+
Hash[*state.entities.flat_map{ |name, entity|
|
39
|
+
[name, entity.attributes]
|
40
|
+
}].to_json
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def dump_db_file(state_name)
|
47
|
+
File.join(FIXTURES_PATH, "#{state_name}.db.dump")
|
48
|
+
end
|
49
|
+
|
50
|
+
def dump_entities_file(state_name)
|
51
|
+
File.join(FIXTURES_PATH, "#{state_name}.entities.json")
|
52
|
+
end
|
53
|
+
|
54
|
+
def dump_db(state_name)
|
55
|
+
args = ['-x', '-O', '-c', '-Fc', '-f', dump_db_file(state_name), DB_NAME]
|
56
|
+
Kernel.system('pg_dump', *args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_db(state_name)
|
60
|
+
args = ['-c', '-d', DB_NAME, dump_db_file(state_name)]
|
61
|
+
Kernel.system('pg_restore', *args)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active-fixtures
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergey Tokarenko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-05 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: active-fixtures provides the way how to populate the server state (DB,
|
14
|
+
sessions) as an application user but not as programmer.
|
15
|
+
email: private.tokarenko.sergey@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENSE
|
21
|
+
- README.md
|
22
|
+
- lib/active-fixtures.rb
|
23
|
+
- lib/active-fixtures/resource.rb
|
24
|
+
- lib/active-fixtures/rspec.rb
|
25
|
+
- lib/active-fixtures/session.rb
|
26
|
+
- lib/active-fixtures/state.rb
|
27
|
+
- lib/active-fixtures/state_builder.rb
|
28
|
+
- lib/active-fixtures/state_dumper.rb
|
29
|
+
- lib/active-fixtures/version.rb
|
30
|
+
homepage: https://github.com/Anadea/active-fixtures
|
31
|
+
licenses:
|
32
|
+
- MIT
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 2.3.1
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 2.5.1
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: active-fixtures provides the way how to populate the server state (DB, sessions)
|
54
|
+
as an application user but not as programmer.
|
55
|
+
test_files: []
|