sham 1.0.0 → 1.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.
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