Commit 65cad57a35002a9fd168863ae8a4d7ca045fb938

Authored by Steven Thonus
1 parent 358426d6

avatar upload on profile page

Showing 40 changed files with 119 additions and 39 deletions   Show diff stats
CHANGELOG
... ... @@ -13,6 +13,7 @@ v 6.2.0
13 13 - Rake tasks for web hooks management (Jonhnny Weslley)
14 14 - Extended User API to expose admin and can_create_group for user creation/updating (Boyan Tabakov)
15 15 - API: Remove group
  16 + - Avatar upload on profile page with a maximum of 200KB (Steven Thonus)
16 17  
17 18 v 6.1.0
18 19 - Project specific IDs for issues, mr, milestones
... ...
app/assets/javascripts/profile.js.coffee
... ... @@ -16,3 +16,13 @@ $ ->
16 16  
17 17 $('.update-notifications').on 'ajax:complete', ->
18 18 $(this).find('.btn-save').enableButton()
  19 +
  20 +
  21 + $('.js-choose-user-avatar-button').bind "click", ->
  22 + form = $(this).closest("form")
  23 + form.find(".js-user-avatar-input").click()
  24 +
  25 + $('.js-user-avatar-input').bind "change", ->
  26 + form = $(this).closest("form")
  27 + filename = $(this).val().replace(/^.*[\\\/]/, '')
  28 + form.find(".js-avatar-filename").text(filename)
... ...
app/assets/javascripts/users_select.js.coffee
1 1 $ ->
2 2 userFormatResult = (user) ->
3   - avatar = gon.gravatar_url
4   - avatar = avatar.replace('%{hash}', md5(user.email))
5   - avatar = avatar.replace('%{size}', '24')
6   -
  3 + if user.avatar
  4 + avatar = user.avatar.url
  5 + else
  6 + avatar = gon.gravatar_url
  7 + avatar = avatar.replace('%{hash}', md5(user.email))
  8 + avatar = avatar.replace('%{size}', '24')
7 9 markup = "<div class='user-result'>"
8 10 markup += "<div class='user-image'><img class='avatar s24' src='" + avatar + "'></div>"
9 11 markup += "<div class='user-name'>" + user.name + "</div>"
... ...
app/helpers/application_helper.rb
... ... @@ -49,6 +49,15 @@ module ApplicationHelper
49 49 args.any? { |v| v.to_s.downcase == action_name }
50 50 end
51 51  
  52 + def avatar_icon(user_email = '', size = nil)
  53 + user = User.find_by_email(user_email)
  54 + if user && user.avatar.present?
  55 + user.avatar.url
  56 + else
  57 + gravatar_icon(user_email, size)
  58 + end
  59 + end
  60 +
