Files

495 lines
18 KiB
Ruby

require File.dirname(__FILE__) + '/../spec_helper'
describe Budget do
it 'should not be an ActiveRecord class' do
Budget.should_not be_a_kind_of(ActiveRecord::Base)
end
end
describe Budget, '.new' do
it 'should error without a project id' do
lambda { @budget = Budget.new }.should raise_error
end
it 'should set @project to the initilized project id' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.project.should eql(@project)
end
end
describe Budget,'.deliverables' do
it 'should return an array of the projects deliverables' do
@project = mock_model(Project)
@deliverable1 = mock_model(Deliverable, :project_id => @project)
@deliverable2 = mock_model(Deliverable, :project_id => @project)
@other_project_deliverable = mock_model(Deliverable, :project_id => 1)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable2, @deliverable1])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.deliverables.should eql([@deliverable2, @deliverable1])
end
it 'should return an empty array if the project has no deliverables' do
@project = mock_model(Project)
@other_project_deliverable = mock_model(Deliverable, :project_id => 1)
Deliverable.stub!(:find_all_by_project_id).and_return([])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.deliverables.should eql([])
end
end
describe Budget, '.next_due_date' do
it 'should get the eariest due date from the projects Deliverables' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => @tomorrow)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.next_due_date.should eql(@tomorrow)
end
it 'should return nil if there are no deliverables' do
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.next_due_date.should be_nil
end
it 'should not count dates that are nil' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => nil)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.next_due_date.should eql(@next_week)
end
it 'should not count dates that are empty' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => '')
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.next_due_date.should eql(@next_week)
end
end
describe Budget, '.final_due_date' do
it 'should get the latest due date from the projects Deliverables' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => @tomorrow)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.final_due_date.should eql(@next_week)
end
it 'should return nil if there are no deliverables' do
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.final_due_date.should be_nil
end
it 'should not count dates that are nil' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => nil)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.final_due_date.should eql(@next_week)
end
it 'should not count dates that are empty' do
@tomorrow = Date.today + 1.days
@next_week = Date.today + 7.days
@deliverable1 = mock_model(Deliverable, :project_id => @project, :due => @next_week)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :due => '')
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.final_due_date.should eql(@next_week)
end
end
describe Budget, '.progress' do
it 'should be the weighted average by the deliverable progress and budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :budget => 2000.00, :progress => 50)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :budget => 3000.00, :progress => 75)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.progress.should eql(65)
end
it 'should return 100 if there are no deliverables' do
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.progress.should eql(100)
end
it 'should return 100 if there is no budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :budget => 0.00, :progress => 50)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :budget => 0.00, :progress => 75)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.progress.should eql(100)
end
end
describe Budget,'.budget' do
it 'should be the sum of all the deliverables budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :budget => 2000.00)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :budget => 3000.00)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.budget.should eql(5000.0)
end
it 'should be 0 if there are no deliverables' do
Deliverable.stub!(:find_all_by_project_id).and_return([])
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.budget.should eql(0.0)
end
it 'should skip deliverables with a nil budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :budget => 2000.00)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :budget => nil)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.budget.should eql(2000.0)
end
end
describe Budget,'.labor_budget' do
it 'should be the sum of all the deliverables labor_budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :labor_budget => 2000.00)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :labor_budget => 3000.00)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.labor_budget.should eql(5000.0)
end
it 'should be 0 if there are no deliverables' do
Deliverable.stub!(:find_all_by_project_id).and_return([])
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.labor_budget.should eql(0.0)
end
it 'should skip deliverables with a nil budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :labor_budget => 2000.00)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :labor_budget => nil)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.labor_budget.should eql(2000.0)
end
end
describe Budget,'.budget_ratio' do
it 'should be the whole number of the budget spent (out of 100)' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:budget).and_return(5000.00)
@budget.should_receive(:spent).and_return(2000.00)
@budget.budget_ratio.should eql(40)
end
it 'should return progress if the budget is < 0' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:budget).and_return(0.0)
@budget.should_receive(:progress).and_return(50)
@budget.budget_ratio.should eql(50)
end
end
describe Budget, '.score' do
it 'should be calculated by the progress and budget for the deliverables' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:progress).and_return(65)
@budget.should_receive(:budget_ratio).and_return(40)
@budget.score.should eql(25)
end
end
describe Budget, '.left' do
it 'should be calculated by the total budget and total spent of the deliverables' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:budget).and_return(6000.0)
@budget.should_receive(:spent).and_return(4500.0)
@budget.left.should eql(1500.0)
end
end
describe Budget, '.labor_budget_left' do
it 'should be calculated by the labor budget and total spent of the deliverables' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:labor_budget).and_return(6000.0)
@budget.should_receive(:spent).and_return(4500.0)
@budget.labor_budget_left.should eql(1500.0)
end
end
describe Budget, '.overruns' do
it 'should be 0 if there is still unspent budget' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:left).and_return(1500.0)
@budget.overruns.should eql(0)
end
it 'should be calculated by the total budget and total spent of the deliverables' do
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.should_receive(:left).twice.and_return(-1500.0)
@budget.overruns.should eql(1500.0)
end
end
describe Budget, '.spent' do
it 'should be calculated by the total spent of the deliverables' do
@deliverable1 = mock_model(HourlyDeliverable, :project_id => @project, :spent => 1000.00)
@deliverable2 = mock_model(HourlyDeliverable, :project_id => @project, :spent => 500.00)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.spent.should eql(1500.0)
end
it 'should be 0 if there are no deliverables' do
Deliverable.stub!(:find_all_by_project_id).and_return([])
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.spent.should eql(0.0)
end
it 'should skip deliverables with a nil budget' do
@deliverable1 = mock_model(Deliverable, :project_id => @project, :spent => 2000.00)
@deliverable2 = mock_model(Deliverable, :project_id => @project, :spent => nil)
@project = mock_model(Project)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.spent.should eql(2000.0)
end
end
describe Budget, '.profit' do
it 'should be calculated by the total profit of the deliverables' do
@project = mock_model(Project)
@deliverable1 = mock_model(HourlyDeliverable, :project_id => @project, :profit => 2000.00, :profit_percent => nil)
@deliverable2 = mock_model(HourlyDeliverable, :project_id => @project, :profit => 3000.00, :profit_percent => nil)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.profit.should eql(5000.0)
end
it 'should be calculated by the total profit of the deliverables with % amounts' do
@project = mock_model(Project)
@deliverable1 = mock_model(HourlyDeliverable, :project_id => @project, :profit_percent => 10, :budget => 2000.0, :profit => 200.0)
@deliverable2 = mock_model(HourlyDeliverable, :project_id => @project, :profit_percent => 10, :budget => 1000.0, :profit => 100.0)
Deliverable.stub!(:find_all_by_project_id).and_return([@deliverable1, @deliverable2])
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.profit.should eql(300.0)
end
it 'should be 0 if there are no deliverables' do
Deliverable.stub!(:find_all_by_project_id).and_return([])
@project = mock_model(Project)
Project.stub!(:find).with(@project.id).and_return(@project)
@budget = Budget.new(@project.id)
@budget.profit.should eql(0.0)
end
end
describe Budget, 'amount_missing_on_issues' do
it 'should caclulate the cost of the time logged to the project itself' do
project = mock_model(Project)
Project.stub!(:find).with(project.id).and_return(project)
budget = Budget.new(project.id)
time_entry_one = mock_model(TimeEntry, :cost => 300.0)
time_entry_two = mock_model(TimeEntry, :cost => 500.0)
TimeEntry.should_receive(:find_all_by_project_id_and_issue_id).with(project.id, nil).and_return([time_entry_one, time_entry_two])
budget.amount_missing_on_issues.should eql(time_entry_one.cost + time_entry_two.cost)
end
end
describe Budget, 'amount_missing_on_deliverables' do
before(:each) do
@project = mock_model(Project)
@project.stub!(:issues).and_return(Issue)
Project.stub!(:find).with(@project.id).and_return(@project)
@deliverable = mock_model(Deliverable, :project => @project)
@budget = Budget.new(@project.id)
@budget.stub!(:deliverables).and_return([@deliverable])
end
it 'should caclulate the cost of the time logged to the issues that are not on a Deliverable' do
time_entry_one = mock_model(TimeEntry, :cost => 300.0)
time_entry_two = mock_model(TimeEntry, :cost => 500.0)
issue_one = mock_model(Issue, :project => @project, :time_entries => [time_entry_one])
issue_two = mock_model(Issue, :project => @project, :time_entries => [time_entry_two])
issues = [issue_one, issue_two]
Issue.should_receive(:find).with(:all).and_return(issues)
Issue.should_receive(:find).with(:all, { :conditions => ["deliverable_id IN (?)", [@deliverable.id]]}).and_return([])
@budget.amount_missing_on_deliverables.should eql(time_entry_one.cost + time_entry_two.cost)
end
it 'should return 0 if there are no issues on the project' do
Issue.should_receive(:find).with(:all).and_return([])
@budget.amount_missing_on_deliverables.should eql(0)
end
it 'should return 0 if all issues are on a Deliverable' do
issue_one = mock_model(Issue, :project => @project)
issue_two = mock_model(Issue, :project => @project)
issues = [issue_one, issue_two]
Issue.should_receive(:find).with(:all).and_return(issues)
Issue.should_receive(:find).with(:all, { :conditions => ["deliverable_id IN (?)", [@deliverable.id]]}).and_return(issues)
@budget.amount_missing_on_deliverables.should eql(0)
end
end