Merge branch 'master' of git://github.com/bsag/tracks

This commit is contained in:
Reinier Balt 2008-06-23 20:59:31 +02:00
commit c58186451f
8 changed files with 332 additions and 39 deletions

View file

@ -1,7 +1,22 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
# one:
# column: value
#
# two:
# column: value
agenda:
id: 2
name: agenda
position: 2
hide: false
user: admin_user
call:
id: 3
name: call
position: 3
hide: true
user: admin_user
email:
id: 4
name: email
position: 4
hide: false
user: admin_user

34
spec/fixtures/preferences.yml vendored Normal file
View file

@ -0,0 +1,34 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
admin_user_prefs:
user: admin_user
staleness_starts: 7
date_format: "%d/%m/%Y"
title_date_format: "%A, %d %B %Y"
show_number_completed: 5
show_completed_projects_in_sidebar: true
show_hidden_contexts_in_sidebar: true
show_hidden_projects_in_sidebar: true
admin_email: butshesagirl@rousette.org.uk
week_starts: 1
due_style: 0
refresh: 0
time_zone: "London"
verbose_action_descriptors: true
show_project_on_todo_done: false
other_user_prefs:
user: jane
staleness_starts: 7
date_format: "%d/%m/%Y"
title_date_format: "%A, %d %B %Y"
show_number_completed: 5
show_completed_projects_in_sidebar: true
show_hidden_contexts_in_sidebar: true
show_hidden_projects_in_sidebar: true
admin_email: butshesagirl@rousette.org.uk
week_starts: 1
due_style: 0
refresh: 0
time_zone: "London"
verbose_action_descriptors: false
show_project_on_todo_done: true

57
spec/fixtures/todos.yml vendored Normal file
View file

@ -0,0 +1,57 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
<%
def today
Time.zone.now.beginning_of_day.to_s(:db)
end
def next_week
1.week.from_now.beginning_of_day.to_s(:db)
end
def last_week
1.week.ago.beginning_of_day.to_s(:db)
end
def two_weeks_ago
2.weeks.ago.beginning_of_day.to_s(:db)
end
def two_weeks_hence
2.weeks.from_now.beginning_of_day.to_s(:db)
end
%>
billgates:
id: 2
context_id: 2
project_id: 2
description: Call Bill Gates to find out how much he makes per day
notes: ~
state: active
due: <%= two_weeks_hence %>
completed_at: ~
user: admin_user
dinoexterm:
id: 3
context_id: 2
project_id: 3
description: Call dinosaur exterminator
notes: Ask him if I need to hire a skip for the corpses.
state: active
due: <%= two_weeks_hence %>
completed_at: ~
user: admin_user
buymilk:
id: 4
context_id: 2
project_id: ~
description: Buy milk
notes: ~
state: completed
due: ~
completed_at: <%= today %>
user: admin_user

27
spec/fixtures/users.yml vendored Normal file
View file

@ -0,0 +1,27 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
admin_user:
login: admin
crypted_password: <%= Digest::SHA1.hexdigest("#{Tracks::Config.salt}--abracadabra--") %>
token: <%= Digest::SHA1.hexdigest("adminSat Feb 25 17:14:00 GMT 20060.236961325863376") %>
is_admin: true
first_name: Admin
last_name: Schmadmin
auth_type: database
other_user:
login: jane
crypted_password: <%= Digest::SHA1.hexdigest("#{Tracks::Config.salt}--sesame--") %>
token: <%= Digest::SHA1.hexdigest("janeSun Feb 19 14:42:45 GMT 20060.408173979260027") %>
is_admin: false
first_name: Jane
last_name: Doe
auth_type: database
ldap_user:
login: john
crypted_password: test
token: <%= Digest::SHA1.hexdigest("johnSun Feb 19 14:42:45 GMT 20060.408173979260027") %>
is_admin: false
first_name: John
last_name: Deere
auth_type: ldap

View file