52 61 def gravatar_icon(user_email = '', size = nil)
53 62 size = 40 if size.nil? || size <= 0
54 63  
... ...
app/helpers/commits_helper.rb
... ... @@ -108,7 +108,7 @@ module CommitsHelper
108 108 source_name = commit.send "#{options[:source]}_name".to_sym
109 109 source_email = commit.send "#{options[:source]}_email".to_sym
110 110 text = if options[:avatar]
111   - avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
  111 + avatar = image_tag(avatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
112 112 %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
113 113 else
114 114 source_name
... ...
app/helpers/projects_helper.rb
... ... @@ -25,7 +25,7 @@ module ProjectsHelper
25 25 author_html = ""
26 26  
27 27 # Build avatar image tag
28   - author_html << image_tag(gravatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
  28 + author_html << image_tag(avatar_icon(author.try(:email), opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
29 29  
30 30 # Build name span tag
31 31 author_html << content_tag(:span, sanitize(author.name), class: 'author') if opts[:name]
... ...
app/models/user.rb
... ... @@ -38,13 +38,16 @@
38 38 # created_by_id :integer
39 39 #
40 40  
  41 +require 'carrierwave/orm/activerecord'
  42 +require 'file_size_validator'
  43 +
41 44 class User < ActiveRecord::Base
42 45 devise :database_authenticatable, :token_authenticatable, :lockable,
43 46 :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :registerable
44 47  
45 48 attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
46 49 :skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password,
47   - :extern_uid, :provider, :password_expires_at,
  50 + :extern_uid, :provider, :password_expires_at, :avatar,
48 51 as: [:default, :admin]
49 52  
50 53 attr_accessible :projects_limit, :can_create_group,
... ... @@ -113,6 +116,8 @@ class User &lt; ActiveRecord::Base
113 116  
114 117 validate :namespace_uniq, if: ->(user) { user.username_changed? }
115 118  
  119 + validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
  120 +
116 121 before_validation :generate_password, on: :create
117 122 before_validation :sanitize_attrs
118 123  
... ... @@ -150,6 +155,8 @@ class User &lt; ActiveRecord::Base
150 155 end
151 156 end
152 157  
  158 + mount_uploader :avatar, AttachmentUploader
  159 +
153 160 # Scopes
154 161 scope :admins, -> { where(admin: true) }
155 162 scope :blocked, -> { with_state(:blocked) }
... ...
app/views/admin/users/show.html.haml
... ... @@ -20,7 +20,7 @@
20 20 .title
21 21 Account:
22 22 .pull-right
23   - = image_tag gravatar_icon(@user.email, 32), class: "avatar s32"
  23 + = image_tag avatar_icon(@user.email, 32), class: "avatar s32"
24 24 %ul.well-list
25 25 %li
26 26 %span.light Name:
... ...
app/views/dashboard/issues.atom.builder
... ... @@ -12,7 +12,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
12 12 xml.link :href => project_issue_url(issue.project, issue)
13 13 xml.title truncate(issue.title, :length => 80)
14 14 xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
15   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
  15 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
16 16 xml.author do |author|
17 17 xml.name issue.author_name
18 18 xml.email issue.author_email
... ...
app/views/dashboard/show.atom.builder
... ... @@ -17,7 +17,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
17 17 xml.link :href => event_link
18 18 xml.title truncate(event_title, :length => 80)
19 19 xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
20   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
  20 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
21 21 xml.author do |author|
22 22 xml.name event.author_name
23 23 xml.email event.author_email
... ...
app/views/events/_event.html.haml
... ... @@ -4,7 +4,7 @@
4 4 #{time_ago_in_words(event.created_at)} ago.
5 5  
6 6 = cache event do
7   - = image_tag gravatar_icon(event.author_email), class: "avatar s24", alt:''
  7 + = image_tag avatar_icon(event.author_email), class: "avatar s24", alt:''
8 8  
9 9 - if event.push?
10 10 = render "events/event/push", event: event
... ...
app/views/groups/issues.atom.builder
... ... @@ -12,7 +12,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
12 12 xml.link :href => project_issue_url(issue.project, issue)
13 13 xml.title truncate(issue.title, :length => 80)
14 14 xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
15   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
  15 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
16 16 xml.author do |author|
17 17 xml.name issue.author_name
18 18 xml.email issue.author_email
... ...
app/views/groups/show.atom.builder
... ... @@ -16,7 +16,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
16 16 xml.link :href => event_link
17 17 xml.title truncate(event_title, :length => 80)
18 18 xml.updated event.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
19   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(event.author_email)
  19 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(event.author_email)
20 20 xml.author do |author|
21 21 xml.name event.author_name
22 22 xml.email event.author_email
... ...
app/views/layouts/_head_panel.html.haml
... ... @@ -37,4 +37,4 @@
37 37 %i.icon-signout
38 38 %li
39 39 = link_to current_user, class: "profile-pic", id: 'profile-pic' do
40   - = image_tag gravatar_icon(current_user.email, 26), alt: ''
  40 + = image_tag avatar_icon(current_user.email, 26), alt: ''
... ...
app/views/profiles/show.html.haml
1   -= image_tag gravatar_icon(@user.email, 60), alt: '', class: 'avatar s60'
  1 += image_tag avatar_icon(@user.email, 60), alt: '', class: 'avatar s60'
2 2 %h3.page-title
3 3 = @user.name
4 4 %br
... ... @@ -12,7 +12,7 @@
12 12 Logout
13 13 %hr
14 14  
15   -= form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f|
  15 += form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit_user form-horizontal" } do |f|
16 16 -if @user.errors.any?
17 17 %div.alert.alert-error
18 18 %ul
... ... @@ -29,7 +29,7 @@
29 29 = f.label :email, class: "control-label"
30 30 .controls
31 31 = f.text_field :email, class: "input-xlarge", required: true
32   - %span.help-block We also use email for avatar detection.
  32 + %span.help-block We also use email for avatar detection if no avatar is uploaded.
33 33 .control-group
34 34 = f.label :skype, class: "control-label"
35 35 .controls= f.text_field :skype, class: "input-xlarge"
... ... @@ -40,6 +40,17 @@
40 40 = f.label :twitter, class: "control-label"
41 41 .controls= f.text_field :twitter, class: "input-xlarge"
42 42 .control-group
  43 + = f.label :avatar, class: "control-label"
  44 + .controls
  45 + .profile-avatar-form-option
  46 + %a.choose-btn.btn.btn-small.js-choose-user-avatar-button
  47 + %i.icon-paper-clip
  48 + %span Choose File ...
  49 + &nbsp;
  50 + %span.file_name.js-avatar-filename File name...
  51 + = f.file_field :avatar, class: "js-user-avatar-input hide"
  52 + %span.help-block The maximum file size allowed is 200KB.
  53 + .control-group
43 54 = f.label :bio, class: "control-label"
44 55 .controls
45 56 = f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
... ... @@ -53,7 +64,7 @@
53 64 %p You can change your password on the Account page
54 65 - if Gitlab.config.gravatar.enabled
55 66 %li
56   - %p You can change your avatar at #{link_to "gravatar.com", "http://gravatar.com"}
  67 + %p You can upload an avatar here or change it at #{link_to "gravatar.com", "http://gravatar.com"}
57 68  
58 69 - if Gitlab.config.omniauth.enabled && @user.provider?
59 70 %li
... ...
app/views/projects/branches/_branch.html.haml
... ... @@ -24,7 +24,7 @@
24 24 %p
25 25 = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
26 26 = commit.short_id
27   - = image_tag gravatar_icon(commit.author_email), class: "avatar s16", alt: ''
  27 + = image_tag avatar_icon(commit.author_email), class: "avatar s16", alt: ''
28 28 %span.light
29 29 = gfm escape_once(truncate(commit.title, length: 40))
30 30 %span
... ...
app/views/projects/commits/show.atom.builder
... ... @@ -12,7 +12,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
12 12 xml.link :href => project_commit_url(@project, :id => commit.id)
13 13 xml.title truncate(commit.title, :length => 80)
14 14 xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")
15   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(commit.author_email)
  15 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(commit.author_email)
16 16 xml.author do |author|
17 17 xml.name commit.author_name
18 18 xml.email commit.author_email
... ...
app/views/projects/issues/_issues.html.haml
... ... @@ -52,7 +52,7 @@
52 52 - @project.team.members.sort_by(&:name).each do |user|
53 53 %li
54 54 = link_to project_filter_path(assignee_id: user.id) do
55   - = image_tag gravatar_icon(user.email), class: "avatar s16", alt: ''
  55 + = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
56 56 = user.name
57 57  
58 58 .dropdown.inline.prepend-left-10
... ...
app/views/projects/issues/index.atom.builder
... ... @@ -12,7 +12,7 @@ xml.feed &quot;xmlns&quot; =&gt; &quot;http://www.w3.org/2005/Atom&quot;, &quot;xmlns:media&quot; =&gt; &quot;http://sear
12 12 xml.link :href => project_issue_url(@project, issue)
13 13 xml.title truncate(issue.title, :length => 80)
14 14 xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
15   - xml.media :thumbnail, :width => "40", :height => "40", :url => gravatar_icon(issue.author_email)
  15 + xml.media :thumbnail, :width => "40", :height => "40", :url => avatar_icon(issue.author_email)
16 16 xml.author do |author|
17 17 xml.name issue.author_name
18 18 xml.email issue.author_email
... ...
app/views/projects/merge_requests/index.html.haml
... ... @@ -35,7 +35,7 @@
35 35 - @project.team.members.sort_by(&:name).each do |user|
36 36 %li
37 37 = link_to project_filter_path(assignee_id: user.id) do
38   - = image_tag gravatar_icon(user.email), class: "avatar s16", alt: ''
  38 + = image_tag avatar_icon(user.email), class: "avatar s16", alt: ''
39 39 = user.name
40 40  
41 41 .dropdown.inline.prepend-left-10
... ...
app/views/projects/milestones/_issues.html.haml
... ... @@ -8,4 +8,4 @@
8 8 = link_to_gfm truncate(issue.title, length: 40), [@project, issue]
9 9 - if issue.assignee
10 10 .pull-right
11   - = image_tag gravatar_icon(issue.assignee.email, 16), class: "avatar s16"
  11 + = image_tag avatar_icon(issue.assignee.email, 16), class: "avatar s16"
... ...
app/views/projects/milestones/show.html.haml
... ... @@ -99,7 +99,7 @@
99 99 - @users.each do |user|
100 100 %li
101 101 = link_to user, title: user.name, class: "dark" do
102   - = image_tag gravatar_icon(user.email, 32), class: "avatar s32"
  102 + = image_tag avatar_icon(user.email, 32), class: "avatar s32"
103 103 %strong= truncate(user.name, lenght: 40)
104 104 %br
105 105 %small.cgray= user.username
... ...
app/views/projects/network/show.json.erb
... ... @@ -9,7 +9,7 @@
9 9 author: {
10 10 name: c.author_name,
11 11 email: c.author_email,
12   - icon: gravatar_icon(c.author_email, 20)
  12 + icon: avatar_icon(c.author_email, 20)
13 13 },
14 14 time: c.time,
15 15 space: c.spaces.first,
... ...
app/views/projects/notes/_discussion.html.haml
... ... @@ -8,7 +8,7 @@
8 8 = link_to "javascript:;", class: "js-details-target turn-off js-toggler-target" do
9 9 %i.icon-eye-open
10 10 Show discussion
11   - = image_tag gravatar_icon(note.author_email), class: "avatar s32"
  11 + = image_tag avatar_icon(note.author_email), class: "avatar s32"
12 12 %div
13 13 = link_to_member(@project, note.author, avatar: false)
14 14 - if note.for_merge_request?
... ...
app/views/projects/notes/_note.html.haml
... ... @@ -13,7 +13,7 @@
13 13 = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure you want to remove this comment?', remote: true, class: "danger js-note-delete" do
14 14 %i.icon-trash.cred
15 15 Remove
16   - = image_tag gravatar_icon(note.author_email), class: "avatar s32"
  16 + = image_tag avatar_icon(note.author_email), class: "avatar s32"
17 17 = link_to_member(@project, note.author, avatar: false)
18 18 %span.note-last-update
19 19 = note_timestamp(note)
... ...
app/views/projects/repositories/_feed.html.haml
... ... @@ -11,7 +11,7 @@
11 11 %div
12 12 = link_to project_commits_path(@project, commit.id) do
13 13 %code= commit.short_id
14   - = image_tag gravatar_icon(commit.author_email), class: "", width: 16, alt: ''
  14 + = image_tag avatar_icon(commit.author_email), class: "", width: 16, alt: ''
15 15 = gfm escape_once(truncate(commit.title, length: 40))
16 16 %td
17 17 %span.pull-right.cgray
... ...
app/views/projects/repositories/stats.html.haml
... ... @@ -19,7 +19,7 @@
19 19 %ol.styled
20 20 - @stats.authors[0...50].each do |author|
21 21 %li
22   - = image_tag gravatar_icon(author.email, 16), class: 'avatar s16', alt: ''
  22 + = image_tag avatar_icon(author.email, 16), class: 'avatar s16', alt: ''
23 23 = author.name
24 24 %small.light= author.email
25 25 .pull-right
... ...
app/views/projects/snippets/_snippet.html.haml
... ... @@ -16,6 +16,6 @@
16 16 = "##{snippet.id}"
17 17 %span
18 18 by
19   - = image_tag gravatar_icon(snippet.author_email), class: "avatar avatar-inline s16"
  19 + = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16"
20 20 = snippet.author_name
21 21 %span.light #{time_ago_in_words(snippet.created_at)} ago
... ...
app/views/projects/snippets/show.html.haml
... ... @@ -5,7 +5,7 @@
5 5 = "##{@snippet.id}"
6 6 %span.light
7 7 by
8   - = image_tag gravatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
  8 + = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
9 9 = @snippet.author_name
10 10 %div= render 'projects/snippets/blob'
11 11 %div#notes= render "projects/notes/notes_with_form"
... ...
app/views/projects/team_members/_team_member.html.haml
... ... @@ -9,7 +9,7 @@
9 9 &nbsp;
10 10 = link_to project_team_member_path(@project, user), confirm: remove_from_project_team_message(@project, user), method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
11 11 %i.icon-minus.icon-white
12   - = image_tag gravatar_icon(user.email, 32), class: "avatar s32"
  12 + = image_tag avatar_icon(user.email, 32), class: "avatar s32"
13 13 %p
14 14 %strong= user.name
15 15 %span.cgray= user.username
... ...
app/views/snippets/_snippet.html.haml
... ... @@ -18,6 +18,6 @@
18 18 %span
19 19 by
20 20 = link_to user_snippets_path(snippet.author) do
21   - = image_tag gravatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: ''
  21 + = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: ''
22 22 = snippet.author_name
23 23 %span.light #{time_ago_in_words(snippet.created_at)} ago
... ...
app/views/snippets/show.html.haml
... ... @@ -17,7 +17,7 @@
17 17 %span.light
18 18 by
19 19 = link_to user_snippets_path(@snippet.author) do
20   - = image_tag gravatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
  20 + = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
21 21 = @snippet.author_name
22 22  
23 23 .back-link
... ...
app/views/snippets/user_index.html.haml
1 1 %h3.page-title
2   - = image_tag gravatar_icon(@user.email), class: "avatar s24"
  2 + = image_tag avatar_icon(@user.email), class: "avatar s24"
3 3 = @user.name
4 4 %span
5 5 \/
... ...
app/views/users/show.html.haml
1 1 .row
2 2 .span8
3 3 %h3.page-title
4   - = image_tag gravatar_icon(@user.email, 90), class: "avatar s90", alt: ''
  4 + = image_tag avatar_icon(@user.email, 90), class: "avatar s90", alt: ''
5 5 = @user.name
6 6 - if @user == current_user
7 7 .pull-right
... ...
app/views/users_groups/_users_group.html.haml
1 1 - user = member.user
2 2 - return unless user
3 3 %li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
4   - = image_tag gravatar_icon(user.email, 16), class: "avatar s16"
  4 + = image_tag avatar_icon(user.email, 16), class: "avatar s16"
5 5 %strong= user.name
6 6 %span.cgray= user.username
7 7 - if user == current_user
... ...
db/migrate/20131005191208_add_avatar_to_users.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +class AddAvatarToUsers < ActiveRecord::Migration
  2 + def change
  3 + add_column :users, :avatar, :string
  4 + end
  5 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20130926081215) do
  14 +ActiveRecord::Schema.define(:version => 20131005191208) do
15 15  
16 16 create_table "deploy_keys_projects", :force => true do |t|
17 17 t.integer "deploy_key_id", :null => false
... ... @@ -283,6 +283,7 @@ ActiveRecord::Schema.define(:version =&gt; 20130926081215) do
283 283 t.integer "notification_level", :default => 1, :null => false
284 284 t.datetime "password_expires_at"
285 285 t.integer "created_by_id"
  286 + t.string "avatar"
286 287 end
287 288  
288 289 add_index "users", ["admin"], :name => "index_users_on_admin"
... ...
features/profile/profile.feature
... ... @@ -22,6 +22,11 @@ Feature: Profile
22 22 Then I change my password
23 23 And I should be redirected to sign in page
24 24  
  25 + Scenario: I edit my avatar
  26 + Given I visit profile page
  27 + Then I change my avatar
  28 + And I should see new avatar
  29 +
25 30 Scenario: My password is expired
26 31 Given my password is expired
27 32 And I am not an ldap user
... ...
features/steps/profile/profile.rb
... ... @@ -22,6 +22,17 @@ class Profile &lt; Spinach::FeatureSteps
22 22 @user.twitter.should == 'testtwitter'
23 23 end
24 24  
  25 + step 'I change my avatar' do
  26 + attach_file(:user_avatar, File.join(Rails.root, 'public', 'gitlab_logo.png'))
  27 + click_button "Save changes"
  28 + @user.reload
  29 + end
  30 +
  31 + step 'I should see new avatar' do
  32 + @user.avatar.should be_instance_of AttachmentUploader
  33 + @user.avatar.url.should == "/uploads/user/avatar/#{ @user.id }/gitlab_logo.png"
  34 + end
  35 +
25 36 step 'I try change my password w/o old one' do
26 37 within '.update-password' do
27 38 fill_in "user_password", with: "222333"
... ...
spec/helpers/application_helper_spec.rb
... ... @@ -38,6 +38,24 @@ describe ApplicationHelper do
38 38 current_action?(:baz, :bar, :foo).should be_true
39 39 end
40 40 end
  41 +
  42 + describe "avatar_icon" do
  43 + avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png')
  44 +
  45 + it "should return an url for the avatar" do
  46 + user = create(:user)
  47 + user.avatar = File.open(avatar_file_path)
  48 + user.save!
  49 + avatar_icon(user.email).to_s.should == "/uploads/user/avatar/#{ user.id }/gitlab_logo.png"
  50 + end
  51 +
  52 + it "should call gravatar_icon when no avatar is present" do
  53 + user = create(:user)
  54 + user.save!
  55 + stub!(:gravatar_icon).and_return('gravatar_method_called')
  56 + avatar_icon(user.email).to_s.should == "gravatar_method_called"
  57 + end
  58 + end
41 59  
42 60 describe "gravatar_icon" do
43 61 let(:user_email) { 'user@email.com' }
... ...