ianwhite-pickle 0.1.4 → 0.1.5

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/History.txt CHANGED
@@ -1,3 +1,21 @@
1
+ == 0.1.5
2
+
3
+ * API change
4
+ * CaptureModel, etc are now 'capture_model' methods
5
+
6
+ * 3 major enhancements
7
+ * Steps for asserting that <n> models exist, matching certain criteria
8
+ * Steps for asserting associations added to generated pickle steps
9
+ 'Then the user should be in the post's commenters'
10
+ 'Then the forum: "awesome" should be the 2nd post's forum'
11
+ * configuration can now occur any time before a step is defined, which makes
12
+ for much more intuitive env.rb
13
+
14
+ * 1 minor enhancement
15
+ * predicate matching is less prone to step conflicts because we preload a
16
+ big list of all the predicate and column methods
17
+ * field values now handle booleans and numerics
18
+
1
19
  == 0.1.4
2
20
 
3
21
  * 1 major enhancement
data/License.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008 Ian White - ian.w.white@ardes.com
1
+ Copyright (c) 2008-2009 Ian White - ian.w.white@gmail.com
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/lib/pickle.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'active_support'
2
+ require 'pickle/version'
2
3
  require 'pickle/adapter'
3
4
  require 'pickle/config'
4
5
  require 'pickle/parser'
@@ -9,12 +10,28 @@ require 'pickle/injector'
9
10
  # make the parser aware of models in the session (for fields refering to models)
10
11
  Pickle::Parser.send :include, Pickle::Parser::WithSession
11
12
 
13
+ module Pickle
14
+ class << self
15
+ def config
16
+ @config ||= Config.new
17
+ end
18
+
19
+ def configure(&block)
20
+ config.configure(&block)
21
+ end
22
+
23
+ def parser(options = {})
24
+ @parser ||= Parser.new({:config => config}.merge(options))
25
+ end
26
+ end
27
+ end
28
+
12
29
  # inject the pickle session into integration session if we have one (TODO: inject into merb etc?)
13
30
  if defined?(ActionController::Integration::Session)
14
31
  Pickle::Injector.inject Pickle::Session, :into => ActionController::Integration::Session
15
32
  end
16
33
 
17
- # shortcuts for useful regexps when defining pickle steps
18
- CaptureModel = Pickle.parser.capture_model
19
- CapturePluralFactory = Pickle.parser.capture_plural_factory
20
- CaptureFields = Pickle.parser.capture_fields
34
+ # shortcuts to regexps for use in step definitions
35
+ class << self
36
+ delegate :capture_model, :capture_fields, :capture_factory, :capture_plural_factory, :capture_predicate, :to => 'Pickle.parser'
37
+ end
@@ -3,12 +3,13 @@ module Pickle
3
3
  # can easily create an adaptor to make it work with Pickle.
4
4
  #
5
5
  # The factory adaptor must have a #factories class method that returns
6
- # its instances, and each instance must respond to a #name method which
7
- # identifies the factory by name (default is attr_reader for @name), and a
8
- # #create method which takes an optional attributes hash,
9
- # and returns a newly created object
6
+ # its instances, and each instance must respond to:
7
+ #
8
+ # #name : identifies the factory by name (default is attr_reader)
9
+ # #klass : returns the associated model class for this factory (default is attr_reader)
10
+ # #create(attrs = {}) : returns a newly created object
10
11
  class Adapter
11
- attr_reader :name
12
+ attr_reader :name, :klass
12
13
 
13
14
  def self.factories
14
15
  raise NotImplementedError, "return an array of factory adapter objects"
@@ -17,25 +18,23 @@ module Pickle
17
18
  def create(attrs = {})
18
19
  raise NotImplementedError, "create and return an object with the given attributes"
19
20
  end
21
+
22
+ cattr_writer :model_classes
23
+ self.model_classes = nil
20
24
 
21
- # by default the models are active_record subclasses, but you can set this to whatever classes you want
22
- class << self
23
- attr_writer :model_classes
24
-
25
- def model_classes
26
- @model_classes ||= returning(::ActiveRecord::Base.send(:subclasses)) do |classes|
27
- defined?(CGI::Session::ActiveRecordStore::Session) && classes.delete(CGI::Session::ActiveRecordStore::Session)
28
- end
25
+ def self.model_classes
26
+ @@model_classes ||= returning(::ActiveRecord::Base.send(:subclasses)) do |classes|
27
+ defined?(CGI::Session::ActiveRecordStore::Session) && classes.delete(CGI::Session::ActiveRecordStore::Session)
29
28
  end
30
29
  end
31
-
30
+
32
31
  # machinist adapter
33
32
  class Machinist < Adapter
34
33
  def self.factories
35
34
  factories = []
36
35
  model_classes.each do |klass|
37
36
  factories << new(klass, "make") if klass.instance_variable_get('@blueprint')
38
- # if there are special make_special methods, add blueprints for them
37
+ # if there are make_<special> methods, add blueprints for them
39
38
  klass.methods.select{|m| m =~ /^make_/ && m !~ /_unsaved$/}.each do |method|
40
39
  factories << new(klass, method)
41
40
  end
@@ -56,11 +55,11 @@ module Pickle
56
55
  # factory-girl adapter
57
56
  class FactoryGirl < Adapter
58
57
  def self.factories
59
- (::Factory.factories.keys rescue []).map {|key| new(key)}
58
+ (::Factory.factories.values rescue []).map {|factory| new(factory)}
60
59
  end
61
60
 
62
- def initialize(key)
63
- @name = key.to_s
61
+ def initialize(factory)
62
+ @klass, @name = factory.build_class, factory.factory_name.to_s
64
63
  end
65
64
 
66
65
  def create(attrs = {})
data/lib/pickle/config.rb CHANGED
@@ -1,17 +1,8 @@
1
1
  require 'ostruct'
2
2
 
3
3
  module Pickle
4
- class << self
5
- def config(&block)
6
- @config ||= Config.new
7
- ensure
8
- @config.configure(&block) if block_given?
9
- end
10
- alias_method :configure, :config
11
- end
12
-
13
4
  class Config
14
- attr_writer :adapters, :factories, :mappings
5
+ attr_writer :adapters, :factories, :mappings, :predicates
15
6
 
16
7
  def initialize(&block)
17
8
  configure(&block) if block_given?
@@ -39,6 +30,12 @@ module Pickle
39
30
  factories.keys
40
31
  end
41
32
 
33
+ def predicates
34
+ @predicates ||= Pickle::Adapter.model_classes.map do |klass|
35
+ klass.public_instance_methods.select{|m| m =~ /\?$/} + klass.column_names
36
+ end.flatten.uniq
37
+ end
38
+
42
39
  def mappings
43
40
  @mappings ||= []
44
41
  end
@@ -1,18 +1,18 @@
1
1
  module Pickle
2
2
  module Injector
3
- def self.inject(session_class, options = {})
4
- target = options[:into] || ActionController::Integration::Session
5
- session_method = options[:name] || session_class.name.underscore.gsub('/','_')
6
- session_options = options[:options] || {}
3
+ def self.inject(delegate_class, options = {})
4
+ target_class = options[:into] || raise('inject requires a target class specified with :into')
5
+ delegate_name = options[:name] || delegate_class.name.underscore.gsub('/','_')
6
+ init_delegate = options[:init] || lambda { new }
7
7
 
8
8
  # create a session object on demand (in target)
9
- target.send(:define_method, session_method) do
10
- instance_variable_get("@#{session_method}") || instance_variable_set("@#{session_method}", session_class.new(session_options))
9
+ target_class.send(:define_method, delegate_name) do
10
+ instance_variable_get("@#{delegate_name}") || instance_variable_set("@#{delegate_name}", delegate_class.instance_eval(&init_delegate))
11
11
  end
12
12
 
13
- # delegate session methods to the session object (in target)
14
- delegate_methods = session_class.public_instance_methods - Object.instance_methods
15
- target.delegate *(delegate_methods + [{:to => session_method}])
13
+ # in the target, delegate the public instance methods of delegate_class to the delegate_name method
14
+ delegate_methods = delegate_class.public_instance_methods - Object.instance_methods
15
+ target_class.delegate *(delegate_methods + [{:to => delegate_name}])
16
16
  end
17
17
  end
18
18
  end
data/lib/pickle/parser.rb CHANGED
@@ -1,17 +1,13 @@
1
1
  require 'pickle/parser/matchers'
2
2
 
3
3
  module Pickle
4
- def self.parser(options = {})
5
- @parser ||= Parser.new(options)
6
- end
7
-
8
4
  class Parser
9
5
  include Matchers
10
6
 
11
7
  attr_reader :config
12
8
 
13
9
  def initialize(options = {})
14
- @config = options[:config] || Pickle.config
10
+ @config = options[:config] || raise(ArgumentError, "Parser.new requires a :config")
15
11
  end
16
12
 
17
13
  # given a string like 'foo: "bar", bar: "baz"' returns {"foo" => "bar", "bar" => "baz"}
@@ -27,10 +23,10 @@ module Pickle
27
23
  end
28
24
  end
29
25
 
30
- # given a string like 'foo: "bar"' returns {key => value}
26
+ # given a string like 'foo: expr' returns {key => value}
31
27
  def parse_field(field)
32
28
  if field =~ /^#{capture_key_and_value_in_field}$/
33
- { $1 => $2 }
29
+ { $1 => eval($2) }
34
30
  else
35
31
  raise ArgumentError, "The field argument is not in the correct format.\n\n'#{field}' did not match: #{match_field}"
36
32
  end
@@ -21,8 +21,12 @@ module Pickle
21
21
  "(?::? \"#{match_quoted}\")"
22
22
  end
23
23
 
24
+ def match_value
25
+ "(?:\"#{match_quoted}\"|true|false|\\d+(?:\\.\\d+)?)"
26
+ end
27
+
24
28
  def match_field
25
- "(?:\\w+: \"#{match_quoted}\")"
29
+ "(?:\\w+: #{match_value})"
26
30
  end
27
31
 
28
32
  def match_fields
@@ -53,6 +57,10 @@ module Pickle
53
57
  "(?:#{match_mapping}|#{match_prefix}?(?:#{match_indexed_model}|#{match_labeled_model}))"
54
58
  end
55
59
 
60
+ def match_predicate
61
+ "(?:#{config.predicates.map{|m| m.sub(/\?$/,'').gsub('_','[_ ]')}.join('|')})"
62
+ end
63
+
56
64
  # create capture analogues of match methods
57
65
  instance_methods.select{|m| m =~ /^match_/}.each do |method|
58
66
  eval <<-end_eval
@@ -72,7 +80,7 @@ module Pickle
72
80
  end
73
81
 
74
82
  def capture_key_and_value_in_field
75
- "(?:(\\w+): \"(#{match_quoted})\")"
83
+ "(?:(\\w+): #{capture_value})"
76
84
  end
77
85
  end
78
86
  end
@@ -9,7 +9,7 @@ module Pickle
9
9
  attr_accessor :session
10
10
 
11
11
  def match_field
12
- "(?:\\w+: (?:#{match_model}|\"#{match_quoted}\"))"
12
+ "(?:\\w+: (?:#{match_model}|#{match_value}))"
13
13
  end
14
14
 
15
15
  def parse_field_with_model(field)
@@ -2,7 +2,7 @@ module Pickle
2
2
  class Session
3
3
  def initialize(options = {})
4
4
  self.parser = options[:parser] || Pickle.parser
5
- @config = options[:config] || parser.config
5
+ @config = parser.config
6
6
  end
7
7
 
8
8
  def create_model(a_model_name, fields = nil)
@@ -12,45 +12,52 @@ module Pickle
12
12
  store_model(factory, label, record)
13
13
  end
14
14
 
15
- def find_model(a_model_name, fields)
16
- model, name = *parser.parse_model(a_model_name)
15
+ def find_model(a_model_name, fields = nil)
16
+ factory, name = *parser.parse_model(a_model_name)
17
17
  raise ArgumentError, "Can't find a model with an ordinal (e.g. 1st user)" if name.is_a?(Integer)
18
- model_class = model.classify.constantize
18
+ model_class = config.factories[factory].klass
19
19
  if record = model_class.find(:first, :conditions => convert_models_to_attributes(model_class, parser.parse_fields(fields)))
20
- store_model(model, name, record)
21
- else
22
- raise ActiveRecord::RecordNotFound, "Couldn't find #{model} with #{fields}"
20
+ store_model(factory, name, record)
23
21
  end
24
22
  end
25
23
 
24
+ def find_models(factory, fields = nil)
25
+ model_class = config.factories[factory].klass
26
+ records = model_class.find(:all, :conditions => convert_models_to_attributes(model_class, parser.parse_fields(fields)))
27
+ records.each {|record| store_model(factory, nil, record)}
28
+ end
29
+
30
+ def clear_models(factory)
31
+ models_by_name(factory).clear
32
+ models_by_factory(factory).clear
33
+ end
34
+
26
35
  # return the original model stored by create_model or find_model
27
- def created_model(a_model_name)
28
- factory, name_or_index = *parser.parse_model(a_model_name)
36
+ def created_model(name)
37
+ factory, name_or_index = *parser.parse_model(name)
29
38
 
30
39
  if name_or_index.blank?
31
40
  models_by_factory(factory).last
32
41
  elsif name_or_index.is_a?(Integer)
33
42
  models_by_factory(factory)[name_or_index]
34
43
  else
35
- models_by_name(factory)[name_or_index] or raise "model: #{a_model_name} does not refer to known model in this scenario"
44
+ models_by_name(factory)[name_or_index] or raise "model: #{name} does not refer to known model in this scenario"
36
45
  end
37
46
  end
38
47
 
39
48
  # predicate version which raises no errors
40
- def created_model?(a_model_name)
41
- (created_model(a_model_name) rescue nil) ? true : false
49
+ def created_model?(name)
50
+ (created_model(name) rescue nil) ? true : false
42
51
  end
43
52
 
44
53
  # return a newly selected model
45
- def model(a_model_name)
46
- if model = created_model(a_model_name)
47
- model.class.find(model.id) or raise ActiveRecord::RecordNotFound, "model: #{a_model_name} could not be found in the database"
48
- end
54
+ def model(name)
55
+ (model = created_model(name)) && model.class.find(model.id)
49
56
  end
50
57
 
51
58
  # predicate version which raises no errors
52
- def model?(a_model_name)
53
- (model(a_model_name) rescue nil) ? true : false
59
+ def model?(name)
60
+ (model(name) rescue nil) ? true : false
54
61
  end
55
62
 
56
63
  # return all original models of specified type
@@ -60,9 +67,7 @@ module Pickle
60
67
 
61
68
  # return all models of specified type (freshly selected from the database)
62
69
  def models(factory)
63
- created_models(factory).map do |model|
64
- model.class.find(model.id)
65
- end
70
+ created_models(factory).map{|model| model.class.find(model.id) }
66
71
  end
67
72
 
68
73
  protected
@@ -2,7 +2,7 @@ module Pickle
2
2
  module Version
3
3
  Major = 0
4
4
  Minor = 1
5
- Tiny = 4
5
+ Tiny = 5
6
6
 
7
7
  String = [Major, Minor, Tiny].join('.')
8
8
  end
@@ -1,9 +1,10 @@
1
1
  <%= current_env %>
2
- # to configure pickle, uncomment the following lines
3
- # require 'pickle/config'
2
+ require 'pickle'
3
+
4
+ # Example of configuring pickle:
5
+ #
4
6
  # Pickle.configure do |config|
5
7
  # config.adaptors = [:machinist]
6
8
  # config.map 'I', 'myself', 'me', 'my', :to => 'user: "me"'
7
9
  # end
8
10
 
9
- require 'pickle'
@@ -1,31 +1,42 @@
1
1
  # this file generated by script/generate pickle
2
2
 
