remote_factory_girl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 013ff8da4195f0fdd96f42fed7e582768da3979f
4
+ data.tar.gz: b2604a88f6b432b72b50117f9206eff9a45fa0c4
5
+ SHA512:
6
+ metadata.gz: 6224e0239b03dec31d06efa4835937c4539724057926e00c11e4d76070741e5000b1ad93aea9c5f6dd8feed895ea6b9cf6797fe6fa5aac080201bb83956aaf7d
7
+ data.tar.gz: ae06c058feccd7413e09d419a3f73222170d10c482ac9e212fde5daf63fbfd07b934274710ae510707aa899fca4e1bac2c6fd38018489fd4dd581b7a058aaac2
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --default_path spec
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'dish' # converts hash to objects with dot syntax
4
+ gem 'virtus', '~> 1.0' # defining attributes on a model: strong typing like objects and defaults
5
+ gem 'rest-client' # http
6
+
7
+
8
+ # Specify your gem's dependencies in remote_factory_girl.gemspec
9
+ gemspec
10
+
11
+ gem 'rspec'
12
+ gem 'pry'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 tdouce
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # RemoteFactoryGirl
2
+
3
+ [factory_girl](https://github.com/thoughtbot/factory_girl) for [Software Oriented Architecture](http://en.wikipedia.org/wiki/Service-oriented_architecture) (SOA). Create [factory_girl](https://github.com/thoughtbot/factory_girl) test data remotely when used in conjunction with [remote_factory_girl_home_rails](https://github.com/tdouce/remote_factory_girl_home_rails).
4
+
5
+ ## Getting Started
6
+
7
+ See [GETTING_STARTED](https://github.com/tdouce/remote_factory_girl/wiki/Getting-Started) for information on installaton and configuration.
8
+
9
+ ## Run tests
10
+
11
+
12
+ $ rspec
13
+
14
+
15
+ ## Contributing
16
+
17
+ 1. Fork it ( http://github.com/<my-github-username>/remote_factory_girl/fork )
18
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
19
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
20
+ 4. Push to the branch (`git push origin my-new-feature`)
21
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new('spec')
6
+
7
+ task :default => :spec
@@ -0,0 +1,55 @@
1
+ require 'remote_factory_girl/exceptions'
2
+ require 'virtus'
3
+
4
+ module RemoteFactoryGirl
5
+ class Config
6
+ include Virtus.model
7
+
8
+ DEFAULT_HOME_CONFIG = { :host => nil,
9
+ :port => nil,
10
+ :end_point => '/remote_factory_girl/home' }
11
+
12
+ attribute :home, Hash, :default => DEFAULT_HOME_CONFIG
13
+ attribute :return_response_as, Symbol, :default => :as_hash
14
+ attribute :return_with_root, Boolean, :default => true
15
+ attribute :return_as_active_resource, Boolean, :default => false
16
+
17
+ def self.configure(configs)
18
+ new(configs)
19
+ end
20
+
21
+ def initialize(attrs = {})
22
+ attrs[:home] = update_home_config(attrs)
23
+ super(attrs)
24
+ end
25
+
26
+ def home_url
27
+ raise_no_host_error
28
+ http = 'http://'
29
+ if home[:port]
30
+ "#{ http }#{ home.fetch(:host) }:#{ home.fetch(:port) }#{ home.fetch(:end_point) }"
31
+ else
32
+ "#{ http }#{ home.fetch(:host) }#{ home.fetch(:end_point) }"
33
+ end
34
+ end
35
+
36
+ def to_hash
37
+ raise_no_host_error
38
+ super.merge(home_url: home_url)
39
+ end
40
+
41
+ def raise_no_host_error
42
+ raise RemoteFactoryGirlConfigError.new("RemoteFactoryGirl.config.home[:host] can not be nil") unless has_home?
43
+ end
44
+
45
+ def has_home?
46
+ !home[:host].nil? && !(home[:host] == '') && !home[:end_point].nil? && !(home[:end_point] == '')
47
+ end
48
+
49
+ private
50
+
51
+ def update_home_config(attrs)
52
+ attrs[:home] = DEFAULT_HOME_CONFIG.merge(attrs.fetch(:home, {}))
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,49 @@
1
+ require 'remote_factory_girl/hash_to_dot'
2
+ require 'remote_factory_girl/json_to_active_resource'
3
+ require 'ostruct'
4
+ require 'json'
5
+
6
+ module RemoteFactoryGirl
7
+ class ConfigApplier
8
+
9
+ attr_reader :json, :config
10
+
11
+ def self.apply_config(json, config = {})
12
+ new(json, config).apply_config
13
+ end
14
+
15
+ def initialize(json, config = {})
16
+ @json = json
17
+ @config = default_config.merge(config)
18
+ end
19
+
20
+ def apply_config
21
+ apply_config_options
22
+ end
23
+
24
+ def default_config
25
+ { :hash_to_dot_klass => HashToDot,
26
+ :json_to_active_resource_klass => JsonToActiveResource }
27
+ end
28
+
29
+ private
30
+
31
+ def apply_config_options
32
+ if config[:return_as_active_resource]
33
+ configured_json = config[:json_to_active_resource_klass].convert(json)
34
+ else
35
+ configured_json = return_with_root(json)
36
+ configured_json = return_response_as(configured_json)
37
+ end
38
+ configured_json
39
+ end
40
+
41
+ def return_response_as(parsed_json)
42
+ config[:return_response_as] == :dot_notation ? config[:hash_to_dot_klass].convert(parsed_json) : parsed_json
43
+ end
44
+
45
+ def return_with_root(parsed_json)
46
+ config[:return_with_root] == false ? Array(parsed_json).flatten.last : parsed_json
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,19 @@
1
+ require 'ostruct'
2
+
3
+ module RemoteFactoryGirl
4
+ class ConfigStruct < OpenStruct
5
+ def self.block_to_hash(block = nil)
6
+ config = self.new
7
+ if block
8
+ block.call(config)
9
+ config.to_hash
10
+ else
11
+ {}
12
+ end
13
+ end
14
+
15
+ def to_hash
16
+ @table
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module RemoteFactoryGirl
2
+ class RemoteFactoryGirlConfigError < StandardError; end
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'dish'
2
+
3
+ module RemoteFactoryGirl
4
+ class HashToDot
5
+ def self.convert(json)
6
+ Dish(json)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ require 'rest-client'
2
+
3
+ module RemoteFactoryGirl
4
+ class Http
5
+ def self.post(config, params, http_lib = RestClient)
6
+ new(config, params, http_lib).response
7
+ end
8
+
9
+ attr_reader :config, :params, :http_lib
10
+
11
+ def initialize(config, params, http_lib = RestClient)
12
+ @config = config
13
+ @params = params
14
+ @http_lib = http_lib
15
+ end
16
+
17
+ def response
18
+ post
19
+ self
20
+ end
21
+
22
+ def post
23
+ config.raise_no_host_error
24
+ @post ||= http_lib.post config.home_url, params, content_type: :json, accept: :json
25
+ end
26
+
27
+ def json
28
+ @json ||= JSON.parse(post)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ module RemoteFactoryGirl
2
+ class JsonToActiveResource
3
+
4
+ def self.convert(json, config = {})
5
+ new(json, config)
6
+ end
7
+
8
+ attr_reader :config, :json
9
+
10
+ alias_method :to_hash, :json
11
+
12
+ def initialize(json, config = {})
13
+ raise 'ActiveResource not defined' if !defined?(ActiveResource)
14
+ @json = json
15
+ @config = config
16
+ end
17
+
18
+ def resource(resource)
19
+ resource.find(id)
20
+ end
21
+
22
+ private
23
+
24
+ def id
25
+ hash = to_array.flatten.last
26
+ (hash['id'] || hash[:id]).to_i
27
+ end
28
+
29
+ def to_array
30
+ @to_arry ||= Array(json)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module RemoteFactoryGirl
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,55 @@
1
+ require "remote_factory_girl/version"
2
+ require 'remote_factory_girl/config'
3
+ require 'remote_factory_girl/http'
4
+ require 'remote_factory_girl/config_applier'
5
+ require 'remote_factory_girl/config_struct'
6
+ require 'remote_factory_girl/hash_to_dot'
7
+ require 'remote_factory_girl/json_to_active_resource'
8
+
9
+ module RemoteFactoryGirl
10
+ class RemoteFactoryGirl
11
+
12
+ attr_reader :name, :attributes, :config
13
+
14
+ def initialize(name, attributes, config)
15
+ @name = name
16
+ @attributes = attributes
17
+ @config = config
18
+ end
19
+
20
+ def apply_config(config_applier = ConfigApplier)
21
+ config_applier.apply_config(post.json, config.to_hash)
22
+ end
23
+
24
+ def post(http = Http)
25
+ @post ||= http.post(config, params)
26
+ end
27
+
28
+ def params
29
+ { factory: name, attributes: attributes }
30
+ end
31
+ end
32
+
33
+ def self.configure(opts = { :config_struct => ConfigStruct, :config => Config }, &block)
34
+ config = opts.fetch(:config_struct).block_to_hash(block)
35
+ self.config = opts.fetch(:config).configure(config)
36
+ end
37
+
38
+ def self.create(factory, attributes = {}, config_applier = ConfigApplier, http = Http)
39
+ factory = RemoteFactoryGirl.new(factory, attributes, config)
40
+ factory.post(http)
41
+ factory.apply_config(config_applier)
42
+ end
43
+
44
+ def self.config
45
+ @config
46
+ end
47
+
48
+ def self.config=(config)
49
+ @config = config
50
+ end
51
+
52
+ def self.reset(config = Config.new)
53
+ self.config = config
54
+ end
55
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'remote_factory_girl/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "remote_factory_girl"
8
+ spec.version = RemoteFactoryGirl::VERSION
9
+ spec.authors = ["tdouce"]
10
+ spec.email = ["travisdouce@gmail.com"]
11
+ spec.summary = %q{}
12
+ spec.description = %q{}
13
+ spec.homepage = "https://github.com/tdouce/remote_factory_girl"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_dependency 'virtus', '~> 1.0'
25
+ spec.add_dependency 'dish'
26
+ spec.add_dependency 'rest-client'
27
+ end
@@ -0,0 +1,127 @@
1
+ require 'remote_factory_girl'
2
+
3
+ describe RemoteFactoryGirl do
4
+
5
+ before { RemoteFactoryGirl.reset }
6
+
7
+ describe 'configuration' do
8
+ it 'should be configured with correct defaults' do
9
+ expect(RemoteFactoryGirl.config.home).to eq({ :host => nil,
10
+ :port => nil,
11
+ :end_point => '/remote_factory_girl/home'})
12
+ expect(RemoteFactoryGirl.config.return_response_as).to eq(:as_hash)
13
+ expect(RemoteFactoryGirl.config.return_with_root).to be_true
14
+ expect(RemoteFactoryGirl.config.return_as_active_resource).to be_false
15
+ end
16
+
17
+ it 'should be able to configure with a block' do
18
+ RemoteFactoryGirl.configure do |config|
19
+ config.home = { host: 'tifton' }
20
+ end
21
+ expect(RemoteFactoryGirl.config.home[:host]).to eq('tifton')
22
+ end
23
+
24
+ it 'should be able to configure .home' do
25
+ RemoteFactoryGirl.config.home[:host] = 'fun_guy'
26
+ RemoteFactoryGirl.config.home[:port] = 3333
27
+ RemoteFactoryGirl.config.home[:end_point] = '/down_home'
28
+ expect(RemoteFactoryGirl.config.home[:host]).to eq('fun_guy')
29
+ expect(RemoteFactoryGirl.config.home[:port]).to eq(3333)
30
+ expect(RemoteFactoryGirl.config.home[:end_point]).to eq('/down_home')
31
+ end
32
+
33
+ it 'should be able to configure .return_response_as' do
34
+ expect(RemoteFactoryGirl.config.return_response_as).to eq(:as_hash)
35
+ end
36
+
37
+ it 'should be able to configure .return_with_root' do
38
+ RemoteFactoryGirl.config.return_with_root = false
39
+ expect(RemoteFactoryGirl.config.return_with_root).to be_false
40
+ end
41
+
42
+ it 'should be able to configure .return_as_active_resource' do
43
+ RemoteFactoryGirl.config.return_with_root = true
44
+ expect(RemoteFactoryGirl.config.return_with_root).to be_true
45
+ end
46
+ end
47
+
48
+ describe 'errors' do
49
+ it 'should raise RemoteFactoryGirlConfigError if .config.home[:host] is nil' do
50
+ RemoteFactoryGirl.config.home[:host] = nil
51
+ expect { RemoteFactoryGirl.create(:site) }.to raise_error(RemoteFactoryGirl::RemoteFactoryGirlConfigError)
52
+ end
53
+
54
+ it 'should raise RemoteFactoryGirlConfigError if .config.home[:end_point] is nil' do
55
+ RemoteFactoryGirl.config.home[:end_point] = nil
56
+ expect { RemoteFactoryGirl.create(:site) }.to raise_error(RemoteFactoryGirl::RemoteFactoryGirlConfigError)
57
+ end
58
+ end
59
+
60
+ describe 'creating a remote factory' do
61
+
62
+ before do
63
+ RestClient.stub(:post).and_return('{"user": {"id": "1", "first_name": "Sam", "last_name": "Iam"}}')
64
+ end
65
+
66
+ describe '.create' do
67
+
68
+ describe 'default .home' do
69
+
70
+ before { RemoteFactoryGirl.config.home[:host] = 'localhost' }
71
+
72
+ it 'should be able to create a factory' do
73
+ user = RemoteFactoryGirl.create(:site)
74
+ expect(user).to have_key('user')
75
+ end
76
+
77
+ it 'should not return root hash key when .return_with_root is false' do
78
+ RemoteFactoryGirl.config.return_with_root = false
79
+ user = RemoteFactoryGirl.create(:user)
80
+ expect(user).to_not have_key('user')
81
+ end
82
+
83
+ it 'should not return an object that responds to dot notation' do
84
+ RemoteFactoryGirl.config.return_response_as = :dot_notation
85
+ user = RemoteFactoryGirl.create(:user)
86
+ expect(user.first_name).to_not eq('Sam')
87
+ end
88
+
89
+ it 'should send a post request to home' do
90
+ expect(RestClient).to receive(:post)
91
+ RemoteFactoryGirl.create(:user, :first_name => 'Sam', :last_name => 'Iam')
92
+ end
93
+ end
94
+
95
+ it 'should not return root hash key and should return an object that responds to dot notation' do
96
+ RemoteFactoryGirl.configure do |config|
97
+ config.home = { :host => 'localhost' }
98
+ config.return_response_as = :dot_notation
99
+ config.return_with_root = false
100
+ end
101
+ user = RemoteFactoryGirl.create(:user)
102
+ expect(user.first_name).to eq('Sam')
103
+ end
104
+
105
+ describe 'when configured to return active_resource object' do
106
+
107
+ class ActiveResource
108
+ def self.find(id); end;
109
+ end
110
+
111
+ class User < ActiveResource; end
112
+
113
+ before do
114
+ RemoteFactoryGirl.configure do |config|
115
+ config.home = { :host => 'localhost' }
116
+ config.return_as_active_resource = true
117
+ end
118
+ end
119
+
120
+ it 'should return an active resource object' do
121
+ expect(ActiveResource).to receive(:find).with(1)
122
+ RemoteFactoryGirl.create(:user).resource(User)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,54 @@
1
+ require 'remote_factory_girl/config_applier'
2
+ require 'remote_factory_girl/json_to_active_resource'
3
+
4
+ describe RemoteFactoryGirl::ConfigApplier do
5
+
6
+ describe '.post' do
7
+
8
+ let(:unparsed_json) {
9
+ '{ "user": {"first_name": "Sam", "last_name": "Iam"}}'
10
+ }
11
+ let(:json) {
12
+ { :user => { :first_name => "Sam", :last_name => "Iam"}}
13
+ }
14
+ let(:hash_to_dot_klass) { double('RemoteFactoryGirl::HashToDot') }
15
+ let(:dish_json_with_user) { OpenStruct.new(:user => OpenStruct.new(:first_name => 'Sam', :last_name => 'Iam')) }
16
+ let(:dish_json_without_user) { OpenStruct.new(:first_name => 'Sam', :last_name => 'Iam') }
17
+
18
+ describe '.apply_config' do
19
+ it 'should not return root hash key when .return_with_root is false' do
20
+ response = RemoteFactoryGirl::ConfigApplier.apply_config(json, :return_with_root => false)
21
+ expect(response).to_not have_key(:user)
22
+ end
23
+
24
+ it 'should not return root hash key when .return_with_root is false' do
25
+ response = RemoteFactoryGirl::ConfigApplier.apply_config(json, :with_root => true)
26
+ expect(response).to have_key(:user)
27
+ end
28
+
29
+ it 'should return an object that responds to dot notation' do
30
+ hash_to_dot_klass.stub(:convert).and_return(dish_json_with_user)
31
+ response = RemoteFactoryGirl::ConfigApplier.apply_config(json, :return_response_as => :dot_notation,
32
+ :hash_to_dot_klass => hash_to_dot_klass)
33
+ expect(response.user.first_name).to eq('Sam')
34
+ end
35
+
36
+ it 'should not return root hash key and should return an object that responds to dot notation' do
37
+ hash_to_dot_klass.stub(:convert).and_return(dish_json_without_user)
38
+ response = RemoteFactoryGirl::ConfigApplier.apply_config(json, :return_response_as => :dot_notation,
39
+ :return_with_root => false,
40
+ :hash_to_dot_klass => hash_to_dot_klass)
41
+ expect(response.first_name).to eq('Sam')
42
+ end
43
+ end
44
+
45
+ describe 'when configured to return active resource objects' do
46
+ it 'should return an active resource object' do
47
+ json_to_active_resource_klass = double('RemoteFactoryGirl::JsonToActiveResource')
48
+ expect(json_to_active_resource_klass).to receive(:convert).with(json)
49
+ RemoteFactoryGirl::ConfigApplier.apply_config(json, :return_as_active_resource => true,
50
+ :json_to_active_resource_klass => json_to_active_resource_klass)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,53 @@
1
+ require 'virtus'
2
+ require 'remote_factory_girl/config.rb'
3
+ require 'remote_factory_girl/http.rb'
4
+ require 'remote_factory_girl/config_applier'
5
+ require 'remote_factory_girl/config_struct'
6
+ require 'remote_factory_girl/hash_to_dot'
7
+
8
+ describe RemoteFactoryGirl::Config do
9
+
10
+ describe 'initialize' do
11
+
12
+ describe '.configure' do
13
+ it 'should be able to set configurations' do
14
+ config = RemoteFactoryGirl::Config.configure({ :home => { :host => 'tifton', :port => 9999, :end_point => '/somewhere' },
15
+ :return_response_as => :as_dot_notation,
16
+ :return_with_root => false })
17
+ expect(config.home).to eq({ :host => 'tifton',
18
+ :port => 9999,
19
+ :end_point => '/somewhere'})
20
+ expect(config.return_response_as).to eq(:as_dot_notation)
21
+ expect(config.return_with_root).to be_false
22
+ end
23
+ end
24
+
25
+ describe 'default configuration' do
26
+ it 'should be configured with correct defaults' do
27
+ config = RemoteFactoryGirl::Config.new
28
+ expect(config.home).to eq({ :host => nil,
29
+ :port => nil,
30
+ :end_point => '/remote_factory_girl/home'})
31
+ expect(config.return_response_as).to eq(:as_hash)
32
+ expect(config.return_with_root).to be_true
33
+ end
34
+ end
35
+
36
+ describe '#home_url' do
37
+
38
+ let(:config) { RemoteFactoryGirl::Config.new }
39
+
40
+ it 'should return a url with port if port is configured' do
41
+ config.home[:host] = 'localhost'
42
+ config.home[:port] = 5555
43
+ expect(config.home_url).to eq('http://localhost:5555/remote_factory_girl/home')
44
+ end
45
+
46
+ it 'should return a url without a port if port is not configured' do
47
+ config.home[:host] = 'localhost_no_port'
48
+ config.home[:port] = nil
49
+ expect(config.home_url).to eq('http://localhost_no_port/remote_factory_girl/home')
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ require 'remote_factory_girl/config_struct.rb'
2
+
3
+ describe RemoteFactoryGirl::ConfigStruct do
4
+
5
+ describe '.block_to_hash' do
6
+ it 'should be able to configure with a block' do
7
+ class Thing
8
+ def self.configure(&block)
9
+ RemoteFactoryGirl::ConfigStruct.block_to_hash(block)
10
+ end
11
+ end
12
+
13
+ thing = Thing.configure do |config|
14
+ config.first_name = 'Sam'
15
+ config.last_name = 'Iam'
16
+ end
17
+
18
+ expect(thing.to_hash).to eq({:first_name => 'Sam', :last_name => 'Iam'})
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ require 'remote_factory_girl/http.rb'
2
+
3
+ describe RemoteFactoryGirl::Http do
4
+
5
+ describe '.post' do
6
+
7
+ let(:config) { double(:home_url => 'http://somewhere') }
8
+ let(:params) { double(:first_name => 'Sam', :last_name => 'Iam') }
9
+ let(:rest_client) { double('RestClient') }
10
+
11
+ it 'should raise no host config errors' do
12
+ rest_client.stub(:post).with(config.home_url, params, content_type: :json, accept: :json).and_return(true)
13
+ expect(config).to receive(:raise_no_host_error)
14
+ RemoteFactoryGirl::Http.post(config, params, rest_client)
15
+ end
16
+
17
+ it 'should send http request to home_url with params' do
18
+ config.stub(:raise_no_host_error)
19
+ expect(rest_client).to receive(:post).with(config.home_url, params, content_type: :json, accept: :json)
20
+ RemoteFactoryGirl::Http.post(config, params, rest_client)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ require 'remote_factory_girl/json_to_active_resource'
2
+
3
+ describe RemoteFactoryGirl::JsonToActiveResource do
4
+
5
+ describe 'when configured to return active_resource object' do
6
+
7
+ class ActiveResource
8
+ def self.find(id); end;
9
+ end
10
+
11
+ class User < ActiveResource; end
12
+
13
+ it 'should return an active resource object' do
14
+ expect(ActiveResource).to receive(:find).with(1)
15
+ RemoteFactoryGirl::JsonToActiveResource.new({:user => {:id => 1}}).resource(User)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,64 @@
1
+ require 'remote_factory_girl'
2
+
3
+ describe RemoteFactoryGirl do
4
+
5
+ let(:config) { double('config', :to_hash => {}) }
6
+
7
+ it 'should return params for http request' do
8
+ rfg = RemoteFactoryGirl::RemoteFactoryGirl.new('user', { :first_name => 'Sam' }, config)
9
+ expect(rfg.params).to eq(
10
+ { :factory => 'user', :attributes => { :first_name => 'Sam'}}
11
+ )
12
+ end
13
+
14
+ describe '#post' do
15
+ it 'should send a post request' do
16
+ http = double('RemoteFactoryGirl::Http')
17
+ attributes = { :first_name => 'Sam' }
18
+ expect(http).to receive(:post).with(config, {:factory => 'user', :attributes => { :first_name => 'Sam'}})
19
+ RemoteFactoryGirl::RemoteFactoryGirl.new('user', attributes, config).post(http)
20
+ end
21
+ end
22
+
23
+ describe '#apply_config' do
24
+ it 'should apply config options to json with supplied configuration' do
25
+ attributes = { :first_name => 'Sam' }
26
+ config_applier = double('RemoteFactoryGirl::ConfigApplier')
27
+ post = double('RemoteFactoryGirl::Http', :json => {})
28
+ RemoteFactoryGirl::Http.stub(:post).and_return(post)
29
+ expect(config_applier).to receive(:apply_config).with(post.json, config.to_hash)
30
+ RemoteFactoryGirl::RemoteFactoryGirl.new('user', attributes, config).apply_config(config_applier)
31
+ end
32
+ end
33
+
34
+ it 'should be able to configure with a block' do
35
+ pending
36
+ end
37
+
38
+ describe '.config' do
39
+ it 'should be able to set and get config' do
40
+ config = double('config')
41
+ RemoteFactoryGirl.config = config
42
+ expect(RemoteFactoryGirl.config).to equal(config)
43
+ end
44
+ end
45
+
46
+ describe '.reset' do
47
+ it 'should be able to reset the configuration' do
48
+ config = double('config')
49
+ RemoteFactoryGirl.config = config
50
+ RemoteFactoryGirl.reset(double('config'))
51
+ expect(RemoteFactoryGirl.config).to_not equal(config)
52
+ end
53
+ end
54
+
55
+ describe '.create' do
56
+ describe 'when not returning active resource object' do
57
+ pending
58
+ end
59
+
60
+ describe 'when returning active resource object' do
61
+ pending
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ # our gem
4
+ require 'remote_factory_girl'
5
+
6
+ RSpec.configure do |config|
7
+
8
+ end
data/wiki.md ADDED
@@ -0,0 +1,179 @@
1
+ # RemoteFactoryGirl and RemoteFactoryGirlHomeRails
2
+
3
+ Create [factory_girl](https://github.com/thoughtbot/factory_girl) factories
4
+ remotely using [remote_factory_girl](https://github.com/tdouce/remote_factory_girl) in conjuction with [remote_factory_girl_home_rails](https://github.com/tdouce/remote_factory_girl_home_rails).
5
+
6
+ # Why RemoteFactoryGirl and RemoteFactoryGirlHomeRails?
7
+
8
+ Integration testing SOA (Software Oriented Architecture) apps is an inherently
9
+ difficult problem (Rails apps included :). SOA is comprised of multiple applications,
10
+ and while individual apps can be tested (and presumably passing) in isolation (usually by
11
+ mocking http requests), it does not guarantee the apps will work in unison. Testing
12
+ interactions between apps is more difficult.
13
+
14
+ One problem with integration testing SOA apps is that it is difficult to write
15
+ integration tests in the client. Due to the nature of SOA you can not
16
+ create the data you need because the database that is needed to create the data
17
+ resides in another application. Consider the following architecture:
18
+
19
+ - image of
20
+ - *home* (with database)
21
+ - with user model
22
+ - *client*
23
+ - communicate over http (via json)
24
+
25
+ The *home* application contains the database, and the *client* application does
26
+ not have a database. If the *client* application wants a list of all the
27
+ users, it has to make an http json request to *home*, *home* requests all the users
28
+ from the database, and *home* sends the response back to the *client*.
29
+
30
+ In traditional applications (apps that contain a database), it is possible to create
31
+ test data with tools such as [FactoryGirl](https://github.com/thoughtbot/factory_girl).
32
+ However, in SOA apps factory_girl alone does not suffice. remote_factory_girl when used in
33
+ conjunction with [remote_factory_girl_home_rails](https://github.com/tdouce/remote_factory_girl_home_rails), builds on top of [factory_girl](https://github.com/thoughtbot/factory_girl) (because we all work on the backs of giants)
34
+ and provides a mechanism to create the data you need from the *client* app in the *home* app.
35
+
36
+
37
+ ## Installation
38
+
39
+ [remote_factory_girl](https://github.com/tdouce/remote_factory_girl) should live in the *client* application and [remote_factory_girl_home_rails](https://github.com/tdouce/remote_factory_girl_home_rails) should live in the *home* app (the app with factory_girl factories).
40
+
41
+ ## Client
42
+
43
+ Add this line to the *client* application's Gemfile:
44
+
45
+ ```ruby
46
+ group :test do
47
+ gem 'remote_factory_girl'
48
+ end
49
+ ```
50
+
51
+ And then execute:
52
+
53
+ $ bundle
54
+
55
+ Or install it yourself as:
56
+
57
+ $ gem install remote_factory_girl
58
+
59
+ ### Basic
60
+
61
+ Configure in `spec/spec_helper.rb`
62
+ ```ruby
63
+ RemoteFactoryGirl.configure do |config|
64
+ config.home = { host: 'localhost', port: 5000, end_point: "/over_the_rainbow" }
65
+ config.return_with_root = false
66
+ config.return_response_as = :dot_notation
67
+ end
68
+ ```
69
+
70
+ Use in specs
71
+
72
+ ```ruby
73
+ require 'spec_helper'
74
+
75
+ describe User do
76
+ it 'should create a user factory in RemoteFactoryGirlHome' do
77
+ user = RemoteFactoryGirl.create(:user, first_name: 'Sam', last_name: 'Iam')
78
+ expect(user.first_name).to eq('Sam')
79
+ end
80
+ end
81
+ ```
82
+
83
+ ### ActiveResource
84
+
85
+ Configure in `spec/spec_helper.rb`
86
+ ```ruby
87
+ RemoteFactoryGirl.configure do |config|
88
+ config.home = { host: 'localhost', port: 5000, end_point: '/remote_factory_girl' }
89
+ config.return_as_active_resource = true
90
+ end
91
+ ```
92
+
93
+ Use in specs
94
+
95
+ ```ruby
96
+ require 'spec_helper'
97
+
98
+ describe User do
99
+ it 'should create a user factory in RemoteFactoryGirlHome' do
100
+ user = RemoteFactoryGirl.create(:user_with_friends, first_name: 'Sam', last_name: 'Iam').resource(User)
101
+ expect(user.first_name).to eq('Sam')
102
+ end
103
+ end
104
+ ```
105
+
106
+ ## Home
107
+
108
+ Add this line to *home* application's Gemfile:
109
+
110
+ ```ruby
111
+ group :test do
112
+ gem 'remote_factory_girl_home_rails'
113
+ end
114
+ ```
115
+
116
+ And then execute:
117
+
118
+ $ bundle
119
+
120
+
121
+ ## Usage
122
+
123
+ Configure in `config/environments/*.rb`
124
+
125
+ Activate [remote_factory_girl_home_rails](https://github.com/tdouce/remote_factory_girl_home_rails) to run in the environments in which it is intended to
126
+ run. For example, if remote_factory_girl_home_rails is included in `group
127
+ :test` (most common), then activate it in `config/environments/test.rb`
128
+
129
+ ```ruby
130
+ YourApplication::Application.configure do
131
+ ...
132
+ config.remote_factory_girl_home_rails.enable = true
133
+ ...
134
+ end
135
+ ```
136
+
137
+ Configure in `config/routes.rb`
138
+
139
+ ```ruby
140
+ YourApplication::Application.routes.draw do
141
+ if defined?(RemoteFactoryGirlHomeRails::Engine)
142
+ mount RemoteFactoryGirlHomeRails::Engine, at: '/remote_factory_girl'
143
+ end
144
+ end
145
+ ```
146
+
147
+ Configure in `config/initializers/remote_factory_girl_home_rails.rb`
148
+
149
+ Specify any methods that should be skipped for incoming http requests. The most
150
+ common methods to skip are authentication related methods that live in
151
+ `ApplicationController`.
152
+
153
+
154
+ ```ruby
155
+ RemoteFactoryGirlHomeRails.configure do |config|
156
+ config.skip_before_filter = [:authenticate, :some_other_method]
157
+ end if defined?(RemoteFactoryGirlHomeRails)
158
+ ```
159
+
160
+
161
+ ## Usage
162
+
163
+ ### Home
164
+
165
+ 1. Run any outstanding migrations.
166
+ 2. Start the *home* application's server at the port and end point specified in the *client*
167
+ application's configuration. Given the above example:
168
+
169
+ ```bash
170
+ rails server --environment=test --pid=/Users/your_app/tmp/pids/test.pid --port=5000
171
+ ```
172
+
173
+ ### Client
174
+
175
+ Run your test suite.
176
+
177
+
178
+
179
+
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remote_factory_girl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - tdouce
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: virtus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: dish
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rest-client
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: ''
84
+ email:
85
+ - travisdouce@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/remote_factory_girl.rb
97
+ - lib/remote_factory_girl/config.rb
98
+ - lib/remote_factory_girl/config_applier.rb
99
+ - lib/remote_factory_girl/config_struct.rb
100
+ - lib/remote_factory_girl/exceptions.rb
101
+ - lib/remote_factory_girl/hash_to_dot.rb
102
+ - lib/remote_factory_girl/http.rb
103
+ - lib/remote_factory_girl/json_to_active_resource.rb
104
+ - lib/remote_factory_girl/version.rb
105
+ - remote_factory_girl.gemspec
106
+ - spec/integration/remote_factory_girl_spec.rb
107
+ - spec/models/remote_factory_girl/config_applier_spec.rb
108
+ - spec/models/remote_factory_girl/config_spec.rb
109
+ - spec/models/remote_factory_girl/config_struct_spec.rb
110
+ - spec/models/remote_factory_girl/http_spec.rb
111
+ - spec/models/remote_factory_girl/json_to_active_resource_spec.rb
112
+ - spec/models/remote_factory_girl_spec.rb
113
+ - spec/spec_helper.rb
114
+ - wiki.md
115
+ homepage: https://github.com/tdouce/remote_factory_girl
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.2.2
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: ''
139
+ test_files:
140
+ - spec/integration/remote_factory_girl_spec.rb
141
+ - spec/models/remote_factory_girl/config_applier_spec.rb
142
+ - spec/models/remote_factory_girl/config_spec.rb
143
+ - spec/models/remote_factory_girl/config_struct_spec.rb
144
+ - spec/models/remote_factory_girl/http_spec.rb
145
+ - spec/models/remote_factory_girl/json_to_active_resource_spec.rb
146
+ - spec/models/remote_factory_girl_spec.rb
147
+ - spec/spec_helper.rb
148
+ has_rdoc: