remote_factory_girl 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 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: