ianwhite-pickle 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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]