3
- Given(/^#{CaptureModel} exists$/) do |name|
4
- create_model(name)
3
+ # create a model
4
+ Given(/^#{capture_model} exists?(?: with #{capture_fields})?$/) do |name, fields|
5
+ create_model(name, fields)
5
6
  end
6
7
 
7
- Given(/^#{CaptureModel} exists with #{CaptureFields}$/) do |name, fields|
8
- create_model(name, fields)
8
+ # create n models
9
+ Given(/^(\d+) #{capture_plural_factory} exist(?: with #{capture_fields})?$/) do |count, plural_factory, fields|
10
+ count.to_i.times { create_model(plural_factory.singularize, fields) }
9
11
  end
10
12
 
11
- Given(/^(\d+) #{CapturePluralFactory} exist$/) do |amount, plural_factory|
12
- amount.to_i.times { create_model(plural_factory.singularize) }
13
+ # find a model
14
+ Then(/^#{capture_model} should exist(?: with #{capture_fields})?$/) do |name, fields|
15
+ find_model(name, fields).should_not be_nil
13
16
  end
14
17
 
15
- Given(/^(\d+) #{CapturePluralFactory} exist with #{CaptureFields}$/) do |amount, plural_factory, fields|
16
- amount.to_i.times { create_model(plural_factory.singularize, fields) }
18
+ # find exactly n models
19
+ Then(/^(\d+) #{capture_plural_factory} should exist(?: with #{capture_fields})?$/) do |count, plural_factory, fields|
20
+ clear_models(plural_factory.singularize)
21
+ find_models(plural_factory.singularize, fields).size.should == count.to_i
17
22
  end
18
23
 
19
- Then(/^#{CaptureModel} should exist with #{CaptureFields}$/) do |name, fields|
20
- find_model(name, fields).should_not be_nil
24
+ # assert model is in another model's has_many assoc
25
+ Then(/^#{capture_model} should be in #{capture_model}'s (\w+)$/) do |target, owner, association|
26
+ model(owner).send(association).should include(model(target))
21
27
  end
22
28
 
23
- Then(/^#{CaptureModel} should (?:be|have) (?:an? )?([\w ]+)$/) do |name, predicate|
24
- predicate_method = predicate.gsub(' ', '_')
25
- model(name).should send("be_#{predicate_method}")
29
+ # assert model is another model's has_one/belongs_to assoc
30
+ Then(/^#{capture_model} should be #{capture_model}'s (\w+)$/) do |target, owner, association|
31
+ model(owner).send(association).should == model(target)
26
32
  end
27
33
 
28
- Then(/^#{CaptureModel} should not (?:be|have) (?:an? )?([\w ]+)$/) do |name, predicate|
29
- predicate_method = predicate.gsub(' ', '_')
30
- model(name).should_not send("be_#{predicate_method}")
34
+ # assert model.predicate?
35
+ Then(/^#{capture_model} should (?:be|have) (?:an? )?#{capture_predicate}$/) do |name, predicate|
36
+ model(name).should send("be_#{predicate.gsub(' ', '_')}")
31
37
  end
38
+
39
+ # assert not model.predicate?
40
+ Then(/^#{capture_model} should not (?:be|have) (?:an? )?#{capture_predicate}$/) do |name, predicate|
41
+ model(name).should_not send("be_#{predicate.gsub(' ', '_')}")
42
+ end
@@ -48,25 +48,31 @@ describe Pickle::Adapter do
48
48
  describe '::FactoryGirl' do
49
49
  before do
50
50
  # set up a fake object space
51
- Factory.stub!(:factories).and_return(:one => nil, :two => nil)
51
+ @factory1 = mock('factory1', :factory_name => :one, :build_class => (@class1 = mock('Class1')))
52
+ @factory2 = mock('factory2', :factory_name => :two, :build_class => (@class2 = mock('Class2')))
53
+ Factory.stub!(:factories).and_return(:factory1 => @factory1, :factory2 => @factory2)
52
54
  end
53
55
 
54
56
  describe ".factories" do
55
57
  it "should create one for each factory" do
56
- Pickle::Adapter::FactoryGirl.should_receive(:new).with(:one).once
57
- Pickle::Adapter::FactoryGirl.should_receive(:new).with(:two).once
58
+ Pickle::Adapter::FactoryGirl.should_receive(:new).with(@factory1).once
59
+ Pickle::Adapter::FactoryGirl.should_receive(:new).with(@factory2).once
58
60
  Pickle::Adapter::FactoryGirl.factories
59
61
  end
60
62
 
61
- describe ".new(:factory_name)" do
63
+ describe ".new(factory)" do
62
64
  before do
63
- @factory = Pickle::Adapter::FactoryGirl.new(:one)
65
+ @factory = Pickle::Adapter::FactoryGirl.new(@factory1)
64
66
  end
65
67
 
66
- it "should have name of factory key" do
68
+ it "should have name of factory_name" do
67
69
  @factory.name.should == 'one'
68
70
  end
69
71
 
72
+ it "should have klass of build_class" do
73
+ @factory.klass.should == @class1
74
+ end
75
+
70
76
  it "#create(attrs) should call Factory(<:key>, attrs)" do
71
77
  Factory.should_receive(:create).with("one", {:key => "val"})
72
78
  @factory.create(:key => "val")
@@ -1,5 +1,4 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
- require 'pickle/config'
3
2
 
4
3
  describe Pickle::Config do
5
4
  before do
@@ -58,6 +57,21 @@ describe Pickle::Config do
58
57
  @config.mappings.should == []
59
58
  end
60
59
 
60
+ describe '#predicates' do
61
+ it "should be list of all ? public instance methods + columns methods of Adapter.model_classes" do
62
+ class1 = mock('Class1', :public_instance_methods => ['nope', 'foo?', 'bar?'], :column_names => ['one', 'two'])
63
+ class2 = mock('Class2', :public_instance_methods => ['not', 'foo?', 'faz?'], :column_names => ['two', 'three'])
64
+ Pickle::Adapter.stub!(:model_classes).and_return([class1, class2])
65
+
66
+ @config.predicates.to_set.should == ['foo?', 'faz?', 'bar?', 'one', 'two', 'three'].to_set
67
+ end
68
+
69
+ it "should be overridable" do
70
+ @config.predicates = %w(lame?)
71
+ @config.predicates.should == %w(lame?)
72
+ end
73
+ end
74
+
61
75
  describe "#map 'foo', :to => 'faz'" do
62
76
  before do
63
77
  @config.map 'foo', :to => 'faz'
@@ -84,17 +98,4 @@ describe Pickle::Config do
84
98
  c.foo :bar
85
99
  end
86
100
  end
87
-
88
- describe "Pickle.config" do
89
- it "should refer to same object" do
90
- Pickle.config.should == Pickle.config
91
- end
92
-
93
- it "called with (&block) should execute on the config" do
94
- Pickle.config.should_receive(:foo).with(:bar)
95
- Pickle.config do |c|
96
- c.foo :bar
97
- end
98
- end
99
- end
100
101
  end
@@ -1,54 +1,70 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
2
 
3
- describe Pickle::Parser::Matchers, "with config defining factories: user, car, fast_car" do
3
+ describe Pickle::Parser::Matchers do
4
4
  include Pickle::Parser::Matchers
5
-
6
- def config
7
- @config ||= Pickle::Config.new do |c|
8
- c.factories = {
9
- 'user' => mock('factory'),
10
- 'car' => mock('factory'),
11
- 'fast_car' => mock('factory')
12
- }
5
+
6
+ describe "(config: [factories: user, car, fast_car] [predicates: name, status, fancy?, super_fancy?]" do
7
+ def config
8
+ @config ||= Pickle::Config.new do |c|
9
+ c.factories = {
10
+ 'user' => mock('factory'),
11
+ 'car' => mock('factory'),
12
+ 'fast_car' => mock('factory')
13
+ }
14
+ c.predicates = %w(name status fancy? super_fancy?)
15
+ end
13
16
  end
14
- end
15
17
 
16
- describe "Match atoms" do
17
- def self.atom_should_match(atom, strings)
18
- Array(strings).each do |string|
19
- it "#{atom} should match '#{string}'" do
20
- string.should match(/^#{send atom}$/)
18
+ describe "Match atoms" do
19
+ def self.atom_should_match(atom, strings)
20
+ Array(strings).each do |string|
21
+ it "#{atom} should match '#{string}'" do
22
+ string.should match(/^#{send atom}$/)
23
+ end
21
24
  end
22
25
  end
23
- end
24
26
 
25
- def self.atom_should_not_match(atom, strings)
26
- Array(strings).each do |string|
27
- it "#{atom} should NOT match '#{string}'" do
28
- string.should_not match(/^#{send atom}$/)
27
+ def self.atom_should_not_match(atom, strings)
28
+ Array(strings).each do |string|
29
+ it "#{atom} should NOT match '#{string}'" do
30
+ string.should_not match(/^#{send atom}$/)
31
+ end
29
32
  end
30
33
  end
31
- end
32
34
 
33
- atom_should_match :match_ordinal, ['1st', '2nd', '23rd', '104th']
34
- atom_should_not_match :match_ordinal, ['1', '2']
35
+ atom_should_match :match_ordinal, ['1st', '2nd', '23rd', '104th']
36
+ atom_should_not_match :match_ordinal, ['1', '2']
35
37
 
36
- atom_should_match :match_index, ['first', 'last', '23rd', '104th']
37
- atom_should_not_match :match_index, ['1', '2', 'foo']
38
+ atom_should_match :match_index, ['first', 'last', '23rd', '104th']
39
+ atom_should_not_match :match_index, ['1', '2', 'foo']
38
40
 
39
- atom_should_match :match_label, [': "gday"', ': "gday mate"']
40
- atom_should_not_match :match_label, [': "gday""', ': gday']
41
+ atom_should_match :match_label, [': "gday"', ': "gday mate"']
42
+ atom_should_not_match :match_label, [': "gday""', ': gday']
41
43
 
42
- atom_should_match :match_field, ['foo: "this is the life"', 'bar_man: "and so is this"']
43
- atom_should_not_match :match_field, ['foo bar: "this aint workin"']
44
+ atom_should_match :match_field, ['foo: "this is the life"', 'bar_man: "and so is this"', 'boolean: false', 'boolean: true', 'numeric: 10', 'numeric: 12.5']
45
+ atom_should_not_match :match_field, ['foo bar: "this aint workin"']
44
46
 
45
- atom_should_match :match_fields, ['foo: "bar"', 'foo: "bar", baz: "bah"']
46
- atom_should_not_match :match_fields, ['foo bar: "baz"', 'email: "a", password: "b", and password_confirmation: "c"']
47
+ atom_should_match :match_fields, ['foo: "bar"', 'foo: "bar", baz: "bah"']
48
+ atom_should_not_match :match_fields, ['foo bar: "baz"', 'email: "a", password: "b", and password_confirmation: "c"']
47
49
 
48
- atom_should_match :match_model, ['a user', '1st fast car', 'the 23rd fast_car', 'the user: "fred flinstone"']
49
- atom_should_not_match :match_model, ['a giraffe', 'a 1st faster car: "jim"', 'an event created']
50
+ atom_should_match :match_model, ['a user', '1st fast car', 'the 23rd fast_car', 'the user: "fred flinstone"']
51
+ atom_should_not_match :match_model, ['a giraffe', 'a 1st faster car: "jim"', 'an event created']
50
52
 
51
- atom_should_match :match_factory, ['user', 'fast car', 'fast_car', 'car']
52
- atom_should_not_match :match_factory, ['users', 'faster car', 'event created']
53
+ atom_should_match :match_predicate, ['name', 'status', 'fancy', 'super fancy', 'super_fancy']
54
+ atom_should_not_match :match_predicate, ['nameo', 'increment', 'not a predicate']
55
+
56
+ atom_should_match :match_factory, ['user', 'fast car', 'fast_car', 'car']
57
+ atom_should_not_match :match_factory, ['users', 'faster car', 'event created']
58
+
59
+ atom_should_match :match_plural_factory, ['users', 'fast cars']
60
+ atom_should_not_match :match_plural_factory, ['usereres', 'fasts cars']
61
+ end
62
+ end
63
+
64
+ describe "capture methods" do
65
+ it "capture_field should == '(' + match_field + ')'" do
66
+ should_receive(:match_field).and_return('MATCH_FIELD')
67
+ capture_field.should == '(MATCH_FIELD)'
68
+ end
53
69
  end
54
70
  end
@@ -2,16 +2,11 @@ require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
2
 
3
3
  describe Pickle::Parser do
4
4
  before do
5
- @parser = Pickle::Parser.new
5
+ @parser = Pickle::Parser.new(:config => Pickle::Config.new)
6
6
  end
7
7
 
8
- it "should use the default config when created with no args" do
9
- @parser.config.should == Pickle.config
10
- end
11
-
12
- it "should use the passed config when created with :config option" do
13
- parser = Pickle::Parser.new :config => (cfg = mock('config'))
14
- parser.config.should == cfg
8
+ it "should raise error when created with no config" do
9
+ lambda{ Pickle::Parser.new }.should raise_error(ArgumentError)
15
10
  end
16
11
 
17
12
  describe 'misc regexps' do
@@ -54,8 +49,24 @@ describe Pickle::Parser do
54
49
  @parser.parse_fields('foo: "bar"').should == { "foo" => "bar"}
55
50
  end
56
51
 
57
- it '(\'foo: "bar", bar_man: "wonga wonga", gump: "123"\') should == {"foo" => "bar", "bar_man" => "wonga wonga", "gump" => "123"}' do
58
- @parser.parse_fields('foo: "bar", bar_man: "wonga wonga", gump: "123"').should == {"foo" => "bar", "bar_man" => "wonga wonga", "gump" => "123"}
52
+ it '("bool: true") should == { "bool" => true}' do
53
+ @parser.parse_fields('bool: true').should == {"bool" => true}
54
+ end
55
+
56
+ it '("bool: false") should == { "bool" => false}' do
57
+ @parser.parse_fields('bool: false').should == {"bool" => false}
58
+ end
59
+
60
+ it '("int: 10") should == { "int" => 10 }' do
61
+ @parser.parse_fields('int: 10').should == {"int" => 10}
62
+ end
63
+
64
+ it '("float: 10.1") should == { "float" => 10.1 }' do
65
+ @parser.parse_fields('float: 10.1').should == {"float" => 10.1}
66
+ end
67
+
68
+ it '(\'foo: "bar", bar_man: "wonga wonga", gump: 123\') should == {"foo" => "bar", "bar_man" => "wonga wonga", "gump" => 123}' do
69
+ @parser.parse_fields('foo: "bar", bar_man: "wonga wonga", gump: 123').should == {"foo" => "bar", "bar_man" => "wonga wonga", "gump" => 123}
59
70
  end
60
71
  end
61
72
 
@@ -135,11 +135,6 @@ describe Pickle::Session do
135
135
  do_find_model
136
136
  end
137
137
 
138
- it "should raise RecordNotFound when no record returned" do
139
- User.should_receive(:find).and_return(nil)
140
- lambda { do_find_model }.should raise_error(ActiveRecord::RecordNotFound)
141
- end
142
-
143
138
  describe "after find," do
144
139
  before { do_find_model }
145
140
 
@@ -147,6 +142,38 @@ describe Pickle::Session do
147
142
  end
148
143
  end
149
144
 
145
+ describe "#find_models" do
146
+ before do
147
+ @user = mock_model(User)
148
+ User.stub!(:find).and_return([@user])
149
+ end
150
+
151
+ def do_find_models
152
+ @session.find_models('user', 'hair: "pink"')
153
+ end
154
+
155
+ it "should call User.find :all, :conditions => {'hair' => 'pink'}" do
156
+ User.should_receive(:find).with(:all, :conditions => {'hair' => 'pink'}).and_return([@user])
157
+ do_find_models
158
+ end
159
+
160
+ describe "after find," do
161
+ before { do_find_models }
162
+
163
+ it_should_behave_like "after storing a single user"
164
+ end
165
+ end
166
+
167
+ describe '#clear_models(<factory_name>)' do
168
+ it "should clear the storage for that factory name" do
169
+ @session.send :store_model, 'user', nil, mock('user')
170
+ @session.send :store_model, 'car', nil, mock('user')
171
+ @session.clear_models('user')
172
+ @session.created_models('user').size.should == 0
173
+ @session.created_models('car').size.should == 1
174
+ end
175
+ end
176
+
150
177
  describe 'creating \'a super admin: "fred"\', then \'a user: "shirl"\', \'then 1 super_admin\'' do
151
178
  before do
152
179
  @user = @fred = mock_model(User)
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '../spec_helper'))
2
+
3
+ describe Pickle do
4
+ it ".config should be same object on multiple calls" do
5
+ Pickle.config.should == Pickle.config
6
+ end
7
+
8
+ it ".configure should configure the .config object" do
9
+ Pickle.config.should_receive(:foo).with(:bar)
10
+ Pickle.configure do |c|
11
+ c.foo :bar
12
+ end
13
+ end
14
+
15
+ it ".parser should create a parser with the default config" do
16
+ Pickle.instance_variable_set('@parser', nil)
17
+ Pickle::Parser.should_receive(:new).with(:config => Pickle.config)
18
+ Pickle.parser
19
+ end
20
+
21
+ it ".parser should be same object on multiple calls" do
22
+ Pickle.parser.should == Pickle.parser
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ianwhite-pickle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian White
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-01 00:00:00 -08:00
12
+ date: 2009-01-03 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -44,6 +44,7 @@ files:
44
44
  - spec/lib/pickle_parser_matchers_spec.rb
45
45
  - spec/lib/pickle_parser_spec.rb
46
46
  - spec/lib/pickle_session_spec.rb
47
+ - spec/lib/pickle_spec.rb
47
48
  has_rdoc: true
48
49
  homepage: http://github.com/ianwhite/pickle/tree
49
50
  post_install_message:
@@ -79,3 +80,4 @@ test_files:
79
80
  - spec/lib/pickle_parser_matchers_spec.rb
80
81
  - spec/lib/pickle_parser_spec.rb
81
82
  - spec/lib/pickle_session_spec.rb
83
+ - spec/lib/pickle_spec.rb
data/README.textile DELETED
@@ -1,98 +0,0 @@
1
- h1. Pickle
2
-
3
- Stick this in vendor/plugins to have cucumber steps that create your models easily from factory_girl/machinist/active_record
4
-
5
- References to the models are stored, not for the purpose of checking the db (although you could use it for
6
- that), but for enabling easy reference to urls, and for building complex givens which require a bunch of
7
- models collaborating
8
-
9
- h2. Get Started
10
-
11
- script/generate pickle
12
-
13
- Now have a look at features/step_definitions/pickle_steps.rb
14
-
15
- h2. API
16
-
17
- h3. Regexps for us in your own steps
18
-
19
- For capturing english versions of model names you get
20
-
21
- *CaptureModel*
22
-
23
- <pre>
24
- Given /^#{CaptureModel} exists$/ do |model_name|
25
- model(model_name).should_not == nil
26
- end
27
-
28
- Then /^I should be at the (.*?) page$/ |page|
29
- if page =~ /#{CaptureModel}'s/
30
- url_for(model($1))
31
- else
32
- # ...
33
- end
34
- end
35
- </pre>
36
-
37
- For capturing a field string, you get
38
-
39
- *CaptureFields*
40
-
41
- <pre>
42
- Given /^#{CaptureModel} exists with #{CaptureFields}$/ do |model_name, fields|
43
- create_model(model_name, fields)
44
- end
45
- </pre>
46
- Take a look at features/step_definitions/pickle_steps.rb for more examples
47
-
48
- h3. Creating and tracking models
49
-
50
- h4. create_model(_model_name_[, _field_string_])
51
-
52
- This will create a model using the factory name, and optional model label, with the field_string provided. The created model can be later referred to via its name.
53
-
54
- For example:
55
-
56
- <pre>
57
- create_model 'a user' # => will create a User
58
- create_model 'the user: "1"' # => will create a User, enabling later reference to it with 'user: "1"'
59
- create_model 'the user', 'name: "Fred"' # => will create a User with attributes {:name => "Fred"}
60
- </pre>
61
-
62
- If you don't use Machinist or FactoryGirl, you can still create models, but you must pass in all the fields required to make them valid.
63
-
64
- However, if you do use Machinist or FactoryGirl, then just use the factory or blueprint name, and will be super sweet.
65
-
66
- h4. find_model(_model_name_, _field_string_)
67
-
68
- This will find a model of the passed class matching the passed field string. The found model can be later referred to by its name.
69
-
70
- For example:
71
-
72
- <pre>
73
- find_model('a user', 'name: "Fred'") # => find a user matching those attributes
74
- </pre>
75
-
76
- h4. model(_model_name_)
77
-
78
- Refers to a model that has already been created/found (ie. referred to in a scenario)
79
-
80
- For example:
81
-
82
- <pre>
83
- create_model('a user')
84
- model('the user') # => refers to above user
85
- model('a user') # => refers to above user
86
-
87
- create_model('a car: "herbie"') # => herbie
88
- create_model('a car: "batmobile"') # => the batmobile
89
- model('the first car') # => herbie
90
- model('the 2nd car') # => batmobile
91
- model('the car "herbie") # => herbie
92
- </pre>
93
-
94
- h4. created_model(_model_name_)
95
-
96
- *model* always pulls from the db to get a fresh copy. If you need to access the originally created object for some reason (perhaps it has a one-time key on it that is used in a mailer for example), you can retreive it with *created_model*
97
-
98
- h4. more [TODO]