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 +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]
|