Commit f24ef96b5e31111336817652222605c0b862debb

Authored by Yann Lugrin
Committed by Antonio Terceiro
1 parent 1f75d111

ActionItem910: Integration of feature "invite a friend"

app/controllers/my_profile/friends_controller.rb
  1 +require "contacts"
  2 +
1 class FriendsController < MyProfileController 3 class FriendsController < MyProfileController
2 4
3 protect 'manage_friends', :profile 5 protect 'manage_friends', :profile
@@ -26,4 +28,69 @@ class FriendsController &lt; MyProfileController @@ -26,4 +28,69 @@ class FriendsController &lt; MyProfileController
26 end 28 end
27 end 29 end
28 30
  31 + def invite
  32 +
  33 + if request.post? && params[:import]
  34 + begin
  35 + case params[:import_from]
  36 + when "gmail"
  37 + @friends = Contacts::Gmail.new(params[:login], params[:password]).contacts
  38 + when "yahoo"
  39 + @friends = Contacts::Yahoo.new(params[:login], params[:password]).contacts
  40 + when "hotmail"
  41 + @friends = Contacts::Hotmail.new(params[:login], params[:password]).contacts
  42 + else
  43 + @friends = []
  44 + end
  45 + @friends.map! {|friend| friend + ["#{friend[0]} <#{friend[1]}>"]}
  46 + rescue
  47 + @login = params[:login]
  48 + flash.now[:notice] = __('There was an error while looking for your contact list. Did you enter correct login and password?')
  49 + end
  50 +
  51 + elsif request.post? && params[:confirmation]
  52 + friends_to_invite = []
  53 + friends_to_invite += (params[:manual_import_addresses].is_a?(Array) ? params[:manual_import_addresses] : params[:manual_import_addresses].split("\r\n")) if params[:manual_import_addresses]
  54 + friends_to_invite += (params[:webmail_import_addresses].is_a?(Array) ? params[:webmail_import_addresses] : params[:webmail_import_addresses].split("\r\n")) if params[:webmail_import_addresses]
  55 +
  56 + if !params[:message].match(/<url>/)
  57 + flash.now[:notice] = __('&lt;url&gt; is needed in invitation message.')
  58 + elsif !friends_to_invite.empty?
  59 + friends_to_invite.each do |friend_to_invite|
  60 + next if friend_to_invite == __("Firstname Lastname <friend@email.com>")
  61 +
  62 + friend_to_invite.strip!
  63 + if match = friend_to_invite.match(/(.*)<(.*)>/) and match[2].match(Noosfero::Constants::EMAIL_FORMAT)
  64 + friend_name = match[1].strip
  65 + friend_email = match[2]
  66 + elsif match = friend_to_invite.strip.match(Noosfero::Constants::EMAIL_FORMAT)
  67 + friend_name = ""
  68 + friend_email = match[0]
  69 + else
  70 + next
  71 + end
  72 +
  73 + friend = User.find_by_email(friend_email)
  74 + if !friend.nil? && friend.person.person?
  75 + InviteFriend.create(:person => profile, :friend => friend.person)
  76 + else
  77 + InviteFriend.create(:person => profile, :friend_name => friend_name, :friend_email => friend_email, :message => params[:message])
  78 + end
  79 + end
  80 +
  81 + flash[:notice] = __('Your invitations have been sent.')
  82 + redirect_to :action => 'index'
  83 + else
  84 + flash.now[:notice] = __('Please enter a valid email address.')
  85 + end
  86 +
  87 + @friends = params[:webmail_friends] ? params[:webmail_friends].map {|e| YAML.load(e)} : []
  88 + @manual_import_addresses = params[:manual_import_addresses] || ""
  89 + @webmail_import_addresses = params[:webmail_import_addresses] || []
  90 + end
  91 +
  92 + @import_from = params[:import_from] || "manual"
  93 + @message = params[:message] || environment.message_for_friend_invitation
  94 + end
  95 +
29 end 96 end
app/controllers/public/account_controller.rb
@@ -42,6 +42,7 @@ class AccountController &lt; ApplicationController @@ -42,6 +42,7 @@ class AccountController &lt; ApplicationController
42 42
43 # action to register an user to the application 43 # action to register an user to the application
44 def signup 44 def signup
  45 + @invitation_code = params[:invitation_code]
45 begin 46 begin
46 @user = User.new(params[:user]) 47 @user = User.new(params[:user])
47 @user.terms_of_use = environment.terms_of_use 48 @user.terms_of_use = environment.terms_of_use
@@ -54,6 +55,11 @@ class AccountController &lt; ApplicationController @@ -54,6 +55,11 @@ class AccountController &lt; ApplicationController
54 self.current_user = @user 55 self.current_user = @user
55 owner_role = Role.find_by_name('owner') 56 owner_role = Role.find_by_name('owner')
56 @user.person.affiliate(@user.person, [owner_role]) if owner_role 57 @user.person.affiliate(@user.person, [owner_role]) if owner_role
  58 + invitation = Task.find_by_code(@invitation_code)
  59 + if invitation
  60 + invitation.update_attributes!({:friend => @user.person})
  61 + invitation.finish
  62 + end
57 go_to_user_initial_page if redirect? 63 go_to_user_initial_page if redirect?
58 flash[:notice] = _("Thanks for signing up!") 64 flash[:notice] = _("Thanks for signing up!")
59 end 65 end
app/models/environment.rb
@@ -280,6 +280,21 @@ class Environment &lt; ActiveRecord::Base @@ -280,6 +280,21 @@ class Environment &lt; ActiveRecord::Base
280 signup_fields 280 signup_fields
281 end 281 end
282 282
  283 + # Default message send to friend when user use invite a friend feature
  284 + def message_for_friend_invitation
  285 + self.settings['message_for_friend_invitation'] || [
  286 + _('Hello <friend>,'),
  287 + _('<user> is inviting you to participate on %{environment}.') % { :environment => self.name },
  288 + _('To accept the invitation, please follow this link:') + "\n" + '<url>',
  289 + "--\n#{self.name}",
  290 + ''
  291 + ].join("\n\n")
  292 + end
  293 +
  294 + def message_for_friend_invitation=(value)
  295 + self.settings['message_for_friend_invitation'] = value
  296 + end
  297 +
283 def custom_enterprise_fields 298 def custom_enterprise_fields
284 self.settings[:custom_enterprise_fields].nil? ? {} : self.settings[:custom_enterprise_fields] 299 self.settings[:custom_enterprise_fields].nil? ? {} : self.settings[:custom_enterprise_fields]
285 end 300 end
app/models/invite_friend.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +class InviteFriend < Task
  2 +
  3 + acts_as_having_settings :group_for_person, :group_for_friend, :message, :friend_name, :friend_email, :field => :data
  4 +
  5 + validates_presence_of :requestor_id
  6 +
  7 + validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank? }
  8 +
  9 + validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank? }
  10 + validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank? }
  11 +
  12 + validates_presence_of :message, :if => Proc.new{|invite| invite.target_id.blank? }
  13 + validates_format_of :message, :with => /<url>/, :if => Proc.new{|invite| invite.target_id.blank? }
  14 +
  15 + alias :person :requestor
  16 + alias :person= :requestor=
  17 +
  18 + alias :friend :target
  19 + alias :friend= :target=
  20 +
  21 + after_create do |task|
  22 + TaskMailer.deliver_invitation_notification(task) unless task.friend
  23 + end
  24 +
  25 + def perform
  26 + requestor.add_friend(target, group_for_person)
  27 + target.add_friend(requestor, group_for_friend)
  28 + end
  29 +
  30 + # Returns <tt>false</tt>. Adding friends by itself does not trigger e-mail
  31 + # sending.
  32 + def sends_email?
  33 + false
  34 + end
  35 +
  36 + def description
  37 + _('%s wants to be your friend') % [requestor.name]
  38 + end
  39 +
  40 + def permission
  41 + :manage_friends
  42 + end
  43 +end
