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 +18 -0
- data/License.txt +1 -1
- data/lib/pickle.rb +21 -4
- data/lib/pickle/adapter.rb +17 -18
- data/lib/pickle/config.rb +7 -10
- data/lib/pickle/injector.rb +9 -9
- data/lib/pickle/parser.rb +3 -7
- data/lib/pickle/parser/matchers.rb +10 -2
- data/lib/pickle/parser/with_session.rb +1 -1
- data/lib/pickle/session.rb +26 -21
- data/lib/pickle/version.rb +1 -1
- data/rails_generators/pickle/templates/env.rb +4 -3
- data/rails_generators/pickle/templates/pickle_steps.rb +27 -16
- data/spec/lib/pickle_adapter_spec.rb +12 -6
- data/spec/lib/pickle_config_spec.rb +15 -14
- data/spec/lib/pickle_parser_matchers_spec.rb +51 -35
- data/spec/lib/pickle_parser_spec.rb +21 -10
- data/spec/lib/pickle_session_spec.rb +32 -5
- data/spec/lib/pickle_spec.rb +24 -0
- metadata +4 -2
- data/README.textile +0 -98
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
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
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
data/lib/pickle/adapter.rb
CHANGED
@@ -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
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
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.
|
58
|
+
(::Factory.factories.values rescue []).map {|factory| new(factory)}
|
60
59
|
end
|
61
60
|
|
62
|
-
def initialize(
|
63
|
-
@name =
|
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
|
data/lib/pickle/injector.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
module Pickle
|
2
2
|
module Injector
|
3
|
-
def self.inject(
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
10
|
-
instance_variable_get("@#{
|
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
|
14
|
-
delegate_methods =
|
15
|
-
|
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] ||
|
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:
|
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+:
|
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+):
|
83
|
+
"(?:(\\w+): #{capture_value})"
|
76
84
|
end
|
77
85
|
end
|
78
86
|
end
|
data/lib/pickle/session.rb
CHANGED
@@ -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 =
|
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
|
-
|
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 =
|
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(
|
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(
|
28
|
-
factory, name_or_index = *parser.parse_model(
|
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: #{
|
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?(
|
41
|
-
(created_model(
|
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(
|
46
|
-
|
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?(
|
53
|
-
(model(
|
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
|
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
|
data/lib/pickle/version.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
<%= current_env %>
|
2
|
-
|
3
|
-
|
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
|
-
|
4
|
-
|
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
|
-
|
8
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
16
|
-
|
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
|
-
|
20
|
-
|
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
|
-
|
24
|
-
|
25
|
-
model(
|
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
|
-
|
29
|
-
|
30
|
-
model(name).
|
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
|
-
|
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(
|
57
|
-
Pickle::Adapter::FactoryGirl.should_receive(:new).with(
|
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(
|
63
|
+
describe ".new(factory)" do
|
62
64
|
before do
|
63
|
-
@factory = Pickle::Adapter::FactoryGirl.new(
|
65
|
+
@factory = Pickle::Adapter::FactoryGirl.new(@factory1)
|
64
66
|
end
|
65
67
|
|
66
|
-
it "should have name of
|
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
|
3
|
+
describe Pickle::Parser::Matchers do
|
4
4
|
include Pickle::Parser::Matchers
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
34
|
-
|
35
|
+
atom_should_match :match_ordinal, ['1st', '2nd', '23rd', '104th']
|
36
|
+
atom_should_not_match :match_ordinal, ['1', '2']
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
+
atom_should_match :match_index, ['first', 'last', '23rd', '104th']
|
39
|
+
atom_should_not_match :match_index, ['1', '2', 'foo']
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
+
atom_should_match :match_label, [': "gday"', ': "gday mate"']
|
42
|
+
atom_should_not_match :match_label, [': "gday""', ': gday']
|
41
43
|
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
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
|
9
|
-
|
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 '(
|
58
|
-
@parser.parse_fields('
|
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
|
+
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-
|
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]
|