@ -13,56 +13,139 @@ module ContextSpecHelper
end
describe Context do
describe "Context validations" do
include ContextSpecHelper
before(:each) do
@context = Context.new
end
it "should be valid" do
@context.name = "FooBar"
@context.should be_valid
before(:each) do
@context = Context.new
end
it "should be valid" do
@context.attributes = valid_context_attributes
@context.should be_valid
@context.save
Context.should have(4).records # 3 in fixtures 1 set up here
end
it "should have two errors with a missing name" do
@context.attributes = valid_context_attributes.except(:name)
@context.should_not be_valid
@context.should have(2).error_on(:name)
@context.errors.on(:name)[0].should eql("context must have a name")
@context.errors.on(:name)[1].should eql("context name must be less than 256 characters")
end
it "should have one error with a name of more than 255 characters" do
@context.name = "z" * 256
@context.should_not be_valid
@context.should have(1).error_on(:name)
@context.errors.on(:name).should eql("context name must be less than 256 characters")
end
it "should have one error with name containing comma" do
@context.name = "Foo,Bar"
@context.should_not be_valid
@context.should have(1).error_on(:name)
@context.errors.on(:name).should eql("cannot contain the comma (',') character")
end
it "should have one error if name already exists for user" do
@existing_context = Context.new
@existing_context.attributes = valid_context_attributes
@existing_context.save
@context.attributes = valid_context_attributes
@context.should_not be_valid
@context.should have(1).error_on(:name)
@context.errors.on(:name).should eql("already exists")
end
it "should have one record in Context model class" do
@context.name = "FooBar"
@context.save
Context.should have(1).record
Context.should have(4).records # 3 in fixture, one set up here
end
end
describe "Context model" do
fixtures :users, :todos, :contexts, :preferences
include ContextSpecHelper
it "should show hidden" do
contexts(:call).should be_hide # :hide should be true
end
it "should be hidden" do
@context.attributes = valid_context_attributes
@context.should be_hide # :hide should be true
it "should be produce correct .summary text for hidden context" do
contexts(:call).summary(1).should eql("<p>1. Context is Hidden.</p>")
end
it "should show not hidden" do
contexts(:call).hide = false
contexts(:call).should_not be_hide # :hide should be true
end
it "should produce correct .summary text for active context" do
contexts(:call).hide = false
contexts(:call).summary(1).should eql("<p>1. Context is Active.</p>")
end
it "should return .title which matches name" do
contexts(:agenda).title.should eql(contexts(:agenda).name)
end
it "should be produce correct summary text for hidden context" do
@context.attributes = valid_context_attributes
@context.summary(1).should eql("<p>1. Context is Hidden.</p>")
it "should .find_by_namepart with exact match" do
@found = Context.find_by_namepart('agenda')
@found.should_not eql(nil)
@found.id.should eql(contexts(:agenda).id)
end
it "should be active" do
@context.attributes = valid_context_attributes
@context.hide = false
@context.save
@context.should_not be_hide # :hide should be true
it "should .find_by_namepart with partial match" do
@found = Context.find_by_namepart('ag')
@found.should_not eql(nil)
@found.id.should eql(contexts(:agenda).id)
end
it "should produce correct summary text for active context" do
@context.attributes = valid_context_attributes
@context.hide = false
@context.save
@context.summary(1).should eql("<p>1. Context is Active.</p>")
it "should return id with .to_param" do
Context.find(2).to_param.should eql("2")
end
end
it "should return feed options" do
opts = Context.feed_options(users(:admin_user))
opts[:title].should eql("Tracks Contexts")
opts[:description].should eql("Lists all the contexts for Admin Schmadmin")
end
it "should create null Context with .null_object" do
@empty = Context.null_object
@empty.should be_an_instance_of(NullContext)
@empty.id.should eql(nil)
@empty.name.should eql('')
end
it "should delete todos within context when context deleted" do
contexts(:agenda).todos.count.should eql(3)
agenda_todo_ids = contexts(:agenda).todos.collect{|t| t.id }
contexts(:agenda).destroy
agenda_todo_ids.each do |todo_id|
Todo.find(:all).should_not include(todo_id)
end
end
it "should return correct number of done todos" do
contexts(:agenda).done_todos.size.should eql(1)
t = contexts(:agenda).not_done_todos[0]
t.complete!
t.save!
Context.find(contexts(:agenda)).done_todos.size.should eql(2)
end
it "should return correct number of not done todos" do
contexts(:agenda).not_done_todos.size.should eql(2)
t = contexts(:agenda).not_done_todos[0]
t.complete!
t.save!
Context.find(contexts(:agenda)).not_done_todos.size.should eql(1)
end
end

