diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d584e8c0..dfc0af68 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -5,6 +5,7 @@ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'spec'
require 'spec/rails'
require 'skinny_spec'
+require 'scenarios'
module LuckySneaks
module ModelSpecHelpers
diff --git a/vendor/plugins/scenarios/.gitignore b/vendor/plugins/scenarios/.gitignore
new file mode 100644
index 00000000..e8edc4ed
--- /dev/null
+++ b/vendor/plugins/scenarios/.gitignore
@@ -0,0 +1,4 @@
+environments
+*.log
+tmp
+vendor
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/LICENSE b/vendor/plugins/scenarios/LICENSE
new file mode 100644
index 00000000..0c9f55a0
--- /dev/null
+++ b/vendor/plugins/scenarios/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2007, Adam Williams and John W. Long.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/README b/vendor/plugins/scenarios/README
new file mode 100644
index 00000000..971472e8
--- /dev/null
+++ b/vendor/plugins/scenarios/README
@@ -0,0 +1,262 @@
+== Rails Scenarios Plugin
+
+Who hasn't experienced the pain of dozens of YAML files filled with hundreds
+of inter-related data structures? When do you look at People of an
+Organization and not have to look at the organization_id, open the
+organizations.yml file, and search for 'id: X'?
+
+In a nutshell, scenarios are a drop in replacement for YAML fixtures. Instead
+of encouraging you to create a mindless amount of raw data in the form of
+YAML, scenarios encourage you to create code that populates your tables with
+the appropriate records.
+
+How is it different from other solutions? A few things:
+
+ * It continues to provide a fundamental, fast insertion method using attributes
+ written directly to a table. This is the
+ Scenarios::TableMethods#create_record method.
+
+ * It allows you to create records using validations if you prefer, or if it's
+ important to have all your callbacks be invoked. See
+ Scenarios::TableMethods#create_model. Both create_record and create_model
+ allow you to name your instances for retrieval by the instance and id reader
+ methods (more below).
+
+ * Nothing stops you from simply invoking YouModel.create!, etc. We'll still
+ keep track of the tables the scenario modifies and clean things up afterward.
+
+ * It allows you to create re-usable scenarios as classes. These classes are
+ like any other class - they may include modules, subclass, and be composed of
+ other scenarios. See Scenarios::Base.uses. This also means that you can load
+ any scenario into any Rails environment. That's what the 'rake
+ db:scenario:load' task is good for (more below). Very handy for re-using all
+ that test support code to create populated demos!
+
+=== Quick Start
+
+Since Scenarios is a Rails plugin at this time, you should get it installed,
+using the appropriate method (script/plugin, svn, piston) into your
+vendor/plugins directory. Once you have this, in your spec_helper.rb or
+test_helper.rb, add the following line after the spec requires:
+
+ require 'scenarios'
+
+The Scenarios you write should be placed in the spec/scenarios directory of your
+Rails project if you're using RSpec, or the test/scenarios directory of your
+Rails project if you're using Test::Unit. Scenario file names always end in
+"_scenario.rb" and classes end in "Scenario".
+
+A simple scenario looks like this:
+
+ # in spec/scenarios/users_scenario.rb or test/scenarios/users_scenario.rb
+ class UsersScenario < Scenario::Base
+ def load
+ create_record :user, :john, :name => 'John', :password => 'doodaht'
+ create_record :user, :cindy, :name => 'Cindy', :password => 'whoot!'
+ end
+ end
+
+In the example above, I'm using the create_record instance method to
+create two users: John and Cindy. Notice the calls to create_record.
+There are three parameters. The first is the singular name of the table to
+insert the record into, the second is the symbolic name of the record (more on
+that later), and the third is a hash of the attributes of the record.
+
+To use the UsersScenario in a description, you should declare it using
+the scenario method. Here it is within a spec file (RSpec):
+
+ # in spec/models/user_spec.rb
+ describe User do
+ scenario :users
+
+ it "should allow me to do something with John" do
+ user = users(:john)
+ user.password.should == "doodaht"
+ end
+ end
+
+and here it is within a standard Test::Unit test:
+
+ # in test/unit/user_test.rb
+ class UserTest < Test::Unit::TestCase
+
+ scenario :users
+
+ def test_do_something
+ user = users(:john)
+ assert_equal "doodaht", user.password
+ end
+ end
+
+Notice that it is easy to load an instance of a model object using its
+symbolic name with a reader method, similar to that of Rails' fixtures. In the
+example above, I loaded John with the reader method users and the
+symbolic name :john. (Remember that in the Users scenario I declared
+that John should be accessible through the symbolic name :john.)
+
+I could also have retrieved an array of user fixtures by passing in
+multiple symbolic names to the reader method:
+
+ # in spec/models/user_spec.rb
+ describe User do
+ scenario :users
+
+ it "should allow me to get all admins" do
+ admins = users(:john, :ryan)
+ User.admins.should eql(admins)
+ end
+ end
+
+=== Composition
+
+In real life your scenarios will probably grow quite complicated. The
+scenarios plugin allows you to deal with this complexity through composition.
+
+Here's a simple example:
+
+ # in spec/scenarios/posts_scenario.rb or test/scenarios/posts_scenario.rb
+ class PostsScenario < Scenario::Base
+ def load
+ create_record :post, :first, :title => "First Post"
+ create_record :post, :second, :title => "Second Post"
+ end
+ end
+
+ # in spec/scenarios/comments_scenario.rb or test/scenarios/comments_scenario.rb
+ class CommentsScenario < Scenario::Base
+ uses :posts
+
+ def load
+ create_record :comment, :first, :body => "Nice post!", :post_id => post_id(:first)
+ create_record :comment, :second, :body => "I like it.", :post_id => post_id(:first)
+ create_record :comment, :third, :body => "I thoroughly disagree.", :post_id => post_id(:second)
+ end
+ end
+
+In the example above, the CommentsScenario declares that it depends on the
+Posts scenario with the uses class method. This means that if you
+load the CommentsScenario, the PostsScenario will be loaded first and the
+CommentsScenario will have access to all the data loaded by the PostsScenario
+in its own load method. Note that inside the load method I'm using
+another form of reader methed which simply gives you the id for a symbolic
+name (in this case: post_id). This is most useful for making
+associations, as done here with comments and posts.
+
+=== Helper Methods
+
+Another way of simplifying your scenarios and specs/tests is through helper
+methods. The Scenarios plugin provides a handy way to declare helper methods
+that are accessible from inside the scenario and also from inside related
+RSpec/Test::Unit examples:
+
+ # in spec/scenarios/users_scenario.rb or test/scenarios/users_scenario.rb
+ class UsersScenario < Scenario::Base
+ def load
+ create_user :name => "John"
+ end
+
+ helpers do
+ def create_user(attributes={})
+ create_record :user, attributes[:name].downcase.intern, attributes
+ end
+ def login_as(user)
+ @request.session[:user_id] = user.id
+ end
+ end
+ end
+
+Helper methods declared inside the helpers block are mixed into the scenario
+when it is instantiated and mixed into examples that declare that they are using
+the scenario. Also, in the case where one scenario uses another, the
+using scenario will have the helper methods of the used scenario.
+
+ # in spec/controllers/projects_controller_spec.rb
+ describe "Projects screen" do
+ scenario :users
+
+ it "should show active projects" do
+ login_as(users(:john))
+ get :projects
+ @response.should have_tag('#active_projects')
+ end
+ end
+
+ # in test/functional/projects_controller_test.rb
+ class PeopleControllerTest < Test::Unit::TestCase
+ scenario :users
+
+ def test_index
+ login_as(users(:john))
+ get :projects
+ assert_tag('#active_projects')
+ end
+ end
+
+Notice that within my specs/tests I have access to the login_as helper method
+declared inside the helpers block of the UsersScenario. Scenario
+helpers are a great way to share helper methods between specs/tests that use a
+specific scenario.
+
+=== Built-in Scenario
+
+There is a scenario named 'blank' that comes with the plugin. This scenario is
+useful when you want to express, and guarantee, that the database is empty. It
+works by using your db/schema.rb, so if the table isn't created in there, it
+won't be cleaned up.
+
+Scenario.load_paths is an array of the locations to look for scenario
+definitions. The built-in scenarios directory is consulted last, so if you'd
+like to re-define, for instance, the 'blank' scenario, simply create
+'blank_scenario.rb' in your spec/scenarios or test/scenarios directory.
+
+=== Load Rake Task
+
+The Scenarios plugin provides a single Rake task, db:scenario:load,
+which you may use in a fashion similar to Rails fixtures'
+db:fixtures:load.
+
+ rake db:scenario:load SCENARIO=comments
+
+When invoked, this task will populate the development database with the named
+scenario.
+
+If you do not specify SCENARIO, the task will expect to find a default scenario
+(a file 'default_scenario.rb' having DefaultScenario defined in it). It is our
+practice to have it such that this scenario uses a number of our other
+scenarios, thereby:
+
+* encouraging us to use test data that looks good in the running development
+ application
+
+* allowing us to troubleshoot failing tests in the running development
+ application
+
+=== More Information
+
+For more information, be sure to look through the documentation over at RubyForge:
+
+* http://faithfulcode.rubyforge.org/docs/scenarios
+
+You might also enjoy taking a look at the specs for the plugin and the example
+scenarios:
+
+* http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios/spec/scenarios_spec.rb
+* http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios/spec/scenarios
+
+Browse the complete source code:
+
+* http://faithfulcode.rubyforge.org/svn/plugins/trunk/scenarios
+
+=== Running Tests
+
+You should be able to simply run rake. Notice in testing/environment.rb the
+revisions under which this project will work. If you intend to test against
+HEAD, you will need to delete the directory testing/tmp/trunk/HEAD. At some
+point, it would be nice to have the script track the revision of HEAD that we
+have, and update the directory automatically.
+
+=== License
+
+The Scenarios plugin is released under the MIT-License and is Copyright (c)
+2007, Adam Williams and John W. Long. Special thanks to Chris Redinger for his
+part in helping us get this plugin ready for the public.
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/Rakefile b/vendor/plugins/scenarios/Rakefile
new file mode 100644
index 00000000..bd0deb95
--- /dev/null
+++ b/vendor/plugins/scenarios/Rakefile
@@ -0,0 +1,10 @@
+require File.expand_path(File.dirname(__FILE__) + '/testing/plugit_descriptor')
+
+require 'rake/rdoctask'
+Rake::RDocTask.new(:doc) do |r|
+ r.title = "Rails Scenarios Plugin"
+ r.main = "README"
+ r.options << "--line-numbers"
+ r.rdoc_files.include("README", "LICENSE", "lib/**/*.rb")
+ r.rdoc_dir = "doc"
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/TODO b/vendor/plugins/scenarios/TODO
new file mode 100644
index 00000000..9be8fb9d
--- /dev/null
+++ b/vendor/plugins/scenarios/TODO
@@ -0,0 +1 @@
+Make sure before :all's that use scenario methods work. They don't right now.
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/helpers.diff b/vendor/plugins/scenarios/helpers.diff
new file mode 100644
index 00000000..340068bb
--- /dev/null
+++ b/vendor/plugins/scenarios/helpers.diff
@@ -0,0 +1,127 @@
+Only in /Users/aiwilliams/Workspaces/faithfulcode/scenarios/: .git
+Only in scenarios/: .svn
+Only in scenarios/: .tm_last_run_ruby
+diff -r scenarios/Rakefile /Users/aiwilliams/Workspaces/faithfulcode/scenarios/Rakefile
+3c3
+< TESTING_ENVIRONMENTS["rspec_3317_rails_8956"].load
+---
+> TESTING_ENVIRONMENTS["rspec_3119_rails_8375"].load
+Only in /Users/aiwilliams/Workspaces/faithfulcode/scenarios/: helpers.diff
+Only in scenarios/lib: .svn
+Only in scenarios/lib/scenarios: .svn
+diff -r scenarios/lib/scenarios/base.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/lib/scenarios/base.rb
+11,14c11,12
+< # be included into the scenario and all specs that include the scenario.
+< # You may also provide names of helpers from your scenarios/helpers
+< # directory, or any other module you'd like included in your Scenario.
+< def helpers(helper_names_or_modules = [], &block)
+---
+> # be included into the scenario and all specs that include the scenario
+> def helpers(&block)
+17,19d14
+< mod.module_eval do
+< [helper_names_or_modules].flatten.each {|h| include h.is_a?(Module) ? h : h.to_scenario_helper}
+< end
+Only in scenarios/lib/scenarios/builtin: .svn
+Only in scenarios/lib/scenarios/extensions: .svn
+diff -r scenarios/lib/scenarios/extensions/string.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/lib/scenarios/extensions/string.rb
+22,39d21
+< # Convert a string into the associated scenario helper module:
+< #
+< # "basic".to_scenario_helper #=> BasicScenarioHelper
+< # "basic_scenario".to_scenario_helper #=> BasicScenarioHelper
+< #
+< # Raises Scenario::NameError if the the helper cannot be loacated as
+< # 'helpers/_helper' in Scenario.load_paths.
+< def to_scenario_helper
+< class_name = "#{self.strip.camelize.sub(/ScenarioHelper$/, '')}ScenarioHelper"
+< Scenario.load_paths.each do |path|
+< filename = "#{path}/#{class_name.underscore}.rb"
+< if File.file?(filename)
+< require filename
+< break
+< end
+< end
+< class_name.constantize rescue raise Scenario::NameError, "Expected to find #{class_name} in #{Scenario.load_paths.inspect}"
+< end
+diff -r scenarios/lib/scenarios/extensions/symbol.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/lib/scenarios/extensions/symbol.rb
+14,23d13
+< # Convert a symbol into the associated scenario helper module:
+< #
+< # :basic.to_scenario_helper #=> BasicScenarioHelper
+< # :basic_scenario.to_scenario_helper #=> BasicScenarioHelper
+< #
+< # Raises Scenario::NameError if the the helper cannot be loacated as
+< # 'helpers/_helper' in Scenario.load_paths.
+< def to_scenario_helper
+< to_s.to_scenario_helper
+< end
+Only in scenarios/spec: .svn
+Only in scenarios/spec: environments.rb
+Only in scenarios/spec/scenarios: .svn
+Only in scenarios/spec/scenarios: helpers
+diff -r scenarios/spec/scenarios_spec.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/spec/scenarios_spec.rb
+23,27d22
+< it 'should allow us to have helpers in scenarios/helpers directory which we can get through the helpers class method' do
+< klass = :empty.to_scenario
+< klass.helpers :myown
+< end
+<
+diff -r scenarios/spec/spec_helper.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/spec/spec_helper.rb
+1,20c1,6
+< $LOAD_PATH << File.dirname(__FILE__) + '/../testing'
+<
+< require File.dirname(__FILE__) + "/environments"
+<
+< require 'active_support'
+< require 'active_record'
+< require 'action_controller'
+< require 'action_view'
+<
+< module Spec
+< module Rails
+< module Example
+< end
+< end
+< end
+<
+< require 'spec/rails'
+< require 'scenarios'
+<
+< require 'models'
+\ No newline at end of file
+---
+> require File.expand_path(File.dirname(__FILE__) + "/../testing/environment")
+> TESTING_ENVIRONMENTS[TESTING_ENVIRONMENT].load(DATABASE_ADAPTER)
+> require "models"
+> require "spec"
+> require "spec/rails"
+> require "scenarios"
+Only in scenarios/tasks: .svn
+Only in scenarios/test: .svn
+Only in scenarios/testing: .svn
+diff -r scenarios/testing/environment.rb /Users/aiwilliams/Workspaces/faithfulcode/scenarios/testing/environment.rb
+15c15
+< TESTING_ENVIRONMENT = "rspec_3317_rails_8956" unless defined?(TESTING_ENVIRONMENT)
+---
+> TESTING_ENVIRONMENT = "rspec_3119_rails_8375" unless defined?(TESTING_ENVIRONMENT)
+31c31
+< # system "cd #{lib.support_directory} && patch -p0 < #{File.join(TESTING_ROOT, "rspec_on_rails_3119.patch")}"
+---
+> system "cd #{lib.support_directory} && patch -p0 < #{File.join(TESTING_ROOT, "rspec_on_rails_3119.patch")}"
+36,38c36,38
+< TESTING_ENVIRONMENTS << TestingLibrary::Environment.new("rspec_3317_rails_8956", SUPPORT_TEMP, DB_CONFIG_FILE, DB_SCHEMA_FILE) do |env|
+< env.package "rails", "http://svn.rubyonrails.org/rails", "trunk", "8956", &rails_package
+< env.package "rspec", "http://rspec.rubyforge.org/svn", "trunk", "3317", &rspec_package
+---
+> TESTING_ENVIRONMENTS << TestingLibrary::Environment.new("rspec_3119_rails_8375", SUPPORT_TEMP, DB_CONFIG_FILE, DB_SCHEMA_FILE) do |env|
+> env.package "rails", "http://svn.rubyonrails.org/rails", "trunk", "8375", &rails_package
+> env.package "rspec", "http://rspec.rubyforge.org/svn", "trunk", "3119", &rspec_package
+40c40
+< TESTING_ENVIRONMENTS << TestingLibrary::Environment.new("rspec_3317_rails_1_2_6", SUPPORT_TEMP, DB_CONFIG_FILE, DB_SCHEMA_FILE) do |env|
+---
+> TESTING_ENVIRONMENTS << TestingLibrary::Environment.new("rspec_3119_rails_1_2_6", SUPPORT_TEMP, DB_CONFIG_FILE, DB_SCHEMA_FILE) do |env|
+42c42
+< env.package "rspec", "http://rspec.rubyforge.org/svn", "trunk", "3317", &rspec_package
+---
+> env.package "rspec", "http://rspec.rubyforge.org/svn", "trunk", "3119", &rspec_package
diff --git a/vendor/plugins/scenarios/lib/scenarios.rb b/vendor/plugins/scenarios/lib/scenarios.rb
new file mode 100644
index 00000000..5950e8ec
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios.rb
@@ -0,0 +1,34 @@
+module Scenarios
+ # Thrown by Scenario.load when it cannot find a specific senario.
+ class NameError < ::NameError; end
+
+ class << self
+ # The locations from which scenarios will be loaded.
+ mattr_accessor :load_paths
+ self.load_paths = ["#{RAILS_ROOT}/spec/scenarios", "#{RAILS_ROOT}/test/scenarios", "#{File.dirname(__FILE__)}/scenarios/builtin"]
+
+ # Load a scenario by name. scenario_name can be a string, symbol,
+ # or the scenario class.
+ def load(scenario_name)
+ klass = scenario_name.to_scenario
+ klass.load
+ klass
+ end
+ end
+end
+
+# The Scenario namespace makes for Scenario::Base
+Scenario = Scenarios
+
+# For Rails 1.2 compatibility
+unless Class.instance_methods.include?(:superclass_delegating_reader)
+ require File.dirname(__FILE__) + "/scenarios/extensions/delegating_attributes"
+end
+
+require 'active_record/fixtures'
+require 'scenarios/configuration'
+require 'scenarios/table_blasting'
+require 'scenarios/table_methods'
+require 'scenarios/loading'
+require 'scenarios/base'
+require 'scenarios/extensions'
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/base.rb b/vendor/plugins/scenarios/lib/scenarios/base.rb
new file mode 100644
index 00000000..3885af3c
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/base.rb
@@ -0,0 +1,73 @@
+module Scenarios
+ class Base
+ class << self
+ # Class method to load the scenario. Used internally by the Scenarios
+ # plugin.
+ def load
+ new.load_scenarios(used_scenarios + [self])
+ end
+
+ # Class method for your own scenario to define helper methods that will
+ # be included into the scenario and all specs that include the scenario
+ def helpers(&block)
+ mod = (const_get(:Helpers) rescue const_set(:Helpers, Module.new))
+ mod.module_eval(&block) if block_given?
+ mod
+ end
+
+ # Class method for your own scenario to define the scenarios that it
+ # depends on. If your scenario depends on other scenarios those
+ # scenarios will be loaded before the load method on your scenario is
+ # executed.
+ def uses(*scenarios)
+ names = scenarios.map(&:to_scenario).reject { |n| used_scenarios.include?(n) }
+ used_scenarios.concat(names)
+ end
+
+ # Class method that returns the scenarios used by your scenario.
+ def used_scenarios # :nodoc:
+ @used_scenarios ||= []
+ @used_scenarios = (@used_scenarios.collect(&:used_scenarios) + @used_scenarios).flatten.uniq
+ end
+
+ # Returns the scenario class.
+ def to_scenario
+ self
+ end
+ end
+
+ include TableMethods
+ include Loading
+
+ attr_reader :table_config
+
+ # Initialize a scenario with a Configuration. Used internally by the
+ # Scenarios plugin.
+ def initialize(config = Configuration.new)
+ @table_config = config
+ table_config.update_scenario_helpers self.class
+ self.extend table_config.table_readers
+ self.extend table_config.scenario_helpers
+ end
+
+ # This method should be implemented in your scenarios. You may also have
+ # scenarios that simply use other scenarios, so it is not required that
+ # this be overridden.
+ def load
+ end
+
+ # Unload a scenario, sort of. This really only deletes the records, all of
+ # them, of every table this scenario modified. The goal is to maintain a
+ # clean database for successive runs. Used internally by the Scenarios
+ # plugin.
+ def unload
+ return if unloaded?
+ record_metas.each_value { |meta| blast_table(meta.table_name) }
+ @unloaded = true
+ end
+
+ def unloaded?
+ @unloaded == true
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/builtin/blank_scenario.rb b/vendor/plugins/scenarios/lib/scenarios/builtin/blank_scenario.rb
new file mode 100644
index 00000000..1ab74d3c
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/builtin/blank_scenario.rb
@@ -0,0 +1,18 @@
+class BlankScenario < Scenarios::Base
+ def load
+ table_names.each do |table|
+ blast_table(table)
+ end
+ end
+
+ def table_names
+ self.class.table_names
+ end
+
+ def self.table_names
+ @table_names ||= begin
+ schema = (open(RAILS_ROOT + '/db/schema.rb') { |f| f.read } rescue '')
+ schema.grep(/create_table\s+(['"])(.+?)\1/m) { $2 }
+ end
+ end
+end
diff --git a/vendor/plugins/scenarios/lib/scenarios/configuration.rb b/vendor/plugins/scenarios/lib/scenarios/configuration.rb
new file mode 100644
index 00000000..6becffcf
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/configuration.rb
@@ -0,0 +1,55 @@
+module Scenarios
+ class Configuration # :nodoc:
+ attr_reader :blasted_tables, :loaded_scenarios, :record_metas, :table_readers, :scenario_helpers, :symbolic_names_to_id
+
+ def initialize
+ @blasted_tables = Set.new
+ @record_metas = Hash.new
+ @table_readers = Module.new
+ @scenario_helpers = Module.new
+ @symbolic_names_to_id = Hash.new {|h,k| h[k] = Hash.new}
+ @loaded_scenarios = Array.new
+ end
+
+ # Given a created record (currently ScenarioModel or ScenarioRecord),
+ # update the table readers module appropriately such that this record and
+ # it's id are findable via methods like 'people(symbolic_name)' and
+ # 'person_id(symbolic_name)'.
+ def update_table_readers(record)
+ ids, record_meta = symbolic_names_to_id, record.record_meta # scoping assignments
+
+ ids[record_meta.table_name][record.symbolic_name] = record.id
+ table_readers.send :define_method, record_meta.id_reader do |*symbolic_names|
+ record_ids = symbolic_names.flatten.collect do |symbolic_name|
+ if symbolic_name.kind_of?(ActiveRecord::Base)
+ symbolic_name.id
+ else
+ record_id = ids[record_meta.table_name][symbolic_name.to_sym]
+ raise ActiveRecord::RecordNotFound, "No object is associated with #{record_meta.table_name}(:#{symbolic_name})" unless record_id
+ record_id
+ end
+ end
+ record_ids.size > 1 ? record_ids : record_ids.first
+ end
+
+ table_readers.send :define_method, record_meta.record_reader do |*symbolic_names|
+ results = symbolic_names.flatten.collect do |symbolic_name|
+ symbolic_name.kind_of?(ActiveRecord::Base) ?
+ symbolic_name :
+ record_meta.record_class.find(send(record_meta.id_reader, symbolic_name))
+ end
+ results.size > 1 ? results : results.first
+ end
+ end
+
+ def update_scenario_helpers(scenario_class)
+ scenario_helpers.module_eval do
+ include scenario_class.helpers
+ end
+ end
+
+ def scenarios_loaded?
+ !loaded_scenarios.blank?
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions.rb b/vendor/plugins/scenarios/lib/scenarios/extensions.rb
new file mode 100644
index 00000000..f442786e
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions.rb
@@ -0,0 +1,5 @@
+require File.dirname(__FILE__) + "/extensions/object"
+require File.dirname(__FILE__) + "/extensions/string"
+require File.dirname(__FILE__) + "/extensions/symbol"
+require File.dirname(__FILE__) + "/extensions/active_record"
+require File.dirname(__FILE__) + "/extensions/test_case" rescue nil
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/active_record.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/active_record.rb
new file mode 100644
index 00000000..509abd27
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/active_record.rb
@@ -0,0 +1,14 @@
+module ActiveRecord
+ class Base
+ cattr_accessor :table_config
+ include Scenarios::TableBlasting
+
+ # In order to guarantee that tables are tracked when _create_model_ is
+ # used, and those models cause other models to be created...
+ def create_with_table_blasting
+ prepare_table(self.class.table_name)
+ create_without_table_blasting
+ end
+ alias_method_chain :create, :table_blasting
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/delegating_attributes.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/delegating_attributes.rb
new file mode 100644
index 00000000..f5f0ef87
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/delegating_attributes.rb
@@ -0,0 +1,40 @@
+# These class attributes behave something like the class
+# inheritable accessors. But instead of copying the hash over at
+# the time the subclass is first defined, the accessors simply
+# delegate to their superclass unless they have been given a
+# specific value. This stops the strange situation where values
+# set after class definition don't get applied to subclasses.
+class Class
+ def superclass_delegating_reader(*names)
+ class_name_to_stop_searching_on = self.superclass.name.blank? ? "Object" : self.superclass.name
+ names.each do |name|
+ class_eval <<-EOS
+ def self.#{name}
+ if defined?(@#{name})
+ @#{name}
+ elsif superclass < #{class_name_to_stop_searching_on} && superclass.respond_to?(:#{name})
+ superclass.#{name}
+ end
+ end
+ def #{name}
+ self.class.#{name}
+ end
+ EOS
+ end
+ end
+
+ def superclass_delegating_writer(*names)
+ names.each do |name|
+ class_eval <<-EOS
+ def self.#{name}=(value)
+ @#{name} = value
+ end
+ EOS
+ end
+ end
+
+ def superclass_delegating_accessor(*names)
+ superclass_delegating_reader(*names)
+ superclass_delegating_writer(*names)
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/object.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/object.rb
new file mode 100644
index 00000000..efd28197
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/object.rb
@@ -0,0 +1,5 @@
+class Object
+ def metaclass
+ (class << self; self; end)
+ end unless method_defined?(:metaclass)
+end
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/string.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/string.rb
new file mode 100644
index 00000000..830aa791
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/string.rb
@@ -0,0 +1,22 @@
+class String
+
+ # Convert a string into the associated scenario class:
+ #
+ # "basic".to_scenario #=> BasicScenario
+ # "basic_scenario".to_scenario #=> BasicScenario
+ #
+ # Raises Scenario::NameError if the the scenario cannot be loacated in
+ # Scenario.load_paths.
+ def to_scenario
+ class_name = "#{self.strip.camelize.sub(/Scenario$/, '')}Scenario"
+ Scenario.load_paths.each do |path|
+ filename = "#{path}/#{class_name.underscore}.rb"
+ if File.file?(filename)
+ require filename
+ break
+ end
+ end
+ class_name.constantize rescue raise Scenario::NameError, "Expected to find #{class_name} in #{Scenario.load_paths.inspect}"
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/symbol.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/symbol.rb
new file mode 100644
index 00000000..35e5f090
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/symbol.rb
@@ -0,0 +1,14 @@
+class Symbol
+
+ # Convert a symbol into the associated scenario class:
+ #
+ # :basic.to_scenario #=> BasicScenario
+ # :basic_scenario.to_scenario #=> BasicScenario
+ #
+ # Raises Scenario::NameError if the the scenario cannot be located in
+ # Scenario.load_paths.
+ def to_scenario
+ to_s.to_scenario
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/extensions/test_case.rb b/vendor/plugins/scenarios/lib/scenarios/extensions/test_case.rb
new file mode 100644
index 00000000..a9f0ef6a
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/extensions/test_case.rb
@@ -0,0 +1,77 @@
+module Test #:nodoc:
+ module Unit #:nodoc:
+ class TestCase #:nodoc:
+ superclass_delegating_accessor :scenario_classes
+ superclass_delegating_accessor :table_config
+
+ # Changing either of these is not supported at this time.
+ self.use_transactional_fixtures = true
+ self.use_instantiated_fixtures = false
+
+ include Scenarios::TableMethods
+ include Scenarios::Loading
+
+ class << self
+ # This class method is mixed into RSpec and allows you to declare that
+ # you are using a given scenario or set of scenarios within a spec:
+ #
+ # scenario :basic # loads BasicScenario and any dependencies
+ # scenario :posts, :comments # loads PostsScenario and CommentsScenario
+ #
+ # It accepts an array of scenarios (strings, symbols, or classes) and
+ # will load them roughly in the order that they are specified.
+ def scenario(*names)
+ self.scenario_classes = []
+ names.each do |name|
+ scenario_class = name.to_scenario
+ scenario_classes.concat(scenario_class.used_scenarios + [scenario_class])
+ end
+ scenario_classes.uniq!
+ end
+
+ # Overridden to provide before all and after all code which sets up and
+ # tears down scenarios
+ def suite_with_scenarios
+ suite = suite_without_scenarios
+ class << suite
+ attr_accessor :test_class
+ def run_with_scenarios(*args, &block)
+ debugger
+ run_without_scenarios(*args, &block)
+ test_class.table_config.loaded_scenarios.each { |s| s.unload } if test_class.table_config
+ end
+ alias_method_chain :run, :scenarios
+ end
+ suite.test_class = self
+ suite
+ end
+ alias_method_chain :suite, :scenarios
+ end
+
+ # Hook into fixtures loading lifecycle to instead load scenarios. This
+ # is expected to be called in a fashion respective of
+ # use_transactional_fixtures. I feel like a leech.
+ def load_fixtures
+ if !scenarios_loaded? || !use_transactional_fixtures?
+ self.class.table_config = Scenarios::Configuration.new if !use_transactional_fixtures? || table_config.nil?
+ load_scenarios(scenario_classes)
+ end
+ self.extend scenario_helpers
+ self.extend table_readers
+ end
+
+ # Here we are counting on existing logic to allow teardown method
+ # overriding as done in fixtures.rb. Only if transaction fixtures are
+ # not being used do we unload scenarios after a test. Otherwise, we wait
+ # until the end of the run of all tests on this test_case (collection of
+ # tests, right!). See the TestSuite extension done in _suite_ for
+ # behaviour when using transaction fixtures.
+ def teardown_with_scenarios
+ teardown_without_scenarios
+ loaded_scenarios.each { |s| s.unload } unless use_transactional_fixtures?
+ end
+ alias_method_chain :teardown, :scenarios
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/loading.rb b/vendor/plugins/scenarios/lib/scenarios/loading.rb
new file mode 100644
index 00000000..b369196e
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/loading.rb
@@ -0,0 +1,51 @@
+module Scenarios
+ # Provides scenario loading and convenience methods around the Configuration
+ # that must be made available through a method _table_config_.
+ module Loading # :nodoc:
+ def load_scenarios(scenario_classes)
+ install_active_record_tracking_hook
+ scenario_classes.each do |scenario_class|
+ scenario = scenario_class.new(table_config)
+ scenario.load
+ table_config.loaded_scenarios << scenario
+ end if scenario_classes
+ end
+
+ def loaded_scenarios
+ table_config.loaded_scenarios
+ end
+
+ def scenarios_loaded?
+ table_config && table_config.scenarios_loaded?
+ end
+
+ # The sum of all the loaded scenario's helper methods. These can be mixed
+ # into anything you like to gain access to them.
+ def scenario_helpers
+ table_config.scenario_helpers
+ end
+
+ # The sum of all the available table reading methods. These will only
+ # include readers for which data has been placed into the table. These can
+ # be mixed into anything you like to gain access to them.
+ def table_readers
+ table_config.table_readers
+ end
+
+ # # This understand nesting descriptions one deep
+ # def table_config
+ # on_my_class = self.class.instance_variable_get("@table_config")
+ # return on_my_class if on_my_class
+ #
+ # if self.class.superclass
+ # on_super_class = self.class.superclass.instance_variable_get("@table_config")
+ # return on_super_class if on_super_class
+ # end
+ # end
+
+ private
+ def install_active_record_tracking_hook
+ ActiveRecord::Base.table_config = table_config
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/table_blasting.rb b/vendor/plugins/scenarios/lib/scenarios/table_blasting.rb
new file mode 100644
index 00000000..9b2efc3d
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/table_blasting.rb
@@ -0,0 +1,20 @@
+module Scenarios
+ module TableBlasting
+ def self.included(base)
+ base.module_eval do
+ delegate :blasted_tables, :to => :table_config
+ end
+ end
+
+ def blast_table(name) # :nodoc:
+ ActiveRecord::Base.silence do
+ ActiveRecord::Base.connection.delete "DELETE FROM #{name}", "Scenario Delete"
+ end
+ blasted_tables << name
+ end
+
+ def prepare_table(name)
+ blast_table(name) unless blasted_tables.include?(name)
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/lib/scenarios/table_methods.rb b/vendor/plugins/scenarios/lib/scenarios/table_methods.rb
new file mode 100644
index 00000000..a9f2be34
--- /dev/null
+++ b/vendor/plugins/scenarios/lib/scenarios/table_methods.rb
@@ -0,0 +1,205 @@
+module Scenarios
+ # This helper module contains the #create_record method. It is made
+ # available to all Scenario instances, test and example classes, and test
+ # and example instances.
+ module TableMethods
+ include TableBlasting
+
+ delegate :record_metas, :to => :table_config
+
+ # Insert a record into the database, add the appropriate helper methods
+ # into the scenario and spec, and return the ID of the inserted record:
+ #
+ # create_record :event, :name => "Ruby Hoedown"
+ # create_record Event, :hoedown, :name => "Ruby Hoedown"
+ #
+ # The first form will create a new record in the given class identifier
+ # and no symbolic name (essentially).
+ #
+ # The second form is exactly like the first, except for that it provides a
+ # symbolic name as the second parameter. The symbolic name will allow you
+ # to access the record through a couple of helper methods:
+ #
+ # events(:hoedown) # The hoedown event
+ # event_id(:hoedown) # The ID of the hoedown event
+ #
+ # These helper methods are only accessible for a particular table after
+ # you have inserted a record into that table using create_record.
+ def create_record(class_identifier, *args)
+ insert(ScenarioRecord, class_identifier, *args) do |record|
+ meta = record.record_meta
+ fixture = record.to_fixture
+ begin
+ meta.connection.insert_fixture(fixture, record.record_meta.table_name)
+ rescue # Rails 1.2 compatible!
+ meta.connection.execute "INSERT INTO #{meta.table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})"
+ end
+ record.id
+ end
+ end
+
+ # Instantiate and save! a model, add the appropriate helper methods into
+ # the scenario and spec, and return the new model instance:
+ #
+ # create_model :event, :name => "Ruby Hoedown"
+ # create_model Event, :hoedown, :name => "Ruby Hoedown"
+ #
+ # The first form will create a new model with no symbolic name
+ # (essentially).
+ #
+ # The second form is exactly like the first, except for that it provides a
+ # symbolic name as the second parameter. The symbolic name will allow you
+ # to access the record through a couple of helper methods:
+ #
+ # events(:hoedown) # The hoedown event
+ # event_id(:hoedown) # The ID of the hoedown event
+ #
+ # These helper methods are only accessible for a particular table after
+ # you have inserted a record into that table using create_model.
+ def create_model(class_identifier, *args)
+ insert(ScenarioModel, class_identifier, *args) do |record|
+ model = record.to_model
+ model.save!
+ model
+ end
+ end
+
+ private
+ def insert(record_or_model, class_identifier, *args, &insertion)
+ symbolic_name, attributes = extract_creation_arguments(args)
+ record_meta = (record_metas[class_identifier] ||= RecordMeta.new(class_identifier))
+ record = record_or_model.new(record_meta, attributes, symbolic_name)
+ return_value = nil
+ ActiveRecord::Base.silence do
+ prepare_table(record_meta.table_name)
+ return_value = insertion.call record
+ table_config.update_table_readers(record)
+ self.extend table_config.table_readers
+ end
+ return_value
+ end
+
+ def extract_creation_arguments(arguments)
+ if arguments.size == 2 && arguments.last.kind_of?(Hash)
+ arguments
+ elsif arguments.size == 1 && arguments.last.kind_of?(Hash)
+ [nil, arguments[0]]
+ else
+ [nil, Hash.new]
+ end
+ end
+
+ class RecordMeta # :nodoc:
+ attr_reader :class_name, :record_class, :table_name
+
+ def initialize(class_identifier)
+ @class_identifier = class_identifier
+ @class_name = resolve_class_name(class_identifier)
+ @record_class = class_name.constantize
+ @table_name = record_class.table_name
+ end
+
+ def timestamp_columns
+ @timestamp_columns ||= begin
+ timestamps = %w(created_at created_on updated_at updated_on)
+ columns.select do |column|
+ timestamps.include?(column.name)
+ end
+ end
+ end
+
+ def columns
+ @columns ||= connection.columns(table_name)
+ end
+
+ def connection
+ record_class.connection
+ end
+
+ def id_reader
+ @id_reader ||= begin
+ reader = ActiveRecord::Base.pluralize_table_names ? table_name.singularize : table_name
+ "#{reader}_id".to_sym
+ end
+ end
+
+ def record_reader
+ table_name.to_sym
+ end
+
+ def resolve_class_name(class_identifier)
+ case class_identifier
+ when Symbol
+ class_identifier.to_s.singularize.camelize
+ when Class
+ class_identifier.name
+ when String
+ class_identifier
+ end
+ end
+
+ def to_s
+ "#"
+ end
+ end
+
+ class ScenarioModel # :nodoc:
+ attr_reader :attributes, :model, :record_meta, :symbolic_name
+ delegate :id, :to => :model
+
+ def initialize(record_meta, attributes, symbolic_name = nil)
+ @record_meta = record_meta
+ @attributes = attributes.stringify_keys
+ @symbolic_name = symbolic_name || object_id
+ end
+
+ def to_hash
+ to_model.attributes
+ end
+
+ def to_model
+ @model ||= record_meta.record_class.new(attributes)
+ end
+ end
+
+ class ScenarioRecord # :nodoc:
+ attr_reader :record_meta, :symbolic_name
+
+ def initialize(record_meta, attributes, symbolic_name = nil)
+ @record_meta = record_meta
+ @attributes = attributes.stringify_keys
+ @symbolic_name = symbolic_name || object_id
+
+ install_default_attributes!
+ end
+
+ def id
+ @attributes['id']
+ end
+
+ def to_hash
+ @attributes
+ end
+
+ def to_fixture
+ Fixture.new(to_hash, record_meta.class_name)
+ end
+
+ def install_default_attributes!
+ @attributes['id'] ||= symbolic_name.to_s.hash.abs
+ install_timestamps!
+ end
+
+ def install_timestamps!
+ record_meta.timestamp_columns.each do |column|
+ @attributes[column.name] = now(column) unless @attributes.key?(column.name)
+ end
+ end
+
+ def now(column)
+ now = ActiveRecord::Base.default_timezone == :utc ? column.klass.now.utc : column.klass.now
+ now.to_s(:db)
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/scenarios/complex_composite_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/complex_composite_scenario.rb
new file mode 100644
index 00000000..1d3c3318
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/complex_composite_scenario.rb
@@ -0,0 +1,9 @@
+class ComplexCompositeScenario < Scenario::Base
+ uses :composite, :places
+
+ helpers do
+ def method_from_complex_composite_scenario
+ :method_from_complex_composite_scenario
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/scenarios/composite_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/composite_scenario.rb
new file mode 100644
index 00000000..09903b28
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/composite_scenario.rb
@@ -0,0 +1,9 @@
+class CompositeScenario < Scenario::Base
+ uses :people, :things
+
+ helpers do
+ def method_from_composite_scenario
+ :method_from_composite_scenario
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/scenarios/empty_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/empty_scenario.rb
new file mode 100644
index 00000000..0ea2ba64
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/empty_scenario.rb
@@ -0,0 +1,4 @@
+class EmptyScenario < Scenario::Base
+ def load
+ end
+end
diff --git a/vendor/plugins/scenarios/spec/scenarios/people_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/people_scenario.rb
new file mode 100644
index 00000000..792e0f4a
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/people_scenario.rb
@@ -0,0 +1,26 @@
+class PeopleScenario < Scenario::Base
+
+ def load
+ create_person "John Long"
+ create_person "Adam Williams"
+ end
+
+ helpers do
+ def create_person(attributes = {})
+ if attributes.kind_of?(String)
+ first, last = attributes.split(/\s+/)
+ attributes = { :first_name => first, :last_name => last }
+ end
+ attributes = person_params(attributes)
+ create_record(:person, attributes[:first_name].strip.gsub(' ', '_').underscore.to_sym, attributes)
+ end
+
+ def person_params(attributes = {})
+ attributes = {
+ :first_name => "John",
+ :last_name => "Q."
+ }.update(attributes)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/scenarios/places_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/places_scenario.rb
new file mode 100644
index 00000000..50d7ddf9
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/places_scenario.rb
@@ -0,0 +1,22 @@
+class PlacesScenario < Scenario::Base
+
+ def load
+ create_place "Taj Mahal", "India"
+ create_place "Whitehouse", "Washington DC"
+ end
+
+ helpers do
+ def create_place(name, location)
+ attributes = place_params(:name => name, :location => location)
+ create_record(:place, name.strip.gsub(' ', '_').underscore.to_sym, attributes)
+ end
+
+ def place_params(attributes = {})
+ attributes = {
+ :name => "Noplace",
+ :location => "Nowhere"
+ }.update(attributes)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/scenarios/things_scenario.rb b/vendor/plugins/scenarios/spec/scenarios/things_scenario.rb
new file mode 100644
index 00000000..d37abd39
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios/things_scenario.rb
@@ -0,0 +1,22 @@
+class ThingsScenario < Scenario::Base
+
+ def load
+ create_thing "one"
+ create_thing "two"
+ end
+
+ helpers do
+ def create_thing(attributes = {})
+ attributes = { :name => attributes } if attributes.kind_of?(String)
+ attributes = thing_params(attributes)
+ create_record(:thing, attributes[:name].strip.gsub(' ', '_').underscore.to_sym, attributes)
+ end
+
+ def thing_params(attributes = {})
+ attributes = {
+ :name => "Unnamed Thing",
+ :description => "I'm not sure what this is."
+ }.update(attributes)
+ end
+ end
+end
diff --git a/vendor/plugins/scenarios/spec/scenarios_spec.rb b/vendor/plugins/scenarios/spec/scenarios_spec.rb
new file mode 100644
index 00000000..c74fd5e0
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/scenarios_spec.rb
@@ -0,0 +1,185 @@
+require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
+
+class ExplodesOnSecondInstantiationScenario < Scenario::Base
+ cattr_accessor :instance
+ def initialize(*args)
+ raise "Should only be created once" if self.class.instance
+ self.class.instance = super(*args)
+ end
+end
+
+describe "Scenario loading" do
+ scenario :explodes_on_second_instantiation
+
+ it "should work" do
+ end
+
+ it 'should work again' do
+ end
+end
+
+describe "Scenario loading" do
+ it "should load from configured directories" do
+ Scenario.load(:empty)
+ EmptyScenario
+ end
+
+ it "should raise Scenario::NameError when the scenario does not exist" do
+ lambda { Scenario.load(:whatcha_talkin_bout) }.should raise_error(Scenario::NameError)
+ end
+
+ it "should allow us to add helper methods through the helpers class method" do
+ klass = :empty.to_scenario
+ klass.helpers do
+ def hello
+ "Hello World"
+ end
+ end
+ klass.new.methods.should include('hello')
+ end
+
+ it "should provide a built-in scenario named :blank which clears all tables found in schema.rb" do
+ Scenario.load(:blank)
+ BlankScenario
+ end
+end
+
+describe Scenarios::TableMethods do
+ scenario :things
+
+ it "should understand namespaced models" do
+ create_record "ModelModule::Model", :raking, :name => "Raking", :description => "Moving leaves around"
+ models(:raking).should_not be_nil
+ end
+
+ it "should include record creation methods" do
+ create_record(:thing, :three, :name => "Three")
+ things(:three).name.should == "Three"
+ end
+
+ it "should include other example helper methods" do
+ create_thing("The Thing")
+ things(:the_thing).name.should == "The Thing"
+ end
+
+ describe "for retrieving objects" do
+ it "should have a pluralized name" do
+ should respond_to("things")
+ should_not respond_to("thing")
+ end
+
+ it "should answer a single object given a single name" do
+ things(:one).should be_kind_of(Thing)
+ things("one").should be_kind_of(Thing)
+ things(:two).name.should == "two"
+ end
+
+ it "should answer an array of objects given multiple names" do
+ things(:one, :two).should be_kind_of(Array)
+ things(:one, :two).should eql([things(:one), things(:two)])
+ end
+
+ it "should just return the argument if an AR instance is given" do
+ thing = things(:one)
+ things(thing).should eql(thing)
+ end
+ end
+
+ describe "for retrieving ids" do
+ it "should have a singular name" do
+ should respond_to("thing_id")
+ should_not respond_to("thing_ids")
+ should_not respond_to("things_id")
+ end
+
+ it "should answer a single id given a single name" do
+ thing_id(:one).should be_kind_of(Fixnum)
+ thing_id("one").should be_kind_of(Fixnum)
+ end
+
+ it "should answer an array of ids given multiple names" do
+ thing_id(:one, :two).should be_kind_of(Array)
+ thing_id(:one, :two).should eql([thing_id(:one), thing_id(:two)])
+ thing_id("one", "two").should eql([thing_id(:one), thing_id(:two)])
+ end
+
+ it "should answer the id of the argument if an AR instance id given" do
+ thing = things(:one)
+ thing_id(thing).should == thing.id
+ end
+ end
+end
+
+describe "it uses people and things scenarios", :shared => true do
+ it "should have reader helper methods for each used scenario" do
+ should respond_to(:things)
+ should respond_to(:people)
+ end
+
+ it "should allow us to use helper methods from each scenario inside an example" do
+ should respond_to(:create_thing)
+ should respond_to(:create_person)
+ end
+end
+
+describe "A composite scenario" do
+ scenario :composite
+
+ it_should_behave_like "it uses people and things scenarios"
+
+ it "should allow us to use helper methods scenario" do
+ should respond_to(:method_from_composite_scenario)
+ end
+end
+
+describe "Multiple scenarios" do
+ scenario :things, :people
+
+ it_should_behave_like "it uses people and things scenarios"
+end
+
+describe "A complex composite scenario" do
+ scenario :complex_composite
+
+ it_should_behave_like "it uses people and things scenarios"
+
+ it "should have correct reader helper methods" do
+ should respond_to(:places)
+ end
+
+ it "should allow us to use correct helper methods" do
+ should respond_to(:create_place)
+ end
+end
+
+describe "Overlapping scenarios" do
+ scenario :composite, :things, :people
+
+ it "should not cause scenarios to be loaded twice" do
+ Person.find_all_by_first_name("John").size.should == 1
+ end
+end
+
+describe "create_record table method" do
+ scenario :empty
+
+ it "should automatically set timestamps" do
+ create_record :note, :first, :content => "first note"
+ note = notes(:first)
+ note.created_at.should be_instance_of(Time)
+ end
+end
+
+describe "create_model table method" do
+ scenario :empty
+
+ it "should support symbolic names" do
+ thing = create_model Thing, :mything, :name => "My Thing", :description => "For testing"
+ things(:mything).should == thing
+ end
+
+ it "should blast any table touched as a side effect of creating a model (callbacks, observers, etc.)" do
+ create_model SideEffectyThing
+ blasted_tables.should include(Thing.table_name)
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/spec.opts b/vendor/plugins/scenarios/spec/spec.opts
new file mode 100644
index 00000000..2144705e
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/spec.opts
@@ -0,0 +1,7 @@
+--colour
+--format
+progress
+--loadby
+mtime
+--reverse
+--backtrace
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/spec/spec_helper.rb b/vendor/plugins/scenarios/spec/spec_helper.rb
new file mode 100644
index 00000000..b641894f
--- /dev/null
+++ b/vendor/plugins/scenarios/spec/spec_helper.rb
@@ -0,0 +1,24 @@
+require File.expand_path(File.dirname(__FILE__) + '/../testing/plugit_descriptor')
+
+TESTING_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../testing")
+TESTING_TMP = "#{TESTING_ROOT}/tmp"
+
+require 'fileutils'
+FileUtils.mkdir_p(TESTING_TMP)
+FileUtils.touch("#{TESTING_TMP}/test.log")
+
+require 'logger'
+RAILS_DEFAULT_LOGGER = Logger.new("#{TESTING_TMP}/test.log")
+RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
+
+ActiveRecord::Base.silence do
+ ActiveRecord::Base.configurations = {'sqlite3' => {
+ 'adapter' => 'sqlite3',
+ 'database' => "#{TESTING_TMP}/sqlite3.db"
+ }}
+ ActiveRecord::Base.establish_connection 'sqlite3'
+ load "#{TESTING_ROOT}/schema.rb"
+end
+
+require "models"
+require "scenarios"
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/tasks/scenario.rake b/vendor/plugins/scenarios/tasks/scenario.rake
new file mode 100644
index 00000000..37b56ebb
--- /dev/null
+++ b/vendor/plugins/scenarios/tasks/scenario.rake
@@ -0,0 +1,19 @@
+namespace :db do
+ namespace :scenario do
+ desc "Load a scenario into the current environment's database using SCENARIO=scenario_name"
+ task :load => 'db:reset' do
+ scenario_name = ENV['SCENARIO'] || 'default'
+ begin
+ klass = Scenarios.load(scenario_name)
+ puts "Loaded #{klass.name.underscore.gsub('_', ' ')}."
+ rescue Scenarios::NameError => e
+ if scenario_name == 'default'
+ puts "Error! Set the SCENARIO environment variable or define a DefaultScenario class."
+ else
+ puts "Error! Invalid scenario name [#{scenario_name}]."
+ end
+ exit(1)
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/testing/application.rb b/vendor/plugins/scenarios/testing/application.rb
new file mode 100644
index 00000000..87f91f64
--- /dev/null
+++ b/vendor/plugins/scenarios/testing/application.rb
@@ -0,0 +1,2 @@
+class ApplicationController < ActionController::Base
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/testing/models.rb b/vendor/plugins/scenarios/testing/models.rb
new file mode 100644
index 00000000..34801db4
--- /dev/null
+++ b/vendor/plugins/scenarios/testing/models.rb
@@ -0,0 +1,14 @@
+class Person < ActiveRecord::Base; end
+class Place < ActiveRecord::Base; end
+class Thing < ActiveRecord::Base; end
+class Note < ActiveRecord::Base; end
+
+class SideEffectyThing < ActiveRecord::Base
+ after_create do
+ Thing.create!
+ end
+end
+
+module ModelModule
+ class Model < ActiveRecord::Base; end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/testing/plugit_descriptor.rb b/vendor/plugins/scenarios/testing/plugit_descriptor.rb
new file mode 100644
index 00000000..17b19e67
--- /dev/null
+++ b/vendor/plugins/scenarios/testing/plugit_descriptor.rb
@@ -0,0 +1,44 @@
+require 'rubygems'
+gem 'plugit'
+require 'plugit'
+
+$LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
+RAILS_ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
+
+Plugit.describe do |scenarios|
+ scenarios.environments_root_path = File.dirname(__FILE__) + '/environments'
+ vendor_directory = File.expand_path(File.dirname(__FILE__) + '/../vendor/plugins')
+
+ scenarios.environment :default, 'Released versions of Rails and RSpec' do |env|
+ env.library :rails, :export => "git clone git://github.com/rails/rails.git" do |rails|
+ rails.after_update { `git co v2.1.0_RC1` }
+ rails.load_paths = %w{/activesupport/lib /activerecord/lib /actionpack/lib}
+ rails.requires = %w{active_support active_record action_controller action_view}
+ end
+ env.library :rspec, :export => "git clone git://github.com/dchelimsky/rspec.git" do |rspec|
+ rspec.after_update { `git co 1.1.4 && mkdir -p #{vendor_directory} && ln -sF #{File.expand_path('.')} #{vendor_directory + '/rspec'}` }
+ rspec.requires = %w{spec}
+ end
+ env.library :rspec_rails, :export => "git clone git://github.com/dchelimsky/rspec-rails.git" do |rspec_rails|
+ rspec_rails.after_update { `git co 1.1.4` }
+ rspec_rails.requires = %w{spec/rails}
+ end
+ end
+
+ scenarios.environment :edge, 'Edge versions of Rails and RSpec' do |env|
+ env.library :rails, :export => "git clone git://github.com/rails/rails.git --depth 1" do |rails|
+ rails.before_install { `git pull` }
+ rails.load_paths = %w{/activesupport/lib /activerecord/lib /actionpack/lib}
+ rails.requires = %w{active_support active_record action_controller action_view}
+ end
+ env.library :rspec, :export => "git clone git://github.com/dchelimsky/rspec.git --depth 1" do |rspec|
+ rspec.after_update { `git pull && mkdir -p #{vendor_directory} && ln -sF #{File.expand_path('.')} #{vendor_directory + '/rspec'}` }
+ rspec.requires = %w{spec}
+ end
+ env.library :rspec_rails, :export => "git clone git://github.com/dchelimsky/rspec-rails.git --depth 1" do |rspec_rails|
+ rspec_rails.after_update { `git pull` }
+ rspec_rails.requires = %w{spec/rails}
+ end
+ end
+end
\ No newline at end of file
diff --git a/vendor/plugins/scenarios/testing/schema.rb b/vendor/plugins/scenarios/testing/schema.rb
new file mode 100644
index 00000000..30a1326c
--- /dev/null
+++ b/vendor/plugins/scenarios/testing/schema.rb
@@ -0,0 +1,31 @@
+ActiveRecord::Schema.define do
+ create_table :people, :force => true do |t|
+ t.column :first_name, :string
+ t.column :last_name, :string
+ end
+
+ create_table :places, :force => true do |t|
+ t.column :name, :string
+ t.column :location, :string
+ end
+
+ create_table :things, :force => true do |t|
+ t.column :name, :string
+ t.column :description, :string
+ end
+
+ create_table :side_effecty_things, :force => true do |t|
+ end
+
+ create_table :models, :force => true do |t|
+ t.column :name, :string
+ t.column :description, :string
+ end
+
+ create_table :notes, :force => true do |t|
+ t.column :content, :string
+ t.column :created_at, :datetime
+ t.column :updated_at, :datetime
+ end
+end
+
\ No newline at end of file