sham 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ bin/
1
2
  pkg/*
2
3
  *.gem
3
4
  *.swp
data/README.markdown CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sham
2
2
 
3
- Lightweight flexible factories for Ruby on Rails testing.
3
+ Lightweight flexible factories for Ruby and Rails testing.
4
4
 
5
5
  ## Installation
6
6
 
@@ -26,6 +26,13 @@ your application.rb or test.rb file:
26
26
  Sham::Config.activate!
27
27
  end
28
28
 
29
+ If you are not using Rails you can activate all of your shams by specifying a
30
+ path under which your shams are defined. For instance, this command will load
31
+ all Ruby files under the `/my/project/path/sham` directory and and all
32
+ subdirectories.
33
+
34
+ Sham::Config.activate!('/my/project/path')
35
+
29
36
  To enable all Shams in cucumber, add the following to your
30
37
  features/support/env.rb file:
31
38
 
data/lib/sham.rb CHANGED
@@ -1,103 +1,8 @@
1
- module Sham
2
- class Base
3
- attr_accessor :klass, :options
1
+ module Sham; end
4
2
 
5
- def initialize klass, options = {}
6
- @klass = klass
7
- @options = options
8
- end
3
+ require 'sham/data'
4
+ require 'sham/util'
5
+ require 'sham/base'
6
+ require 'sham/config'
7
+ require 'sham/shammable'
9
8
 
10
- def sham!
11
- @klass.sham! @options
12
- end
13
- end
14
-
15
- class Config
16
- def self.activate!
17
- Dir["#{Rails.root}/sham/**/*.rb"].each do |f|
18
- load f
19
- end
20
- end
21
-
22
- attr_accessor :klass, :name
23
-
24
- def initialize klass, name
25
- self.klass = klass
26
- self.name = name
27
- end
28
-
29
- def attributes &attributes
30
- klass.add_sham_attributes(name, attributes)
31
- end
32
-
33
- def empty
34
- klass.add_sham_attributes(name, Proc.new{ Hash.new() })
35
- end
36
- end
37
-
38
- def self.config klass, name = :default
39
- unless klass.include?(Sham::Shammable)
40
- klass.send(:include, Sham::Shammable)
41
- end
42
- yield(Sham::Config.new(klass, name))
43
- end
44
-
45
- def self.string!
46
- ActiveSupport::SecureRandom.hex(5)
47
- end
48
-
49
- def self.parse! value
50
- if value.is_a?(Array)
51
- value.map{ |k| parse! k }
52
- elsif value.is_a?(Hash)
53
- Hash.new value.map{ |k,v| [k, parse!(v)] }
54
- elsif value.is_a?(Sham::Base)
55
- value.sham!
56
- else
57
- value
58
- end
59
- end
60
-
61
- def self.add_options! klass, options = {}, attributes
62
- attributes.call.each do |key, value|
63
- options[key] = self.parse!(value) unless options.has_key?(key)
64
- end
65
- end
66
-
67
- module Shammable
68
- def self.included(klass)
69
- klass.extend(ClassMethods)
70
-
71
- klass.class_eval <<-EVAL
72
- def self.add_sham_attributes name, attributes
73
- @@sham_attributes ||= {}
74
- @@sham_attributes[name] = attributes
75
- end
76
-
77
- def self.sham_attributes
78
- @@sham_attributes
79
- end
80
- EVAL
81
- end
82
-
83
- module ClassMethods
84
- def sham! *args
85
- options = (args.extract_options! || {})
86
- type = (args[0] == :build ? args[1] : args[0]) || :default
87
- build = args[0] == :build || args[1] == :build
88
-
89
- ::Sham.add_options! self.name, options, sham_attributes[type]
90
- klass = (options.delete(:type) || self.name).constantize
91
- if build
92
- klass.new(options)
93
- else
94
- klass.create(options)
95
- end
96
- end
97
-
98
- def sham_alternate! type, *args
99
- sham!(type, *args)
100
- end
101
- end
102
- end
103
- end
data/lib/sham/base.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Sham
2
+ class Base
3
+ attr_accessor :klass, :options
4
+
5
+ def initialize klass, options = {}
6
+ @klass = klass
7
+ @options = options
8
+ end
9
+
10
+ def sham!
11
+ @klass.sham!(@options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Sham
2
+ class << self
3
+ def config klass, name = :default
4
+ unless klass.include?(Sham::Shammable)
5
+ klass.send(:include, Sham::Shammable)
6
+ end
7
+ yield(Sham::Config.new(klass, name))
8
+ end
9
+ end
10
+
11
+ class Config
12
+ def self.activate! root = nil
13
+ root = Rails.root if root.nil? && defined?(Rails.root)
14
+ root = File.join(root, 'sham', '**', '*.rb')
15
+ Dir[root].each{ |f| load(f) }
16
+ end
17
+
18
+ attr_accessor :klass, :name
19
+
20
+ def initialize klass, name
21
+ self.klass = klass
22
+ self.name = name
23
+ end
24
+
25
+ def attributes &config
26
+ klass.add_sham_config(name, config)
27
+ end
28
+
29
+ def empty
30
+ klass.add_sham_config(name, Proc.new{ Hash.new() })
31
+ end
32
+ end
33
+ end
data/lib/sham/data.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'securerandom'
2
+
3
+ module Sham
4
+ class << self
5
+ def string! len = 5
6
+ ::SecureRandom.hex(len)
7
+ end
8
+
9
+ def integer! top = 100
10
+ ::SecureRandom.random_number(top)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,62 @@
1
+ module Sham
2
+ class << self
3
+ def parse! value
4
+ if value.is_a?(Array)
5
+ value.map{ |k| parse!(k) }
6
+ elsif value.is_a?(Hash)
7
+ Hash.new value.map{ |k,v| [k, parse!(v)] }
8
+ elsif value.is_a?(Sham::Base)
9
+ value.sham!
10
+ else
11
+ value
12
+ end
13
+ end
14
+
15
+ def add_options! klass, options = {}, attributes
16
+ attributes.call.each do |key, value|
17
+ options[key] = parse!(value) unless options.has_key?(key)
18
+ end
19
+ end
20
+ end
21
+
22
+ module Shammable
23
+ def self.included(klass)
24
+ klass.extend(ClassMethods)
25
+
26
+ (class << klass; self; end).instance_eval do
27
+ attr_accessor :sham_configs
28
+
29
+ define_method(:add_sham_config) do |name, config|
30
+ self.sham_configs ||= {}
31
+ self.sham_configs[name] = config
32
+ end
33
+
34
+ define_method(:sham_config) do |name|
35
+ if sham_configs && sham_configs.has_key?(name)
36
+ sham_configs[name]
37
+ else
38
+ superclass.sham_config(name)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ module ClassMethods
45
+ def sham! *args
46
+ options = Sham::Util.extract_options!(args)
47
+ type = (args[0] == :build ? args[1] : args[0]) || :default
48
+ build = args[0] == :build || args[1] == :build
49
+
50
+ ::Sham.add_options!(name, options, sham_config(type))
51
+ klass = Sham::Util.constantize(options.delete(:type) || self.name)
52
+ if build || !klass.respond_to?(:create)
53
+ klass.new(options)
54
+ else
55
+ klass.create(options)
56
+ end
57
+ end
58
+
59
+ alias :sham_alternate! :sham!
60
+ end
61
+ end
62
+ end
data/lib/sham/util.rb ADDED
@@ -0,0 +1,15 @@
1
+ module Sham
2
+ module Util
3
+ def self.extract_options!(ary)
4
+ ary.last.is_a?(::Hash) ? ary.pop : {}
5
+ end
6
+
7
+ def self.constantize(word)
8
+ unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ word
9
+ raise NameError, "#{word.inspect} is not a valid constant name!"
10
+ end
11
+
12
+ Object.module_eval("::#{$1}", __FILE__, __LINE__)
13
+ end
14
+ end
15
+ end
data/lib/sham/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sham
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/sham.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.email = ["pan.thomakos@gmail.com"]
11
11
  s.homepage = "http://github.com/panthomakos/sham"
12
12
  s.summary = "sham-#{Sham::VERSION}"
13
- s.description = %q{Lightweight flexible factories for Ruby on Rails testing.}
13
+ s.description = %q{Lightweight flexible factories for Ruby and Rails testing.}
14
14
 
15
15
  s.rubyforge_project = "sham"
16
16
 
@@ -20,5 +20,6 @@ Gem::Specification.new do |s|
20
20
  s.extra_rdoc_files = ["README.markdown", "License.txt"]
21
21
  s.rdoc_options = ["--charset=UTF-8"]
22
22
  s.require_paths = ["lib"]
23
- s.add_development_dependency('rails', '>= 3.0.1')
23
+
24
+ s.add_development_dependency('rspec')
24
25
  end
@@ -0,0 +1,11 @@
1
+ class Employee < User
2
+ end
3
+
4
+ Sham.config(Employee) do |c|
5
+ c.attributes do
6
+ {
7
+ name: "Employee #{Sham.string!}",
8
+ email: "#{Sham.string!}@company.com"
9
+ }
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sham::Base do
4
+ let(:base){ Sham::Base.new(User, name: Sham.string!) }
5
+
6
+ it 'should call sham! on the klass' do
7
+ User.should_receive(:sham!)
8
+ base.sham!
9
+ end
10
+
11
+ it 'should properly set the attributes' do
12
+ user = base.sham!
13
+ user[:name].should == base.options[:name]
14
+ end
15
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ class Company < Object; end
4
+
5
+ describe Sham::Config do
6
+ it 'should activate shams in the root directory' do
7
+ begin
8
+ expect {
9
+ described_class.activate!(SPEC_DIR)
10
+ }.to change{ defined?(Employee) }.from(nil).to('constant')
11
+ ensure
12
+ Object.send(:remove_const, :Employee) rescue nil
13
+ end
14
+ end
15
+
16
+ it 'should include Sham::Shammable when configured' do
17
+ expect {
18
+ Sham.config(Company){ |c| c.empty }
19
+ }.to change{ Company.include?(Sham::Shammable) }.from(false).to(true)
20
+ end
21
+
22
+ it 'should only include Sham::Shammable once when configured' do
23
+ Company.should_receive(:include).never
24
+
25
+ Sham.config(Company, :alternate){ |c| c.empty }
26
+ end
27
+
28
+ it 'should define sham! on the class' do
29
+ class BiggerCompany < Object; end
30
+
31
+ expect {
32
+ Sham.config(BiggerCompany){ |c| c.empty }
33
+ }.to change{ BiggerCompany.respond_to?(:sham!) }.from(false).to(true)
34
+ end
35
+
36
+ it 'should define sham_alternate! on the class' do
37
+ class BiggestCompany < Object; end
38
+
39
+ expect {
40
+ Sham.config(BiggestCompany){ |c| c.empty }
41
+ }.to change{ BiggestCompany.respond_to?(:sham_alternate!) }
42
+ .from(false).to(true)
43
+ end
44
+
45
+ context 'shams' do
46
+ it 'should carry shams over to subclasses' do
47
+ class SuperUser < User; end
48
+
49
+ SuperUser.should respond_to(:sham!)
50
+ SuperUser.sham![:identifier].should == User.sham![:identifier]
51
+ end
52
+
53
+ it 'should allow subclasses to define their own shams' do
54
+ class PowerUser < User; end
55
+
56
+ Sham.config(PowerUser){ |c| c.empty }
57
+
58
+ User.sham_config(:default)
59
+ .should_not == PowerUser.sham_config(:default)
60
+ end
61
+
62
+ it 'should default to calling #new when #create is not present' do
63
+ class SimpleUser
64
+ def initialize(options = {}); end
65
+ end
66
+
67
+ Sham.config(SimpleUser){ |c| c.empty }
68
+
69
+ SimpleUser.should_receive(:new).once
70
+
71
+ SimpleUser.sham!
72
+ end
73
+
74
+ it 'should allow shams to be built instead of created' do
75
+ User.should_receive(:create).never
76
+
77
+ User.sham!(:build)
78
+ end
79
+
80
+ it 'should create shams by default' do
81
+ User.should_receive(:create).once
82
+
83
+ User.sham!
84
+ end
85
+
86
+ it 'should allow alternate shams to be built' do
87
+ User.should_receive(:create).never
88
+
89
+ User.sham!(:build, :super)
90
+ end
91
+
92
+ it 'should allow alternate shams to be created' do
93
+ User.should_receive(:create).once
94
+
95
+ User.sham!(:super)
96
+ end
97
+
98
+ it 'should sham alternatives with alternative options' do
99
+ User.sham!(:super)[:identifier]
100
+ .should_not == User.sham![:identifier]
101
+ end
102
+
103
+ it 'should perform nested shams' do
104
+ Profile.should_receive(:sham!).once
105
+
106
+ User.sham!(:with_profile)
107
+ end
108
+
109
+ it 'should allow nested shams to be overwritten' do
110
+ profile = Profile.new
111
+
112
+ User.sham!(:with_profile, profile: profile)[:profile]
113
+ .should == profile
114
+
115
+ User.sham!(:with_profile)[:profile]
116
+ .should_not == profile
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sham do
4
+ context '#string!' do
5
+ it 'should be a string' do
6
+ described_class.string!.should be_an_instance_of(String)
7
+ end
8
+
9
+ it 'should have a length of 10' do
10
+ described_class.string!.length.should == 10
11
+ end
12
+
13
+ it 'should allow different lengths' do
14
+ described_class.string!(10).length.should == 20
15
+ end
16
+ end
17
+
18
+ context '#integer!' do
19
+ it 'should be an integer' do
20
+ described_class.integer!.should \
21
+ be_an_instance_of(Fixnum)
22
+ end
23
+
24
+ it 'should be between 0 and 100' do
25
+ 10.times do
26
+ described_class.integer!.should satisfy{ |x| x >= 0 && x < 100 }
27
+ end
28
+ end
29
+
30
+ it 'should allow a differnet top' do
31
+ 10.times do
32
+ described_class.integer!(10).should satisfy{ |x| x >= 0 && x < 10 }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sham::Util do
4
+ context '#extract_options!' do
5
+ let(:ary){ [1, 2, 3, 4, opt: 'arg', opt2: 'arg'] }
6
+
7
+ it 'should alter the original array' do
8
+ expect {
9
+ described_class.extract_options!(ary)
10
+ }.to change{ ary.count }.from(5).to(4)
11
+ end
12
+
13
+ it 'should return the hash' do
14
+ described_class.extract_options!(ary).keys.should include(:opt, :opt2)
15
+ end
16
+
17
+ it 'should succeed when there are no options to extract' do
18
+ described_class.extract_options!([1,2,3]).should == {}
19
+ end
20
+
21
+ it 'should succeed when the array is empty' do
22
+ described_class.extract_options!([]).should == {}
23
+ end
24
+
25
+ it 'should fail if the argument is not an array' do
26
+ expect {
27
+ described_class.extract_options!(10)
28
+ }.to raise_error(NoMethodError)
29
+ end
30
+ end
31
+
32
+ context '#constantize' do
33
+ it 'should raise a NameError when the constant is not valid' do
34
+ expect {
35
+ described_class.constantize('user')
36
+ }.to raise_error(NameError)
37
+ end
38
+
39
+ it 'should raise a NameError when the constant is undefined' do
40
+ expect {
41
+ described_class.constantize("U#{Sham.string!}")
42
+ }.to raise_error(NameError)
43
+ end
44
+
45
+ it 'should return the constant' do
46
+ described_class.constantize('User').should == User
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,45 @@
1
+ require 'bundler'
2
+ Bundler.require(:default)
3
+
4
+ SPEC_DIR = File.join(File.dirname(File.expand_path(__FILE__)), 'root')
5
+
6
+ class User
7
+ attr_accessor :attributes
8
+
9
+ def initialize attributes = {}
10
+ self.attributes = attributes
11
+ end
12
+
13
+ def self.create attributes = {}
14
+ new(attributes)
15
+ end
16
+
17
+ def [] attribute
18
+ attributes[attribute]
19
+ end
20
+ end
21
+
22
+ Sham.config(User) do |c|
23
+ c.attributes do
24
+ {
25
+ name: Sham.string!,
26
+ email: "#{Sham.string!}@gmail.com",
27
+ identifier: 100
28
+ }
29
+ end
30
+ end
31
+
32
+ Sham.config(User, :super) do |c|
33
+ c.attributes do
34
+ { identifier: 200 }
35
+ end
36
+ end
37
+
38
+ class Profile < User; end
39
+
40
+ Sham.config(User, :with_profile) do |c|
41
+ c.attributes do
42
+ { profile: Sham::Base.new(Profile) }
43
+ end
44
+ end
45
+ Sham.config(Profile){ |c| c.empty }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sham
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,20 +9,20 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-13 00:00:00.000000000Z
12
+ date: 2011-10-03 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rails
16
- requirement: &70123949484060 !ruby/object:Gem::Requirement
15
+ name: rspec
16
+ requirement: &70284343539020 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 3.0.1
21
+ version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70123949484060
25
- description: Lightweight flexible factories for Ruby on Rails testing.
24
+ version_requirements: *70284343539020
25
+ description: Lightweight flexible factories for Ruby and Rails testing.
26
26
  email:
27
27
  - pan.thomakos@gmail.com
28
28
  executables: []
@@ -38,8 +38,19 @@ files:
38
38
  - README.markdown
39
39
  - Rakefile
40
40
  - lib/sham.rb
41
+ - lib/sham/base.rb
42
+ - lib/sham/config.rb
43
+ - lib/sham/data.rb
44
+ - lib/sham/shammable.rb
45
+ - lib/sham/util.rb
41
46
  - lib/sham/version.rb
42
47
  - sham.gemspec
48
+ - spec/root/sham/employee.rb
49
+ - spec/sham/base_spec.rb
50
+ - spec/sham/config_spec.rb
51
+ - spec/sham/data_spec.rb
52
+ - spec/sham/util_spec.rb
53
+ - spec/spec_helper.rb
43
54
  homepage: http://github.com/panthomakos/sham
44
55
  licenses: []
45
56
  post_install_message:
@@ -64,5 +75,11 @@ rubyforge_project: sham
64
75
  rubygems_version: 1.8.6
65
76
  signing_key:
66
77
  specification_version: 3
67
- summary: sham-1.0.0
68
- test_files: []
78
+ summary: sham-1.0.1
79
+ test_files:
80
+ - spec/root/sham/employee.rb
81
+ - spec/sham/base_spec.rb
82
+ - spec/sham/config_spec.rb
83
+ - spec/sham/data_spec.rb
84
+ - spec/sham/util_spec.rb
85
+ - spec/spec_helper.rb