View file

@ -0,0 +1,15 @@
Story: Change context name
As a Tracks user
I want to change the name of a context
So that it can best reflect my daily life
Scenario: In place edit of context name
Given a logged in user Luis
And Luis has a context Errands
When Luis visits the Errands context page
And he edits the Errands context name in place to be OutAndAbout
Then he should see the context name is OutAndAbout
When Luis visits the context listing page
Then he should see that a context named Errands is not present
And he should see that a context named OutAndAbout is present

View file

@ -0,0 +1,34 @@
steps_for :context_detail do
include_steps_for :users
Given "Luis has a context Errands" do
@errands = @luis.contexts.create!(:name => 'Errands')
end
When "Luis visits the Errands context page" do
visits "/contexts/#{@errands.to_param}"
end
When "he edits the Errands context name in place to be OutAndAbout" do
selenium.click 'context_name_in_place_editor'
wait_for_ajax_and_effects
selenium.type "css=#context_name_in_place_editor-inplaceeditor input.editor_field", "OutAndAbout"
clicks_button "ok", :wait => :ajax
end
When "Luis visits the context listing page" do
visits "/contexts"
end
Then "he should see the context name is OutAndAbout" do
should_see 'OutAndAbout'
end
Then "he should see that a context named Errands is not present" do
should_not_see 'Errands'
end
Then "he should see that a context named OutAndAbout is present" do
should_see 'OutAndAbout'
end
end

View file

@ -10,8 +10,13 @@ module Webrat
@selenium.open(url)
end
def fills_in(label_text, options)
@selenium.type("webrat=#{label_text}", "#{options[:with]}")
def fills_in(field_identifier, options)
locator = if field_identifier == :current
"css=:focus"
else
"webrat=#{Regexp.escape(field_identifier)}"
end
@selenium.type(locator, "#{options[:with]}")
end
def response_body
@ -25,11 +30,16 @@ module Webrat
wait_for_result(options[:wait])
end
def clicks_link(link_text, options = {})
def clicks_link(link_text, options = {})
@selenium.click("webratlink=#{link_text}")
wait_for_result(options[:wait])
end
def clicks_link_within(selector, link_text, options = {})
@selenium.click("webratlinkwithin=#{selector}|#{link_text}")
wait_for_result(options[:wait])
end
def wait_for_result(wait_type)
if wait_type == :ajax
wait_for_ajax
@ -55,8 +65,8 @@ module Webrat
def wait_for_ajax_and_effects
wait_for_ajax
wait_for_effects
end
end
def selects(option_text, options = {})
id_or_name_or_label = options[:from]
@ -130,6 +140,24 @@ module Webrat
return candidateLinks.first();
JS
@selenium.add_location_strategy('webratlinkwithin', <<-JS)
var locatorParts = locator.split('|');
var cssAncestor = locatorParts[0];
var linkText = locatorParts[1];
var matchingElements = cssQuery(cssAncestor, inDocument);
var candidateLinks = matchingElements.collect(function(ancestor){
var links = ancestor.getElementsByTagName('a');
return $A(links).select(function(candidateLink) {
return PatternMatcher.matches(linkText, getText(candidateLink));
});
}).flatten().compact();
if (candidateLinks.length == 0) {
return null;
}
candidateLinks = candidateLinks.sortBy(function(s) { return s.length * -1; }); //reverse length sort
return candidateLinks.first();
JS
@selenium.add_location_strategy('webratselectwithoption', <<-JS)
var optionElements = inDocument.getElementsByTagName('option');
var locatedOption = $A(optionElements).find(function(candidate){