mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-29 21:38:49 +01:00
Eliminated use of scenarios plugin
It doesn't work on Rails 2.3.5
This commit is contained in:
parent
d1fc119e2d
commit
6d3770c5fb
42 changed files with 24 additions and 1576 deletions
|
|
@ -17,7 +17,7 @@ class Todo < ActiveRecord::Base
|
|||
after_save :save_predecessors
|
||||
|
||||
named_scope :active, :conditions => { :state => 'active' }
|
||||
named_scope :not_completed, :conditions => ['NOT (state = ? )', 'completed']
|
||||
named_scope :not_completed, :conditions => ['NOT (todos.state = ? )', 'completed']
|
||||
named_scope :are_due, :conditions => ['NOT (todos.due IS NULL)']
|
||||
|
||||
STARRED_TAG_NAME = "starred"
|
||||
|
|
|
|||
11
spec/fixtures/todos.yml
vendored
11
spec/fixtures/todos.yml
vendored
|
|
@ -55,3 +55,14 @@ buymilk:
|
|||
due: ~
|
||||
completed_at: <%= today %>
|
||||
user: admin_user
|
||||
|
||||
callmom:
|
||||
id: 5
|
||||
context_id: 3 # call
|
||||
project_id: ~
|
||||
description: Call mom
|
||||
notes: Remember her birthday
|
||||
state: active
|
||||
due: ~
|
||||
completed_at: ~
|
||||
user: admin_user
|
||||
|
|
|
|||
|
|
@ -51,37 +51,37 @@ describe Context do
|
|||
end
|
||||
|
||||
describe 'when finding by namepart' do
|
||||
scenario :todos
|
||||
fixtures :todos, :contexts
|
||||
|
||||
it 'finds with exact match' do
|
||||
Context.find_by_namepart('errand').should == contexts(:errand)
|
||||
Context.find_by_namepart('agenda').should == contexts(:agenda)
|
||||
end
|
||||
|
||||
it 'finds with partial match' do
|
||||
Context.find_by_namepart('err').should == contexts(:errand)
|
||||
Context.find_by_namepart('age').should == contexts(:agenda)
|
||||
end
|
||||
|
||||
it 'deletes todos within context when context deleted' do
|
||||
contexts(:call).should have(2).todos
|
||||
call_todos = contexts(:call).todos
|
||||
contexts(:call).destroy
|
||||
contexts(:agenda).should have(3).todos
|
||||
call_todos = contexts(:agenda).todos
|
||||
contexts(:agenda).destroy
|
||||
Todo.find(:all).should_not include(call_todos)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when counting todos' do
|
||||
scenario :todos
|
||||
fixtures :todos, :contexts, :users, :preferences
|
||||
|
||||
it 'returns correct number of completed todos' do
|
||||
contexts(:call).should_not have(:any).done_todos
|
||||
contexts(:call).done_todos.should_not have(:any).items
|
||||
contexts(:call).todos.first.complete!
|
||||
contexts(:call).should have(1).done_todos
|
||||
Context.find(contexts(:call).id).done_todos.should have(1).items
|
||||
end
|
||||
|
||||
it 'returns correct number of not done todos' do
|
||||
contexts(:call).should have(2).not_done_todos
|
||||
contexts(:call).todos.last.complete!
|
||||
contexts(:call).should have(1).not_done_todos
|
||||
contexts(:agenda).todos.not_completed.should have(2).items
|
||||
contexts(:agenda).todos.last.complete!
|
||||
contexts(:agenda).todos.not_completed.should have(1).items
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
class ContextsScenario < Scenario::Base
|
||||
uses :users
|
||||
|
||||
def load
|
||||
%w(Call Email Errand Someday).each_with_index do |context, index|
|
||||
create_context context, index+1
|
||||
end
|
||||
end
|
||||
|
||||
def create_context(name, position)
|
||||
create_model :context, name.downcase.to_sym,
|
||||
:name => name,
|
||||
:position => position,
|
||||
:hide => name == 'Someday' ? true : false,
|
||||
:created_at => Time.now,
|
||||
:updated_at => Time.now,
|
||||
:user_id => user_id(:sean)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
class ProjectsScenario < Scenario::Base
|
||||
def load
|
||||
create_project :build_time_machine, 'Build a working time machine'
|
||||
create_project :make_more_money, 'Make more money than Billy Gates'
|
||||
create_project :evict_dinosaurs, 'Evict dinosaurs from the garden'
|
||||
create_project :attend_railsconf, 'Attend RailsConf'
|
||||
end
|
||||
|
||||
def create_project(identifier, name)
|
||||
attributes = {
|
||||
:name => name,
|
||||
:state => 'active',
|
||||
:created_at => 4.day.ago,
|
||||
:updated_at => 1.minute.ago
|
||||
}
|
||||
create_model :project,
|
||||
identifier || attributes[:name].split.first.downcase.to_sym,
|
||||
attributes
|
||||
end
|
||||
end
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
class TodosScenario < Scenario::Base
|
||||
uses :contexts, :projects, :users
|
||||
|
||||
def load
|
||||
create_todo :bill,
|
||||
:description => 'Call Bill Gates to find out how much he makes per day',
|
||||
:user => :sean,
|
||||
:context => :call,
|
||||
:project => :make_more_money
|
||||
create_todo :bank,
|
||||
:description => 'Call my bank',
|
||||
:user => :sean,
|
||||
:context => :call,
|
||||
:project => :make_more_money
|
||||
end
|
||||
|
||||
def create_todo(identifier, options={})
|
||||
context = options.delete(:context)
|
||||
project = options.delete(:project)
|
||||
user = options.delete(:user)
|
||||
attributes = {
|
||||
:state => 'active',
|
||||
:created_at => 1.week.ago,
|
||||
:context_id => context_id(context),
|
||||
:project_id => project_id(project),
|
||||
:user_id => user_id(user)
|
||||
}.merge(options)
|
||||
create_model :todo, identifier, attributes
|
||||
end
|
||||
end
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
class UsersScenario < Scenario::Base
|
||||
def load
|
||||
create_user :login => 'johnny', :first_name => 'Johnny', :last_name => 'Smith'
|
||||
create_user :login => 'jane', :first_name => 'Jane', :last_name => 'Pilbeam'
|
||||
create_user :login => 'sean', :first_name => 'Sean', :last_name => 'Pallmer'
|
||||
end
|
||||
|
||||
def create_user(attributes={})
|
||||
password = attributes[:login] + Time.now.to_s
|
||||
attributes = {
|
||||
:password => password,
|
||||
:password_confirmation => password,
|
||||
:is_admin => attributes[:is_admin] || false,
|
||||
}.merge(attributes)
|
||||
identifier = attributes[:login].downcase.to_sym
|
||||
user = create_model :user, identifier, attributes
|
||||
Preference.create(:show_number_completed => 5, :user => user)
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,6 @@ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
|
|||
require 'spec'
|
||||
require 'spec/rails'
|
||||
require 'skinny_spec'
|
||||
require 'scenarios'
|
||||
|
||||
module LuckySneaks
|
||||
module ModelSpecHelpers
|
||||
|
|
|
|||
4
vendor/plugins/scenarios/.gitignore
vendored
4
vendor/plugins/scenarios/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
|||
environments
|
||||
*.log
|
||||
tmp
|
||||
vendor
|
||||
19
vendor/plugins/scenarios/LICENSE
vendored
19
vendor/plugins/scenarios/LICENSE
vendored
|
|
@ -1,19 +0,0 @@
|
|||
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.
|
||||
262
vendor/plugins/scenarios/README
vendored
262
vendor/plugins/scenarios/README
vendored
|
|
@ -1,262 +0,0 @@
|
|||
== 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 <tt>create_record</tt> instance method to
|
||||
create two users: John and Cindy. Notice the calls to <tt>create_record</tt>.
|
||||
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 <tt>scenario</tt> 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 <tt>users</tt> and the
|
||||
symbolic name <tt>:john</tt>. (Remember that in the Users scenario I declared
|
||||
that John should be accessible through the symbolic name <tt>:john</tt>.)
|
||||
|
||||
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 <tt>uses</tt> 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 <tt>load</tt> 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: <tt>post_id</tt>). 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 <tt>uses</tt> 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 <tt>helpers</tt> 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, <tt>db:scenario:load</tt>,
|
||||
which you may use in a fashion similar to Rails fixtures'
|
||||
<tt>db:fixtures:load</tt>.
|
||||
|
||||
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 <tt>uses</tt> 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.
|
||||
10
vendor/plugins/scenarios/Rakefile
vendored
10
vendor/plugins/scenarios/Rakefile
vendored
|
|
@ -1,10 +0,0 @@
|
|||
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
|
||||
1
vendor/plugins/scenarios/TODO
vendored
1
vendor/plugins/scenarios/TODO
vendored
|
|
@ -1 +0,0 @@
|
|||
Make sure before :all's that use scenario methods work. They don't right now.
|
||||
127
vendor/plugins/scenarios/helpers.diff
vendored
127
vendor/plugins/scenarios/helpers.diff
vendored
|
|
@ -1,127 +0,0 @@
|
|||
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/<name>_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/<name>_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
|
||||
34
vendor/plugins/scenarios/lib/scenarios.rb
vendored
34
vendor/plugins/scenarios/lib/scenarios.rb
vendored
|
|
@ -1,34 +0,0 @@
|
|||
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. <tt>scenario_name</tt> 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'
|
||||
73
vendor/plugins/scenarios/lib/scenarios/base.rb
vendored
73
vendor/plugins/scenarios/lib/scenarios/base.rb
vendored
|
|
@ -1,73 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
class Object
|
||||
def metaclass
|
||||
(class << self; self; end)
|
||||
end unless method_defined?(:metaclass)
|
||||
end
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
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 <tt>create_record</tt>.
|
||||
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 <tt>create_model</tt>.
|
||||
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
|
||||
"#<RecordMeta: #{table_name}>"
|
||||
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
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
class ComplexCompositeScenario < Scenario::Base
|
||||
uses :composite, :places
|
||||
|
||||
helpers do
|
||||
def method_from_complex_composite_scenario
|
||||
:method_from_complex_composite_scenario
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
class CompositeScenario < Scenario::Base
|
||||
uses :people, :things
|
||||
|
||||
helpers do
|
||||
def method_from_composite_scenario
|
||||
:method_from_composite_scenario
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
class EmptyScenario < Scenario::Base
|
||||
def load
|
||||
end
|
||||
end
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
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
|
||||
185
vendor/plugins/scenarios/spec/scenarios_spec.rb
vendored
185
vendor/plugins/scenarios/spec/scenarios_spec.rb
vendored
|
|
@ -1,185 +0,0 @@
|
|||
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
|
||||
7
vendor/plugins/scenarios/spec/spec.opts
vendored
7
vendor/plugins/scenarios/spec/spec.opts
vendored
|
|
@ -1,7 +0,0 @@
|
|||
--colour
|
||||
--format
|
||||
progress
|
||||
--loadby
|
||||
mtime
|
||||
--reverse
|
||||
--backtrace
|
||||
24
vendor/plugins/scenarios/spec/spec_helper.rb
vendored
24
vendor/plugins/scenarios/spec/spec_helper.rb
vendored
|
|
@ -1,24 +0,0 @@
|
|||
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"
|
||||
19
vendor/plugins/scenarios/tasks/scenario.rake
vendored
19
vendor/plugins/scenarios/tasks/scenario.rake
vendored
|
|
@ -1,19 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
end
|
||||
14
vendor/plugins/scenarios/testing/models.rb
vendored
14
vendor/plugins/scenarios/testing/models.rb
vendored
|
|
@ -1,14 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
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
|
||||
31
vendor/plugins/scenarios/testing/schema.rb
vendored
31
vendor/plugins/scenarios/testing/schema.rb
vendored
|
|
@ -1,31 +0,0 @@
|
|||
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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue