Author: assaf
Date: Mon Jun 2 21:53:34 2008
New Revision: 662651
URL: http://svn.apache.org/viewvc?rev=662651&view=rev
Log:
Now meeting all activity specs.
Modified:
ode/sandbox/singleshot/app/models/person.rb
ode/sandbox/singleshot/app/models/task.rb
ode/sandbox/singleshot/spec/common.rb
ode/sandbox/singleshot/spec/models/activities.rb
ode/sandbox/singleshot/spec/models/stakeholder_spec.rb
ode/sandbox/singleshot/spec/models/task_spec.rb
Modified: ode/sandbox/singleshot/app/models/person.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/person.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/person.rb (original)
+++ ode/sandbox/singleshot/app/models/person.rb Mon Jun 2 21:53:34 2008
@@ -117,4 +117,7 @@
read_attribute(:identity)
end
+ has_many :activities, :dependent=>:delete_all
+ has_many :stakeholders, :dependent=>:delete_all
+
end
Modified: ode/sandbox/singleshot/app/models/task.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/app/models/task.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/app/models/task.rb (original)
+++ ode/sandbox/singleshot/app/models/task.rb Mon Jun 2 21:53:34 2008
@@ -57,28 +57,12 @@
# * suspended -- Task is suspended.
# * completed -- Task has completed.
# * cancelled -- Task was cancelled.
-
- # A task can start as reserved and remain there until populated with enough
- # information to transition to ready. From ready, a stakeholder can claim
- # the task, transitioning it to active. The task transitions back to ready
- # if stakeholder releases that claim.
- #
- # Task can transition from ready/active to suspended and back. Task can
- # transition to completed only from active, and transition to cancelled from
- # any other state but completed. Completed and cancelled are terminal
- # states.
STATUSES = ['reserved', 'ready', 'active', 'suspended', 'completed',
'cancelled']
-
- # Cannot change in mass update.
validates_inclusion_of :status, :in=>STATUSES
# Check method for each status (active?, completed?, etc).
- STATUSES.each do |status|
- define_method "#{status}?" do
- self.status == status
- end
- end
+ STATUSES.each { |status| define_method("#{status}?") { self.status == status
} }
before_validation do |task|
# Default status is ready.
@@ -86,39 +70,42 @@
case task.status
when 'ready'
# When task first created, if we only have one potential owner, pick
them as owner.
- task.owner = task.potential_owners.first unless task.owner ||
task.potential_owners.size > 1
+ task.owner = task.potential_owners.first if task.owner.nil? &&
task.potential_owners.size == 1
# Assigned task => active.
task.status = 'active' if task.owner
when 'active'
# Unassigned task => ready.
task.status = 'ready' unless task.owner
- when 'completed', 'cancelled'
- # Cannot modify completed/cancelled tasks.
- task.readonly! unless task.status_changed?
end
end
validate do |task|
# Check state transitions.
from, to = task.status_change
- if from == 'completed'
+ case from # States you cannot transition from.
+ when 'suspended'
+ task.errors.add :status, 'You are not allowed to resume this task.'
unless task.admin?(task.modified_by)
+ when 'completed'
task.errors.add :status, 'Cannot change status of completed task.'
- elsif from == 'cancelled'
+ when 'cancelled'
task.errors.add :status, 'Cannot change status of cancelled task.'
- elsif to == 'reserved'
+ end or case to # or, states you cannot transition to.
+ when 'reserved'
task.errors.add :status, 'Cannot change status to reserved.' unless
from.nil?
- elsif to == 'completed'
- task.errors.add :status, 'Only owner can complete task.' unless
task.owner
+ when 'active'
+ #task.errors.add :status, "#{task.owner.fullname} is not allowed to
claim this task." unless
+ # task.potential_owners.empty? || task.potential_owner?(task.owner) ||
task.admin?(task.owner)
+ when 'suspended'
+ task.errors.add :status, 'You are not allowed to suspend this task.'
unless task.admin?(task.modified_by)
+ when 'completed'
task.errors.add :status, 'Cannot change to completed from any status but
active.' unless from =='active'
+ task.errors.add :status, 'Only owner can complete task.' unless
task.owner && task.modified_by == task.owner && !task.owner_changed?
+ when 'cancelled'
+ task.errors.add :status, 'You are not allowed to cancel this task.'
unless task.admin?(task.modified_by)
end
end
- # -- Common task attributes --
-
- validates_presence_of :title
-
-
# -- View and perform ---
# Some tasks are performed offline, for example, calling a customer. Other
@@ -169,6 +156,11 @@
validates_url :details_url, :allow_nil=>true
+ # -- Common task attributes --
+
+ validates_presence_of :title
+
+
# --- Task data ---
serialize :data
@@ -206,15 +198,17 @@
new_value = set_role(role, identity)
changed_attributes[role] = old_value unless
changed_attributes.has_key?(role) || old_value == new_value
end
+ define_method("#{role}_changed?") { attribute_changed?(role) }
+ define_method("#{role}_change") { attribute_change(role) }
+ define_method("#{role}_was") { attribute_was(role) }
end
def creator=(identity)
- return creator unless new_record?
set_role 'creator', identity
end
- ACCESSOR_FROM_ROLE = { 'potential'=>'potential_owners',
'excluded'=>'excluded_owners', 'observer'=>'observers', 'admin'=>'admins' }
- ACCESSOR_FROM_ROLE.default = lambda { |role| role }
+ ACCESSOR_FROM_ROLE = { 'creator'=>'creator', 'owner'=>'owner',
'potential'=>'potential_owners', 'excluded'=>'excluded_owners',
+ 'observer'=>'observers', 'admin'=>'admins' }
# Task observer, admins and potential/excluded owner. Adds three methods
for each role:
# * {plural} -- Returns people associated with this role.
@@ -252,20 +246,24 @@
return new_set
end
- # Can only have one member of a singular role.
- validate do |record|
+ validate do |task|
+ # Can only have one member of a singular role.
Stakeholder::SINGULAR_ROLES.each do |role|
- record.errors.add role, "Can only have one #{role}." if
record.stakeholders.select { |sh| sh.role == role }.size > 1
+ task.errors.add role, "Can only have one #{role}." if
task.stakeholders.select { |sh| sh.role == role }.size > 1
end
- end
-
- validate do |record|
- creator = record.stakeholders.detect { |sh| sh.role == 'creator' }
- record.errors.add :creator, 'Cannot change creator.' if
record.changed.include?(:creator) && !record.new_record?
- record.errors.add :owner, "#{record.owner.fullname} is on the excluded
owners list and cannot be owner of this task." if
- record.excluded_owner?(record.owner)
- conflicting = record.potential_owners & record.excluded_owners
- record.errors.add :potential_owners,
"#{conflicting.map(&:fullname).join(', ')} listed on both excluded and
potential owners list" unless
+ task.errors.add :creator, 'Cannot change creator.' if
task.creator_changed? && !task.new_record?
+ task.errors.add :owner, "#{task.owner.fullname} is on the excluded owners
list and cannot be owner of this task." if
+ task.excluded_owner?(task.owner)
+ to, from = task.owner_change
+ if task.potential_owners.empty?
+ # With no potential owners, task must have a set owner.
+ #task.errors.add :owner, "This task intended for one owner." unless
task.owner || task.reserved?
+ else
+ # We have a limited set of potential owners, owner must be one of them.
+ #task.errors.add :owner, "#{task.owner.fullname} is not allowd as owner
of this task" unless task.owner && task.potential_owners?(task.owner)
+ end
+ conflicting = task.potential_owners & task.excluded_owners
+ task.errors.add :potential_owners, "#{conflicting.map(&:fullname).join(',
')} listed on both excluded and potential owners list" unless
conflicting.empty?
end
@@ -306,6 +304,8 @@
[ person == task.owner ? 1 : 0, task.can_claim?(person) ? 1 : 0,
(task.due_on && task.due_on <= today) ? today - task.due_on : -1,
-task.priority, today - task.created_at.to_date ] }
+ # involved.role <> 'owner'
+ # tasks.priority, tasks.created_at
self.sort { |a,b| rank[b] <=> rank[a] }
end
@@ -313,52 +313,42 @@
# --- Activities ---
-
- has_many :activities, :include=>[:task, :person],
:order=>'activities.created_at DESC'
- # Associate person with all modifications done on this task.
- # This results in activities linked to the person and task when
- # the task is saved.
- def modified_by(person)
- @modified_by = person
- self
- end
+ has_many :activities, :include=>[:task, :person],
:order=>'activities.created_at DESC', :dependent=>:delete_all
LOG_CHANGE_ATTRIBUTES = [:title, :description, :priority, :due_on]
before_save :unless=>lambda { |task| task.status == 'reserved' } do |task|
- task.log_activities do |log|
- if task.status_changed?
- from, to = task.status_change
- log.add task.creator, 'created' if from.nil? || from == 'reserved'
- case to
- when 'ready'
- log.add nil, 'resumed' if from == 'suspended'
- log.add nil, 'released' if from == 'active'
- when 'active'
- log.add nil, 'resumed' if from == 'suspended'
- log.add task.owner, 'is owner of' if task.changed.include?('owner')
- when 'suspended' then log.add nil, 'suspended'
- when 'completed' then log.add task.owner, 'completed'
- when 'cancelled' then log.add nil, 'cancelled'
- end
- elsif task.changed.include?('owner')
- # TODO: get this working!
- log.add task.owner, 'is owner of'
- elsif task.changed.any? { |attr| LOG_CHANGE_ATTRIBUTES.include?(attr) }
- log.add nil, 'changed'
- end
- end
- end
-
- def log_activities
log = Hash.new
def log.add(person, action)
self[person] = Array(self[person]).push(action)
end
- yield log
+ task.log_activities log
log.each do |person, actions|
- activities.build :person=>person || @modified_by,
:action=>actions.to_sentence
+ task.activities.build :person=>person || task.modified_by,
:action=>actions.to_sentence
+ end
+ end
+
+ def log_activities(log)
+ if status_changed?
+ from, to = status_change
+ log.add creator, 'created' if from.nil? || from == 'reserved'
+ case to
+ when 'ready'
+ log.add nil, 'resumed' if from == 'suspended'
+ log.add nil, 'released' if from == 'active'
+ when 'active'
+ log.add nil, 'resumed' if from == 'suspended'
+ log.add owner, 'is owner of' if changed.include?('owner')
+ when 'suspended' then log.add nil, 'suspended'
+ when 'completed' then log.add owner, 'completed'
+ when 'cancelled' then log.add nil, 'cancelled'
+ end
+ elsif changed.include?('owner')
+ # TODO: get this working!
+ log.add owner, 'is owner of'
+ elsif changed.any? { |attr| LOG_CHANGE_ATTRIBUTES.include?(attr) }
+ log.add nil, 'changed'
end
end
@@ -411,28 +401,36 @@
# --- Access control ---
+ # Person who is modifying this task: required to activity logging and access
control.
+ attr_reader :modified_by
+
+ # Changes the modified_by person and return self.
+ def modify_by(person)
+ @modified_by = person
+ self
+ end
+
+ after_save do |task|
+ task.modify_by nil
+ end
+
+
enumerable :cancellation, [:admin, :owner], :default=>:admin
- # Returns true if this person can cancel this task.
def can_cancel?(person)
- return false if completed? || cancelled?
- #return true if person.admin? || admin?(person)
- #return owner?(person) if cancellation == :owner
- return true if admin?(person)
- false
+ admin?(person) && !completed && !cancelled?
end
- # Returns true if this person can complete this task.
def can_complete?(person)
active? && owner?(person)
end
def can_suspend?(person)
- admin?(person) && active? || ready? # || person.admin?
+ admin?(person) && (active? || ready? || suspended?)
end
def can_claim?(person)
- owner.nil? && potential_owner?(person)
+ owner.nil? && (potential_owners.empty? || potential_owner?(person))
end
def can_delegate?(person)
Modified: ode/sandbox/singleshot/spec/common.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/common.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/common.rb (original)
+++ ode/sandbox/singleshot/spec/common.rb Mon Jun 2 21:53:34 2008
@@ -5,13 +5,12 @@
def self.included(base)
base.after :all do
Person.delete_all
+ @authenticated = nil
end
end
def person(identity)
- @_people ||= {}
- @_people[identity.to_s] ||= Person.identify(identity) ||
- Person.create(:email=>"[EMAIL PROTECTED]", :password=>'secret')
+ Person.identify(identity) || Person.create(:email=>"[EMAIL PROTECTED]",
:password=>'secret')
end
def people(*identities)
@@ -19,7 +18,7 @@
end
def su
- @_su ||= Person.create(:email=>'[EMAIL PROTECTED]', :admin=>true)
+ Person.identify('super') || Person.create(:email=>'[EMAIL PROTECTED]',
:admin=>true)
end
def authenticate(person)
@@ -50,9 +49,9 @@
base.send :include, Authentication
end
- def default_task(with = {})
+ def default_task(attributes = {})
{ :title=>'Test this',
- :outcome_url=>'http://test.host/outcome' }.merge(with)
+ :outcome_url=>'http://test.host/outcome' }.merge(attributes)
end
def task_with_status(status, attributes = nil)
Modified: ode/sandbox/singleshot/spec/models/activities.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/models/activities.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/models/activities.rb (original)
+++ ode/sandbox/singleshot/spec/models/activities.rb Mon Jun 2 21:53:34 2008
@@ -3,109 +3,123 @@
describe Activity do
include Specs::Tasks
- before :all do
- @person = person('person')
- @task = Task.create(default_task)
- end
-
describe 'person' do
- it 'should be stored' do
- Activity.create! :person=>@person, :action=>'created', :task=>@task
- Activity.last.person.should == @person
+ it 'should be part of activity' do
+ Task.create! default_task(:creator=>person('person'))
+ Activity.last.person.should == person('person')
end
it 'should be optional' do
- lambda { Activity.create! :action=>'created', :task=>@task }.should_not
raise_error
+ lambda { Task.create! default_task }.should_not raise_error
Activity.last.person.should be_nil
end
end
describe 'task' do
- it 'should be stored' do
- Activity.create! :person=>@person, :action=>'created', :task=>@task
- Activity.last.task.should == @task
+ it 'should be part of activity' do
+ Task.create! default_task
+ Activity.last.task.should == Task.last
end
it 'should be required' do
- Activity.create(:person=>@person, :action=>'created').should
have(1).error_on(:task)
+ Activity.create(:person=>person('person'), :action=>'created').should
have(1).error_on(:task)
end
end
describe 'action' do
- it 'should be stored' do
- Activity.create! :person=>@person, :action=>'created', :task=>@task
+ it 'should be part of activity' do
+ Task.create! default_task
Activity.last.action.should == 'created'
end
it 'should be required' do
- Activity.create(:person=>@person, :task=>@task).should
have(1).error_on(:action)
+ Task.create! default_task
+ Activity.create(:person=>person('person'), :task=>Task.last).should
have(1).error_on(:action)
end
end
it 'should have created_at timestamp' do
- Activity.create!(:person=>@person, :action=>'created',
:task=>@task).created_at.should be_close(Time.now, 2)
+ Task.create! default_task
+ Activity.last.created_at.should be_close(Time.now, 2)
end
it 'should allow creation but not modification' do
- Activity.create! :person=>@person, :action=>'created', :task=>@task
+ Task.create! default_task
lambda { Activity.last.update_attributes! :action=>'updated' }.should
raise_error(ActiveRecord::ReadOnlyRecord)
end
+ it 'should delete when destroying task' do
+ Task.create! default_task
+ lambda { Task.last.destroy }.should change(Activity, :count).to(0)
+ end
+
+ it 'should delete when destroying person' do
+ Task.create! default_task(:creator=>person('creator'))
+ lambda { person('creator').destroy }.should change(Activity, :count).to(0)
+ end
+
describe 'for_dates' do
it 'should return activities in date range' do
- # 0 days (today) already created for activity associated with task
creation.
- now = Activity.last.created_at
- activities = (1..3).each do |i|
- last = Activity.create! :person=>@person, :action=>'created',
:task=>@task
- Activity.update_all(['created_at=?', now - i.day], ['id=?', last.id])
+ now = Time.zone.now
+ activities = (0..3).each do |i|
+ Task.create! default_task(:creator=>person('creator'))
+ Activity.update_all ['created_at=?', now - i.day], ['id=?',
Activity.last.id]
end
- Activity.for_dates(now.to_date - 2.days..now.to_date).count == 1
- Activity.for_dates(now.to_date - 2.days..now.to_date).each do |activity|
- activity.created_at.should >= now - 2.days and activity.created_at <=
now.end_of_date
+ min, max = Activity.minimum(:created_at) + 1.day,
Activity.maximum(:created_at)
+ Activity.for_dates(min.to_date..max.to_date).count == 1
+ Activity.for_dates(min.to_date..max.to_date).each do |activity|
+ activity.created_at.should be_between(min, max)
end
end
end
describe 'for_stakeholder' do
- before { Activity.delete_all }
it 'should return activities for tasks associated with person' do
for role in Stakeholder::ALL_ROLES - ['excluded_owners']
- Task.create!
default_task.merge(Task::ACCESSOR_FROM_ROLE[role]=>@person)
+ Task.create!
default_task.merge(Task::ACCESSOR_FROM_ROLE[role]=>person('person'))
end
- Activity.for_stakeholder(@person).map(&:task).uniq.size.should ==
Stakeholder::ALL_ROLES.size - 1
+ Activity.for_stakeholder(person('person')).map(&:task).uniq.size.should
== Stakeholder::ALL_ROLES.size - 1
end
it 'should not return activities for excluded owners' do
- Task.create! default_task.merge(:excluded_owners=>@person)
- Activity.for_stakeholder(@person).should be_empty
+ Task.create! default_task.merge(:excluded_owners=>person('person'))
+ Activity.for_stakeholder(person('person')).should be_empty
end
it 'should not return activities for other stakeholders' do
Task.create! default_task.merge(:status=>'reserved',
:potential_owners=>person('other'))
- Activity.for_stakeholder(@person).should be_empty
+ Activity.for_stakeholder(person('person')).should be_empty
end
it 'should return activities for tasks with visible status' do
for status in Task::STATUSES - ['reserved']
- task_with_status status, :potential_owners=>@person
+ task_with_status status, :potential_owners=>person('person')
end
- Activity.for_stakeholder(@person).map(&:task).uniq.size.should ==
Task::STATUSES.size - 1
+ Activity.for_stakeholder(person('person')).map(&:task).uniq.size.should
== Task::STATUSES.size - 1
end
it 'should not return activities for reserved tasks' do
- Task.create! default_task.merge(:status=>'reserved',
:potential_owners=>@person)
- Activity.for_stakeholder(@person).should be_empty
+ Task.create! default_task.merge(:status=>'reserved',
:potential_owners=>person('person'))
+ Activity.for_stakeholder(person('person')).should be_empty
end
it 'should return all activities for a visible task' do
Task.create! default_task.merge(:creator=>person('creator'))
- Task.last.update_attributes(:owner=>person('owner'))
+ Task.last.update_attributes! :owner=>person('owner')
Activity.for_stakeholder(person('creator')).should ==
Activity.for_stakeholder(person('owner'))
Activity.for_stakeholder(person('creator')).map(&:action).should
include('created', 'is owner of')
Activity.for_stakeholder(person('owner')).map(&:person).should
include(person('creator'), person('owner'))
end
+ it 'should return activities from most recent to last' do
+ Task.create! default_task.merge(:creator=>person('creator'))
+ Activity.update_all ['created_at=?', Time.zone.now - 5.seconds]
+ Task.last.update_attributes! :owner=>person('owner')
+ activities = Activity.for_stakeholder(person('creator'))
+ activities.first.created_at.should > activities.last.created_at
+ end
+
end
end
Modified: ode/sandbox/singleshot/spec/models/stakeholder_spec.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/models/stakeholder_spec.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/models/stakeholder_spec.rb (original)
+++ ode/sandbox/singleshot/spec/models/stakeholder_spec.rb Mon Jun 2 21:53:34
2008
@@ -9,41 +9,74 @@
@task = Task.create(default_task)
end
- it 'should have person' do
- Stakeholder.create(:task=>@task, :role=>'admin').should
have(1).error_on(:person)
- end
+ describe 'person' do
+ it 'should be stored' do
+ Stakeholder.create! :task=>@task, :person=>@person, :role=>'admin'
+ Stakeholder.last.person.should == @person
+ end
- it 'should have task' do
- lambda { Stakeholder.create(:person=>@person, :role=>'admin') }.should
raise_error(ActiveRecord::StatementInvalid)
+ it 'should be required' do
+ Stakeholder.create(:task=>@task, :role=>'admin').should
have(1).error_on(:person)
+ end
end
- it 'should have role' do
- Stakeholder.create(:person=>@person, :task=>@task).should
have(1).error_on(:role)
- end
- it 'should have supported role' do
- Stakeholder::ALL_ROLES.each do |role|
- Stakeholder.create(:person=>@person, :task=>@task, :role=>role).should
have(:no).errors
+ describe 'task' do
+ it 'should be stored' do
+ Stakeholder.create! :task=>@task, :person=>@person, :role=>'admin'
+ Stakeholder.last.task.should == @task
+ end
+
+ it 'should be required' do
+ lambda { Stakeholder.create(:person=>@person, :role=>'admin') }.should
raise_error(ActiveRecord::StatementInvalid)
end
end
- it 'should not have unsupported role' do
- ['foo', 'bar'].each do |role|
- Stakeholder.create(:person=>@person, :task=>@task, :role=>role).should
have(1).error_on(:role)
+
+ describe 'role' do
+ it 'should be stored' do
+ Stakeholder.create! :task=>@task, :person=>@person, :role=>'admin'
+ Stakeholder.last.role.should == 'admin'
+ end
+
+ it 'should be required' do
+ Stakeholder.create(:person=>@person, :task=>@task).should
have(1).error_on(:role)
+ end
+
+ it 'should be any valid role names' do
+ Stakeholder::ALL_ROLES.each do |role|
+ Stakeholder.create(:person=>@person, :task=>@task, :role=>role).should
have(:no).errors
+ end
+ end
+
+ it 'should not allow unknown role names' do
+ ['foo', 'bar'].each do |role|
+ Stakeholder.create(:person=>@person, :task=>@task, :role=>role).should
have(1).error_on(:role)
+ end
end
end
+
it 'should be unique combination of task person and role' do
Stakeholder.create(:person=>@person, :task=>@task, :role=>'admin').should
have(:no).errors
Stakeholder.create(:person=>@person, :task=>@task,
:role=>'observer').should have(:no).errors
Stakeholder.create(:person=>@person, :task=>@task, :role=>'admin').should
have(1).errors_on(:role)
end
+
+ it 'should be deleted when task destroyed' do
+ Stakeholder.create! :person=>@person, :task=>@task, :role=>'admin'
+ lambda { @task.destroy }.should change(Stakeholder, :count).to(0)
+ end
+
+ it 'should be deleted when person destroyed' do
+ Stakeholder.create! :person=>@person, :task=>@task, :role=>'admin'
+ lambda { @person.destroy }.should change(Stakeholder, :count).to(0)
+ end
+
end
shared_examples_for 'singular role' do
- include Specs::Tasks
-
it 'should not be required' do
Task.create(default_task.except(@role)).should have(:no).errors
end
@@ -70,75 +103,7 @@
end
-describe Task, 'creator' do
- before { @role = :creator }
- it_should_behave_like 'singular role'
-
- it 'should not allow changing creator' do
- Task.create! default_task.merge(:creator=>person('creator'))
- Task.last.update_attributes :creator=>person('other')
- Task.last.creator.should == person('creator')
- end
-
- it 'should not allow setting creator on existing task' do
- Task.create! default_task
- Task.last.update_attributes :creator=>person('creator')
- Task.last.creator.should be_nil
- end
-
-end
-
-
-describe Task, 'owner' do
- before { @role = :owner }
- it_should_behave_like 'singular role'
-
- it 'should allow changing owner on existing task' do
- Task.create! default_task.merge(:owner=>person('owner'))
- Task.last.update_attributes! :owner=>person('other')
- Task.last.owner.should == person('other')
- end
-
- it 'should only store one owner association for task' do
- Task.create! default_task.merge(:owner=>person('owner'))
- Task.last.update_attributes! :owner=>person('other')
- Stakeholder.find(:all, :conditions=>{:task_id=>Task.last.id}).size.should
== 1
- end
-
- it 'should allow setting owner to nil' do
- Task.create! default_task.merge(:owner=>person('owner'))
- Task.last.update_attributes! :owner=>nil
- Task.last.owner.should be_nil
- end
-
- it 'should not allow owner if listed in excluded owners' do
- Task.create! default_task.merge(:excluded_owners=>person('excluded'))
- lambda { Task.last.update_attributes! :owner=>person('excluded') }.should
raise_error
- Task.last.owner.should be_nil
- end
-
- it 'should be potential owner if task created with one potential owner' do
- Task.create! default_task.merge(:potential_owners=>person('foo'))
- Task.last.owner.should == person('foo')
- end
-
- it 'should not be potential owner if task created with more than one' do
- Task.create! default_task.merge(:potential_owners=>people('foo', 'bar'))
- Task.last.owner.should be_nil
- end
-
- it 'should not be potential owner if task updated to have no owner' do
- Task.create! default_task.merge(:potential_owners=>person('foo'))
- Task.last.update_attributes! :owner=>person('bar')
- Task.last.update_attributes! :owner=>nil
- Task.last.owner.should be(nil)
- end
-end
-
-
shared_examples_for 'plural role' do
- include Specs::Tasks
-
before do
@people = person('foo'), person('bar'), person('baz')
end
@@ -208,31 +173,100 @@
end
-describe Task, 'potential_owners' do
- before { @role = :potential_owners }
- it_should_behave_like 'plural role'
-
- it 'should not allow excluded owners' do
- mixed_up = { :potential_owners=>[person('foo'), person('bar')],
- :excluded_owners=>[person('bar'), person('baz')] }
- Task.create(default_task.merge(mixed_up)).should
have(1).error_on(:potential_owners)
+describe Task do
+ include Specs::Tasks
+
+ describe 'creator' do
+ before { @role = :creator }
+ it_should_behave_like 'singular role'
+
+ it 'should not allow changing creator' do
+ Task.create! default_task.merge(:creator=>person('creator'))
+ Task.last.update_attributes :creator=>person('other')
+ Task.last.creator.should == person('creator')
+ end
+
+ it 'should not allow setting creator on existing task' do
+ Task.create! default_task
+ Task.last.update_attributes :creator=>person('creator')
+ Task.last.creator.should be_nil
+ end
end
-end
-describe Task, 'excluded_owners' do
- before { @role = :excluded_owners }
- it_should_behave_like 'plural role'
-end
+ describe 'owner' do
+ before { @role = :owner }
+ it_should_behave_like 'singular role'
+
+ it 'should allow changing owner on existing task' do
+ Task.create! default_task.merge(:owner=>person('owner'))
+ Task.last.update_attributes! :owner=>person('other')
+ Task.last.owner.should == person('other')
+ end
+ it 'should only store one owner association for task' do
+ Task.create! default_task.merge(:owner=>person('owner'))
+ Task.last.update_attributes! :owner=>person('other')
+ Stakeholder.find(:all,
:conditions=>{:task_id=>Task.last.id}).size.should == 1
+ end
-describe Task, 'observers' do
- before { @role = :observers }
- it_should_behave_like 'plural role'
-end
+ it 'should allow setting owner to nil' do
+ Task.create! default_task.merge(:owner=>person('owner'))
+ Task.last.update_attributes! :owner=>nil
+ Task.last.owner.should be_nil
+ end
+ it 'should not allow owner if listed in excluded owners' do
+ Task.create! default_task.merge(:excluded_owners=>person('excluded'))
+ lambda { Task.last.update_attributes! :owner=>person('excluded')
}.should raise_error
+ Task.last.owner.should be_nil
+ end
-describe Task, 'admins' do
- before { @role = :admins }
- it_should_behave_like 'plural role'
+ it 'should be potential owner if task created with one potential owner' do
+ Task.create! default_task.merge(:potential_owners=>person('foo'))
+ Task.last.owner.should == person('foo')
+ end
+
+ it 'should not be potential owner if task created with more than one' do
+ Task.create! default_task.merge(:potential_owners=>people('foo', 'bar'))
+ Task.last.owner.should be_nil
+ end
+
+ it 'should not be potential owner if task updated to have no owner' do
+ Task.create! default_task.merge(:potential_owners=>person('foo'))
+ Task.last.update_attributes! :owner=>person('bar')
+ Task.last.update_attributes! :owner=>nil
+ Task.last.owner.should be(nil)
+ end
+ end
+
+
+ describe 'potential_owners' do
+ before { @role = :potential_owners }
+ it_should_behave_like 'plural role'
+
+ it 'should not allow excluded owners' do
+ mixed_up = { :potential_owners=>[person('foo'), person('bar')],
+ :excluded_owners=>[person('bar'), person('baz')] }
+ Task.create(default_task.merge(mixed_up)).should
have(1).error_on(:potential_owners)
+ end
+ end
+
+
+ describe 'excluded_owners' do
+ before { @role = :excluded_owners }
+ it_should_behave_like 'plural role'
+ end
+
+
+ describe 'observers' do
+ before { @role = :observers }
+ it_should_behave_like 'plural role'
+ end
+
+
+ describe 'admins' do
+ before { @role = :admins }
+ it_should_behave_like 'plural role'
+ end
end
Modified: ode/sandbox/singleshot/spec/models/task_spec.rb
URL:
http://svn.apache.org/viewvc/ode/sandbox/singleshot/spec/models/task_spec.rb?rev=662651&r1=662650&r2=662651&view=diff
==============================================================================
--- ode/sandbox/singleshot/spec/models/task_spec.rb (original)
+++ ode/sandbox/singleshot/spec/models/task_spec.rb Mon Jun 2 21:53:34 2008
@@ -80,12 +80,17 @@
def task_with_status(status, attributes = nil)
attributes ||= {}
+ attributes = attributes.reverse_merge(:admins=>person('admin'))
task = case status
when 'active'
- Task.create!(default_task.merge(attributes).merge(:status=>status,
:owner=>person('owner')))
- when 'completed'
- active =
Task.create!(default_task.merge(attributes).merge(:status=>'active',
:owner=>person('owner')))
- active.update_attributes :status=>'completed'
+ Task.create!(default_task.merge(attributes).merge(:status=>'active',
:owner=>person('owner')))
+ when 'completed' # Start as active, modified by owner.
+ active = task_with_status('active', attributes)
+ active.modify_by(person('owner')).update_attributes!
:status=>'completed'
+ active
+ when 'cancelled', 'suspended' # Start as active, modified by admin.
+ active = task_with_status('active', attributes)
+ active.modify_by(person('admin')).update_attributes! :status=>status
active
else
Task.create!(default_task.merge(attributes).merge(:status=>status))
@@ -93,7 +98,7 @@
def task.transition_to(status, attributes = nil)
attributes ||= {}
- update_attributes attributes.merge(:status=>status)
+ modify_by(attributes.delete(:modified_by) ||
Person.identify('admin')).update_attributes attributes.merge(:status=>status)
self
end
def task.can_transition?(status, attributes = nil)
@@ -146,8 +151,8 @@
lambda { task.update_attributes :owner=>nil }.should change(task,
:status).to('ready')
end
- it 'should accept suspended as initial value' do
- Task.create!(default_task.merge(:status=>'suspended')).status.should ==
'suspended'
+ it 'should not accept suspended as initial value' do
+ Task.create(default_task.merge(:status=>'suspended')).should
have(1).error_on(:status)
end
it 'should transition from ready to suspended' do
@@ -170,7 +175,7 @@
it 'should only transition to completed from active' do
for status in Task::STATUSES - ['completed']
- task_with_status(status).can_transition?('completed').should ==
(status =='active')
+ task_with_status(status).can_transition?('completed',
:modified_by=>person('owner')).should == (status =='active')
end
end
@@ -185,7 +190,7 @@
end
it 'should transition to cancelled from any other status but completed' do
- for status in Task::STATUSES - ['cancelled']
+ for status in Task::STATUSES - ['reserved', 'cancelled']
task_with_status(status).can_transition?('cancelled').should ==
(status !='completed')
end
end