app/models/task_mailer.rb
@@ -24,6 +24,19 @@ class TaskMailer &lt; ActionMailer::Base @@ -24,6 +24,19 @@ class TaskMailer &lt; ActionMailer::Base
24 :tasks_url => url_for(task.target.url.merge(:controller => 'tasks', :action => 'index')) 24 :tasks_url => url_for(task.target.url.merge(:controller => 'tasks', :action => 'index'))
25 end 25 end
26 26
  27 + def invitation_notification(task)
  28 + msg = task.message
  29 + msg = msg.gsub(/<user>/, task.requestor.name)
  30 + msg = msg.gsub(/<friend>/, task.friend_name)
  31 + msg = msg.gsub(/<url>/, url_for(:host => task.requestor.environment.default_hostname, :controller => 'account', :action => 'signup', :invitation_code => task.code))
  32 +
  33 + recipients task.friend_email
  34 +
  35 + from self.class.generate_from(task)
  36 + subject '[%s] %s' % [ task.requestor.environment.name, task.description ]
  37 + body :message => msg
  38 + end
  39 +
27 protected 40 protected
28 41
29 def extract_message(message) 42 def extract_message(message)
app/views/account/_signup_form.rhtml
@@ -14,6 +14,8 @@ in this environment.&#39;) % [environment.name, __(&#39;communities&#39;), __(&#39;enterprises&#39;) @@ -14,6 +14,8 @@ in this environment.&#39;) % [environment.name, __(&#39;communities&#39;), __(&#39;enterprises&#39;)
14 :html => { :help=>_('Fill all this fields to join in this environment. <p/> If you forgot your password, do not create a new account, click on the "<b>I forgot my password!</b>" link. ;-)'), :id => 'profile-data' 14 :html => { :help=>_('Fill all this fields to join in this environment. <p/> If you forgot your password, do not create a new account, click on the "<b>I forgot my password!</b>" link. ;-)'), :id => 'profile-data'
15 } do |f| -%> 15 } do |f| -%>
16 16
  17 +<%= hidden_field_tag :invitation_code, @invitation_code %>
  18 +
17 <%= required_fields_message %> 19 <%= required_fields_message %>
18 20
19 <%= required f.text_field(:login, 21 <%= required f.text_field(:login,
app/views/friends/index.rhtml
@@ -37,6 +37,7 @@ @@ -37,6 +37,7 @@
37 <% button_bar do %> 37 <% button_bar do %>
38 <%= button(:back, _('Go back'), :controller => 'profile_editor') %> 38 <%= button(:back, _('Go back'), :controller => 'profile_editor') %>
39 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %> 39 <%= button(:search, _('Find people'), :controller => 'search', :action => 'assets', :asset => 'people') %>
  40 + <%= button(:search, _('Invite friends from my e-mail contacts'), :action => 'invite') %>
40 <% end %> 41 <% end %>
41 42
42 </div><!-- end id="manage_friends" --> 43 </div><!-- end id="manage_friends" -->
app/views/friends/invite.rhtml 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +<h1><%= __('Invite your friends') %></h1>
  2 +
  3 +
  4 +<% unless @friends %>
  5 +
  6 + <h2><%= __('Step 1 of 1: Accessing your contact list') %></h2>
  7 +
  8 + <p>
  9 + <%= __('Choose your webmail provider and enter your login and password so we can fetch your contact list. If you only want to invite specific people by listing their e-mail addresses, select the "Enter e-mail addresses manually" option.') %>
  10 + </p>
  11 +
  12 + <% form_tag do %>
  13 + <%= hidden_field_tag(:import, 1) %>
  14 +
  15 + <%= labelled_form_field(_('Select your e-mail provider:'), [
  16 + radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Gmail', :for => 'import_from_gmail'),
  17 + radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"),
  18 + radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password()') + content_tag('label', 'Hotmail', :for => "import_from_hotmail"),
  19 + radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', __('Enter e-mail addresses manually'), :for => "import_from_manual")
  20 + ].join("\n<br/>\n")) %>
  21 +
  22 + <script type="text/javascript">
  23 + function hide_invite_friend_login_password() {
  24 + $('invite-friends-login-password').hide();
  25 + }
  26 + function show_invite_friend_login_password() {
  27 + $('invite-friends-login-password').show();
  28 + $('login').focus();
  29 + }
  30 + </script>
  31 + <div id='invite-friends-login-password' <%= "style='display: none;'" if (@import_from == 'manual') %>>
  32 + <%= labelled_form_field(__("Login:"), text_field_tag(:login, @login)) %>
  33 + <%= labelled_form_field(__("Password:"), password_field_tag(:password)) %>
  34 + </div>
  35 +
  36 + <% button_bar do %>
  37 + <%= submit_button(:forward, __("Next")) %>
  38 + <% end %>
  39 + <p><%= __("We won't store your password or contact anyone without your permission.")%></p>
  40 +
  41 + <% end %>
  42 +
  43 +<% else %>
  44 +
  45 + <h2><%= __('Step 2 of 2: Selecting Friends') %></h2>
  46 + <p>
  47 + <%= __('Indicate which friends you want to invite.') %>
  48 + </p>
  49 +
  50 + <% form_tag do %>
  51 + <%= hidden_field_tag(:confirmation, 1) %>
  52 + <%= hidden_field_tag(:import_from, @import_from) %>
  53 +
  54 + <div>
  55 + <%= __("Enter one e-mail address per line, following the example below.")%>
  56 + <%= labelled_form_field(__('E-mail addresses'), text_area_tag(:manual_import_addresses, (@manual_import_addresses || __("Firstname Lastname <friend@email.com>")), :cols => 72, :rows => 5)) %>
  57 + </div>
  58 + <% if @import_from != 'manual' %>
  59 + <div>
  60 + <%= link_to_function __('Check all'), "$$('input.friend_to_invite').each(function(checkbox) { checkbox.checked = true; });" %>
  61 + <%= link_to_function __('Uncheck all'), "$$('input.friend_to_invite').each(function(checkbox) { checkbox.checked = false; });" %>
  62 + <% friend_pos = 0 %>
  63 + <% @friends.each do |friend| %>
  64 + <% friend_pos += 1 %>
  65 + <p>
  66 + <%= hidden_field_tag("webmail_friends[]", friend.to_yaml) %>
  67 + <%= check_box_tag("webmail_import_addresses[]", friend[2], (!@webmail_import_addresses || @webmail_import_addresses.include?(friend[2])), :id => "friends_to_invite_#{friend_pos}", :class => "friend_to_invite" ) %><label for="<%= "friends_to_invite_#{friend_pos}" %>"><%= "#{friend[0]} (#{friend[1]})" %></label>
  68 + </p>
  69 + <% end %>
  70 + </div>
  71 + <% end -%>
  72 +
  73 + <div>
  74 + <%= h __("Now enter an invitation message. You must keep the <url> code in your invitation message. When your friends receive the invitation e-mail, <url> will be replaced by a link that they need to click to activate their account. <user> and <friend> codes will be replaced by your name and friend name, but they are optional.") %>
  75 + <%= labelled_form_field(__('Invitation message'), text_area_tag(:message, @message, :cols => 72, :rows => 8)) %>
  76 + </div>
  77 +
  78 + <% button_bar do %>
  79 + <%= submit_button(:ok, __("Invite my friends!")) %>
  80 + <% end %>
  81 + <% end %>
  82 +
  83 +<% end %>
app/views/profile/friends.rhtml
@@ -10,6 +10,9 @@ @@ -10,6 +10,9 @@
10 </ul> 10 </ul>
11 11
12 <% button_bar do %> 12 <% button_bar do %>
  13 + <% if user == profile %>
  14 + <%= button :edit, _('Manage my friends'), :controller => 'friends', :action => 'index', :profile => profile.identifier %>
  15 + <% end %>
13 <%= button :back, _('Go back'), { :controller => 'profile' }, 16 <%= button :back, _('Go back'), { :controller => 'profile' },
14 :help => _('Back to the page where you come from.') %> 17 :help => _('Back to the page where you come from.') %>
15 <% end %> 18 <% end %>
app/views/task_mailer/invitation_notification.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= @message %>
0 \ No newline at end of file 2 \ No newline at end of file
doc/README_FOR_APP.en
@@ -20,6 +20,7 @@ You need to have a Subversion client (svn) installed, as well as: @@ -20,6 +20,7 @@ You need to have a Subversion client (svn) installed, as well as:
20 * RedCloth: http://whytheluckystiff.net/ruby/redcloth/ 20 * RedCloth: http://whytheluckystiff.net/ruby/redcloth/
21 * Ruby Locale: http://rubyforge.org/projects/locale/ 21 * Ruby Locale: http://rubyforge.org/projects/locale/
22 * will_paginate: http://github.com/mislav/will_paginate/wikis 22 * will_paginate: http://github.com/mislav/will_paginate/wikis
  23 +* contacts: http://github.com/cardmagic/contacts/tree/master
23 24
24 There are Debian packages available for all of them but ferret. Try: 25 There are Debian packages available for all of them but ferret. Try:
25 26
test/functional/friends_controller_test.rb
@@ -73,4 +73,32 @@ class FriendsControllerTest &lt; Test::Unit::TestCase @@ -73,4 +73,32 @@ class FriendsControllerTest &lt; Test::Unit::TestCase
73 get :index, :profile => 'testuser' 73 get :index, :profile => 'testuser'
74 assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' } 74 assert_tag :tag => 'a', :content => 'Find people', :attributes => { :href => '/assets/people' }
75 end 75 end
  76 +
  77 + should 'display invitation page' do
  78 + get :invite
  79 + assert_response :success
  80 + assert_template 'invite'
  81 + end
  82 +
  83 + should 'actualy add invite' do
  84 + assert_difference InviteFriend, :count, 1 do
  85 + post :invite, :manual_import_addresses => "Test Name <test@test.com>", :import_from => "manual", :message => "click: <url>", :confirmation => 1
  86 + assert_redirected_to :action => 'index'
  87 + end
  88 +
  89 + assert_difference InviteFriend, :count, 1 do
  90 + post :invite, :manual_import_addresses => "test@test.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1
  91 + assert_redirected_to :action => 'index'
  92 + end
  93 +
  94 + assert_difference InviteFriend, :count, 1 do
  95 + post :invite, :manual_import_addresses => "test@test.cz.com", :import_from => "manual", :message => "click: <url>", :confirmation => 1
  96 + assert_redirected_to :action => 'index'
  97 + end
  98 +
  99 + assert_difference InviteFriend, :count, 1 do
  100 + post :invite, :manual_import_addresses => "#{friend.name} <#{friend.email}>", :import_from => "manual", :message => "click: <url>", :confirmation => 1
  101 + assert_redirected_to :action => 'index'
  102 + end
  103 + end
76 end 104 end
test/functional/profile_controller_test.rb
@@ -31,6 +31,18 @@ class ProfileControllerTest &lt; Test::Unit::TestCase @@ -31,6 +31,18 @@ class ProfileControllerTest &lt; Test::Unit::TestCase
31 assert_kind_of Array, assigns(:friends) 31 assert_kind_of Array, assigns(:friends)
32 end 32 end
33 33
  34 + should 'point to manage friends in user is seeing his own friends' do
  35 + login_as('testuser')
  36 + get :friends
  37 + assert_tag :tag => 'a', :attributes => { :href => '/myprofile/testuser/friends' }
  38 + end
  39 +
  40 + should 'not point to manage friends of other users' do
  41 + login_as('ze')
  42 + get :friends
  43 + assert_no_tag :tag => 'a', :attributes => { :href => '/myprofile/testuser/friends' }
  44 + end
  45 +
34 should 'list communities' do 46 should 'list communities' do
35 get :communities 47 get :communities
36 48
test/unit/environment_test.rb
@@ -584,6 +584,19 @@ class EnvironmentTest &lt; Test::Unit::TestCase @@ -584,6 +584,19 @@ class EnvironmentTest &lt; Test::Unit::TestCase
584 assert_equal ['birth_date'], env.required_person_fields 584 assert_equal ['birth_date'], env.required_person_fields
585 end 585 end
586 586
  587 + should 'provide a default invitation message' do
  588 + env = Environment.create!(:name => 'test environment')
  589 + message = [
  590 + 'Hello <friend>,',
  591 + "<user> is inviting you to participate on #{env.name}.",
  592 + 'To accept the invitation, please follow this link:' + "\n" + '<url>',
  593 + "--\n#{env.name}",
  594 + ''
  595 + ].join("\n\n")
  596 +
  597 + assert_equal message, env.message_for_friend_invitation
  598 + end
  599 +
587 should 'set custom_enterprises_fields' do 600 should 'set custom_enterprises_fields' do
588 env = Environment.new 601 env = Environment.new
589 env.custom_enterprise_fields = {'contact_person' => {'required' => 'true', 'active' => 'true'},'contact_email'=> {'required' => 'true', 'active' => 'true'}} 602 env.custom_enterprise_fields = {'contact_person' => {'required' => 'true', 'active' => 'true'},'contact_email'=> {'required' => 'true', 'active' => 'true'}}
test/unit/invite_friend_test.rb 0 → 100644
@@ -0,0 +1,137 @@ @@ -0,0 +1,137 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class InviteFriendTest < ActiveSupport::TestCase
  4 +
  5 + should 'be a task' do
  6 + ok { InviteFriend.new.kind_of?(Task) }
  7 + end
  8 +
  9 + should 'actually create friendships (two way) when confirmed' do
  10 + p1 = create_user('testuser1').person
  11 + p2 = create_user('testuser2').person
  12 +
  13 + task = InviteFriend.create!(:person => p1, :friend => p2)
  14 +
  15 + assert_difference Friendship, :count, 2 do
  16 + task.finish
  17 + end
  18 +
  19 + ok('p1 should have p2 as friend') { p1.friends.include?(p2) }
  20 + ok('p2 should have p1 as friend') { p2.friends.include?(p1) }
  21 + end
  22 +
  23 + should 'require requestor (person inviting other as friend)' do
  24 + task = InviteFriend.new
  25 + task.valid?
  26 +
  27 + ok('must not validate with empty requestor') { task.errors.invalid?(:requestor_id) }
  28 +
  29 + task.requestor = create_user('testuser2').person
  30 + task.valid?
  31 + ok('must validate when requestor is given') { !task.errors.invalid?(:requestor_id)}
  32 + end
  33 +
  34 + should 'require friend email if no target given (person being invited)' do
  35 + task = InviteFriend.new
  36 + task.valid?
  37 +
  38 + ok('must not validate with empty target email') { task.errors.invalid?(:friend_email) }
  39 +
  40 + task.friend_email = 'test@test.com'
  41 + task.valid?
  42 + ok('must validate when target email is given') { !task.errors.invalid?(:friend_email)}
  43 + end
  44 +
  45 + should 'dont require friend email if target given (person being invited)' do
  46 + task = InviteFriend.new(:target => create_user('testuser2').person)
  47 + task.valid?
  48 +
  49 + ok('must validate with empty target email') { !task.errors.invalid?(:friend_email) }
  50 + end
  51 +
  52 + should 'require target (person being invited) if no friend email given' do
  53 + task = InviteFriend.new
  54 + task.valid?
  55 +
  56 + ok('must not validate with no target') { task.errors.invalid?(:target_id) }
  57 +
  58 + task.target = create_user('testuser2').person
  59 + task.valid?
  60 + ok('must validate when target is given') { !task.errors.invalid?(:target_id)}
  61 + end
  62 +
  63 + should 'dont require target (person being invited) if friend email given' do
  64 + task = InviteFriend.new(:friend_email => "test@test.com")
  65 + task.valid?
  66 +
  67 + ok('must validate with no target') { !task.errors.invalid?(:target_id) }
  68 + end
  69 +
  70 + should 'require message with <url> tag if no target given' do
  71 + task = InviteFriend.new
  72 + task.valid?
  73 +
  74 + ok('must not validate with no message') { task.errors.invalid?(:message) }
  75 +
  76 + task.message = 'a simple message'
  77 + task.valid?
  78 + ok('must not validate with no <url> tag in message') { task.errors.invalid?(:message) }
  79 +
  80 + task.message = 'a simple message with <url>'
  81 + task.valid?
  82 + ok('must validate when message is given with <url> tag') { !task.errors.invalid?(:message)}
  83 + end
  84 +
  85 + should 'dont require message if target given (person being invited)' do
  86 + task = InviteFriend.new(:target => create_user('testuser2').person)
  87 + task.valid?
  88 +
  89 + ok('must validate with no target') { !task.errors.invalid?(:message) }
  90 + end
  91 +
  92 + should 'not send e-mails to requestor' do
  93 + p1 = create_user('testuser1').person
  94 + p2 = create_user('testuser2').person
  95 +
  96 + TaskMailer.expects(:deliver_task_finished).never
  97 + TaskMailer.expects(:deliver_task_created).never
  98 +
  99 + task = InviteFriend.create!(:person => p1, :friend => p2)
  100 + task.finish
  101 + end
  102 +
  103 + should 'send e-mails to friend if friend_email given' do
  104 + p1 = create_user('testuser1').person
  105 +
  106 + TaskMailer.expects(:deliver_invitation_notification).once
  107 +
  108 + task = InviteFriend.create!(:person => p1, :friend_email => 'test@test.com', :message => '<url>')
  109 + end
  110 +
  111 + should 'not send e-mails to friend if target given (person being invited)' do
  112 + p1 = create_user('testuser1').person
  113 + p2 = create_user('testuser2').person
  114 +
  115 + TaskMailer.expects(:deliver_invitation_notification).never
  116 +
  117 + task = InviteFriend.create!(:person => p1, :friend => p2)
  118 + end
  119 +
  120 + should 'provide proper description' do
  121 + p1 = create_user('testuser1').person
  122 + p2 = create_user('testuser2').person
  123 +
  124 + TaskMailer.expects(:deliver_task_finished).never
  125 + TaskMailer.expects(:deliver_task_created).never
  126 +
  127 + task = InviteFriend.create!(:person => p1, :friend => p2)
  128 +
  129 + assert_equal 'testuser1 wants to be your friend', task.description
  130 + end
  131 +
  132 + should 'has permission to manage friends' do
  133 + t = InviteFriend.new
  134 + assert_equal :manage_friends, t.permission
  135 + end
  136 +
  137 +end
test/unit/task_mailer_test.rb
@@ -105,6 +105,35 @@ class TaskMailerTest &lt; Test::Unit::TestCase @@ -105,6 +105,35 @@ class TaskMailerTest &lt; Test::Unit::TestCase
105 assert !ActionMailer::Base.deliveries.empty? 105 assert !ActionMailer::Base.deliveries.empty?
106 end 106 end
107 107
  108 + should 'be able to send a "invitatiom notification" message' do
  109 +
  110 + task = InviteFriend.new
  111 + task.expects(:description).returns('the task')
  112 + task.expects(:code).returns('123456')
  113 +
  114 + task.expects(:message).returns('Hello <friend>, <user> invite you, please follow this link: <url>')
  115 + task.expects(:friend_email).returns('friend@exemple.com')
  116 + task.expects(:friend_name).returns('friend name')
  117 +
  118 + requestor = mock()
  119 + requestor.expects(:name).returns('my name')
  120 +
  121 + environment = mock()
  122 + environment.expects(:contact_email).returns('sender@example.com')
  123 + environment.expects(:default_hostname).returns('example.com')
  124 + environment.expects(:name).returns('example').at_least_once
  125 +
  126 + task.expects(:requestor).returns(requestor).at_least_once
  127 + requestor.expects(:environment).returns(environment).at_least_once
  128 +
  129 + mail = TaskMailer.create_invitation_notification(task)
  130 +
  131 + assert_equal "Hello friend name, my name invite you, please follow this link: http://example.com/account/signup?invitation_code=123456", mail.body
  132 +
  133 + TaskMailer.deliver(mail)
  134 + assert !ActionMailer::Base.deliveries.empty?
  135 + end
  136 +
108 should 'use environment name and contact email' do 137 should 'use environment name and contact email' do
109 task = mock 138 task = mock
110 requestor = mock 139 requestor = mock