.*?}m) do |match|
"#{match}#{link_to("", url, html_options)[0..-5]}" # "".length +1
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
new file mode 100644
index 00000000..65389e38
--- /dev/null
+++ b/app/helpers/notes_helper.rb
@@ -0,0 +1,17 @@
+module NotesHelper
+ def loading_more_notes?
+ params[:loading_more].present?
+ end
+
+ def loading_new_notes?
+ params[:loading_new].present?
+ end
+
+ def note_vote_class(note)
+ if note.upvote?
+ "vote upvote"
+ elsif note.downvote?
+ "vote downvote"
+ end
+ end
+end
diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb
new file mode 100644
index 00000000..80d67009
--- /dev/null
+++ b/app/helpers/profile_helper.rb
@@ -0,0 +1,7 @@
+module ProfileHelper
+ def oauth_active_class provider
+ if current_user.provider == provider.to_s
+ 'active'
+ end
+ end
+end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 34dbb06c..c7dc54ee 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -2,5 +2,9 @@ module ProjectsHelper
def grouper_project_members(project)
@project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
end
+
+ def remove_from_team_message(project, member)
+ "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+ end
end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 1740864b..b5d7ccb7 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -8,7 +8,7 @@ module TabHelper
end
def project_tab_class
- [:show, :files, :team, :edit, :update].each do |action|
+ [:show, :files, :edit, :update].each do |action|
return "current" if current_page?(controller: "projects", action: action, id: @project)
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index c51ee84a..a5d5c742 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -18,7 +18,8 @@ module TreeHelper
end
def tree_full_path(content)
- if params[:path]
+ content.name.force_encoding('utf-8')
+ if params[:path]
File.join(params[:path], content.name)
else
content.name
diff --git a/app/models/event.rb b/app/models/event.rb
index 308ffd63..b11b21bd 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -35,13 +35,21 @@ class Event < ActiveRecord::Base
end
# Next events currently enabled for system
- # - push
+ # - push
# - new issue
# - merge request
def allowed?
push? || issue? || merge_request? || membership_changed?
end
+ def project_name
+ if project
+ project.name
+ else
+ "(deleted)"
+ end
+ end
+
def push?
action == self.class::Pushed && valid_push?
end
@@ -58,31 +66,31 @@ class Event < ActiveRecord::Base
action == self.class::Reopened
end
- def issue?
+ def issue?
target_type == "Issue"
end
- def merge_request?
+ def merge_request?
target_type == "MergeRequest"
end
- def new_issue?
- target_type == "Issue" &&
+ def new_issue?
+ target_type == "Issue" &&
action == Created
end
- def new_merge_request?
- target_type == "MergeRequest" &&
+ def new_merge_request?
+ target_type == "MergeRequest" &&
action == Created
end
- def changed_merge_request?
- target_type == "MergeRequest" &&
+ def changed_merge_request?
+ target_type == "MergeRequest" &&
[Closed, Reopened].include?(action)
end
- def changed_issue?
- target_type == "Issue" &&
+ def changed_issue?
+ target_type == "Issue" &&
[Closed, Reopened].include?(action)
end
@@ -98,7 +106,7 @@ class Event < ActiveRecord::Base
joined? || left?
end
- def issue
+ def issue
target if target_type == "Issue"
end
@@ -106,7 +114,7 @@ class Event < ActiveRecord::Base
target if target_type == "MergeRequest"
end
- def author
+ def author
@author ||= User.find(author_id)
end
@@ -119,7 +127,7 @@ class Event < ActiveRecord::Base
'joined'
elsif left?
'left'
- else
+ else
"opened"
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 6409eeba..96a54907 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -1,6 +1,6 @@
class Issue < ActiveRecord::Base
include IssueCommonality
- include Upvote
+ include Votes
acts_as_taggable_on :labels
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 2e457f72..184ac5fc 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit")
class MergeRequest < ActiveRecord::Base
include IssueCommonality
- include Upvote
+ include Votes
BROKEN_DIFF = "--broken-diff"
diff --git a/app/models/note.rb b/app/models/note.rb
index d8494edd..34edb94e 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -36,7 +36,7 @@ class Note < ActiveRecord::Base
scope :today, where("created_at >= :date", date: Date.today)
scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
scope :since, lambda { |day| where("created_at >= :date", date: (day)) }
- scope :fresh, order("created_at DESC")
+ scope :fresh, order("created_at ASC, id ASC")
scope :inc_author_project, includes(:project, :author)
scope :inc_author, includes(:author)
@@ -105,6 +105,12 @@ class Note < ActiveRecord::Base
def upvote?
note.start_with?('+1') || note.start_with?(':+1:')
end
+
+ # Returns true if this is a downvote note,
+ # otherwise false is returned
+ def downvote?
+ note.start_with?('-1') || note.start_with?(':-1:')
+ end
end
# == Schema Information
#
diff --git a/app/models/project.rb b/app/models/project.rb
index 4de836c7..56d5d791 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -171,6 +171,10 @@ class Project < ActiveRecord::Base
end
end
+ def wiki_notes
+ Note.where(noteable_id: wikis.map(&:id), noteable_type: 'Wiki', project_id: self.id)
+ end
+
def project_id
self.id
end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index bc95d335..d65e50ab 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -16,7 +16,7 @@ class Tree
def initialize(raw_tree, project, ref = nil, path = nil)
@project, @ref, @path = project, ref, path,
@tree = if path
- raw_tree / path
+ raw_tree / path.dup.force_encoding('ascii-8bit')
else
raw_tree
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ad6af6a6..47876722 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -86,33 +86,20 @@ class User < ActiveRecord::Base
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
end
- def self.find_for_ldap_auth(auth, signed_in_resource=nil)
- uid = auth.info.uid
- provider = auth.provider
- name = auth.info.name.force_encoding("utf-8")
- email = auth.info.email.downcase unless auth.info.email.nil?
- raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
+ def self.create_from_omniauth(auth, ldap = false)
+ gitlab_auth.create_from_omniauth(auth, ldap)
+ end
- if @user = User.find_by_extern_uid_and_provider(uid, provider)
- @user
- # workaround for backward compatibility
- elsif @user = User.find_by_email(email)
- logger.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
- @user.update_attributes(:extern_uid => uid, :provider => provider)
- @user
- else
- logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
- password = Devise.friendly_token[0, 8].downcase
- @user = User.create(
- :extern_uid => uid,
- :provider => provider,
- :name => name,
- :email => email,
- :password => password,
- :password_confirmation => password,
- :projects_limit => Gitlab.config.default_projects_limit
- )
- end
+ def self.find_or_new_for_omniauth(auth)
+ gitlab_auth.find_or_new_for_omniauth(auth)
+ end
+
+ def self.find_for_ldap_auth(auth, signed_in_resource = nil)
+ gitlab_auth.find_for_ldap_auth(auth, signed_in_resource)
+ end
+
+ def self.gitlab_auth
+ Gitlab::Auth.new
end
def self.search query
@@ -148,4 +135,3 @@ end
# bio :string(255)
# blocked :boolean(1) default(FALSE), not null
#
-
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 3c4952cd..ebb1ff49 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -28,7 +28,6 @@ class Wiki < ActiveRecord::Base
end
new_wiki
end
-
end
end
# == Schema Information
diff --git a/app/observers/project_observer.rb b/app/observers/project_observer.rb
index 135959ab..03a61709 100644
--- a/app/observers/project_observer.rb
+++ b/app/observers/project_observer.rb
@@ -4,6 +4,18 @@ class ProjectObserver < ActiveRecord::Observer
end
def after_destroy(project)
+ log_info("Project \"#{project.name}\" was removed")
+
project.destroy_repository
end
+
+ def after_create project
+ log_info("#{project.owner.name} created a new project \"#{project.name}\"")
+ end
+
+ protected
+
+ def log_info message
+ Gitlab::AppLogger.info message
+ end
end
diff --git a/app/observers/user_observer.rb b/app/observers/user_observer.rb
index d12bcc99..654621f7 100644
--- a/app/observers/user_observer.rb
+++ b/app/observers/user_observer.rb
@@ -1,5 +1,17 @@
class UserObserver < ActiveRecord::Observer
def after_create(user)
+ log_info("User \"#{user.name}\" (#{user.email}) was created")
+
Notify.new_user_email(user.id, user.password).deliver
end
+
+ def after_destroy user
+ log_info("User \"#{user.name}\" (#{user.email}) was removed")
+ end
+
+ protected
+
+ def log_info message
+ Gitlab::AppLogger.info message
+ end
end
diff --git a/app/observers/users_project_observer.rb b/app/observers/users_project_observer.rb
index 1df33237..0c9c2b26 100644
--- a/app/observers/users_project_observer.rb
+++ b/app/observers/users_project_observer.rb
@@ -14,8 +14,8 @@ class UsersProjectObserver < ActiveRecord::Observer
def after_destroy(users_project)
Event.create(
- project_id: users_project.project.id,
- action: Event::Left,
+ project_id: users_project.project.id,
+ action: Event::Left,
author_id: users_project.user.id
)
end
diff --git a/app/roles/upvote.rb b/app/roles/upvote.rb
deleted file mode 100644
index 7efa6f20..00000000
--- a/app/roles/upvote.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Upvote
- # Return the number of +1 comments (upvotes)
- def upvotes
- notes.select(&:upvote?).size
- end
-end
diff --git a/app/roles/votes.rb b/app/roles/votes.rb
new file mode 100644
index 00000000..043a6feb
--- /dev/null
+++ b/app/roles/votes.rb
@@ -0,0 +1,32 @@
+module Votes
+ # Return the number of +1 comments (upvotes)
+ def upvotes
+ notes.select(&:upvote?).size
+ end
+
+ def upvotes_in_percent
+ if votes_count.zero?
+ 0
+ else
+ 100.0 / votes_count * upvotes
+ end
+ end
+
+ # Return the number of -1 comments (downvotes)
+ def downvotes
+ notes.select(&:downvote?).size
+ end
+
+ def downvotes_in_percent
+ if votes_count.zero?
+ 0
+ else
+ 100.0 - upvotes_in_percent
+ end
+ end
+
+ # Return the total number of votes
+ def votes_count
+ upvotes + downvotes
+ end
+end
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index 800d3bb2..0efe6db7 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -1,9 +1,26 @@
-.file_holder#README
- .file_title
- %i.icon-file
- githost.log
- .file_content.logs
- %ol
- - Gitlab::Logger.read_latest.each do |line|
- %li
- %p= line
+%ul.nav.nav-tabs.log-tabs
+ %li.active
+ = link_to "githost.log", "#githost", 'data-toggle' => 'tab'
+ %li
+ = link_to "application.log", "#application", 'data-toggle' => 'tab'
+.tab-content
+ .tab-pane.active#githost
+ .file_holder#README
+ .file_title
+ %i.icon-file
+ githost.log
+ .file_content.logs
+ %ol
+ - Gitlab::GitLogger.read_latest.each do |line|
+ %li
+ %p= line
+ .tab-pane#application
+ .file_holder#README
+ .file_title
+ %i.icon-file
+ application.log
+ .file_content.logs
+ %ol
+ - Gitlab::AppLogger.read_latest.each do |line|
+ %li
+ %p= line
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
index 87d212e5..4848e739 100644
--- a/app/views/admin/projects/_form.html.haml
+++ b/app/views/admin/projects/_form.html.haml
@@ -32,7 +32,7 @@
- unless project.new_record?
.clearfix
= f.label :owner_id
- .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }
+ .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
- if project.repo_exists?
.clearfix
@@ -69,7 +69,6 @@
:javascript
$(function(){
- $('#project_owner_id').chosen();
new Projects();
})
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 65d888f5..63987410 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -71,25 +71,11 @@
%th Project Access:
%tr
- %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true
- %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+ %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
+ %td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
%tr
%td= submit_tag 'Add', class: "btn primary"
%td
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
-
-:css
- form select {
- width:150px;
- }
-
- #user_ids {
- width:300px;
- }
-
-:javascript
- $('select#user_ids').chosen();
- $('select#repo_access').chosen();
- $('select#project_access').chosen();
diff --git a/app/views/admin/resque/show.html.haml b/app/views/admin/resque/show.html.haml
index d889a5d0..8850e378 100644
--- a/app/views/admin/resque/show.html.haml
+++ b/app/views/admin/resque/show.html.haml
@@ -1,2 +1,4 @@
-%h3 Resque
-%iframe{src: resque_url, width: 1168, height: 600, style: "border: none"}
+%h3.page_title Resque
+%br
+.ui-box
+ %iframe{src: resque_url, width: '100%', height: 600, style: "border: none"}
diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml
index 6a128de9..9cd94fdd 100644
--- a/app/views/admin/team_members/_form.html.haml
+++ b/app/views/admin/team_members/_form.html.haml
@@ -8,20 +8,9 @@
.clearfix
%label Project Access:
.input
- = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select"
+ = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
%br
.actions
= f.submit 'Save', class: "btn primary"
= link_to 'Cancel', :back, class: "btn"
-
-:css
- form select {
- width:300px;
- }
-
-:javascript
- $('select#team_member_user_id').chosen();
- $('select#team_member_project_id').chosen();
- $('select#team_member_repo_access').chosen();
- $('select#team_member_project_access').chosen();
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 4d2b9832..731916e9 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -68,8 +68,8 @@
%th Project Access:
%tr
- %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true
- %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
+ %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
+ %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
%tr
%td= submit_tag 'Add', class: "btn primary"
@@ -97,17 +97,3 @@
%td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), class: "medium project-access-select", disabled: :disabled
%td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
%td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
-
-:css
- form select {
- width:150px;
- }
-
- #project_ids {
- width:300px;
- }
-
-:javascript
- $('select#project_ids').chosen();
- $('select#repo_access').chosen();
- $('select#project_access').chosen();
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index 506f4e09..572337de 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -11,10 +11,10 @@
= link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
%strong Browse Code »
%h3.commit-title.page_title
- = gfm @commit.title
+ = gfm escape_once(@commit.title)
- if @commit.description.present?
%pre.commit-description
- = gfm @commit.description
+ = gfm escape_once(@commit.description)
.commit-info
.row
.span4
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index a211329f..a8111a72 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -1,9 +1,5 @@
%ul.nav.nav-tabs
- %li
- = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
- = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
- = hidden_field_tag :destination, "commits"
-
+ %li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'}
%li{class: "#{'active' if current_page?(project_commits_path(@project)) }"}
= link_to project_commits_path(@project) do
Commits
@@ -20,14 +16,8 @@
Tags
%span.badge= @project.repo.tag_count
-
- if current_page?(project_commits_path(@project)) && current_user.private_token
%li.right
%span.rss-icon
= link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do
= image_tag "rss_ui.png", title: "feed"
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- });
diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml
index 0f6210f2..9f5b5345 100644
--- a/app/views/commits/_text_file.html.haml
+++ b/app/views/commits/_text_file.html.haml
@@ -13,14 +13,11 @@
%td.old_line
= link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code
- if @comments_allowed
- = link_to "", "#", class: "line_note_link", "line_code" => line_code, title: "Add note for this line"
+ = render "notes/per_line_note_link", line_code: line_code
%td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} "
- if @comments_allowed
- - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse
+ - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
- unless comments.empty?
- - comments.each_with_index do |note, i|
- = render "notes/reply_button", line_code: line_code if i.zero?
- = render "notes/per_line_show", note: note
- - @line_notes.reject!{ |n| n == note }
+ = render "notes/per_line_notes_with_reply", notes: comments
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index e01f8ea5..d12fff96 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -1,6 +1,6 @@
= render "commits/commit_box"
= render "commits/diffs", diffs: @commit.diffs
-= render "notes/notes", tid: @commit.id, tt: "commit"
+= render "notes/notes_with_form", tid: @commit.id, tt: "commit"
= render "notes/per_line_form"
diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml
index e13640fb..791c18e3 100644
--- a/app/views/dashboard/index.html.haml
+++ b/app/views/dashboard/index.html.haml
@@ -31,13 +31,19 @@
%span= project_last_activity(project)
.bottom= paginate @projects, theme: "gitlab"
- %hr
%div
%span.rss-icon
= link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
= image_tag "rss_ui.png", title: "feed"
%strong News Feed
+ %hr
+ .gitlab-promo
+ = link_to "Homepage", "http://gitlabhq.com"
+ = link_to "Blog", "http://blog.gitlabhq.com"
+ = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
+
+
- else
%h3.nothing_here_message There are no projects you have access to.
%br
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 85010df7..4233aa61 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -15,7 +15,7 @@
$(function() {
$('#new_user').toggle();
});
- = form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
+= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
= f.text_field :email, :class => "text top", :placeholder => "Email"
= f.password_field :password, :class => "text bottom", :placeholder => "Password"
- if devise_mapping.rememberable?
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 6e86186c..07ecf70b 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -15,7 +15,7 @@
.right
= render :partial => "devise/shared/links"
- if devise_mapping.omniauthable?
+ %hr/
- resource_class.omniauth_providers.each do |provider|
- %hr/
- = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
- %br/
+ %span
+ = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index 1e5c00cb..cb25d831 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -5,4 +5,4 @@
%strong.cdark= commit.author_name
–
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
- = gfm truncate(commit.title, length: 50) rescue "--broken encoding"
+ = gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding"
diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml
index 66e14936..aa1d28f2 100644
--- a/app/views/events/_event_last_push.html.haml
+++ b/app/views/events/_event_last_push.html.haml
@@ -2,7 +2,7 @@
.event_lp
%div
= image_tag gravatar_icon(event.author_email), class: "avatar"
- %span Your pushed to
+ %span Your pushed to
= event.ref_type
= link_to project_commits_path(event.project, ref: event.ref_name) do
%strong= truncate(event.ref_name, length: 28)
diff --git a/app/views/events/_event_membership_changed.html.haml b/app/views/events/_event_membership_changed.html.haml
index b079c138..464f24b3 100644
--- a/app/views/events/_event_membership_changed.html.haml
+++ b/app/views/events/_event_membership_changed.html.haml
@@ -2,7 +2,7 @@
%strong #{event.author_name}
%span.event_label{class: event.action_name}= event.action_name
project
-%strong= link_to event.project.name, event.project
+%strong= link_to event.project_name, event.project
%span.cgray
= time_ago_in_words(event.created_at)
ago.
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index 23de7e8e..813ecab2 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -18,12 +18,12 @@
= f.label :assignee_id do
%i.icon-user
Assign to
- .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
+ .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
.issue_milestone
= f.label :milestone_id do
%i.icon-time
Milestone
- .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
+ .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
.issue_description
.clearfix
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index 8500cd40..64401bdd 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -4,7 +4,7 @@
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
.right
- issue.labels.each do |label|
- %span.label.label-issue.grouped
+ %span.label.label-tag.grouped
%i.icon-tag
= label.name
- if issue.notes.any?
@@ -34,5 +34,5 @@
- else
- - if issue.upvotes > 0
- %span.badge.badge-success= "+#{issue.upvotes}"
+ - if issue.votes_count > 0
+ = render 'votes/votes_inline', votable: issue
diff --git a/app/views/issues/edit.html.haml b/app/views/issues/edit.html.haml
index 3c9877f8..b1bc3ba0 100644
--- a/app/views/issues/edit.html.haml
+++ b/app/views/issues/edit.html.haml
@@ -1,8 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- $('select#issue_milestone_id').chosen();
- });
-
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index bc5c86e6..22c34baa 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -12,7 +12,7 @@
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do
= hidden_field_tag :project_id, @project.id, { id: 'project_id' }
= hidden_field_tag :status, params[:f]
- = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib' }
+ = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
.clearfix
diff --git a/app/views/issues/new.html.haml b/app/views/issues/new.html.haml
index 3c9877f8..b1bc3ba0 100644
--- a/app/views/issues/new.html.haml
+++ b/app/views/issues/new.html.haml
@@ -1,8 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- $('select#issue_milestone_id').chosen();
- });
-
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index dce8cf6a..da2aeac4 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -8,22 +8,22 @@
%span.right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
- if @issue.closed
- = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn small"
+ = link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn grouped success"
- else
- = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small", title: "Close Issue"
+ = link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped danger", title: "Close Issue"
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
- = link_to edit_project_issue_path(@project, @issue), class: "btn small" do
+ = link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
%i.icon-edit
Edit
- %br
- - if @issue.upvotes > 0
- .upvotes#upvotes= "+#{pluralize @issue.upvotes, 'upvote'}"
+.right
+ .span3#votes= render 'votes/votes_block', votable: @issue
.back_link
= link_to project_issues_path(@project) do
← To issues list
+
.main_box
.top_box_content
%h4
@@ -31,7 +31,7 @@
.alert-message.error.status_info Closed
- else
.alert-message.success.status_info Open
- = gfm @issue.title
+ = gfm escape_once(@issue.title)
.middle_box_content
%cite.cgray Created by
@@ -61,4 +61,4 @@
= markdown @issue.description
-.issue_notes#notes= render "notes/notes", tid: @issue.id, tt: "issue"
+.issue_notes.voting_notes#notes= render "notes/notes_with_form", tid: @issue.id, tt: "issue"
diff --git a/app/views/labels/_label.html.haml b/app/views/labels/_label.html.haml
index 32158c20..8a465a9e 100644
--- a/app/views/labels/_label.html.haml
+++ b/app/views/labels/_label.html.haml
@@ -1,4 +1,9 @@
%li.wll
- %strong= label.name
+ %strong
+ %i.icon-tag
+ = label.name
.right
- %span= pluralize label.count, 'issue'
+ = link_to project_issues_path(label_name: label.name) do
+ %strong
+ = pluralize(label.count, 'issue')
+ = "»"
diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml
index b624415d..62c8db5b 100644
--- a/app/views/layouts/profile.html.haml
+++ b/app/views/layouts/profile.html.haml
@@ -9,20 +9,20 @@
%li.home{class: tab_class(:profile)}
= link_to "Profile", profile_path
- %li{class: tab_class(:password)}
- = link_to "Password", profile_password_path
+ %li{class: tab_class(:account)}
+ = link_to "Account", profile_account_path
%li{class: tab_class(:ssh_keys)}
= link_to keys_path do
SSH Keys
%span.count= current_user.keys.count
- %li{class: tab_class(:token)}
- = link_to "Token", profile_token_path
-
%li{class: tab_class(:design)}
= link_to "Design", profile_design_path
+ %li{class: tab_class(:history)}
+ = link_to "History", profile_history_path
+
.content
= yield
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index d5271ed0..96692c0f 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -16,7 +16,7 @@
.padded
= f.label :source_branch, "From", class: "control-label"
.controls
- = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
+ = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
.mr_source_commit
.span2
@@ -28,7 +28,7 @@
.padded
= f.label :target_branch, "To", class: "control-label"
.controls
- = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
+ = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
.mr_target_commit
%h4.cdark 2. Fill info
@@ -43,7 +43,7 @@
= f.label :assignee_id do
%i.icon-user
Assign to
- .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, style: "width:250px")
+ .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
.control-group
@@ -56,18 +56,12 @@
= link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
Cancel
-
-
:javascript
$(function(){
disableButtonIfEmptyField("#merge_request_title", ".save-btn");
- $('select#merge_request_assignee_id').chosen();
- $('select#merge_request_source_branch').chosen();
- $('select#merge_request_target_branch').chosen();
var source_branch = $("#merge_request_source_branch");
var target_branch = $("#merge_request_target_branch");
-
$.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() });
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() });
@@ -79,4 +73,3 @@
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() });
});
});
-
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index 74996090..9d94d670 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -23,5 +23,6 @@
authored by #{merge_request.author_name}
= time_ago_in_words(merge_request.created_at)
ago
- - if merge_request.upvotes > 0
- %span.badge.badge-success= "+#{merge_request.upvotes}"
+
+ - if merge_request.votes_count > 0
+ = render 'votes/votes_inline', votable: merge_request
diff --git a/app/views/merge_requests/_show.html.haml b/app/views/merge_requests/_show.html.haml
index f1b3fa9f..f1d0c8aa 100644
--- a/app/views/merge_requests/_show.html.haml
+++ b/app/views/merge_requests/_show.html.haml
@@ -15,8 +15,8 @@
%i.icon-list-alt
Diff
-.merge_request_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
- = render("notes/notes", tid: @merge_request.id, tt: "merge_request")
+.merge_request_notes.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
+ = render("notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")
.merge-request-diffs
= render "merge_requests/show/diffs" if @diffs
.status
diff --git a/app/views/merge_requests/diffs.html.haml b/app/views/merge_requests/diffs.html.haml
index 176b19bc..a755491c 100644
--- a/app/views/merge_requests/diffs.html.haml
+++ b/app/views/merge_requests/diffs.html.haml
@@ -1,2 +1,6 @@
= render "show"
+:javascript
+ $(function(){
+ PerLineNotes.init();
+ });
diff --git a/app/views/merge_requests/diffs.js.haml b/app/views/merge_requests/diffs.js.haml
index b147e5be..98539985 100644
--- a/app/views/merge_requests/diffs.js.haml
+++ b/app/views/merge_requests/diffs.js.haml
@@ -1,4 +1,7 @@
:plain
$(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
+ $(function(){
+ PerLineNotes.init();
+ });
diff --git a/app/views/merge_requests/show.js.haml b/app/views/merge_requests/show.js.haml
index 7a27b166..f44ccbb5 100644
--- a/app/views/merge_requests/show.js.haml
+++ b/app/views/merge_requests/show.js.haml
@@ -1,2 +1,2 @@
:plain
- $(".merge-request-notes").html("#{escape_javascript(render("notes/notes", tid: @merge_request.id, tt: "merge_request"))}");
+ $(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")}");
diff --git a/app/views/merge_requests/show/_mr_box.html.haml b/app/views/merge_requests/show/_mr_box.html.haml
index 81ab83f3..89c3110b 100644
--- a/app/views/merge_requests/show/_mr_box.html.haml
+++ b/app/views/merge_requests/show/_mr_box.html.haml
@@ -5,7 +5,7 @@
.alert-message.error.status_info Closed
- else
.alert-message.success.status_info Open
- = gfm @merge_request.title
+ = gfm escape_once(@merge_request.title)
.middle_box_content
%div
diff --git a/app/views/merge_requests/show/_mr_title.html.haml b/app/views/merge_requests/show/_mr_title.html.haml
index 3ae1050d..8708469c 100644
--- a/app/views/merge_requests/show/_mr_title.html.haml
+++ b/app/views/merge_requests/show/_mr_title.html.haml
@@ -23,10 +23,8 @@
%i.icon-edit
Edit
- %br
- - if @merge_request.upvotes > 0
- .upvotes#upvotes= "+#{pluralize @merge_request.upvotes, 'upvote'}"
-
+.right
+ .span3#votes= render 'votes/votes_block', votable: @merge_request
.back_link
= link_to project_merge_requests_path(@project) do
diff --git a/app/views/milestones/edit.html.haml b/app/views/milestones/edit.html.haml
index af975a84..b1bc3ba0 100644
--- a/app/views/milestones/edit.html.haml
+++ b/app/views/milestones/edit.html.haml
@@ -1,7 +1 @@
= render "form"
-
-:javascript
- $(function(){
- $('select#issue_assignee_id').chosen();
- });
-
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index 0d6cb2a0..ba71ead7 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -21,7 +21,7 @@
.alert-message.error.status_info Closed
- else
.alert-message.success.status_info Open
- = gfm @milestone.title
+ = gfm escape_once(@milestone.title)
%small.right= @milestone.expires_at
.middle_box_content
diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_common_form.html.haml
similarity index 97%
rename from app/views/notes/_form.html.haml
rename to app/views/notes/_common_form.html.haml
index 6d559cfc..fc6e3c7e 100644
--- a/app/views/notes/_form.html.haml
+++ b/app/views/notes/_common_form.html.haml
@@ -14,7 +14,7 @@
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
.clearfix
- .row.note_advanced_opts.hide
+ .row.note_advanced_opts
.span3
= f.submit 'Add Comment', class: "btn success submit_note grouped", id: "submit_note"
= link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'
diff --git a/app/views/notes/_create_common.js.haml b/app/views/notes/_create_common_note.js.haml
similarity index 72%
rename from app/views/notes/_create_common.js.haml
rename to app/views/notes/_create_common_note.js.haml
index e80eccb1..bbebc247 100644
--- a/app/views/notes/_create_common.js.haml
+++ b/app/views/notes/_create_common_note.js.haml
@@ -5,8 +5,9 @@
$('.note-form-holder #preview-link').text('Preview');
$('.note-form-holder #preview-note').hide();
$('.note-form-holder').show();
- NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
+ NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
+
- else
:plain
- $(".note-form-holder").replaceWith("#{escape_javascript(render('form'))}");
+ $(".note-form-holder").replaceWith("#{escape_javascript(render 'form')}");
diff --git a/app/views/notes/_create_line.js.haml b/app/views/notes/_create_line.js.haml
deleted file mode 100644
index 662909f7..00000000
--- a/app/views/notes/_create_line.js.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-- if note.valid?
- :plain
- $(".per_line_form").hide();
- $('.line-note-form-holder textarea').val("");
- $("a.line_note_reply_link[line_code='#{note.line_code}']").closest("tr").remove();
- var trEl = $(".#{note.line_code}").parent();
- trEl.after("#{escape_javascript(render partial: "notes/per_line_show", locals: {note: note})}");
- trEl.after("#{escape_javascript(render partial: "notes/reply_button", locals: {line_code: note.line_code})}");
diff --git a/app/views/notes/_create_per_line_note.js.haml b/app/views/notes/_create_per_line_note.js.haml
new file mode 100644
index 00000000..180960e3
--- /dev/null
+++ b/app/views/notes/_create_per_line_note.js.haml
@@ -0,0 +1,19 @@
+- if note.valid?
+ :plain
+ // hide and reset the form
+ $(".per_line_form").hide();
+ $('.line-note-form-holder textarea').val("");
+
+ // find the reply button for this line
+ // (might not be there if this is the first note)
+ var trRpl = $("a.line_note_reply_link[data-line-code='#{note.line_code}']").closest("tr");
+ if (trRpl.size() == 0) {
+ // find the commented line ...
+ var trEl = $(".#{note.line_code}").parent();
+ // ... and insert the note and the reply button after it
+ trEl.after("#{escape_javascript(render "notes/per_line_reply_button", line_code: note.line_code)}");
+ trEl.after("#{escape_javascript(render "notes/per_line_note", note: note)}");
+ } else {
+ // instert new note before reply button
+ trRpl.before("#{escape_javascript(render "notes/per_line_note", note: note)}");
+ }
diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml
deleted file mode 100644
index c16a699a..00000000
--- a/app/views/notes/_load.js.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-- unless @notes.blank?
- - if params[:last_id]
- :plain
- NoteList.replace("#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
- - elsif params[:first_id]
- :plain
- NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
- - else
- :plain
- NoteList.setContent(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
-
-- else
- - if params[:first_id]
- :plain
- NoteList.append(#{params[:first_id]}, "");
diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_note.html.haml
similarity index 73%
rename from app/views/notes/_show.html.haml
rename to app/views/notes/_note.html.haml
index 3412e4eb..5234e55d 100644
--- a/app/views/notes/_show.html.haml
+++ b/app/views/notes/_note.html.haml
@@ -1,4 +1,4 @@
-%li{id: dom_id(note), class: "note"}
+%li{id: dom_id(note), class: "note #{note_vote_class(note)}"}
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
%div.note-author
%strong= note.author_name
@@ -6,8 +6,16 @@
%cite.cgray
= time_ago_in_words(note.updated_at)
ago
+ - if note.upvote?
+ %span.label.label-success
+ %i.icon-thumbs-up
+ \+1
+ - if note.downvote?
+ %span.label.label-error
+ %i.icon-thumbs-down
+ \-1
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
- = link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
+ = link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
%i.icon-trash
Remove
diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml
index e692e746..adb5dfcb 100644
--- a/app/views/notes/_notes.html.haml
+++ b/app/views/notes/_notes.html.haml
@@ -1,13 +1,4 @@
-- if can? current_user, :write_note, @project
- = render "notes/form"
-.clear
-%hr
-%ul#new_notes_list
-%ul#notes-list
-.status
+- @notes.each do |note|
+ - next unless note.author
+ = render "note", note: note
-
-:javascript
- $(function(){
- NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
- });
diff --git a/app/views/notes/_notes_list.html.haml b/app/views/notes/_notes_list.html.haml
deleted file mode 100644
index 5673988d..00000000
--- a/app/views/notes/_notes_list.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- @notes.each do |note|
- - next unless note.author
- = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_notes_with_form.html.haml b/app/views/notes/_notes_with_form.html.haml
new file mode 100644
index 00000000..53716c1d
--- /dev/null
+++ b/app/views/notes/_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+%ul#notes-list
+%ul#new-notes-list
+.notes-status
+
+- if can? current_user, :write_note, @project
+ = render "notes/common_form"
+
+:javascript
+ $(function(){
+ NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+ });
diff --git a/app/views/notes/_per_line_note.html.haml b/app/views/notes/_per_line_note.html.haml
new file mode 100644
index 00000000..28bcd6e0
--- /dev/null
+++ b/app/views/notes/_per_line_note.html.haml
@@ -0,0 +1,5 @@
+%tr.line_notes_row
+ %td{colspan: 3}
+ %ul
+ = render "notes/note", note: note
+
diff --git a/app/views/notes/_per_line_note_link.html.haml b/app/views/notes/_per_line_note_link.html.haml
new file mode 100644
index 00000000..72b59a59
--- /dev/null
+++ b/app/views/notes/_per_line_note_link.html.haml
@@ -0,0 +1 @@
+= link_to "", "#", class: "line_note_link", data: { line_code: line_code }, title: "Add note for this line"
diff --git a/app/views/notes/_per_line_notes_with_reply.html.haml b/app/views/notes/_per_line_notes_with_reply.html.haml
new file mode 100644
index 00000000..1bcfc41f
--- /dev/null
+++ b/app/views/notes/_per_line_notes_with_reply.html.haml
@@ -0,0 +1,3 @@
+- notes.each do |note|
+ = render "notes/per_line_note", note: note
+= render "notes/per_line_reply_button", line_code: notes.first.line_code
diff --git a/app/views/notes/_per_line_reply_button.html.haml b/app/views/notes/_per_line_reply_button.html.haml
new file mode 100644
index 00000000..42c737c7
--- /dev/null
+++ b/app/views/notes/_per_line_reply_button.html.haml
@@ -0,0 +1,4 @@
+%tr.line_notes_row.reply
+ %td{colspan: 3}
+ %i.icon-comment
+ = link_to "Reply", "#", class: "line_note_reply_link", data: { line_code: line_code }, title: "Add note for this line"
diff --git a/app/views/notes/_per_line_show.html.haml b/app/views/notes/_per_line_show.html.haml
deleted file mode 100644
index cf1769c0..00000000
--- a/app/views/notes/_per_line_show.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%tr.line_notes_row
- %td{colspan: 3}
- %ul
- = render partial: "notes/show", locals: {note: note}
-
diff --git a/app/views/notes/_reply_button.html.haml b/app/views/notes/_reply_button.html.haml
deleted file mode 100644
index c981fb9f..00000000
--- a/app/views/notes/_reply_button.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-%tr.line_notes_row.reply
- %td{colspan: 3}
- %i.icon-comment
- = link_to "Reply", "#", class: "line_note_reply_link", "line_code" => line_code, title: "Add note for this line"
diff --git a/app/views/notes/_reversed_notes_with_form.html.haml b/app/views/notes/_reversed_notes_with_form.html.haml
new file mode 100644
index 00000000..24d59924
--- /dev/null
+++ b/app/views/notes/_reversed_notes_with_form.html.haml
@@ -0,0 +1,11 @@
+- if can? current_user, :write_note, @project
+ = render "notes/common_form"
+
+%ul.reversed#new-notes-list
+%ul.reversed#notes-list
+.notes-status
+
+:javascript
+ $(function(){
+ NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
+ });
diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml
index 8f631f38..03866591 100644
--- a/app/views/notes/create.js.haml
+++ b/app/views/notes/create.js.haml
@@ -1,7 +1,7 @@
- if @note.line_code
- = render "create_line", note: @note
+ = render "create_per_line_note", note: @note
- else
- = render "create_common", note: @note
+ = render "create_common_note", note: @note
-# Enable submit button
:plain
diff --git a/app/views/notes/index.js.haml b/app/views/notes/index.js.haml
index ee31c0b8..3814dbd4 100644
--- a/app/views/notes/index.js.haml
+++ b/app/views/notes/index.js.haml
@@ -1 +1,17 @@
-= render "notes/load"
+- unless @notes.blank?
+ - if loading_more_notes?
+ :plain
+ NoteList.appendMoreNotes(#{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+ - elsif loading_new_notes?
+ :plain
+ NoteList.replaceNewNotes("#{escape_javascript(render 'notes/notes')}");
+
+ - else
+ :plain
+ NoteList.setContent(#{@notes.first.id}, #{@notes.last.id}, "#{escape_javascript(render 'notes/notes')}");
+
+- else
+ - if loading_more_notes?
+ :plain
+ NoteList.finishedLoadingMore();
diff --git a/app/views/profile/account.html.haml b/app/views/profile/account.html.haml
new file mode 100644
index 00000000..6707a8ff
--- /dev/null
+++ b/app/views/profile/account.html.haml
@@ -0,0 +1,57 @@
+- if Gitlab.config.omniauth_enabled?
+ %fieldset
+ %legend
+ %h3.page_title Social Accounts
+ .oauth_select_holder
+ %p.hint Tip: Click on icon to activate sigin with one of the following services
+ - User.omniauth_providers.each do |provider|
+ %span{class: oauth_active_class(provider) }
+ = link_to authbutton(provider, 32), omniauth_authorize_path(User, provider)
+
+
+%fieldset
+ %legend
+ %h3.page_title
+ Private token
+ %span.cred.right
+ keep it in secret!
+ .padded
+ = form_for @user, url: profile_reset_private_token_path, method: :put do |f|
+ .data
+ %p.slead
+ Private token used to access application resources without authentication.
+ %br
+ It can be used for atom feed or API
+ %p.cgray
+ - if current_user.private_token
+ = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
+ = f.submit 'Reset', confirm: "Are you sure?", class: "btn primary btn-build-token"
+ - else
+ %span You don`t have one yet. Click generate to fix it.
+ = f.submit 'Generate', class: "btn success btn-build-token"
+
+%fieldset
+ %legend
+ %h3.page_title Password
+ = form_for @user, url: profile_password_path, method: :put do |f|
+ .padded
+ %p.slead After successful password update you will be redirected to login page where you should login with new password
+ -if @user.errors.any?
+ .alert-message.block-message.error
+ %ul
+ - @user.errors.full_messages.each do |msg|
+ %li= msg
+
+ .clearfix
+ = f.label :password
+ .input= f.password_field :password
+ .clearfix
+ = f.label :password_confirmation
+ .input= f.password_field :password_confirmation
+ .actions
+ = f.submit 'Save', class: "btn save-btn"
+
+
+
+
+
diff --git a/app/views/profile/history.html.haml b/app/views/profile/history.html.haml
new file mode 100644
index 00000000..aa7006c5
--- /dev/null
+++ b/app/views/profile/history.html.haml
@@ -0,0 +1,5 @@
+.profile_history
+ = render @events
+%hr
+= paginate @events, theme: "gitlab"
+
diff --git a/app/views/profile/password.html.haml b/app/views/profile/password.html.haml
deleted file mode 100644
index d0aee7ac..00000000
--- a/app/views/profile/password.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-%h3.page_title Password
-%hr
-= form_for @user, url: profile_password_path, method: :put do |f|
- .data
- %p.slead After successful password update you will be redirected to login page where you should login with new password
- -if @user.errors.any?
- .alert-message.block-message.error
- %ul
- - @user.errors.full_messages.each do |msg|
- %li= msg
-
- .clearfix
- = f.label :password
- .input= f.password_field :password
- .clearfix
- = f.label :password_confirmation
- .input= f.password_field :password_confirmation
- .actions
- = f.submit 'Save', class: "btn save-btn"
diff --git a/app/views/profile/show.html.haml b/app/views/profile/show.html.haml
index 22e840a0..7b625291 100644
--- a/app/views/profile/show.html.haml
+++ b/app/views/profile/show.html.haml
@@ -6,7 +6,6 @@
%small
= @user.email
-
%hr
= form_for @user, url: profile_update_path, method: :put, html: { class: "edit_user form-horizontal" } do |f|
@@ -28,7 +27,23 @@
= f.text_field :email, class: "input-xlarge"
%span.help-block We also use email for avatar detection.
- %hr
+ .span5.right
+ %div.tips
+ %h6 Tips:
+ %ul
+ -unless Gitlab.config.disable_gravatar?
+ %li
+ %p.hint You can change your avatar at #{link_to "gravatar.com", "http://gravatar.com"}
+
+ - if Gitlab.config.omniauth_enabled? && @user.provider?
+ %li
+ %p.hint
+ You can login through #{@user.provider.titleize}!
+ = link_to "click here to change", profile_account_path
+
+ %hr
+ .row
+ .span7
.control-group
= f.label :skype, class: "control-label"
.controls= f.text_field :skype, class: "input-xlarge"
@@ -44,27 +59,24 @@
= f.text_area :bio, rows: 6, class: "input-xlarge", maxlength: 250
%span.help-block Tell us about yourself in fewer than 250 characters.
.span5.right
+ .ui-box.white
+ .ui-box-body
+ %h4
+ Personal projects:
+ %small.right
+ %span= current_user.my_own_projects.count
+ of
+ %span= current_user.projects_limit
+ .progress
+ .bar{style: "width: #{current_user.projects_limit_percent}%;"}
- -unless Gitlab.config.disable_gravatar?
- %p.alert.alert-info
- %strong Tip:
- You can change your avatar at gravatar.com
+ .ui-box.white
+ .ui-box-body
+ %h4
+ SSH public keys:
+ %strong.right= link_to current_user.keys.count, keys_path
- %h4
- Personal projects:
- %small.right
- %span= current_user.my_own_projects.count
- of
- %span= current_user.projects_limit
- .progress
- .bar{style: "width: #{current_user.projects_limit_percent}%;"}
-
- %h4
- SSH public keys:
- %small.right
- %span= link_to current_user.keys.count, keys_path
-
- = link_to "Add Public Key", new_key_path, class: "btn small right"
+ = link_to "Add Public Key", new_key_path, class: "btn small"
.form-actions
= f.submit 'Save', class: "btn save-btn"
diff --git a/app/views/profile/token.html.haml b/app/views/profile/token.html.haml
deleted file mode 100644
index 6c870c36..00000000
--- a/app/views/profile/token.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-%h3.page_title
- Private token
- %span.cred.right
- keep it in secret!
-%hr
-= form_for @user, url: profile_reset_private_token_path, method: :put do |f|
- .data
- %p.slead
- Private token used to access application resources without authentication.
- %br
- It can be used for atom feed or API
- %p.cgray
- - if current_user.private_token
- = text_field_tag "token", current_user.private_token, class: "xxlarge large_text"
- - else
- You don`t have one yet. Click generate to fix it.
- .actions
- - if current_user.private_token
- = f.submit 'Reset', confirm: "Are you sure?", class: "btn"
- - else
- = f.submit 'Generate', class: "btn primary"
-
-
diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml
index ba64ee7f..4f38bef8 100644
--- a/app/views/projects/_project_head.html.haml
+++ b/app/views/projects/_project_head.html.haml
@@ -3,8 +3,8 @@
= link_to project_path(@project), class: "activities-tab tab" do
%i.icon-home
Show
- %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(team_project_path(@project)) }" }
- = link_to team_project_path(@project), class: "team-tab tab" do
+ %li{ class: " #{'active' if (controller.controller_name == "team_members") || current_page?(project_team_index_path(@project)) }" }
+ = link_to project_team_index_path(@project), class: "team-tab tab" do
%i.icon-user
Team
%li{ class: "#{'active' if current_page?(files_project_path(@project)) }" }
diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml
deleted file mode 100644
index 804b8523..00000000
--- a/app/views/projects/_refs.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
- = select_tag "ref", grouped_options_refs, onchange: "this.form.submit();", class: "project-refs-select"
- = hidden_field_tag :destination, destination
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- })
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 987d43ec..fdd537da 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -3,10 +3,10 @@
%h3.page_title Edit Project
%hr
= render "projects/form"
-%div.ajax_loader.hide
+%div.save-project-loader.hide
%center
- %div.padded= image_tag "ajax_loader.gif"
- %h3.prepend-top Saving project & repository. Please wait...
+ = image_tag "ajax_loader.gif"
+ %h3 Saving project. Please wait a few minutes
:javascript
$(function(){ new Projects(); });
diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml
index 97765d7a..591a8cd0 100644
--- a/app/views/projects/wall.html.haml
+++ b/app/views/projects/wall.html.haml
@@ -1,2 +1,2 @@
%div.wall_page
- = render "notes/notes", tid: nil, tt: "wall"
+ = render "notes/reversed_notes_with_form", tid: nil, tt: "wall"
diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml
index 33bb448a..43884de1 100644
--- a/app/views/protected_branches/index.html.haml
+++ b/app/views/protected_branches/index.html.haml
@@ -19,7 +19,7 @@
.entry.clearfix
= f.label :name, "Branch"
.span3
- = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { include_blank: "-- Select branch" }, { class: "span3" })
+ = f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: "Select branch"}, {class: "chosen span3"})
= f.submit 'Protect', class: "primary btn"
@@ -46,6 +46,3 @@
%td
- if can? current_user, :admin_project, @project
= link_to 'Unprotect', [@project, branch], confirm: 'Are you sure?', method: :delete, class: "danger btn small"
-
-:javascript
- $('select#protected_branch_name').chosen();
diff --git a/app/views/refs/_head.html.haml b/app/views/refs/_head.html.haml
index d51602de..3592f573 100644
--- a/app/views/refs/_head.html.haml
+++ b/app/views/refs/_head.html.haml
@@ -1,9 +1,6 @@
%ul.nav.nav-tabs
%li
- = form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form", remote: true do
- = select_tag "ref", grouped_options_refs, onchange: "$(this.form).trigger('submit');", class: "project-refs-select"
- = hidden_field_tag :destination, "tree"
- = hidden_field_tag :path, params[:path]
+ = render partial: 'shared/ref_switcher', locals: {destination: 'tree', path: params[:path]}
%li{class: "#{'active' if (controller.controller_name == "refs") }"}
= link_to tree_project_ref_path(@project, @ref) do
Source
diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml
index 297a3b5f..ec6dba4e 100644
--- a/app/views/refs/_tree.html.haml
+++ b/app/views/refs/_tree.html.haml
@@ -47,17 +47,15 @@
:javascript
$(function(){
- $('.project-refs-select').chosen();
-
history.pushState({ path: this.path }, '', "#{@history_path}");
-
- });
-
- // Load last commit log for each file in tree
- $(window).load(function(){
- ajaxGet('#{@logs_path}');
});
+- unless tree.is_blob?
+ :javascript
+ // Load last commit log for each file in tree
+ $(window).load(function(){
+ ajaxGet('#{@logs_path}');
+ });
- if params[:path] && request.xhr?
:javascript
diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml
index 765f271a..f6566ccf 100644
--- a/app/views/refs/_tree_file.html.haml
+++ b/app/views/refs/_tree_file.html.haml
@@ -2,7 +2,7 @@
.file_title
%i.icon-file
%span.file_name
- = name
+ = name.force_encoding('utf-8')
%small #{file.mode}
%span.options
= link_to "raw", blob_project_ref_path(@project, @ref, path: params[:path]), class: "btn very_small", target: "_blank"
diff --git a/app/views/refs/blame.html.haml b/app/views/refs/blame.html.haml
index 34478d4b..eb66f597 100644
--- a/app/views/refs/blame.html.haml
+++ b/app/views/refs/blame.html.haml
@@ -38,8 +38,3 @@
= preserve do
%pre
= Gitlab::Encode.utf8 lines.join("\n")
-
-:javascript
- $(function(){
- $('.project-refs-select').chosen();
- });
diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml
index cf8558ec..64a633be 100644
--- a/app/views/repositories/_branch.html.haml
+++ b/app/views/repositories/_branch.html.haml
@@ -11,7 +11,7 @@
%code= commit.short_id
= image_tag gravatar_icon(commit.author_email), class: "", width: 16
- = gfm truncate(commit.title, length: 40)
+ = gfm escape_once(truncate(commit.title, length: 40))
%span.update-author.right
= time_ago_in_words(commit.committed_date)
ago
diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml
index ac4eb483..0c13551d 100644
--- a/app/views/repositories/_feed.html.haml
+++ b/app/views/repositories/_feed.html.haml
@@ -13,7 +13,7 @@
= link_to project_commits_path(@project, commit.id) do
%code= commit.short_id
= image_tag gravatar_icon(commit.author_email), class: "", width: 16
- = gfm truncate(commit.title, length: 40)
+ = gfm escape_once(truncate(commit.title, length: 40))
%td
%span.right.cgray
= time_ago_in_words(commit.committed_date)
diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml
index 0e870c80..a4114586 100644
--- a/app/views/repositories/tags.html.haml
+++ b/app/views/repositories/tags.html.haml
@@ -17,7 +17,7 @@
= link_to project_commit_path(@project, commit.id) do
%code= commit.short_id
= image_tag gravatar_icon(commit.author_email), class: "", width: 16
- = gfm truncate(commit.title, length: 40)
+ = gfm escape_once(truncate(commit.title, length: 40))
%td
%span.update-author.right
= time_ago_in_words(commit.committed_date)
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index b4a38b57..d85c24ec 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -3,8 +3,8 @@
= label_tag :search do
%strong Looking for
.input
- = text_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge", id: "dashboard_search"
- = submit_tag 'Search', class: "btn primary"
+ = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
+ = submit_tag 'Search', class: "btn primary wide"
- if params[:search].present?
%br
%h3
@@ -15,8 +15,9 @@
.row
.span6
%table
- %tr
- %th Projects
+ %thead
+ %tr
+ %th Projects
%tbody
- @projects.each do |project|
%tr
@@ -32,8 +33,9 @@
%h4.nothing_here_message No Projects
%br
%table
- %tr
- %th Merge Requests
+ %thead
+ %tr
+ %th Merge Requests
%tbody
- @merge_requests.each do |merge_request|
%tr
@@ -50,8 +52,9 @@
%h4.nothing_here_message No Merge Requests
.span6
%table
- %tr
- %th Issues
+ %thead
+ %tr
+ %th Issues
%tbody
- @issues.each do |issue|
%tr
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
new file mode 100644
index 00000000..e0c89522
--- /dev/null
+++ b/app/views/shared/_ref_switcher.html.haml
@@ -0,0 +1,5 @@
+= form_tag switch_project_refs_path(@project), method: :get, class: "project-refs-form" do
+ = select_tag "ref", grouped_options_refs, class: "project-refs-select chosen"
+ = hidden_field_tag :destination, destination
+ - if respond_to?(:path)
+ = hidden_field_tag :path, path
diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml
index b8d8c098..e61e61a7 100644
--- a/app/views/snippets/_form.html.haml
+++ b/app/views/snippets/_form.html.haml
@@ -16,7 +16,7 @@
.input= f.text_field :file_name, placeholder: "example.rb"
.clearfix
= f.label "Lifetime"
- .input= f.select :expires_at, lifetime_select_options, {}, style: "width:200px;"
+ .input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
.clearfix
= f.label :content, "Code"
.input= f.text_area :content, class: "span8"
@@ -26,11 +26,3 @@
= link_to "Cancel", project_snippets_path(@project), class: " btn"
- unless @snippet.new_record?
.right= link_to 'Destroy', [@project, @snippet], confirm: 'Are you sure?', method: :delete, class: "btn right danger delete-snippet", id: "destroy_snippet_#{@snippet.id}"
-
-
-
-:javascript
- $(function(){
- $('select#snippet_expires_at').chosen();
- });
-
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 0800b81d..4188a9f1 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -17,4 +17,4 @@
%div{class: current_user.dark_scheme ? "black" : ""}
= raw @snippet.colorize(options: { linenos: 'True'})
-= render "notes/notes", tid: @snippet.id, tt: "snippet"
+= render "notes/notes_with_form", tid: @snippet.id, tt: "snippet"
diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml
index 192f2735..92167138 100644
--- a/app/views/team_members/_form.html.haml
+++ b/app/views/team_members/_form.html.haml
@@ -10,21 +10,14 @@
%h6 1. Choose people you want in the team
.clearfix
- = f.label :user_ids, "Peolpe"
- .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), { class: "xxlarge", multiple: true })
-
+ = f.label :user_ids, "People"
+ .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
%h6 2. Set access level for them
.clearfix
= f.label :project_access, "Project Access"
- .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select"
-
+ .input= select_tag :project_access, options_for_select(Project.access_options, @team_member.project_access), class: "project-access-select chosen"
.actions
= f.submit 'Save', class: "btn save-btn"
- = link_to "Cancel", team_project_path(@project), class: "btn cancel-btn"
-
-
-:javascript
- $('select#user_ids').chosen();
- $('select#project_access').chosen();
+ = link_to "Cancel", project_team_index_path(@project), class: "btn cancel-btn"
diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml
index d9a72494..f68f8eb4 100644
--- a/app/views/team_members/_show.html.haml
+++ b/app/views/team_members/_show.html.haml
@@ -1,20 +1,26 @@
- user = member.user
- allow_admin = can? current_user, :admin_project, @project
%tr{id: dom_id(member), class: "team_member_row user_#{user.id}"}
- %td
+ %td.span6
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
= image_tag gravatar_icon(user.email, 40), class: "avatar s32"
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
%strong= truncate(user.name, lenght: 40)
- %br
- %div.cgray= user.email
+ %br
+ %small.cgray= user.email
- %td
+ %td.span5
.right
+ - if current_user == user
+ %span.btn.disabled This is you!
- if @project.owner == user
- %span.btn.disabled.success Project Owner
- - if user.blocked
+ %span.btn.disabled.success Owner
+ - elsif user.blocked
%span.btn.disabled.blocked Blocked
+ - elsif allow_admin
+ = link_to project_team_member_path(project_id: @project, id: member.id), confirm: remove_from_team_message(@project, member), method: :delete, class: "very_small btn danger" do
+ %i.icon-minus.icon-white
+
- if allow_admin
= form_for(member, as: :team_member, url: project_team_member_path(@project, member)) do |f|
- = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select"
+ = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, class: "medium project-access-select span2"
diff --git a/app/views/projects/_team.html.haml b/app/views/team_members/_team.html.haml
similarity index 100%
rename from app/views/projects/_team.html.haml
rename to app/views/team_members/_team.html.haml
diff --git a/app/views/projects/team.html.haml b/app/views/team_members/index.html.haml
similarity index 79%
rename from app/views/projects/team.html.haml
rename to app/views/team_members/index.html.haml
index e8a825c7..b3b7b72a 100644
--- a/app/views/projects/team.html.haml
+++ b/app/views/team_members/index.html.haml
@@ -1,4 +1,4 @@
-= render "project_head"
+= render "projects/project_head"
%h3.page_title
Team Members
%small (#{@project.users_projects.count})
@@ -10,6 +10,4 @@
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
-
-= render partial: "team", locals: {project: @project}
-
+= render partial: "team_members/team", locals: {project: @project}
diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml
index 3b5c78a8..9d03cd2c 100644
--- a/app/views/team_members/show.html.haml
+++ b/app/views/team_members/show.html.haml
@@ -14,7 +14,7 @@
%hr
.back_link
%br
- = link_to team_project_path(@project), class: "" do
+ = link_to project_team_index_path(@project), class: "" do
← To team list
%br
.row
diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml
new file mode 100644
index 00000000..bded53b2
--- /dev/null
+++ b/app/views/votes/_votes_block.html.haml
@@ -0,0 +1,6 @@
+.votes.votes-block
+ .progress
+ .bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
+ .bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
+ .upvotes= "#{votable.upvotes} up"
+ .downvotes= "#{votable.downvotes} down"
diff --git a/app/views/votes/_votes_inline.html.haml b/app/views/votes/_votes_inline.html.haml
new file mode 100644
index 00000000..91bd200d
--- /dev/null
+++ b/app/views/votes/_votes_inline.html.haml
@@ -0,0 +1,6 @@
+.votes.votes-inline
+ .upvotes= votable.upvotes
+ .progress
+ .bar.bar-success{style: "width: #{votable.upvotes_in_percent}%;"}
+ .bar.bar-danger{style: "width: #{votable.downvotes_in_percent}%;"}
+ .downvotes= votable.downvotes
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index fc235227..579ea1b3 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -21,4 +21,4 @@
Delete this page
%hr
-.wiki_notes#notes= render "notes/notes", tid: @wiki.id, tt: "wiki"
+.wiki_notes#notes= render "notes/notes_with_form", tid: @wiki.id, tt: "wiki"
diff --git a/config/cucumber.yml b/config/cucumber.yml
deleted file mode 100644
index 19b288df..00000000
--- a/config/cucumber.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-<%
-rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
-rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
-std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
-%>
-default: <%= std_opts %> features
-wip: --tags @wip:3 --wip features
-rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 08e3427f..28323484 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -25,8 +25,43 @@ app:
# backup_keep_time: 604800 # default: 0 (forever) (in seconds)
# disable_gravatar: true # default: false - Disable user avatars from Gravatar.com
+
#
-# 2. Advanced settings:
+# 2. Auth settings
+# ==========================
+ldap:
+ enabled: false
+ host: '_your_ldap_server'
+ base: '_the_base_where_you_search_for_users'
+ port: 636
+ uid: 'sAMAccountName'
+ method: 'ssl' # plain
+ bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
+ password: '_the_password_of_the_bind_user'
+
+omniauth:
+ # Enable ability for users
+ # to login via twitter, google ..
+ enabled: false
+
+ # IMPORTANT!
+ # It allows user to login without having user account
+ allow_single_sign_on: false
+ block_auto_created_users: true
+
+ # Auth providers
+ providers:
+ # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
+ # app_secret: 'YOUR APP SECRET',
+ # args: { access_type: 'offline', approval_prompt: '' } }
+ # - { name: 'twitter', app_id: 'YOUR APP ID',
+ # app_secret: 'YOUR APP SECRET'}
+ # - { name: 'github', app_id: 'YOUR APP ID',
+ # app_secret: 'YOUR APP SECRET' }
+
+
+#
+# 3. Advanced settings:
# ==========================
# Git Hosting configuration
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index df9ccf32..7a7ca43f 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -6,7 +6,7 @@ class Settings < Settingslogic
self.web['protocol'] ||= web.https ? "https" : "http"
end
- def web_host
+ def web_host
self.web['host'] ||= 'localhost'
end
@@ -14,11 +14,11 @@ class Settings < Settingslogic
self.email['from'] ||= ("notify@" + web_host)
end
- def url
+ def url
self['url'] ||= build_url
- end
+ end
- def web_port
+ def web_port
if web.https
web['port'] = 443
else
@@ -36,7 +36,7 @@ class Settings < Settingslogic
raw_url << web_host
if web_custom_port?
- raw_url << ":#{web_port}"
+ raw_url << ":#{web_port}"
end
raw_url
@@ -120,6 +120,22 @@ class Settings < Settingslogic
app['backup_keep_time'] || 0
end
+ def ldap_enabled?
+ ldap && ldap['enabled']
+ rescue Settingslogic::MissingSetting
+ false
+ end
+
+ def omniauth_enabled?
+ omniauth && omniauth['enabled']
+ rescue Settingslogic::MissingSetting
+ false
+ end
+
+ def omniauth_providers
+ (omniauth_enabled? && omniauth['providers']) || []
+ end
+
def disable_gravatar?
app['disable_gravatar'] || false
end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 54011ba5..8f3cef5a 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -204,4 +204,21 @@ Devise.setup do |config|
# manager.intercept_401 = false
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
# end
+
+ gl = Gitlab.config
+
+ if gl.ldap_enabled?
+ config.omniauth :ldap,
+ :host => gl.ldap['host'],
+ :base => gl.ldap['base'],
+ :uid => gl.ldap['uid'],
+ :port => gl.ldap['port'],
+ :method => gl.ldap['method'],
+ :bind_dn => gl.ldap['bind_dn'],
+ :password => gl.ldap['password']
+ end
+
+ gl.omniauth_providers.each do |gl_provider|
+ config.omniauth gl_provider['name'].to_sym, gl_provider['app_id'], gl_provider['app_secret']
+ end
end
diff --git a/config/initializers/omniauth.rb.sample b/config/initializers/omniauth.rb.sample
deleted file mode 100644
index 6e844efd..00000000
--- a/config/initializers/omniauth.rb.sample
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copy this file to 'omniauth.rb' and configure it as necessary.
-# The wiki has further details on configuring each provider.
-
-Devise.setup do |config|
- # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
-
- # config.omniauth :ldap,
- # :host => 'YOUR_LDAP_SERVER',
- # :base => 'THE_BASE_WHERE_YOU_SEARCH_FOR_USERS',
- # :uid => 'sAMAccountName',
- # :port => 389,
- # :method => :plain,
- # :bind_dn => 'THE_FULL_DN_OF_THE_USER_YOU_WILL_BIND_WITH',
- # :password => 'THE_PASSWORD_OF_THE_BIND_USER'
-end
diff --git a/config/initializers/resque.rb b/config/initializers/resque.rb
new file mode 100644
index 00000000..b333ceee
--- /dev/null
+++ b/config/initializers/resque.rb
@@ -0,0 +1,8 @@
+rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
+rails_env = ENV['RAILS_ENV'] || 'development'
+config_file = File.join(rails_root, 'config', 'resque.yml')
+
+if File.exists?(config_file)
+ resque_config = YAML.load_file(config_file)
+ Resque.redis = resque_config[rails_env]
+end
diff --git a/config/resque.yml.example b/config/resque.yml.example
new file mode 100644
index 00000000..cd3d4874
--- /dev/null
+++ b/config/resque.yml.example
@@ -0,0 +1,3 @@
+development: localhost:6379
+test: localhost:6379
+production: redis.example.com:6379
diff --git a/config/routes.rb b/config/routes.rb
index ed5eac0d..cfb9bdb9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -10,7 +10,7 @@ Gitlab::Application.routes.draw do
# Optionally, enable Resque here
require 'resque/server'
- mount Resque::Server.new, at: '/info/resque', as: 'resque'
+ mount Resque::Server => '/info/resque', as: 'resque'
# Enable Grack support
mount Grack::Bundle.new({
@@ -23,14 +23,14 @@ Gitlab::Application.routes.draw do
#
# Help
#
- get 'help' => 'help#index'
- get 'help/permissions' => 'help#permissions'
- get 'help/workflow' => 'help#workflow'
- get 'help/api' => 'help#api'
- get 'help/web_hooks' => 'help#web_hooks'
+ get 'help' => 'help#index'
+ get 'help/permissions' => 'help#permissions'
+ get 'help/workflow' => 'help#workflow'
+ get 'help/api' => 'help#api'
+ get 'help/web_hooks' => 'help#web_hooks'
get 'help/system_hooks' => 'help#system_hooks'
- get 'help/markdown' => 'help#markdown'
- get 'help/ssh' => 'help#ssh'
+ get 'help/markdown' => 'help#markdown'
+ get 'help/ssh' => 'help#ssh'
#
# Admin Area
@@ -43,19 +43,19 @@ Gitlab::Application.routes.draw do
put :unblock
end
end
- resources :projects, :constraints => { :id => /[^\/]+/ } do
+ resources :projects, constraints: { id: /[^\/]+/ } do
member do
get :team
put :team_update
end
end
- resources :team_members, :only => [:edit, :update, :destroy]
- resources :hooks, :only => [:index, :create, :destroy] do
+ resources :team_members, only: [:edit, :update, :destroy]
+ resources :hooks, only: [:index, :create, :destroy] do
get :test
end
- resource :logs
- resource :resque, :controller => 'resque'
- root :to => "dashboard#index"
+ resource :logs, only: [:show]
+ resource :resque, controller: 'resque', only: [:show]
+ root to: "dashboard#index"
end
get "errors/githost"
@@ -63,38 +63,39 @@ Gitlab::Application.routes.draw do
#
# Profile Area
#
- get "profile/password", :to => "profile#password"
- put "profile/password", :to => "profile#password_update"
- get "profile/token", :to => "profile#token"
- put "profile/reset_private_token", :to => "profile#reset_private_token"
- get "profile", :to => "profile#show"
- get "profile/design", :to => "profile#design"
- put "profile/update", :to => "profile#update"
+ get "profile/account" => "profile#account"
+ get "profile/history" => "profile#history"
+ put "profile/password" => "profile#password_update"
+ get "profile/token" => "profile#token"
+ put "profile/reset_private_token" => "profile#reset_private_token"
+ get "profile" => "profile#show"
+ get "profile/design" => "profile#design"
+ put "profile/update" => "profile#update"
+
resources :keys
#
# Dashboard Area
#
- get "dashboard", :to => "dashboard#index"
- get "dashboard/issues", :to => "dashboard#issues"
- get "dashboard/merge_requests", :to => "dashboard#merge_requests"
+ get "dashboard" => "dashboard#index"
+ get "dashboard/issues" => "dashboard#issues"
+ get "dashboard/merge_requests" => "dashboard#merge_requests"
- resources :projects, :constraints => { :id => /[^\/]+/ }, :only => [:new, :create]
+ resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
- devise_for :users, :controllers => { :omniauth_callbacks => :omniauth_callbacks }
+ devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks }
#
# Project Area
#
- resources :projects, :constraints => { :id => /[^\/]+/ }, :except => [:new, :create, :index], :path => "/" do
+ resources :projects, constraints: { id: /[^\/]+/ }, except: [:new, :create, :index], path: "/" do
member do
- get "team"
get "wall"
get "graph"
get "files"
end
- resources :wikis, :only => [:show, :edit, :destroy, :create] do
+ resources :wikis, only: [:show, :edit, :destroy, :create] do
collection do
get :pages
end
@@ -113,46 +114,45 @@ Gitlab::Application.routes.draw do
end
resources :deploy_keys
- resources :protected_branches, :only => [:index, :create, :destroy]
+ resources :protected_branches, only: [:index, :create, :destroy]
- resources :refs, :only => [], :path => "/" do
+ resources :refs, only: [], path: "/" do
collection do
get "switch"
end
member do
- get "tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
- get "logs_tree", :constraints => { :id => /[a-zA-Z.\/0-9_\-]+/ }
+ get "tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
+ get "logs_tree", constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }
get "blob",
- :constraints => {
- :id => /[a-zA-Z.0-9\/_\-]+/,
- :path => /.*/
+ constraints: {
+ id: /[a-zA-Z.0-9\/_\-]+/,
+ path: /.*/
}
-
# tree viewer
get "tree/:path" => "refs#tree",
- :as => :tree_file,
- :constraints => {
- :id => /[a-zA-Z.0-9\/_\-]+/,
- :path => /.*/
+ as: :tree_file,
+ constraints: {
+ id: /[a-zA-Z.0-9\/_\-]+/,
+ path: /.*/
}
# tree viewer
get "logs_tree/:path" => "refs#logs_tree",
- :as => :logs_file,
- :constraints => {
- :id => /[a-zA-Z.0-9\/_\-]+/,
- :path => /.*/
+ as: :logs_file,
+ constraints: {
+ id: /[a-zA-Z.0-9\/_\-]+/,
+ path: /.*/
}
# blame
get "blame/:path" => "refs#blame",
- :as => :blame_file,
- :constraints => {
- :id => /[a-zA-Z.0-9\/_\-]+/,
- :path => /.*/
+ as: :blame_file,
+ constraints: {
+ id: /[a-zA-Z.0-9\/_\-]+/,
+ path: /.*/
}
end
end
@@ -177,7 +177,7 @@ Gitlab::Application.routes.draw do
end
end
- resources :hooks, :only => [:index, :create, :destroy] do
+ resources :hooks, only: [:index, :create, :destroy] do
member do
get :test
end
@@ -191,9 +191,10 @@ Gitlab::Application.routes.draw do
get :patch
end
end
+ resources :team, controller: 'team_members', only: [:index]
resources :team_members
resources :milestones
- resources :labels, :only => [:index]
+ resources :labels, only: [:index]
resources :issues do
collection do
@@ -202,11 +203,12 @@ Gitlab::Application.routes.draw do
get :search
end
end
- resources :notes, :only => [:index, :create, :destroy] do
+ resources :notes, only: [:index, :create, :destroy] do
collection do
post :preview
end
end
end
- root :to => "dashboard#index"
+
+ root to: "dashboard#index"
end
diff --git a/config/unicorn.rb.orig b/config/unicorn.rb.example
similarity index 100%
rename from config/unicorn.rb.orig
rename to config/unicorn.rb.example
diff --git a/doc/api/README.md b/doc/api/README.md
index 93919b42..9741072c 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -34,3 +34,4 @@ When listing resources you can pass the following parameters:
+ [Snippets](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/snippets.md)
+ [Issues](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/issues.md)
+ [Milestones](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/milestones.md)
++ [SSH Keys](https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/keys.md)
diff --git a/doc/api/keys.md b/doc/api/keys.md
new file mode 100644
index 00000000..d22b22e2
--- /dev/null
+++ b/doc/api/keys.md
@@ -0,0 +1,79 @@
+## List keys
+
+Get a list of currently authenticated user's keys.
+
+```
+GET /keys
+```
+
+```json
+[
+ {
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
+ },
+ {
+ "id": 3,
+ "title" : "Another Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+ }
+]
+```
+
+## Single key
+
+Get a single key.
+
+```
+GET /keys/:id
+```
+
+Parameters:
+
++ `id` (required) - The ID of a key
+
+```json
+{
+ "id": 1,
+ "title" : "Public key"
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
+ 596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
+ soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
+}
+```
+## Add key
+
+Create new key owned by currently authenticated user
+
+```
+POST /keys
+```
+
+Parameters:
+
++ `title` (required) - new SSH Key's title
++ `key` (required) - new SSH key
+
+Will return created key with status `201 Created` on success, or `404 Not
+found` on fail.
+
+## Delete key
+
+Delete key owned by currently authenticated user
+
+```
+DELETE /keys/:id
+```
+
+Parameters:
+
++ `id` (required) - key ID
+
+Will return `200 OK` on success, or `404 Not Found` on fail.
+
+
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 72874e59..73d6adc9 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -173,6 +173,50 @@ Parameters:
Will return status `200 OK` on success, or `404 Not found` on fail.
+## Get project hooks
+
+Get hooks for project
+
+```
+GET /projects/:id/hooks
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+Will return hooks with status `200 OK` on success, or `404 Not found` on fail.
+
+## Add project hook
+
+Add hook to project
+
+```
+POST /projects/:id/hooks
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `url` (required) - The hook URL
+
+Will return status `201 Created` on success, or `404 Not found` on fail.
+
+## Delete project hook
+
+Delete hook from project
+
+```
+DELETE /projects/:id/hooks
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `hook_id` (required) - The ID of hook to delete
+
+Will return status `200 OK` on success, or `404 Not found` on fail.
+
## Project repository branches
Get a list of repository branches from a project, sorted by name alphabetically.
diff --git a/doc/development.md b/doc/development.md
index 55be2bc3..67bcb8e1 100644
--- a/doc/development.md
+++ b/doc/development.md
@@ -36,10 +36,10 @@
### 3. Run Tests
# All in one
- bundle exec gitlab:test
+ bundle exec rake gitlab:test
# Rspec
bundle exec rake spec
- # Cucumber
- bundle exec rake cucumber
+ # Spinach
+ bundle exec rake spinach
diff --git a/doc/installation.md b/doc/installation.md
index af169d81..865cde3c 100644
--- a/doc/installation.md
+++ b/doc/installation.md
@@ -152,7 +152,14 @@ and ensure you have followed all of the above steps carefully.
sudo pip install pygments
sudo gem install bundler
cd /home/gitlab
+
+ # Get gitlab code. Use this for stable setup
sudo -H -u gitlab git clone -b stable https://github.com/gitlabhq/gitlabhq.git gitlab
+
+ # Skip this for stable setup.
+ # Master branch (recent changes, less stable)
+ sudo -H -u gitlab git clone -b master https://github.com/gitlabhq/gitlabhq.git gitlab
+
cd gitlab
# Rename config files
@@ -244,6 +251,14 @@ You can login via web using admin generated with setup:
# if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root
# causing the resque worker not to start via init script on next boot/service restart
+## Customizing Resque's Redis connection
+
+If you'd like Resque to connect to a Redis server on a non-standard port or on
+a different host, you can configure its connection string in the
+**config/resque.yml** file:
+
+ production: redis.example.com:6379
+
**Ok - we have a working application now. **
**But keep going - there are some things that should be done **
@@ -252,7 +267,7 @@ You can login via web using admin generated with setup:
## 1. Unicorn
cd /home/gitlab/gitlab
- sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb
+ sudo -u gitlab cp config/unicorn.rb.example config/unicorn.rb
sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
## 2. Nginx
@@ -269,7 +284,6 @@ You can login via web using admin generated with setup:
# of the host serving GitLab.
sudo vim /etc/nginx/sites-enabled/gitlab
-
# Restart nginx:
/etc/init.d/nginx restart
diff --git a/features/dashboard/dashboard.feature b/features/dashboard/dashboard.feature
index 98bb4980..9756bc7f 100644
--- a/features/dashboard/dashboard.feature
+++ b/features/dashboard/dashboard.feature
@@ -1,9 +1,9 @@
Feature: Dashboard
- Background:
- Given I signin as a user
+ Background:
+ Given I sign in as a user
And I own project "Shop"
And project "Shop" has push event
- And I visit dashboard page
+ And I visit dashboard page
Scenario: I should see projects list
Then I should see "New Project" link
@@ -25,4 +25,3 @@ Feature: Dashboard
And user with name "John Doe" left project "Shop"
When I visit dashboard page
Then I should see "John Doe left project Shop" event
-
diff --git a/features/dashboard/issues.feature b/features/dashboard/issues.feature
index c3361bb3..895b89aa 100644
--- a/features/dashboard/issues.feature
+++ b/features/dashboard/issues.feature
@@ -1,8 +1,8 @@
Feature: Dashboard Issues
- Background:
- Given I signin as a user
+ Background:
+ Given I sign in as a user
And I have assigned issues
- And I visit dashboard issues page
+ And I visit dashboard issues page
Scenario: I should see issues list
Then I should see issues assigned to me
diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature
index 90b8749c..cad65b0d 100644
--- a/features/dashboard/merge_requests.feature
+++ b/features/dashboard/merge_requests.feature
@@ -1,8 +1,8 @@
-Feature: Dashboard MR
- Background:
- Given I signin as a user
+Feature: Dashboard Merge Requests
+ Background:
+ Given I sign in as a user
And I have authored merge requests
- And I visit dashboard merge requests page
+ And I visit dashboard merge requests page
Scenario: I should see projects list
Then I should see my merge requests
diff --git a/features/dashboard/search.feature b/features/dashboard/search.feature
index f053fe86..91d870f4 100644
--- a/features/dashboard/search.feature
+++ b/features/dashboard/search.feature
@@ -1,11 +1,9 @@
Feature: Dashboard Search
- Background:
- Given I signin as a user
+ Background:
+ Given I sign in as a user
And I own project "Shop"
- And I visit dashboard search page
+ And I visit dashboard search page
- Scenario: I should see project i'm looking for
+ Scenario: I should see project I am looking for
Given I search for "Sho"
Then I should see "Shop" project link
-
-
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index afda4b55..134cabb5 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -1,6 +1,6 @@
Feature: Profile
- Background:
- Given I signin as a user
+ Background:
+ Given I sign in as a user
Scenario: I look at my profile
Given I visit profile page
@@ -12,11 +12,11 @@ Feature: Profile
And I should see new contact info
Scenario: I change my password
- Given I visit profile password page
+ Given I visit profile account page
Then I change my password
And I should be redirected to sign in page
Scenario: I reset my token
- Given I visit profile token page
+ Given I visit profile account page
Then I reset my token
And I should see new token
diff --git a/features/profile/ssh_keys.feature b/features/profile/ssh_keys.feature
index c81503ed..018d124e 100644
--- a/features/profile/ssh_keys.feature
+++ b/features/profile/ssh_keys.feature
@@ -1,13 +1,10 @@
-Feature: SSH Keys
- Background:
- Given I signin as a user
- And I have ssh keys:
- | title |
- | ssh-rsa Work |
- | ssh-rsa Home |
+Feature: Profile SSH Keys
+ Background:
+ Given I sign in as a user
+ And I have ssh key "ssh-rsa Work"
And I visit profile keys page
- Scenario: I should see SSH keys
+ Scenario: I should see ssh keys
Then I should see my ssh keys
Scenario: Add new ssh key
diff --git a/features/projects/commits/branches.feature b/features/project/commits/branches.feature
similarity index 66%
rename from features/projects/commits/branches.feature
rename to features/project/commits/branches.feature
index 74575c51..4fa4dc26 100644
--- a/features/projects/commits/branches.feature
+++ b/features/project/commits/branches.feature
@@ -1,6 +1,6 @@
-Feature: Browse branches
- Background:
- Given I signin as a user
+Feature: Project Browse branches
+ Background:
+ Given I sign in as a user
And I own project "Shop"
And project "Shop" has protected branches
Given I visit project branches page
@@ -16,8 +16,11 @@ Feature: Browse branches
Given I click link "Protected"
Then I should see "Shop" protected branches list
- Scenario: I can download project by branch
+ # @wip
+ # Scenario: I can download project by branch
- Scenario: I can view protected branches
+ # @wip
+ # Scenario: I can view protected branches
- Scenario: I can manage protected branches
+ # @wip
+ # Scenario: I can manage protected branches
diff --git a/features/projects/commits/commit_comments.feature b/features/project/commits/commit_comments.feature
similarity index 72%
rename from features/projects/commits/commit_comments.feature
rename to features/project/commits/commit_comments.feature
index 9bd56d29..5acf541a 100644
--- a/features/projects/commits/commit_comments.feature
+++ b/features/project/commits/commit_comments.feature
@@ -1,6 +1,6 @@
-Feature: Comment commit
- Background:
- Given I signin as a user
+Feature: Project Comment commit
+ Background:
+ Given I sign in as a user
And I own project "Shop"
Given I visit project commit page
diff --git a/features/projects/commits/commits.feature b/features/project/commits/commits.feature
similarity index 82%
rename from features/projects/commits/commits.feature
rename to features/project/commits/commits.feature
index 69d39d78..53de6e6a 100644
--- a/features/projects/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -1,6 +1,6 @@
-Feature: Browse commits
- Background:
- Given I signin as a user
+Feature: Project Browse commits
+ Background:
+ Given I sign in as a user
And I own project "Shop"
Given I visit project commits page
@@ -18,5 +18,4 @@ Feature: Browse commits
Scenario: I compare refs
Given I visit compare refs page
And I fill compare fields with refs
- And I see compared refs
-
+ And I see compared refs
diff --git a/features/projects/commits/tags.feature b/features/project/commits/tags.feature
similarity index 53%
rename from features/projects/commits/tags.feature
rename to features/project/commits/tags.feature
index f7899fc3..1ac0f8bf 100644
--- a/features/projects/commits/tags.feature
+++ b/features/project/commits/tags.feature
@@ -1,10 +1,11 @@
-Feature: Browse tags
- Background:
- Given I signin as a user
+Feature: Project Browse tags
+ Background:
+ Given I sign in as a user
And I own project "Shop"
Given I visit project tags page
Scenario: I can see all git tags
Then I should see "Shop" all tags list
- Scenario: I can download project by tag
+ # @wip
+ # Scenario: I can download project by tag
diff --git a/features/projects/create_project.feature b/features/project/create_project.feature
similarity index 91%
rename from features/projects/create_project.feature
rename to features/project/create_project.feature
index 42d25b3f..b7cdfdb8 100644
--- a/features/projects/create_project.feature
+++ b/features/project/create_project.feature
@@ -4,7 +4,7 @@ Feature: Create Project
Should be able to create a new one
Scenario: User create a project
- Given I signin as a user
+ Given I sign in as a user
When I visit new project page
And fill project form with valid data
Then I should see project page
diff --git a/features/projects/issues/issues.feature b/features/project/issues/issues.feature
similarity index 97%
rename from features/projects/issues/issues.feature
rename to features/project/issues/issues.feature
index b2301b3f..596e8bd7 100644
--- a/features/projects/issues/issues.feature
+++ b/features/project/issues/issues.feature
@@ -1,6 +1,6 @@
-Feature: Issues
+Feature: Project Issues
Background:
- Given I signin as a user
+ Given I sign in as a user
And I own project "Shop"
And project "Shop" have "Release 0.4" open issue
And project "Shop" have "Release 0.3" closed issue
@@ -79,4 +79,3 @@ Feature: Issues
When I select first assignee from "Shop" project
And I click link "New Issue"
Then I should see first assignee from "Shop" as selected assignee
-
diff --git a/features/project/issues/labels.feature b/features/project/issues/labels.feature
new file mode 100644
index 00000000..e601a41b
--- /dev/null
+++ b/features/project/issues/labels.feature
@@ -0,0 +1,10 @@
+Feature: Project Labels
+ Background:
+ Given I sign in as a user
+ And I own project "Shop"
+ And project "Shop" have issues tags: "bug", "feature"
+ Given I visit project "Shop" labels page
+
+ Scenario: I should see active milestones
+ Then I should see label "bug"
+ And I should see label "feature"
diff --git a/features/projects/issues/milestones.feature b/features/project/issues/milestones.feature
similarity index 79%
rename from features/projects/issues/milestones.feature
rename to features/project/issues/milestones.feature
index d78096a4..a57f67d6 100644
--- a/features/projects/issues/milestones.feature
+++ b/features/project/issues/milestones.feature
@@ -1,9 +1,9 @@
-Feature: Milestones
+Feature: Project Milestones
Background:
- Given I signin as a user
+ Given I sign in as a user
And I own project "Shop"
And project "Shop" has milestone "v2.2"
- Given I visit project "Shop" milestones page
+ Given I visit project "Shop" milestones page
Scenario: I should see active milestones
Then I should see milestone "v2.2"
diff --git a/features/projects/merge_requests.feature b/features/project/merge_requests.feature
similarity index 92%
rename from features/projects/merge_requests.feature
rename to features/project/merge_requests.feature
index 54b6ccde..80f00986 100644
--- a/features/projects/merge_requests.feature
+++ b/features/project/merge_requests.feature
@@ -1,10 +1,10 @@
-Feature: Merge Requests
+Feature: Project Merge Requests
Background:
- Given I signin as a user
+ Given I sign in as a user
And I own project "Shop"
And project "Shop" have "Bug NS-04" open merge request
And project "Shop" have "Feature NS-03" closed merge request
- And I visit project "Shop" merge requests page
+ And I visit project "Shop" merge requests page
Scenario: I should see open merge requests
Then I should see "Bug NS-04" in merge requests
diff --git a/features/projects/network.feature b/features/project/network.feature
similarity index 81%
rename from features/projects/network.feature
rename to features/project/network.feature
index 61c05eb3..31ce5ad3 100644
--- a/features/projects/network.feature
+++ b/features/project/network.feature
@@ -1,10 +1,9 @@
-@javascript
Feature: Project Network Graph
-
Background:
- Given I signin as a user
+ Given I sign in as a user
And I own project "Shop"
And I visit project "Shop" network page
+ @javascript
Scenario: I should see project network
Then page should have network graph
diff --git a/features/project/project.feature b/features/project/project.feature
new file mode 100644
index 00000000..1c9f201d
--- /dev/null
+++ b/features/project/project.feature
@@ -0,0 +1,14 @@
+Feature: Projects
+ Background:
+ Given I signin as a user
+ And I own project "Shop"
+ And I visit project "Shop" page
+
+ # @wip
+ # Scenario: I should see project activity
+
+ # @wip
+ # Scenario: I edit project
+
+ # @wip
+ # Scenario: I visit attachments
diff --git a/features/projects/source/browse_files.feature b/features/project/source/browse_files.feature
similarity index 71%
rename from features/projects/source/browse_files.feature
rename to features/project/source/browse_files.feature
index 04aebc19..b12b0ee3 100644
--- a/features/projects/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -1,6 +1,6 @@
-Feature: Browse git repo
- Background:
- Given I signin as a user
+Feature: Project Browse files
+ Background:
+ Given I sign in as a user
And I own project "Shop"
Given I visit project source page
@@ -12,12 +12,10 @@ Feature: Browse git repo
Then I should see files from repository for "8470d70"
Scenario: I browse file content
- Given I click on file from repo
+ Given I click on "Gemfile" file in repo
Then I should see it content
Scenario: I browse raw file
- Given I visit blob file from repo
- And I click on raw button
+ Given I visit blob file from repo
+ And I click link "raw"
Then I should see raw file content
-
-
diff --git a/features/project/source/git_blame.feature b/features/project/source/git_blame.feature
new file mode 100644
index 00000000..93ed20a8
--- /dev/null
+++ b/features/project/source/git_blame.feature
@@ -0,0 +1,10 @@
+Feature: Project Browse git repo
+ Background:
+ Given I sign in as a user
+ And I own project "Shop"
+ Given I visit project source page
+
+ Scenario: I blame file
+ Given I click on "Gemfile" file in repo
+ And I click blame button
+ Then I should see git file blame
diff --git a/features/projects/team_management.feature b/features/project/team_management.feature
similarity index 78%
rename from features/projects/team_management.feature
rename to features/project/team_management.feature
index b5b485e2..ae0c459f 100644
--- a/features/projects/team_management.feature
+++ b/features/project/team_management.feature
@@ -1,11 +1,11 @@
Feature: Project Team management
- Background:
- Given I signin as a user
+ Background:
+ Given I sign in as a user
And I own project "Shop"
- And gitlab user "Mike"
- And gitlab user "Sam"
+ And gitlab user "Mike"
+ And gitlab user "Sam"
And "Sam" is "Shop" developer
- And I visit project "Shop" team page
+ And I visit project "Shop" team page
Scenario: See all team members
Then I should be able to see myself in team
@@ -20,7 +20,7 @@ Feature: Project Team management
Scenario: Update user access
Given I should see "Sam" in team list as "Developer"
And I change "Sam" role to "Reporter"
- Then I visit project "Shop" team page
+ Then I visit project "Shop" team page
And I should see "Sam" in team list as "Reporter"
Scenario: View team member profile
@@ -30,6 +30,5 @@ Feature: Project Team management
Scenario: Cancel team member
Given I click link "Sam"
And I click link "Remove from team"
- Then I visit project "Shop" team page
+ Then I visit project "Shop" team page
And I should not see "Sam" in team list
-
diff --git a/features/projects/wall.feature b/features/project/wall.feature
similarity index 63%
rename from features/projects/wall.feature
rename to features/project/wall.feature
index ed675e2c..c38d046a 100644
--- a/features/projects/wall.feature
+++ b/features/project/wall.feature
@@ -1,17 +1,16 @@
-@javascript
Feature: Project Wall
In order to use Project Wall
- A user
- Should be able to read & write messages
+ A user should be able to read and write messages
Background:
- Given I signin as a user
+ Given I sign in as a user
And I own project "Shop"
- And I visit project "Shop" wall page
+ And I visit project "Shop" wall page
+ @javascript
Scenario: Write comment
Given I write new comment "my special test message"
Then I should see project wall note "my special test message"
- Then I visit project "Shop" wall page
+ Then I visit project "Shop" wall page
And I should see project wall note "my special test message"
diff --git a/features/projects/wiki.feature b/features/project/wiki.feature
similarity index 83%
rename from features/projects/wiki.feature
rename to features/project/wiki.feature
index 4441ada2..51370565 100644
--- a/features/projects/wiki.feature
+++ b/features/project/wiki.feature
@@ -1,6 +1,6 @@
-Feature: Wiki
- Background:
- Given I signin as a user
+Feature: Project Wiki
+ Background:
+ Given I sign in as a user
And I own project "Shop"
Given I visit project wiki page
diff --git a/features/projects/deploy_keys.feature b/features/projects/deploy_keys.feature
deleted file mode 100644
index e69de29b..00000000
diff --git a/features/projects/issues/labels.feature b/features/projects/issues/labels.feature
deleted file mode 100644
index 5a20bfd6..00000000
--- a/features/projects/issues/labels.feature
+++ /dev/null
@@ -1,13 +0,0 @@
-Feature: Labels
- Background:
- Given I signin as a user
- And I own project "Shop"
- And project "Shop" have issues tags:
- | name |
- | bug |
- | feature |
- Given I visit project "Shop" labels page
-
- Scenario: I should see active milestones
- Then I should see label "bug"
- And I should see label "feature"
diff --git a/features/projects/project.feature b/features/projects/project.feature
deleted file mode 100644
index 895a928f..00000000
--- a/features/projects/project.feature
+++ /dev/null
@@ -1,11 +0,0 @@
-Feature: Project
- Background:
- Given I signin as a user
- And I own project "Shop"
- And I visit project "Shop" page
-
- Scenario: I should see project activity
-
- Scenario: I edit project
-
- Scenario: I visit attachments
diff --git a/features/projects/snippets.feature b/features/projects/snippets.feature
deleted file mode 100644
index e69de29b..00000000
diff --git a/features/projects/source/git_blame.feature b/features/projects/source/git_blame.feature
deleted file mode 100644
index 6aa6be47..00000000
--- a/features/projects/source/git_blame.feature
+++ /dev/null
@@ -1,10 +0,0 @@
-Feature: Browse git repo
- Background:
- Given I signin as a user
- And I own project "Shop"
- Given I visit project source page
-
- Scenario: I blame file
- Given I click on file from repo
- And I click blame button
- Then I should see git file blame
diff --git a/features/projects/web_hooks.feature b/features/projects/web_hooks.feature
deleted file mode 100644
index e69de29b..00000000
diff --git a/features/step_definitions/common_steps.rb b/features/step_definitions/common_steps.rb
deleted file mode 100644
index e9023f92..00000000
--- a/features/step_definitions/common_steps.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-include LoginHelpers
-
-Given /^I signin as a user$/ do
- login_as :user
-end
-
-When /^I click link "(.*?)"$/ do |link|
- click_link link
-end
-
-When /^I click button "(.*?)"$/ do |button|
- click_button button
-end
-
-When /^I fill in "(.*?)" with "(.*?)"$/ do |field, value|
- fill_in field, :with => value
-end
-
-Given /^show me page$/ do
- save_and_open_page
-end
diff --git a/features/step_definitions/dashboard_steps.rb b/features/step_definitions/dashboard_steps.rb
deleted file mode 100644
index 3ddc68e9..00000000
--- a/features/step_definitions/dashboard_steps.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-Then /^I should see "(.*?)" link$/ do |arg1|
- page.should have_link(arg1)
-end
-
-Then /^I should see "(.*?)" project link$/ do |arg1|
- page.should have_link(arg1)
-end
-
-Then /^I should see project "(.*?)" activity feed$/ do |arg1|
- project = Project.find_by_name(arg1)
- page.should have_content "#{@user.name} pushed new branch new_design at #{project.name}"
-end
-
-Given /^project "(.*?)" has push event$/ do |arg1|
- @project = Project.find_by_name(arg1)
-
- data = {
- :before => "0000000000000000000000000000000000000000",
- :after => "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
- :ref => "refs/heads/new_design",
- :user_id => @user.id,
- :user_name => @user.name,
- :repository => {
- :name => @project.name,
- :url => "localhost/rubinius",
- :description => "",
- :homepage => "localhost/rubinius",
- :private => true
- }
- }
-
- @event = Event.create(
- :project => @project,
- :action => Event::Pushed,
- :data => data,
- :author_id => @user.id
- )
-end
-
-Then /^I should see last push widget$/ do
- page.should have_content "Your pushed to branch new_design"
- page.should have_link "Create Merge Request"
-end
-
-Then /^I click "(.*?)" link$/ do |arg1|
- click_link arg1 #Create Merge Request"
-end
-
-Then /^I see prefilled new Merge Request page$/ do
- current_path.should == new_project_merge_request_path(@project)
- find("#merge_request_source_branch").value.should == "new_design"
- find("#merge_request_target_branch").value.should == "master"
- find("#merge_request_title").value.should == "New Design"
-end
-
-Given /^I visit dashboard search page$/ do
- visit search_path
-end
-
-Given /^I search for "(.*?)"$/ do |arg1|
- fill_in "dashboard_search", :with => arg1
- click_button "Search"
-end
-
-Then /^I should see issues assigned to me$/ do
- issues = @user.issues
- issues.each do |issue|
- page.should have_content(issue.title[0..10])
- page.should have_content(issue.project.name)
- end
-end
-
-Then /^I should see my merge requests$/ do
- merge_requests = @user.merge_requests
- merge_requests.each do |mr|
- page.should have_content(mr.title[0..10])
- page.should have_content(mr.project.name)
- end
-end
-
-Given /^I have assigned issues$/ do
- project = Factory :project
- project.add_access(@user, :read, :write)
-
- issue1 = Factory :issue,
- :author => @user,
- :assignee => @user,
- :project => project
-
- issue2 = Factory :issue,
- :author => @user,
- :assignee => @user,
- :project => project
-end
-
-Given /^I have authored merge requests$/ do
- project1 = Factory :project
-
- project2 = Factory :project
-
- project1.add_access(@user, :read, :write)
- project2.add_access(@user, :read, :write)
-
- merge_request1 = Factory :merge_request,
- :author => @user,
- :project => project1
-
- merge_request2 = Factory :merge_request,
- :author => @user,
- :project => project2
-end
-
-Given /^user with name "(.*?)" joined project "(.*?)"$/ do |user_name, project_name|
- user = Factory.create(:user, {name: user_name})
- project = Project.find_by_name project_name
- Event.create(
- project: project,
- author_id: user.id,
- action: Event::Joined
- )
-end
-
-Given /^user with name "(.*?)" left project "(.*?)"$/ do |user_name, project_name|
- user = User.find_by_name user_name
- project = Project.find_by_name project_name
- Event.create(
- project: project,
- author_id: user.id,
- action: Event::Left
- )
-end
-
-Then /^I should see "(.*?)" event$/ do |event_text|
- page.should have_content(event_text)
-end
-
diff --git a/features/step_definitions/profile/profile_keys_steps.rb b/features/step_definitions/profile/profile_keys_steps.rb
deleted file mode 100644
index 25926c53..00000000
--- a/features/step_definitions/profile/profile_keys_steps.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-Given /^I visit profile keys page$/ do
- visit keys_path
-end
-
-Then /^I should see my ssh keys$/ do
- @user.keys.each do |key|
- page.should have_content(key.title)
- end
-end
-
-Given /^I have ssh keys:$/ do |table|
- table.hashes.each do |row|
- Factory :key, :user => @user, :title => row[:title], :key => "jfKLJDFKSFJSHFJ#{row[:title]}"
- end
-end
-
-Given /^I submit new ssh key "(.*?)"$/ do |arg1|
- fill_in "key_title", :with => arg1
- fill_in "key_key", :with => "ssh-rsa publickey234="
- click_button "Save"
-end
-
-Then /^I should see new ssh key "(.*?)"$/ do |arg1|
- key = Key.find_by_title(arg1)
- page.should have_content(key.title)
- page.should have_content(key.key)
- current_path.should == key_path(key)
-end
-
-Then /^I should not see "(.*?)" ssh key$/ do |arg1|
- within "#keys-table" do
- page.should_not have_content(arg1)
- end
-end
diff --git a/features/step_definitions/profile/profile_steps.rb b/features/step_definitions/profile/profile_steps.rb
deleted file mode 100644
index 525d43f5..00000000
--- a/features/step_definitions/profile/profile_steps.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-Then /^I should see my profile info$/ do
- page.should have_content "Profile"
- page.should have_content @user.name
- page.should have_content @user.email
-end
-
-Then /^I change my password$/ do
- fill_in "user_password", :with => "222333"
- fill_in "user_password_confirmation", :with => "222333"
- click_button "Save"
-end
-
-Then /^I should be redirected to sign in page$/ do
- current_path.should == new_user_session_path
-end
-
-Then /^I reset my token$/ do
- @old_token = @user.private_token
- click_button "Reset"
-end
-
-Then /^I should see new token$/ do
- find("#token").value.should_not == @old_token
- find("#token").value.should == @user.reload.private_token
-end
-
-Then /^I change my contact info$/ do
- fill_in "user_skype", :with => "testskype"
- fill_in "user_linkedin", :with => "testlinkedin"
- fill_in "user_twitter", :with => "testtwitter"
- click_button "Save"
- @user.reload
-end
-
-Then /^I should see new contact info$/ do
- @user.skype.should == 'testskype'
- @user.linkedin.should == 'testlinkedin'
- @user.twitter.should == 'testtwitter'
-end
diff --git a/features/step_definitions/project/browse_code_steps.rb b/features/step_definitions/project/browse_code_steps.rb
deleted file mode 100644
index d2ed9a0a..00000000
--- a/features/step_definitions/project/browse_code_steps.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-Then /^I should see files from repository$/ do
- page.should have_content("app")
- page.should have_content("History")
- page.should have_content("Gemfile")
-end
-
-Then /^I should see files from repository for "(.*?)"$/ do |arg1|
- current_path.should == tree_project_ref_path(@project, arg1)
- page.should have_content("app")
- page.should have_content("History")
- page.should have_content("Gemfile")
-end
-
-Given /^I click on file from repo$/ do
- click_link "Gemfile"
-end
-
-Then /^I should see it content$/ do
- page.should have_content("rubygems.org")
-end
-
-Given /^I click on raw button$/ do
- click_link "raw"
-end
-
-Then /^I should see raw file content$/ do
- page.source.should == ValidCommit::BLOB_FILE
-end
-
-Given /^I click blame button$/ do
- click_link "blame"
-end
-
-Then /^I should see git file blame$/ do
- page.should have_content("rubygems.org")
- page.should have_content("Dmitriy Zaporozhets")
- page.should have_content("bc3735004cb Moving to rails 3.2")
-end
diff --git a/features/step_definitions/project/project_commits_steps.rb b/features/step_definitions/project/project_commits_steps.rb
deleted file mode 100644
index 7f20ade4..00000000
--- a/features/step_definitions/project/project_commits_steps.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-Then /^I see project commits$/ do
- current_path.should == project_commits_path(@project)
-
- commit = @project.commit
- page.should have_content(@project.name)
- page.should have_content(commit.message)
- page.should have_content(commit.id.to_s[0..5])
-end
-
-Given /^I click atom feed link$/ do
- click_link "Feed"
-end
-
-Then /^I see commits atom feed$/ do
- commit = CommitDecorator.decorate(@project.commit)
- page.response_headers['Content-Type'].should have_content("application/atom+xml")
- page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
- page.body.should have_selector("author email", :text => commit.author_email)
- page.body.should have_selector("entry summary", :text => commit.description)
-end
-
-Then /^I see commit info$/ do
- page.should have_content ValidCommit::MESSAGE
- page.should have_content "Showing 1 changed file"
-end
-
-Given /^I fill compare fields with refs$/ do
- fill_in "from", :with => "master"
- fill_in "to", :with => "stable"
- click_button "Compare"
-end
-
-Given /^I see compared refs$/ do
- page.should have_content "Commits (27)"
- page.should have_content "Compare View"
- page.should have_content "Showing 73 changed files"
-end
-
-Then /^I should see "(.*?)" recent branches list$/ do |arg1|
- page.should have_content("Branches")
- page.should have_content("master")
-end
-
-Then /^I should see "(.*?)" all branches list$/ do |arg1|
- page.should have_content("Branches")
- page.should have_content("master")
-end
-
-Then /^I should see "(.*?)" all tags list$/ do |arg1|
- page.should have_content("Tags")
- page.should have_content("v1.2.1")
-end
-
-Then /^I should see "(.*?)" protected branches list$/ do |arg1|
- within "table" do
- page.should have_content "stable"
- page.should_not have_content "master"
- end
-end
-
-Given /^project "(.*?)" has protected branches$/ do |arg1|
- project = Project.find_by_name(arg1)
- project.protected_branches.create(:name => "stable")
-end
diff --git a/features/step_definitions/project/project_issues_steps.rb b/features/step_definitions/project/project_issues_steps.rb
deleted file mode 100644
index d78da53c..00000000
--- a/features/step_definitions/project/project_issues_steps.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-Given /^project "(.*?)" have "(.*?)" open issue$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
- Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first)
-end
-
-Given /^project "(.*?)" have "(.*?)" closed issue$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
- Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first, :closed => true)
-end
-
-Given /^I should see "(.*?)" in issues$/ do |arg1|
- page.should have_content arg1
-end
-
-Given /^I should not see "(.*?)" in issues$/ do |arg1|
- page.should_not have_content arg1
-end
-
-Then /^I should see issue "(.*?)"$/ do |arg1|
- issue = Issue.find_by_title(arg1)
- page.should have_content issue.title
- page.should have_content issue.author_name
- page.should have_content issue.project.name
-end
-
-Given /^I submit new issue "(.*?)"$/ do |arg1|
- fill_in "issue_title", with: arg1
- click_button "Submit new issue"
-end
-
-Given /^project "(.*?)" have issues tags:$/ do |arg1, table|
- project = Project.find_by_name(arg1)
- table.hashes.each do |hash|
- Factory :issue,
- project: project,
- label_list: [hash[:name]]
- end
-end
-
-Given /^I visit project "(.*?)" labels page$/ do |arg1|
- visit project_labels_path(Project.find_by_name(arg1))
-end
-
-Then /^I should see label "(.*?)"$/ do |arg1|
- within ".labels-table" do
- page.should have_content arg1
- end
-end
-
-Given /^I fill in issue search with "(.*?)"$/ do |arg1|
- # Because fill_in, with: "" triggers nothing
- # we need to trigger a keyup event
- if arg1 == ''
- page.execute_script("$('.issue_search').val('').keyup();");
- end
- fill_in 'issue_search', with: arg1
-end
-
-When /^I select milestone "(.*?)"$/ do |milestone_title|
- select milestone_title, from: "milestone_id"
-end
-
-Then /^I should see selected milestone with title "(.*?)"$/ do |milestone_title|
- issues_milestone_selector = "#issue_milestone_id_chzn/a"
- wait_until{ page.has_content?("Details") }
- page.find(issues_milestone_selector).should have_content(milestone_title)
-end
-
-When /^I select first assignee from "(.*?)" project$/ do |project_name|
- project = Project.find_by_name project_name
- first_assignee = project.users.first
- select first_assignee.name, from: "assignee_id"
-end
-
-Then /^I should see first assignee from "(.*?)" as selected assignee$/ do |project_name|
- issues_assignee_selector = "#issue_assignee_id_chzn/a"
- wait_until{ page.has_content?("Details") }
- project = Project.find_by_name project_name
- assignee_name = project.users.first.name
- page.find(issues_assignee_selector).should have_content(assignee_name)
-end
diff --git a/features/step_definitions/project/project_merge_requests_steps.rb b/features/step_definitions/project/project_merge_requests_steps.rb
deleted file mode 100644
index fddb18ad..00000000
--- a/features/step_definitions/project/project_merge_requests_steps.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-Given /^project "(.*?)" have "(.*?)" open merge request$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
- Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first)
-end
-
-Given /^project "(.*?)" have "(.*?)" closed merge request$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
- Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first, :closed => true)
-end
-
-Then /^I should see "(.*?)" in merge requests$/ do |arg1|
- page.should have_content arg1
-end
-
-Then /^I should not see "(.*?)" in merge requests$/ do |arg1|
- page.should_not have_content arg1
-end
-
-Then /^I should see merge request "(.*?)"$/ do |arg1|
- merge_request = MergeRequest.find_by_title(arg1)
- page.should have_content(merge_request.title[0..10])
- page.should have_content(merge_request.target_branch)
- page.should have_content(merge_request.source_branch)
-end
-
-Given /^I submit new merge request "(.*?)"$/ do |arg1|
- fill_in "merge_request_title", :with => arg1
- select "master", :from => "merge_request_source_branch"
- select "stable", :from => "merge_request_target_branch"
- click_button "Save"
-end
-
-Then /^I should see closed merge request "(.*?)"$/ do |arg1|
- mr = MergeRequest.find_by_title(arg1)
- mr.closed.should be_true
- page.should have_content "Closed by"
-end
-
diff --git a/features/step_definitions/project/project_milestones_steps.rb b/features/step_definitions/project/project_milestones_steps.rb
deleted file mode 100644
index 936c52df..00000000
--- a/features/step_definitions/project/project_milestones_steps.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-Given /^project "(.*?)" has milestone "(.*?)"$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
-
- milestone = Factory :milestone,
- :title => arg2,
- :project => project
-
- 3.times do |i|
- issue = Factory :issue,
- :project => project,
- :milestone => milestone
- end
-end
-
-Then /^I should see active milestones$/ do
- milestone = @project.milestones.first
- page.should have_content(milestone.title[0..10])
- page.should have_content(milestone.expires_at)
- page.should have_content("Browse Issues")
-end
-
-Then /^I should see milestone "(.*?)"$/ do |arg1|
- milestone = @project.milestones.find_by_title(arg1)
- page.should have_content(milestone.title[0..10])
- page.should have_content(milestone.expires_at)
- page.should have_content("Browse Issues")
-end
-
-Given /^I submit new milestone "(.*?)"$/ do |arg1|
- fill_in "milestone_title", :with => arg1
- click_button "Create milestone"
-end
-
diff --git a/features/step_definitions/project/project_team_steps.rb b/features/step_definitions/project/project_team_steps.rb
deleted file mode 100644
index 91885e46..00000000
--- a/features/step_definitions/project/project_team_steps.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-Given /^gitlab user "(.*?)"$/ do |arg1|
- Factory :user, :name => arg1
-end
-
-Given /^"(.*?)" is "(.*?)" developer$/ do |arg1, arg2|
- user = User.find_by_name(arg1)
- project = Project.find_by_name(arg2)
- project.add_access(user, :write)
-end
-
-Then /^I should be able to see myself in team$/ do
- page.should have_content(@user.name)
- page.should have_content(@user.email)
-end
-
-Then /^I should see "(.*?)" in team list$/ do |arg1|
- user = User.find_by_name(arg1)
- page.should have_content(user.name)
- page.should have_content(user.email)
-end
-
-Given /^I select "(.*?)" as "(.*?)"$/ do |arg1, arg2|
- user = User.find_by_name(arg1)
- within "#new_team_member" do
- select user.name, :from => "user_ids"
- select arg2, :from => "project_access"
- end
- click_button "Save"
-end
-
-Then /^I should see "(.*?)" in team list as "(.*?)"$/ do |arg1, arg2|
- user = User.find_by_name(arg1)
- role_id = find(".user_#{user.id} #team_member_project_access").value
- role_id.should == UsersProject.access_roles[arg2].to_s
-end
-
-Given /^I change "(.*?)" role to "(.*?)"$/ do |arg1, arg2|
- user = User.find_by_name(arg1)
- within ".user_#{user.id}" do
- select arg2, :from => "team_member_project_access"
- end
-end
-
-Then /^I should see "(.*?)" team profile$/ do |arg1|
- user = User.find_by_name(arg1)
- page.should have_content(user.name)
- page.should have_content(user.email)
- page.should have_content("To team list")
-end
-
-Then /^I should not see "(.*?)" in team list$/ do |arg1|
- user = User.find_by_name(arg1)
- page.should_not have_content(user.name)
- page.should_not have_content(user.email)
-end
diff --git a/features/step_definitions/project/project_wiki_steps.rb b/features/step_definitions/project/project_wiki_steps.rb
deleted file mode 100644
index 31fc050a..00000000
--- a/features/step_definitions/project/project_wiki_steps.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-Given /^I create Wiki page$/ do
- fill_in "Title", :with => 'Test title'
- fill_in "Content", :with => '[link test](test)'
- click_on "Save"
-end
-
-Then /^I should see newly created wiki page$/ do
- page.should have_content("Test title")
- page.should have_content("link test")
-
- click_link "link test"
-
- page.should have_content("Editing page")
-end
diff --git a/features/step_definitions/project/projects_steps.rb b/features/step_definitions/project/projects_steps.rb
deleted file mode 100644
index d22b805f..00000000
--- a/features/step_definitions/project/projects_steps.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-When /^I visit new project page$/ do
- visit new_project_path
-end
-
-When /^fill project form with valid data$/ do
- fill_in 'project_name', :with => 'NewProject'
- fill_in 'project_code', :with => 'NPR'
- fill_in 'project_path', :with => 'newproject'
- click_button "Create project"
-end
-
-Then /^I should see project page$/ do
- current_path.should == project_path(Project.last)
- page.should have_content('NewProject')
-end
-
-Then /^I should see empty project instuctions$/ do
- page.should have_content("git init")
- page.should have_content("git remote")
- page.should have_content(Project.last.url_to_repo)
-end
-
-Given /^I own project "(.*?)"$/ do |arg1|
- @project = Factory :project, :name => arg1
- @project.add_access(@user, :admin)
-end
-
-Given /^I visit project "(.*?)" wall page$/ do |arg1|
- project = Project.find_by_name(arg1)
- visit wall_project_path(project)
-end
-
-Then /^I should see project wall note "(.*?)"$/ do |arg1|
- page.should have_content arg1
-end
-
-Given /^project "(.*?)" has comment "(.*?)"$/ do |arg1, arg2|
- project = Project.find_by_name(arg1)
- project.notes.create(:note => arg1, :author => project.users.first)
-end
-
-Given /^I write new comment "(.*?)"$/ do |arg1|
- fill_in "note_note", :with => arg1
- click_button "Add Comment"
-end
-
-Given /^I visit project "(.*?)" page$/ do |arg1|
- project = Project.find_by_name(arg1)
- visit project_path(project)
-end
-
-Given /^I visit project "(.*?)" network page$/ do |arg1|
- project = Project.find_by_name(arg1)
-
- # Stub out find_all to speed this up (10 commits vs. 650)
- commits = Grit::Commit.find_all(project.repo, nil, {max_count: 10})
- Grit::Commit.stub(:find_all).and_return(commits)
-
- visit graph_project_path(project)
-end
-
-Given /^page should have network graph$/ do
- page.should have_content "Project Network Graph"
- within ".graph" do
- page.should have_content "master"
- page.should have_content "scss_refactor..."
- end
-end
-
-Given /^I leave a comment like "(.*?)"$/ do |arg1|
- fill_in "note_note", :with => arg1
- click_button "Add Comment"
-end
-
-Then /^I should see comment "(.*?)"$/ do |arg1|
- page.should have_content(arg1)
-end
diff --git a/features/step_definitions/visit_steps.rb b/features/step_definitions/visit_steps.rb
deleted file mode 100644
index 35fc6d44..00000000
--- a/features/step_definitions/visit_steps.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-Given /^I visit project "(.*?)" issues page$/ do |arg1|
- visit project_issues_path(Project.find_by_name(arg1))
-end
-
-Given /^I visit issue page "(.*?)"$/ do |arg1|
- issue = Issue.find_by_title(arg1)
- visit project_issue_path(issue.project, issue)
-end
-
-Given /^I visit project "(.*?)" merge requests page$/ do |arg1|
- visit project_merge_requests_path(Project.find_by_name(arg1))
-end
-
-Given /^I visit merge request page "(.*?)"$/ do |arg1|
- mr = MergeRequest.find_by_title(arg1)
- visit project_merge_request_path(mr.project, mr)
-end
-
-Given /^I visit project "(.*?)" milestones page$/ do |arg1|
- @project = Project.find_by_name(arg1)
- visit project_milestones_path(@project)
-end
-
-Given /^I visit project commits page$/ do
- visit project_commits_path(@project)
-end
-
-Given /^I visit compare refs page$/ do
- visit compare_project_commits_path(@project)
-end
-
-Given /^I visit project branches page$/ do
- visit branches_project_repository_path(@project)
-end
-
-Given /^I visit project commit page$/ do
- visit project_commit_path(@project, ValidCommit::ID)
-end
-
-Given /^I visit project tags page$/ do
- visit tags_project_repository_path(@project)
-end
-
-Given /^I click on commit link$/ do
- visit project_commit_path(@project, ValidCommit::ID)
-end
-
-Given /^I visit project source page$/ do
- visit tree_project_ref_path(@project, @project.root_ref)
-end
-
-Given /^I visit project source page for "(.*?)"$/ do |arg1|
- visit tree_project_ref_path(@project, arg1)
-end
-
-Given /^I visit blob file from repo$/ do
- visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
-end
-
-Given /^I visit project "(.*?)" team page$/ do |arg1|
- visit team_project_path(Project.find_by_name(arg1))
-end
-
-Given /^I visit project wiki page$/ do
- visit project_wiki_path(@project, :index)
-end
-
-Given /^I visit profile page$/ do
- visit profile_path
-end
-
-Given /^I visit profile token page$/ do
- visit profile_token_path
-end
-
-Given /^I visit profile password page$/ do
- visit profile_password_path
-end
-
-Given /^I visit dashboard page$/ do
- visit dashboard_path
-end
-
-Given /^I visit dashboard issues page$/ do
- visit dashboard_issues_path
-end
-
-Given /^I visit dashboard merge requests page$/ do
- visit dashboard_merge_requests_path
-end
-
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
new file mode 100644
index 00000000..6c603bbe
--- /dev/null
+++ b/features/steps/dashboard/dashboard.rb
@@ -0,0 +1,92 @@
+class Dashboard < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ Then 'I should see "New Project" link' do
+ page.should have_link "New Project"
+ end
+
+ Then 'I should see "Shop" project link' do
+ page.should have_link "Shop"
+ end
+
+ Then 'I should see project "Shop" activity feed' do
+ project = Project.find_by_name("Shop")
+ page.should have_content "#{@user.name} pushed new branch new_design at #{project.name}"
+ end
+
+ Then 'I should see last push widget' do
+ page.should have_content "Your pushed to branch new_design"
+ page.should have_link "Create Merge Request"
+ end
+
+ And 'I click "Create Merge Request" link' do
+ click_link "Create Merge Request"
+ end
+
+ Then 'I see prefilled new Merge Request page' do
+ current_path.should == new_project_merge_request_path(@project)
+ find("#merge_request_source_branch").value.should == "new_design"
+ find("#merge_request_target_branch").value.should == "master"
+ find("#merge_request_title").value.should == "New Design"
+ end
+
+ Given 'user with name "John Doe" joined project "Shop"' do
+ user = Factory.create(:user, {name: "John Doe"})
+ project = Project.find_by_name "Shop"
+ Event.create(
+ project: project,
+ author_id: user.id,
+ action: Event::Joined
+ )
+ end
+
+ Then 'I should see "John Doe joined project Shop" event' do
+ page.should have_content "John Doe joined project Shop"
+ end
+
+ And 'user with name "John Doe" left project "Shop"' do
+ user = User.find_by_name "John Doe"
+ project = Project.find_by_name "Shop"
+ Event.create(
+ project: project,
+ author_id: user.id,
+ action: Event::Left
+ )
+ end
+
+ Then 'I should see "John Doe left project Shop" event' do
+ page.should have_content "John Doe left project Shop"
+ end
+
+ And 'I own project "Shop"' do
+ @project = Factory :project, :name => 'Shop'
+ @project.add_access(@user, :admin)
+ end
+
+ And 'project "Shop" has push event' do
+ @project = Project.find_by_name("Shop")
+
+ data = {
+ :before => "0000000000000000000000000000000000000000",
+ :after => "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
+ :ref => "refs/heads/new_design",
+ :user_id => @user.id,
+ :user_name => @user.name,
+ :repository => {
+ :name => @project.name,
+ :url => "localhost/rubinius",
+ :description => "",
+ :homepage => "localhost/rubinius",
+ :private => true
+ }
+ }
+
+ @event = Event.create(
+ :project => @project,
+ :action => Event::Pushed,
+ :data => data,
+ :author_id => @user.id
+ )
+ end
+end
diff --git a/features/steps/dashboard/dashboard_issues.rb b/features/steps/dashboard/dashboard_issues.rb
new file mode 100644
index 00000000..9368782b
--- /dev/null
+++ b/features/steps/dashboard/dashboard_issues.rb
@@ -0,0 +1,19 @@
+class DashboardIssues < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ Then 'I should see issues assigned to me' do
+ issues = @user.issues
+ issues.each do |issue|
+ page.should have_content(issue.title[0..10])
+ page.should have_content(issue.project.name)
+ end
+ end
+
+ And 'I have assigned issues' do
+ project = Factory :project
+ project.add_access(@user, :read, :write)
+
+ 2.times { Factory :issue, :author => @user, :assignee => @user, :project => project }
+ end
+end
diff --git a/features/steps/dashboard/dashboard_merge_requests.rb b/features/steps/dashboard/dashboard_merge_requests.rb
new file mode 100644
index 00000000..fc339e75
--- /dev/null
+++ b/features/steps/dashboard/dashboard_merge_requests.rb
@@ -0,0 +1,23 @@
+class DashboardMergeRequests < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ Then 'I should see my merge requests' do
+ merge_requests = @user.merge_requests
+ merge_requests.each do |mr|
+ page.should have_content(mr.title[0..10])
+ page.should have_content(mr.project.name)
+ end
+ end
+
+ And 'I have authored merge requests' do
+ project1 = Factory :project
+ project2 = Factory :project
+
+ project1.add_access(@user, :read, :write)
+ project2.add_access(@user, :read, :write)
+
+ merge_request1 = Factory :merge_request, :author => @user, :project => project1
+ merge_request2 = Factory :merge_request, :author => @user, :project => project2
+ end
+end
diff --git a/features/steps/dashboard/dashboard_search.rb b/features/steps/dashboard/dashboard_search.rb
new file mode 100644
index 00000000..e3585898
--- /dev/null
+++ b/features/steps/dashboard/dashboard_search.rb
@@ -0,0 +1,18 @@
+class DashboardSearch < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ Given 'I search for "Sho"' do
+ fill_in "dashboard_search", :with => "Sho"
+ click_button "Search"
+ end
+
+ Then 'I should see "Shop" project link' do
+ page.should have_link "Shop"
+ end
+
+ And 'I own project "Shop"' do
+ @project = Factory :project, :name => "Shop"
+ @project.add_access(@user, :admin)
+ end
+end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
new file mode 100644
index 00000000..d3261a16
--- /dev/null
+++ b/features/steps/profile/profile.rb
@@ -0,0 +1,44 @@
+class Profile < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ Then 'I should see my profile info' do
+ page.should have_content "Profile"
+ page.should have_content @user.name
+ page.should have_content @user.email
+ end
+
+ Then 'I change my contact info' do
+ fill_in "user_skype", :with => "testskype"
+ fill_in "user_linkedin", :with => "testlinkedin"
+ fill_in "user_twitter", :with => "testtwitter"
+ click_button "Save"
+ @user.reload
+ end
+
+ And 'I should see new contact info' do
+ @user.skype.should == 'testskype'
+ @user.linkedin.should == 'testlinkedin'
+ @user.twitter.should == 'testtwitter'
+ end
+
+ Then 'I change my password' do
+ fill_in "user_password", :with => "222333"
+ fill_in "user_password_confirmation", :with => "222333"
+ click_button "Save"
+ end
+
+ And 'I should be redirected to sign in page' do
+ current_path.should == new_user_session_path
+ end
+
+ Then 'I reset my token' do
+ @old_token = @user.private_token
+ click_button "Reset"
+ end
+
+ And 'I should see new token' do
+ find("#token").value.should_not == @old_token
+ find("#token").value.should == @user.reload.private_token
+ end
+end
diff --git a/features/steps/profile/profile_ssh_keys.rb b/features/steps/profile/profile_ssh_keys.rb
new file mode 100644
index 00000000..96df2d73
--- /dev/null
+++ b/features/steps/profile/profile_ssh_keys.rb
@@ -0,0 +1,48 @@
+class ProfileSshKeys < Spinach::FeatureSteps
+ include SharedAuthentication
+
+ Then 'I should see my ssh keys' do
+ @user.keys.each do |key|
+ page.should have_content(key.title)
+ end
+ end
+
+ Given 'I click link "Add new"' do
+ click_link "Add new"
+ end
+
+ And 'I submit new ssh key "Laptop"' do
+ fill_in "key_title", :with => "Laptop"
+ fill_in "key_key", :with => "ssh-rsa publickey234="
+ click_button "Save"
+ end
+
+ Then 'I should see new ssh key "Laptop"' do
+ key = Key.find_by_title("Laptop")
+ page.should have_content(key.title)
+ page.should have_content(key.key)
+ current_path.should == key_path(key)
+ end
+
+ Given 'I click link "Work"' do
+ click_link "Work"
+ end
+
+ And 'I click link "Remove"' do
+ click_link "Remove"
+ end
+
+ Then 'I visit profile keys page' do
+ visit keys_path
+ end
+
+ And 'I should not see "Work" ssh key' do
+ within "#keys-table" do
+ page.should_not have_content "Work"
+ end
+ end
+
+ And 'I have ssh key "ssh-rsa Work"' do
+ Factory :key, :user => @user, :title => "ssh-rsa Work", :key => "jfKLJDFKSFJSHFJssh-rsa Work"
+ end
+end
diff --git a/features/steps/project/create_project.rb b/features/steps/project/create_project.rb
new file mode 100644
index 00000000..6d2ca3f9
--- /dev/null
+++ b/features/steps/project/create_project.rb
@@ -0,0 +1,22 @@
+class CreateProject < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedPaths
+
+ And 'fill project form with valid data' do
+ fill_in 'project_name', :with => 'NewProject'
+ fill_in 'project_code', :with => 'NPR'
+ fill_in 'project_path', :with => 'newproject'
+ click_button "Create project"
+ end
+
+ Then 'I should see project page' do
+ current_path.should == project_path(Project.last)
+ page.should have_content "NewProject"
+ end
+
+ And 'I should see empty project instuctions' do
+ page.should have_content "git init"
+ page.should have_content "git remote"
+ page.should have_content Project.last.url_to_repo
+ end
+end
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
new file mode 100644
index 00000000..f33f12eb
--- /dev/null
+++ b/features/steps/project/project.rb
@@ -0,0 +1,5 @@
+class Projects < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+end
diff --git a/features/steps/project/project_browse_branches.rb b/features/steps/project/project_browse_branches.rb
new file mode 100644
index 00000000..2f6e185d
--- /dev/null
+++ b/features/steps/project/project_browse_branches.rb
@@ -0,0 +1,35 @@
+class ProjectBrowseBranches < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should see "Shop" recent branches list' do
+ page.should have_content "Branches"
+ page.should have_content "master"
+ end
+
+ Given 'I click link "All"' do
+ click_link "All"
+ end
+
+ Then 'I should see "Shop" all branches list' do
+ page.should have_content "Branches"
+ page.should have_content "master"
+ end
+
+ Given 'I click link "Protected"' do
+ click_link "Protected"
+ end
+
+ Then 'I should see "Shop" protected branches list' do
+ within "table" do
+ page.should have_content "stable"
+ page.should_not have_content "master"
+ end
+ end
+
+ And 'project "Shop" has protected branches' do
+ project = Project.find_by_name("Shop")
+ project.protected_branches.create(:name => "stable")
+ end
+end
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
new file mode 100644
index 00000000..01479987
--- /dev/null
+++ b/features/steps/project/project_browse_commits.rb
@@ -0,0 +1,47 @@
+class ProjectBrowseCommits < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I see project commits' do
+ current_path.should == project_commits_path(@project)
+
+ commit = @project.commit
+ page.should have_content(@project.name)
+ page.should have_content(commit.message)
+ page.should have_content(commit.id.to_s[0..5])
+ end
+
+ Given 'I click atom feed link' do
+ click_link "Feed"
+ end
+
+ Then 'I see commits atom feed' do
+ commit = CommitDecorator.decorate(@project.commit)
+ page.response_headers['Content-Type'].should have_content("application/atom+xml")
+ page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
+ page.body.should have_selector("author email", :text => commit.author_email)
+ page.body.should have_selector("entry summary", :text => commit.description)
+ end
+
+ Given 'I click on commit link' do
+ visit project_commit_path(@project, ValidCommit::ID)
+ end
+
+ Then 'I see commit info' do
+ page.should have_content ValidCommit::MESSAGE
+ page.should have_content "Showing 1 changed file"
+ end
+
+ And 'I fill compare fields with refs' do
+ fill_in "from", :with => "master"
+ fill_in "to", :with => "stable"
+ click_button "Compare"
+ end
+
+ And 'I see compared refs' do
+ page.should have_content "Commits (27)"
+ page.should have_content "Compare View"
+ page.should have_content "Showing 73 changed files"
+ end
+end
diff --git a/features/steps/project/project_browse_files.rb b/features/steps/project/project_browse_files.rb
new file mode 100644
index 00000000..67c553ce
--- /dev/null
+++ b/features/steps/project/project_browse_files.rb
@@ -0,0 +1,34 @@
+class ProjectBrowseFiles < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should see files from repository' do
+ page.should have_content "app"
+ page.should have_content "History"
+ page.should have_content "Gemfile"
+ end
+
+ Then 'I should see files from repository for "8470d70"' do
+ current_path.should == tree_project_ref_path(@project, "8470d70")
+ page.should have_content "app"
+ page.should have_content "History"
+ page.should have_content "Gemfile"
+ end
+
+ Given 'I click on "Gemfile" file in repo' do
+ click_link "Gemfile"
+ end
+
+ Then 'I should see it content' do
+ page.should have_content "rubygems.org"
+ end
+
+ And 'I click link "raw"' do
+ click_link "raw"
+ end
+
+ Then 'I should see raw file content' do
+ page.source.should == ValidCommit::BLOB_FILE
+ end
+end
diff --git a/features/steps/project/project_browse_git_repo.rb b/features/steps/project/project_browse_git_repo.rb
new file mode 100644
index 00000000..e966f407
--- /dev/null
+++ b/features/steps/project/project_browse_git_repo.rb
@@ -0,0 +1,19 @@
+class ProjectBrowseGitRepo < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Given 'I click on "Gemfile" file in repo' do
+ click_link "Gemfile"
+ end
+
+ And 'I click blame button' do
+ click_link "blame"
+ end
+
+ Then 'I should see git file blame' do
+ page.should have_content "rubygems.org"
+ page.should have_content "Dmitriy Zaporozhets"
+ page.should have_content "bc3735004cb Moving to rails 3.2"
+ end
+end
diff --git a/features/steps/project/project_browse_tags.rb b/features/steps/project/project_browse_tags.rb
new file mode 100644
index 00000000..0cbfa0d8
--- /dev/null
+++ b/features/steps/project/project_browse_tags.rb
@@ -0,0 +1,10 @@
+class ProjectBrowseTags < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should see "Shop" all tags list' do
+ page.should have_content "Tags"
+ page.should have_content "v1.2.1"
+ end
+end
diff --git a/features/steps/project/project_comment_commit.rb b/features/steps/project/project_comment_commit.rb
new file mode 100644
index 00000000..cb8385e1
--- /dev/null
+++ b/features/steps/project/project_comment_commit.rb
@@ -0,0 +1,6 @@
+class ProjectCommentCommit < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedNote
+ include SharedPaths
+end
diff --git a/features/steps/project/project_issues.rb b/features/steps/project/project_issues.rb
new file mode 100644
index 00000000..64af2449
--- /dev/null
+++ b/features/steps/project/project_issues.rb
@@ -0,0 +1,134 @@
+class ProjectIssues < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedNote
+ include SharedPaths
+
+ Given 'I should see "Release 0.4" in issues' do
+ page.should have_content "Release 0.4"
+ end
+
+ And 'I should not see "Release 0.3" in issues' do
+ page.should_not have_content "Release 0.3"
+ end
+
+ Given 'I click link "Closed"' do
+ click_link "Closed"
+ end
+
+ Then 'I should see "Release 0.3" in issues' do
+ page.should have_content "Release 0.3"
+ end
+
+ And 'I should not see "Release 0.4" in issues' do
+ page.should_not have_content "Release 0.4"
+ end
+
+ Given 'I click link "All"' do
+ click_link "All"
+ end
+
+ Given 'I click link "Release 0.4"' do
+ click_link "Release 0.4"
+ end
+
+ Then 'I should see issue "Release 0.4"' do
+ page.should have_content "Release 0.4"
+ end
+
+ Given 'I click link "New Issue"' do
+ click_link "New Issue"
+ end
+
+ And 'I submit new issue "500 error on profile"' do
+ fill_in "issue_title", :with => "500 error on profile"
+ click_button "Submit new issue"
+ end
+
+ Given 'I click link "500 error on profile"' do
+ click_link "500 error on profile"
+ end
+
+ Then 'I should see issue "500 error on profile"' do
+ issue = Issue.find_by_title("500 error on profile")
+ page.should have_content issue.title
+ page.should have_content issue.author_name
+ page.should have_content issue.project.name
+ end
+
+ Given 'I fill in issue search with "Release"' do
+ fill_in 'issue_search', with: "Release"
+ end
+
+ Given 'I fill in issue search with "Bug"' do
+ fill_in 'issue_search', with: "Bug"
+ end
+
+ And 'I fill in issue search with "0.3"' do
+ fill_in 'issue_search', with: "0.3"
+ end
+
+ And 'I fill in issue search with "Something"' do
+ fill_in 'issue_search', with: "Something"
+ end
+
+ And 'I fill in issue search with ""' do
+ page.execute_script("$('.issue_search').val('').keyup();");
+ fill_in 'issue_search', with: ""
+ end
+
+ Given 'project "Shop" has milestone "v2.2"' do
+ project = Project.find_by_name("Shop")
+ milestone = Factory :milestone, :title => "v2.2", :project => project
+
+ 3.times { Factory :issue, :project => project, :milestone => milestone }
+ end
+
+ And 'project "Shop" has milestone "v3.0"' do
+ project = Project.find_by_name("Shop")
+ milestone = Factory :milestone, :title => "v3.0", :project => project
+
+ 3.times { Factory :issue, :project => project, :milestone => milestone }
+ end
+
+ When 'I select milestone "v3.0"' do
+ select "v3.0", from: "milestone_id"
+ end
+
+ Then 'I should see selected milestone with title "v3.0"' do
+ issues_milestone_selector = "#issue_milestone_id_chzn/a"
+ wait_until { page.has_content?("Details") }
+ page.find(issues_milestone_selector).should have_content("v3.0")
+ end
+
+ When 'I select first assignee from "Shop" project' do
+ project = Project.find_by_name "Shop"
+ first_assignee = project.users.first
+ select first_assignee.name, from: "assignee_id"
+ end
+
+ Then 'I should see first assignee from "Shop" as selected assignee' do
+ issues_assignee_selector = "#issue_assignee_id_chzn/a"
+ wait_until { page.has_content?("Details") }
+ project = Project.find_by_name "Shop"
+ assignee_name = project.users.first.name
+ page.find(issues_assignee_selector).should have_content(assignee_name)
+ end
+
+ And 'project "Shop" have "Release 0.4" open issue' do
+ project = Project.find_by_name("Shop")
+ Factory.create(:issue,
+ :title => "Release 0.4",
+ :project => project,
+ :author => project.users.first)
+ end
+
+ And 'project "Shop" have "Release 0.3" closed issue' do
+ project = Project.find_by_name("Shop")
+ Factory.create(:issue,
+ :title => "Release 0.3",
+ :project => project,
+ :author => project.users.first,
+ :closed => true)
+ end
+end
diff --git a/features/steps/project/project_labels.rb b/features/steps/project/project_labels.rb
new file mode 100644
index 00000000..1a347bf3
--- /dev/null
+++ b/features/steps/project/project_labels.rb
@@ -0,0 +1,24 @@
+class ProjectLabels < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should see label "bug"' do
+ within ".labels-table" do
+ page.should have_content "bug"
+ end
+ end
+
+ And 'I should see label "feature"' do
+ within ".labels-table" do
+ page.should have_content "feature"
+ end
+ end
+
+ And 'project "Shop" have issues tags: "bug", "feature"' do
+ project = Project.find_by_name("Shop")
+ ['bug', 'feature'].each do |label|
+ Factory :issue, project: project, label_list: label
+ end
+ end
+end
diff --git a/features/steps/project/project_merge_requests.rb b/features/steps/project/project_merge_requests.rb
new file mode 100644
index 00000000..80e83906
--- /dev/null
+++ b/features/steps/project/project_merge_requests.rb
@@ -0,0 +1,80 @@
+class ProjectMergeRequests < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedNote
+ include SharedPaths
+
+ Then 'I should see "Bug NS-04" in merge requests' do
+ page.should have_content "Bug NS-04"
+ end
+
+ And 'I should not see "Feature NS-03" in merge requests' do
+ page.should_not have_content "Feature NS-03"
+ end
+
+ Given 'I click link "Closed"' do
+ click_link "Closed"
+ end
+
+ Then 'I should see "Feature NS-03" in merge requests' do
+ page.should have_content "Feature NS-03"
+ end
+
+ And 'I should not see "Bug NS-04" in merge requests' do
+ page.should_not have_content "Bug NS-04"
+ end
+
+ Given 'I click link "All"' do
+ click_link "All"
+ end
+
+ Given 'I click link "Bug NS-04"' do
+ click_link "Bug NS-04"
+ end
+
+ Then 'I should see merge request "Bug NS-04"' do
+ page.should have_content "Bug NS-04"
+ end
+
+ And 'I click link "Close"' do
+ click_link "Close"
+ end
+
+ Then 'I should see closed merge request "Bug NS-04"' do
+ mr = MergeRequest.find_by_title("Bug NS-04")
+ mr.closed.should be_true
+ page.should have_content "Closed by"
+ end
+
+ Given 'I click link "New Merge Request"' do
+ click_link "New Merge Request"
+ end
+
+ And 'I submit new merge request "Wiki Feature"' do
+ fill_in "merge_request_title", :with => "Wiki Feature"
+ select "master", :from => "merge_request_source_branch"
+ select "stable", :from => "merge_request_target_branch"
+ click_button "Save"
+ end
+
+ Then 'I should see merge request "Wiki Feature"' do
+ page.should have_content "Wiki Feature"
+ end
+
+ And 'project "Shop" have "Bug NS-04" open merge request' do
+ project = Project.find_by_name("Shop")
+ Factory.create(:merge_request,
+ :title => "Bug NS-04",
+ :project => project,
+ :author => project.users.first)
+ end
+
+ And 'project "Shop" have "Feature NS-03" closed merge request' do
+ project = Project.find_by_name("Shop")
+ Factory.create(:merge_request,
+ :title => "Feature NS-03",
+ :project => project,
+ :author => project.users.first,
+ :closed => true)
+ end
+end
diff --git a/features/steps/project/project_milestones.rb b/features/steps/project/project_milestones.rb
new file mode 100644
index 00000000..83ed6859
--- /dev/null
+++ b/features/steps/project/project_milestones.rb
@@ -0,0 +1,39 @@
+class ProjectMilestones < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should see milestone "v2.2"' do
+ milestone = @project.milestones.find_by_title("v2.2")
+ page.should have_content(milestone.title[0..10])
+ page.should have_content(milestone.expires_at)
+ page.should have_content("Browse Issues")
+ end
+
+ Given 'I click link "v2.2"' do
+ click_link "v2.2"
+ end
+
+ Given 'I click link "New Milestone"' do
+ click_link "New Milestone"
+ end
+
+ And 'I submit new milestone "v2.3"' do
+ fill_in "milestone_title", :with => "v2.3"
+ click_button "Create milestone"
+ end
+
+ Then 'I should see milestone "v2.3"' do
+ milestone = @project.milestones.find_by_title("v2.3")
+ page.should have_content(milestone.title[0..10])
+ page.should have_content(milestone.expires_at)
+ page.should have_content("Browse Issues")
+ end
+
+ And 'project "Shop" has milestone "v2.2"' do
+ project = Project.find_by_name("Shop")
+ milestone = Factory :milestone, :title => "v2.2", :project => project
+
+ 3.times { Factory :issue, :project => project, :milestone => milestone }
+ end
+end
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
new file mode 100644
index 00000000..f34a81a4
--- /dev/null
+++ b/features/steps/project/project_network_graph.rb
@@ -0,0 +1,22 @@
+class ProjectNetworkGraph < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+
+ Then 'page should have network graph' do
+ page.should have_content "Project Network Graph"
+ within ".graph" do
+ page.should have_content "master"
+ page.should have_content "scss_refactor..."
+ end
+ end
+
+ And 'I visit project "Shop" network page' do
+ project = Project.find_by_name("Shop")
+
+ # Stub out find_all to speed this up (10 commits vs. 650)
+ commits = Grit::Commit.find_all(project.repo, nil, {max_count: 10})
+ Grit::Commit.stub(:find_all).and_return(commits)
+
+ visit graph_project_path(project)
+ end
+end
diff --git a/features/steps/project/project_team_management.rb b/features/steps/project/project_team_management.rb
new file mode 100644
index 00000000..7beca257
--- /dev/null
+++ b/features/steps/project/project_team_management.rb
@@ -0,0 +1,89 @@
+class ProjectTeamManagement < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+
+ Then 'I should be able to see myself in team' do
+ page.should have_content(@user.name)
+ page.should have_content(@user.email)
+ end
+
+ And 'I should see "Sam" in team list' do
+ user = User.find_by_name("Sam")
+ page.should have_content(user.name)
+ page.should have_content(user.email)
+ end
+
+ Given 'I click link "New Team Member"' do
+ click_link "New Team Member"
+ end
+
+ And 'I select "Mike" as "Reporter"' do
+ user = User.find_by_name("Mike")
+ within "#new_team_member" do
+ select user.name, :from => "user_ids"
+ select "Reporter", :from => "project_access"
+ end
+ click_button "Save"
+ end
+
+ Then 'I should see "Mike" in team list as "Reporter"' do
+ user = User.find_by_name("Mike")
+ role_id = find(".user_#{user.id} #team_member_project_access").value
+ role_id.should == UsersProject.access_roles["Reporter"].to_s
+ end
+
+ Given 'I should see "Sam" in team list as "Developer"' do
+ user = User.find_by_name("Sam")
+ role_id = find(".user_#{user.id} #team_member_project_access").value
+ role_id.should == UsersProject.access_roles["Developer"].to_s
+ end
+
+ And 'I change "Sam" role to "Reporter"' do
+ user = User.find_by_name("Sam")
+ within ".user_#{user.id}" do
+ select "Reporter", :from => "team_member_project_access"
+ end
+ end
+
+ And 'I should see "Sam" in team list as "Reporter"' do
+ user = User.find_by_name("Sam")
+ role_id = find(".user_#{user.id} #team_member_project_access").value
+ role_id.should == UsersProject.access_roles["Reporter"].to_s
+ end
+
+ Given 'I click link "Sam"' do
+ click_link "Sam"
+ end
+
+ Then 'I should see "Sam" team profile' do
+ user = User.find_by_name("Sam")
+ page.should have_content(user.name)
+ page.should have_content(user.email)
+ page.should have_content("To team list")
+ end
+
+ And 'I click link "Remove from team"' do
+ click_link "Remove from team"
+ end
+
+ And 'I should not see "Sam" in team list' do
+ user = User.find_by_name("Sam")
+ page.should_not have_content(user.name)
+ page.should_not have_content(user.email)
+ end
+
+ And 'gitlab user "Mike"' do
+ Factory :user, :name => "Mike"
+ end
+
+ And 'gitlab user "Sam"' do
+ Factory :user, :name => "Sam"
+ end
+
+ And '"Sam" is "Shop" developer' do
+ user = User.find_by_name("Sam")
+ project = Project.find_by_name("Shop")
+ project.add_access(user, :write)
+ end
+end
diff --git a/features/steps/project/project_wall.rb b/features/steps/project/project_wall.rb
new file mode 100644
index 00000000..ba9d3533
--- /dev/null
+++ b/features/steps/project/project_wall.rb
@@ -0,0 +1,6 @@
+class ProjectWall < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedNote
+ include SharedPaths
+end
diff --git a/features/steps/project/project_wiki.rb b/features/steps/project/project_wiki.rb
new file mode 100644
index 00000000..902e9ce1
--- /dev/null
+++ b/features/steps/project/project_wiki.rb
@@ -0,0 +1,20 @@
+class ProjectWiki < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedNote
+ include SharedPaths
+
+ Given 'I create Wiki page' do
+ fill_in "Title", :with => 'Test title'
+ fill_in "Content", :with => '[link test](test)'
+ click_on "Save"
+ end
+
+ Then 'I should see newly created wiki page' do
+ page.should have_content "Test title"
+ page.should have_content "link test"
+
+ click_link "link test"
+ page.should have_content "Editing page"
+ end
+end
diff --git a/features/steps/shared/authentication.rb b/features/steps/shared/authentication.rb
new file mode 100644
index 00000000..77d9839f
--- /dev/null
+++ b/features/steps/shared/authentication.rb
@@ -0,0 +1,10 @@
+require Rails.root.join('spec', 'support', 'login_helpers')
+
+module SharedAuthentication
+ include Spinach::DSL
+ include LoginHelpers
+
+ Given 'I sign in as a user' do
+ login_as :user
+ end
+end
diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb
new file mode 100644
index 00000000..923e69b6
--- /dev/null
+++ b/features/steps/shared/note.rb
@@ -0,0 +1,21 @@
+module SharedNote
+ include Spinach::DSL
+
+ Given 'I leave a comment like "XML attached"' do
+ fill_in "note_note", :with => "XML attached"
+ click_button "Add Comment"
+ end
+
+ Then 'I should see comment "XML attached"' do
+ page.should have_content "XML attached"
+ end
+
+ Given 'I write new comment "my special test message"' do
+ fill_in "note_note", :with => "my special test message"
+ click_button "Add Comment"
+ end
+
+ Then 'I should see project wall note "my special test message"' do
+ page.should have_content "my special test message"
+ end
+end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
new file mode 100644
index 00000000..93ad0219
--- /dev/null
+++ b/features/steps/shared/paths.rb
@@ -0,0 +1,112 @@
+module SharedPaths
+ include Spinach::DSL
+
+ And 'I visit dashboard search page' do
+ visit search_path
+ end
+
+ And 'I visit dashboard merge requests page' do
+ visit dashboard_merge_requests_path
+ end
+
+ And 'I visit dashboard issues page' do
+ visit dashboard_issues_path
+ end
+
+ When 'I visit dashboard page' do
+ visit dashboard_path
+ end
+
+ Given 'I visit profile page' do
+ visit profile_path
+ end
+
+ Given 'I visit profile account page' do
+ visit profile_account_path
+ end
+
+ Given 'I visit profile token page' do
+ visit profile_token_path
+ end
+
+ When 'I visit new project page' do
+ visit new_project_path
+ end
+
+ And 'I visit project "Shop" page' do
+ project = Project.find_by_name("Shop")
+ visit project_path(project)
+ end
+
+ Given 'I visit project branches page' do
+ visit branches_project_repository_path(@project)
+ end
+
+ Given 'I visit compare refs page' do
+ visit compare_project_commits_path(@project)
+ end
+
+ Given 'I visit project commits page' do
+ visit project_commits_path(@project)
+ end
+
+ Given 'I visit project source page' do
+ visit tree_project_ref_path(@project, @project.root_ref)
+ end
+
+ Given 'I visit blob file from repo' do
+ visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
+ end
+
+ Given 'I visit project source page for "8470d70"' do
+ visit tree_project_ref_path(@project, "8470d70")
+ end
+
+ Given 'I visit project tags page' do
+ visit tags_project_repository_path(@project)
+ end
+
+ Given 'I visit project commit page' do
+ visit project_commit_path(@project, ValidCommit::ID)
+ end
+
+ And 'I visit project "Shop" issues page' do
+ visit project_issues_path(Project.find_by_name("Shop"))
+ end
+
+ Given 'I visit issue page "Release 0.4"' do
+ issue = Issue.find_by_title("Release 0.4")
+ visit project_issue_path(issue.project, issue)
+ end
+
+ Given 'I visit project "Shop" labels page' do
+ visit project_labels_path(Project.find_by_name("Shop"))
+ end
+
+ Given 'I visit merge request page "Bug NS-04"' do
+ mr = MergeRequest.find_by_title("Bug NS-04")
+ visit project_merge_request_path(mr.project, mr)
+ end
+
+ And 'I visit project "Shop" merge requests page' do
+ visit project_merge_requests_path(Project.find_by_name("Shop"))
+ end
+
+ Given 'I visit project "Shop" milestones page' do
+ @project = Project.find_by_name("Shop")
+ visit project_milestones_path(@project)
+ end
+
+ Then 'I visit project "Shop" team page' do
+ visit project_team_index_path(Project.find_by_name("Shop"))
+ end
+
+ Then 'I visit project "Shop" wall page' do
+ project = Project.find_by_name("Shop")
+ visit wall_project_path(project)
+ end
+
+ Given 'I visit project wiki page' do
+ visit project_wiki_path(@project, :index)
+ end
+end
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
new file mode 100644
index 00000000..9b64ca59
--- /dev/null
+++ b/features/steps/shared/project.rb
@@ -0,0 +1,8 @@
+module SharedProject
+ include Spinach::DSL
+
+ And 'I own project "Shop"' do
+ @project = Factory :project, :name => "Shop"
+ @project.add_access(@user, :admin)
+ end
+end
diff --git a/features/support/env.rb b/features/support/env.rb
index 53578152..9c6cef07 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -1,59 +1,27 @@
-unless ENV['CI']
- require 'simplecov'
- SimpleCov.start 'rails'
+ENV['RAILS_ENV'] = 'test'
+require './config/environment'
+
+require 'rspec'
+require 'database_cleaner'
+require 'spinach/capybara'
+
+%w(gitolite_stub stubbed_repository valid_commit).each do |f|
+ require Rails.root.join('spec', 'support', f)
end
-require 'cucumber/rails'
-require 'webmock/cucumber'
-
-WebMock.allow_net_connect!
-
-require Rails.root.join 'spec/support/gitolite_stub'
-require Rails.root.join 'spec/support/stubbed_repository'
-require Rails.root.join 'spec/support/login_helpers'
-require Rails.root.join 'spec/support/valid_commit'
-
-Capybara.default_selector = :css
-Capybara.javascript_driver = :webkit
-
-# By default, any exception happening in your Rails application will bubble up
-# to Cucumber so that your scenario will fail. This is a different from how
-# your application behaves in the production environment, where an error page will
-# be rendered instead.
-#
-# Sometimes we want to override this default behaviour and allow Rails to rescue
-# exceptions and display an error page (just like when the app is running in production).
-# Typical scenarios where you want to do this is when you test your error pages.
-# There are two ways to allow Rails to rescue exceptions:
-#
-# 1) Tag your scenario (or feature) with @allow-rescue
-#
-# 2) Set the value below to true. Beware that doing this globally is not
-# recommended as it will mask a lot of errors for you!
-#
-ActionController::Base.allow_rescue = false
-
-# Remove/comment out the lines below if your app doesn't have a database.
-# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
-begin
- DatabaseCleaner.strategy = :transaction
-rescue NameError
- raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
-end
-
-Cucumber::Rails::Database.javascript_strategy = :truncation
-
-require 'headless'
-
-headless = Headless.new
-headless.start
-
-require 'cucumber/rspec/doubles'
+Dir["#{Rails.root}/features/steps/shared/*.rb"].each {|file| require file}
include GitoliteStub
-Before do
+WebMock.allow_net_connect!
+Capybara.javascript_driver = :webkit
+
+DatabaseCleaner.strategy = :truncation
+Spinach.hooks.before_scenario { DatabaseCleaner.start }
+Spinach.hooks.after_scenario { DatabaseCleaner.clean }
+
+Spinach.hooks.before_run do
+ RSpec::Mocks::setup self
+
stub_gitolite!
end
-
-World(FactoryGirl::Syntax::Methods)
diff --git a/lib/api.rb b/lib/api.rb
index be04701c..37e03849 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -17,5 +17,6 @@ module Gitlab
mount Projects
mount Issues
mount Milestones
+ mount Keys
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index fef5328d..13a48e12 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -9,6 +9,10 @@ module Gitlab
expose :id, :email, :name, :blocked, :created_at
end
+ class Hook < Grape::Entity
+ expose :id, :url
+ end
+
class Project < Grape::Entity
expose :id, :code, :name, :description, :path, :default_branch
expose :owner, using: Entities::UserBasic
@@ -44,5 +48,11 @@ module Gitlab
expose :assignee, :author, using: Entities::UserBasic
expose :closed, :updated_at, :created_at
end
+
+ class Key < Grape::Entity
+ expose :id,
+ :title,
+ :key
+ end
end
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index c0ba8747..9a08b995 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -8,7 +8,7 @@ module Gitlab
if @project ||= current_user.projects.find_by_id(params[:id]) ||
current_user.projects.find_by_code(params[:id])
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
@project
@@ -19,15 +19,48 @@ module Gitlab
end
def authenticate!
- error!({'message' => '401 Unauthorized'}, 401) unless current_user
+ unauthorized! unless current_user
end
def authorize! action, subject
unless abilities.allowed?(current_user, action, subject)
- error!({'message' => '403 Forbidden'}, 403)
+ forbidden!
end
end
+ def attributes_for_keys(keys)
+ attrs = {}
+ keys.each do |key|
+ attrs[key] = params[key] if params[key].present?
+ end
+ attrs
+ end
+
+ # error helpers
+
+ def forbidden!
+ render_api_error!('403 Forbidden', 403)
+ end
+
+ def not_found!(resource = nil)
+ message = ["404"]
+ message << resource if resource
+ message << "Not Found"
+ render_api_error!(message.join(' '), 404)
+ end
+
+ def unauthorized!
+ render_api_error!('401 Unauthorized', 401)
+ end
+
+ def not_allowed!
+ render_api_error!('Method Not Allowed', 405)
+ end
+
+ def render_api_error!(message, status)
+ error!({'message' => message}, status)
+ end
+
private
def abilities
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 4cfa7500..4ee2d11f 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -48,19 +48,14 @@ module Gitlab
# Example Request:
# POST /projects/:id/issues
post ":id/issues" do
- @issue = user_project.issues.new(
- title: params[:title],
- description: params[:description],
- assignee_id: params[:assignee_id],
- milestone_id: params[:milestone_id],
- label_list: params[:labels]
- )
+ attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
+ @issue = user_project.issues.new attrs
@issue.author = current_user
-
if @issue.save
present @issue, with: Entities::Issue
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -81,19 +76,12 @@ module Gitlab
@issue = user_project.issues.find(params[:issue_id])
authorize! :modify_issue, @issue
- parameters = {
- title: (params[:title] || @issue.title),
- description: (params[:description] || @issue.description),
- assignee_id: (params[:assignee_id] || @issue.assignee_id),
- milestone_id: (params[:milestone_id] || @issue.milestone_id),
- label_list: (params[:labels] || @issue.label_list),
- closed: (params[:closed] || @issue.closed)
- }
-
- if @issue.update_attributes(parameters)
+ attrs = attributes_for_keys [:title, :description, :assignee_id, :milestone_id, :closed]
+ attrs[:label_list] = params[:labels] if params[:labels].present?
+ if @issue.update_attributes attrs
present @issue, with: Entities::Issue
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -105,7 +93,7 @@ module Gitlab
# Example Request:
# DELETE /projects/:id/issues/:issue_id
delete ":id/issues/:issue_id" do
- error!({'message' => 'method not allowed'}, 405)
+ not_allowed!
end
end
end
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
new file mode 100644
index 00000000..4c302727
--- /dev/null
+++ b/lib/api/keys.rb
@@ -0,0 +1,50 @@
+module Gitlab
+ # Keys API
+ class Keys < Grape::API
+ before { authenticate! }
+ resource :keys do
+ # Get currently authenticated user's keys
+ #
+ # Example Request:
+ # GET /keys
+ get do
+ present current_user.keys, with: Entities::Key
+ end
+ # Get single key owned by currently authenticated user
+ #
+ # Example Request:
+ # GET /keys/:id
+ get "/:id" do
+ key = current_user.keys.find params[:id]
+ present key, with: Entities::Key
+ end
+ # Add new ssh key to currently authenticated user
+ #
+ # Parameters:
+ # key (required) - New SSH Key
+ # title (required) - New SSH Key's title
+ # Example Request:
+ # POST /keys
+ post do
+ attrs = attributes_for_keys [:title, :key]
+ key = current_user.keys.new attrs
+ if key.save
+ present key, with: Entities::Key
+ else
+ not_found!
+ end
+ end
+ # Delete existed ssh key of currently authenticated user
+ #
+ # Parameters:
+ # id (required) - SSH Key ID
+ # Example Request:
+ # DELETE /keys/:id
+ delete "/:id" do
+ key = current_user.keys.find params[:id]
+ key.delete
+ end
+ end
+ end
+end
+
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index 7c684667..daaff940 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -36,16 +36,12 @@ module Gitlab
# Example Request:
# POST /projects/:id/milestones
post ":id/milestones" do
- @milestone = user_project.milestones.new(
- title: params[:title],
- description: params[:description],
- due_date: params[:due_date]
- )
-
+ attrs = attributes_for_keys [:title, :description, :due_date]
+ @milestone = user_project.milestones.new attrs
if @milestone.save
present @milestone, with: Entities::Milestone
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -64,17 +60,11 @@ module Gitlab
authorize! :admin_milestone, user_project
@milestone = user_project.milestones.find(params[:milestone_id])
- parameters = {
- title: (params[:title] || @milestone.title),
- description: (params[:description] || @milestone.description),
- due_date: (params[:due_date] || @milestone.due_date),
- closed: (params[:closed] || @milestone.closed)
- }
-
- if @milestone.update_attributes(parameters)
+ attrs = attributes_for_keys [:title, :description, :due_date, :closed]
+ if @milestone.update_attributes attrs
present @milestone, with: Entities::Milestone
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 05b07e8d..1d9004f8 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -40,17 +40,20 @@ module Gitlab
post do
params[:code] ||= params[:name]
params[:path] ||= params[:name]
- project_attrs = {}
- params.each_pair do |k ,v|
- if Project.attribute_names.include? k
- project_attrs[k] = v
- end
- end
- @project = Project.create_by_user(project_attrs, current_user)
+ attrs = attributes_for_keys [:code,
+ :path,
+ :name,
+ :description,
+ :default_branch,
+ :issues_enabled,
+ :wall_enabled,
+ :merge_requests_enabled,
+ :wiki_enabled]
+ @project = Project.create_by_user(attrs, current_user)
if @project.saved?
present @project, with: Entities::Project
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -106,6 +109,49 @@ module Gitlab
nil
end
+ # Get project hooks
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # Example Request:
+ # GET /projects/:id/hooks
+ get ":id/hooks" do
+ authorize! :admin_project, user_project
+ @hooks = paginate user_project.hooks
+ present @hooks, with: Entities::Hook
+ end
+
+ # Add hook to project
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # url (required) - The hook URL
+ # Example Request:
+ # POST /projects/:id/hooks
+ post ":id/hooks" do
+ authorize! :admin_project, user_project
+ @hook = user_project.hooks.new({"url" => params[:url]})
+ if @hook.save
+ present @hook, with: Entities::Hook
+ else
+ error!({'message' => '404 Not found'}, 404)
+ end
+ end
+
+ # Delete project hook
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # hook_id (required) - The ID of hook to delete
+ # Example Request:
+ # DELETE /projects/:id/hooks
+ delete ":id/hooks" do
+ authorize! :admin_project, user_project
+ @hook = user_project.hooks.find(params[:hook_id])
+ @hook.destroy
+ nil
+ end
+
# Get a project repository branches
#
# Parameters:
@@ -161,18 +207,16 @@ module Gitlab
# Example Request:
# POST /projects/:id/snippets
post ":id/snippets" do
- @snippet = user_project.snippets.new(
- title: params[:title],
- file_name: params[:file_name],
- expires_at: params[:lifetime],
- content: params[:code]
- )
+ attrs = attributes_for_keys [:title, :file_name]
+ attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+ attrs[:content] = params[:code] if params[:code].present?
+ @snippet = user_project.snippets.new attrs
@snippet.author = current_user
if @snippet.save
present @snippet, with: Entities::ProjectSnippet
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -191,17 +235,14 @@ module Gitlab
@snippet = user_project.snippets.find(params[:snippet_id])
authorize! :modify_snippet, @snippet
- parameters = {
- title: (params[:title] || @snippet.title),
- file_name: (params[:file_name] || @snippet.file_name),
- expires_at: (params[:lifetime] || @snippet.expires_at),
- content: (params[:code] || @snippet.content)
- }
+ attrs = attributes_for_keys [:title, :file_name]
+ attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+ attrs[:content] = params[:code] if params[:code].present?
- if @snippet.update_attributes(parameters)
+ if @snippet.update_attributes attrs
present @snippet, with: Entities::ProjectSnippet
else
- error!({'message' => '404 Not found'}, 404)
+ not_found!
end
end
@@ -244,10 +285,10 @@ module Gitlab
ref = params[:sha]
commit = user_project.commit ref
- error!('404 Commit Not Found', 404) unless commit
+ not_found! "Commit" unless commit
tree = Tree.new commit.tree, user_project, ref, params[:filepath]
- error!('404 File Not Found', 404) unless tree.try(:tree)
+ not_found! "File" unless tree.try(:tree)
if tree.text?
encoding = Gitlab::Encode.detect_encoding(tree.data)
diff --git a/lib/gitlab/app_logger.rb b/lib/gitlab/app_logger.rb
new file mode 100644
index 00000000..8e4717b4
--- /dev/null
+++ b/lib/gitlab/app_logger.rb
@@ -0,0 +1,11 @@
+module Gitlab
+ class AppLogger < Gitlab::Logger
+ def self.file_name
+ 'application.log'
+ end
+
+ def format_message(severity, timestamp, progname, msg)
+ "#{timestamp.to_s(:long)}: #{msg}\n"
+ end
+ end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
new file mode 100644
index 00000000..90bd5d74
--- /dev/null
+++ b/lib/gitlab/auth.rb
@@ -0,0 +1,66 @@
+module Gitlab
+ class Auth
+ def find_for_ldap_auth(auth, signed_in_resource = nil)
+ uid = auth.info.uid
+ provider = auth.provider
+ email = auth.info.email.downcase unless auth.info.email.nil?
+ raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
+
+ if @user = User.find_by_extern_uid_and_provider(uid, provider)
+ @user
+ elsif @user = User.find_by_email(email)
+ log.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
+ @user.update_attributes(:extern_uid => uid, :provider => provider)
+ @user
+ else
+ create_from_omniauth(auth, true)
+ end
+ end
+
+ def create_from_omniauth(auth, ldap = false)
+ provider = auth.provider
+ uid = auth.info.uid || auth.uid
+ name = auth.info.name.force_encoding("utf-8")
+ email = auth.info.email.downcase unless auth.info.email.nil?
+
+ ldap_prefix = ldap ? '(LDAP) ' : ''
+ raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
+ " address" if auth.info.email.blank?
+
+ log.info "#{ldap_prefix}Creating user from #{provider} login"\
+ " {uid => #{uid}, name => #{name}, email => #{email}}"
+ password = Devise.friendly_token[0, 8].downcase
+ @user = User.new(
+ extern_uid: uid,
+ provider: provider,
+ name: name,
+ email: email,
+ password: password,
+ password_confirmation: password,
+ projects_limit: Gitlab.config.default_projects_limit,
+ )
+ if Gitlab.config.omniauth['block_auto_created_users'] && !ldap
+ @user.blocked = true
+ end
+ @user.save!
+ @user
+ end
+
+ def find_or_new_for_omniauth(auth)
+ provider, uid = auth.provider, auth.uid
+
+ if @user = User.find_by_provider_and_extern_uid(provider, uid)
+ @user
+ else
+ if Gitlab.config.omniauth['allow_single_sign_on']
+ @user = create_from_omniauth(auth)
+ @user
+ end
+ end
+ end
+
+ def log
+ Gitlab::AppLogger
+ end
+ end
+end
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index 60eef8e8..f51e8efc 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -58,18 +58,22 @@ module Gitlab
end
end
rescue PullError => ex
- Gitlab::Logger.error("Pull error -> " + ex.message)
+ log("Pull error -> " + ex.message)
raise Gitolite::AccessDenied, ex.message
rescue PushError => ex
- Gitlab::Logger.error("Push error -> " + " " + ex.message)
+ log("Push error -> " + " " + ex.message)
raise Gitolite::AccessDenied, ex.message
rescue Exception => ex
- Gitlab::Logger.error(ex.class.name + " " + ex.message)
+ log(ex.class.name + " " + ex.message)
raise Gitolite::AccessDenied.new("gitolite timeout")
end
+ def log message
+ Gitlab::GitLogger.error(message)
+ end
+
def destroy_project(project)
FileUtils.rm_rf(project.path_to_repo)
conf.rm_repo(project.path)
@@ -148,7 +152,7 @@ module Gitlab
# Enable access to all repos for gitolite admin.
# We use it for accept merge request feature
def admin_all_repo
- owner_name = Gitlab.settings.gitolite_admin_key
+ owner_name = Gitlab.config.gitolite_admin_key
# @ALL repos premission for gitolite owner
repo_name = "@all"
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index 4f77c327..43a75cc3 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -12,21 +12,22 @@ module Grack
# Pass Gitolite update hook
ENV['GL_BYPASS_UPDATE_HOOK'] = "true"
- # Need this patch because the rails mount
- @env['PATH_INFO'] = @env['REQUEST_PATH']
+ # Need this patch due to the rails mount
+ @env['PATH_INFO'] = @request.path
+ @env['SCRIPT_NAME'] = ""
# Find project by PATH_INFO from env
- if m = /^\/([\w-]+).git/.match(@env['PATH_INFO']).to_a
+ if m = /^\/([\w-]+).git/.match(@request.path_info).to_a
return false unless project = Project.find_by_path(m.last)
end
# Git upload and receive
- if @env['REQUEST_METHOD'] == 'GET'
+ if @request.get?
true
- elsif @env['REQUEST_METHOD'] == 'POST'
- if @env['REQUEST_URI'].end_with?('git-upload-pack')
+ elsif @request.post?
+ if @request.path_info.end_with?('git-upload-pack')
return project.dev_access_for?(user)
- elsif @env['REQUEST_URI'].end_with?('git-receive-pack')
+ elsif @request.path_info.end_with?('git-receive-pack')
if project.protected_branches.map(&:name).include?(current_ref)
project.master_access_for?(user)
else
diff --git a/lib/gitlab/git_logger.rb b/lib/gitlab/git_logger.rb
new file mode 100644
index 00000000..fbfed205
--- /dev/null
+++ b/lib/gitlab/git_logger.rb
@@ -0,0 +1,11 @@
+module Gitlab
+ class GitLogger < Gitlab::Logger
+ def self.file_name
+ 'githost.log'
+ end
+
+ def format_message(severity, timestamp, progname, msg)
+ "#{timestamp.to_s(:long)} -> #{severity} -> #{msg}\n"
+ end
+ end
+end
diff --git a/lib/gitlab/graph_commit.rb b/lib/gitlab/graph_commit.rb
index b9859d79..e14d670e 100644
--- a/lib/gitlab/graph_commit.rb
+++ b/lib/gitlab/graph_commit.rb
@@ -5,6 +5,8 @@ module Gitlab
attr_accessor :time, :space
attr_accessor :refs
+ include ActionView::Helpers::SanitizeHelper
+
def self.to_graph(project)
@repo = project.repo
commits = Grit::Commit.find_all(@repo, nil, {max_count: 650})
@@ -164,7 +166,7 @@ module Gitlab
h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
h[:id] = sha
h[:date] = date
- h[:message] = Gitlab::Encode.utf8(message)
+ h[:message] = sanitize(Gitlab::Encode.utf8(message))
h[:login] = author.email
h
end
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index c3a19e71..9405163d 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -9,17 +9,13 @@ module Gitlab
end
def self.read_latest
- path = Rails.root.join("log/githost.log")
+ path = Rails.root.join("log", file_name)
self.build unless File.exist?(path)
logs = File.read(path).split("\n")
end
def self.build
- new(File.join(Rails.root, "log/githost.log"))
+ new(File.join(Rails.root, "log", file_name))
end
-
- def format_message(severity, timestamp, progname, msg)
- "#{timestamp.to_s(:long)} -> #{severity} -> #{msg}\n"
- end
end
end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 4fc0c392..9201003e 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -26,13 +26,13 @@ module Gitlab
# => "
module Markdown
REFERENCE_PATTERN = %r{
- ([^\w&;])? # Prefix (1)
+ (\W)? # Prefix (1)
( # Reference (2)
@([\w\._]+) # User name (3)
|[#!$](\d+) # Issue/MR/Snippet ID (4)
|([\h]{6,40}) # Commit ID (5)
)
- ([^\w&;])? # Suffix (6)
+ (\W)? # Suffix (6)
}x.freeze
EMOJI_PATTERN = %r{(:(\S+):)}.freeze
@@ -48,8 +48,10 @@ module Gitlab
def gfm(text, html_options = {})
return text if text.nil?
- # prevents the string supplied through the _text_ argument to be altered
- text = text.dup
+ # Duplicate the string so we don't alter the original, then call to_str
+ # to cast it back to a String instead of a SafeBuffer. This is required
+ # for gsub calls to work as we need them to.
+ text = text.dup.to_str
@html_options = html_options
@@ -84,6 +86,13 @@ module Gitlab
#
# Returns parsed text
def parse(text)
+ parse_references(text) if @project
+ parse_emoji(text)
+
+ text
+ end
+
+ def parse_references(text)
# parse reference links
text.gsub!(REFERENCE_PATTERN) do |match|
prefix = $1 || ''
@@ -91,13 +100,18 @@ module Gitlab
identifier = $3 || $4 || $5
suffix = $6 || ''
- if ref_link = reference_link(reference, identifier)
+ # Avoid HTML entities
+ if prefix.ends_with?('&') || suffix.starts_with?(';')
+ match
+ elsif ref_link = reference_link(reference, identifier)
prefix + ref_link + suffix
else
match
end
- end if @project
+ end
+ end
+ def parse_emoji(text)
# parse emoji
text.gsub!(EMOJI_PATTERN) do |match|
if valid_emoji?($2)
@@ -106,8 +120,6 @@ module Gitlab
match
end
end
-
- text
end
# Private: Checks if an emoji icon exists in the image asset directory
diff --git a/lib/tasks/cucumber.rake b/lib/tasks/cucumber.rake
deleted file mode 100644
index 83f79471..00000000
--- a/lib/tasks/cucumber.rake
+++ /dev/null
@@ -1,65 +0,0 @@
-# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
-# It is recommended to regenerate this file in the future when you upgrade to a
-# newer version of cucumber-rails. Consider adding your own code to a new file
-# instead of editing this one. Cucumber will automatically load all features/**/*.rb
-# files.
-
-
-unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
-
-vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
-$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
-
-begin
- require 'cucumber/rake/task'
-
- namespace :cucumber do
- Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
- t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
- t.fork = true # You may get faster startup if you set this to false
- t.profile = 'default'
- end
-
- Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
- t.binary = vendored_cucumber_bin
- t.fork = true # You may get faster startup if you set this to false
- t.profile = 'wip'
- end
-
- Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
- t.binary = vendored_cucumber_bin
- t.fork = true # You may get faster startup if you set this to false
- t.profile = 'rerun'
- end
-
- desc 'Run all features'
- task :all => [:ok, :wip]
-
- task :statsetup do
- require 'rails/code_statistics'
- ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
- ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
- end
- end
- desc 'Alias for cucumber:ok'
- task :cucumber => 'cucumber:ok'
-
- task :default => :cucumber
-
- task :features => :cucumber do
- STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
- end
-
- # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
- task 'db:test:prepare' do
- end
-
- task :stats => 'cucumber:statsetup'
-rescue LoadError
- desc 'cucumber rake task not available (cucumber not installed)'
- task :cucumber do
- abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
- end
-end
-
-end
diff --git a/lib/tasks/gitlab/test.rake b/lib/tasks/gitlab/test.rake
index 77e148cf..ad1bfb2e 100644
--- a/lib/tasks/gitlab/test.rake
+++ b/lib/tasks/gitlab/test.rake
@@ -1,5 +1,4 @@
namespace :gitlab do
- desc "GITLAB | Run both cucumber & rspec"
- task :test => ['cucumber', 'spec']
+ desc "GITLAB | Run both spinach and rspec"
+ task :test => ['spinach', 'spec']
end
-
diff --git a/lib/tasks/travis.rake b/lib/tasks/travis.rake
index 58767e10..13e32135 100644
--- a/lib/tasks/travis.rake
+++ b/lib/tasks/travis.rake
@@ -1,5 +1,5 @@
task :travis do
- ["cucumber", "rspec spec"].each do |cmd|
+ ["spinach", "rspec spec"].each do |cmd|
puts "Starting to run #{cmd}..."
system("export DISPLAY=:99.0 && bundle exec #{cmd}")
raise "#{cmd} failed!" unless $?.exitstatus == 0
diff --git a/script/cucumber b/script/cucumber
deleted file mode 100755
index 7fa5c920..00000000
--- a/script/cucumber
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env ruby
-
-vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
-if vendored_cucumber_bin
- load File.expand_path(vendored_cucumber_bin)
-else
- require 'rubygems' unless ENV['NO_RUBYGEMS']
- require 'cucumber'
- load Cucumber::BINARY
-end
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index 4dd3802a..a6708a7a 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -31,6 +31,7 @@ describe GitlabMarkdownHelper do
end
it "should not touch HTML entities" do
+ @project.issues.stub(:where).with(id: '39').and_return([issue])
actual = expected = "We'll accept good pull requests."
gfm(actual).should == expected
end
@@ -291,11 +292,18 @@ describe GitlabMarkdownHelper do
actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo')
actual.should have_selector 'a.gfm.gfm-commit.foo'
end
+
+ it "escapes HTML passed in as the body" do
+ actual = "This is a test
- see ##{issues[0].id}"
+ link_to_gfm(actual, commit_path).should match('<h1>test</h1>')
+ end
end
describe "#markdown" do
it "should handle references in paragraphs" do
- markdown("\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. #{commit.id} Nam pulvinar sapien eget odio adipiscing at faucibus orci vestibulum.\n").should == "Lorem ipsum dolor sit amet, consectetur adipiscing elit. #{link_to commit.id, project_commit_path(project, commit), title: commit.link_title, class: "gfm gfm-commit "} Nam pulvinar sapien eget odio adipiscing at faucibus orci vestibulum.
\n"
+ actual = "\n\nLorem ipsum dolor sit amet. #{commit.id} Nam pulvinar sapien eget.\n"
+ expected = project_commit_path(project, commit)
+ markdown(actual).should match(expected)
end
it "should handle references in headers" do
diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
new file mode 100644
index 00000000..1e03bc59
--- /dev/null
+++ b/spec/lib/auth_spec.rb
@@ -0,0 +1,95 @@
+require 'spec_helper'
+
+describe Gitlab::Auth do
+ let(:gl_auth) { Gitlab::Auth.new }
+
+ before do
+ Gitlab.config.stub(omniauth: {})
+
+ @info = mock(
+ uid: '12djsak321',
+ name: 'John',
+ email: 'john@mail.com'
+ )
+ end
+
+ describe :find_for_ldap_auth do
+ before do
+ @auth = mock(
+ uid: '12djsak321',
+ info: @info,
+ provider: 'ldap'
+ )
+ end
+
+ it "should find by uid & provider" do
+ User.should_receive :find_by_extern_uid_and_provider
+ gl_auth.find_for_ldap_auth(@auth)
+ end
+
+ it "should update credentials by email if missing uid" do
+ user = double('User')
+ User.stub find_by_extern_uid_and_provider: nil
+ User.stub find_by_email: user
+ user.should_receive :update_attributes
+ gl_auth.find_for_ldap_auth(@auth)
+ end
+
+
+ it "should create from auth if user doesnot exist"do
+ User.stub find_by_extern_uid_and_provider: nil
+ User.stub find_by_email: nil
+ gl_auth.should_receive :create_from_omniauth
+ gl_auth.find_for_ldap_auth(@auth)
+ end
+ end
+
+ describe :find_or_new_for_omniauth do
+ before do
+ @auth = mock(
+ info: @info,
+ provider: 'twitter',
+ uid: '12djsak321',
+ )
+ end
+
+ it "should find user"do
+ User.should_receive :find_by_provider_and_extern_uid
+ gl_auth.should_not_receive :create_from_omniauth
+ gl_auth.find_or_new_for_omniauth(@auth)
+ end
+
+ it "should not create user"do
+ User.stub find_by_provider_and_extern_uid: nil
+ gl_auth.should_not_receive :create_from_omniauth
+ gl_auth.find_or_new_for_omniauth(@auth)
+ end
+
+ it "should create user if single_sing_on"do
+ Gitlab.config.omniauth['allow_single_sign_on'] = true
+ User.stub find_by_provider_and_extern_uid: nil
+ gl_auth.should_receive :create_from_omniauth
+ gl_auth.find_or_new_for_omniauth(@auth)
+ end
+ end
+
+ describe :create_from_omniauth do
+ it "should create user from LDAP" do
+ @auth = mock(info: @info, provider: 'ldap')
+ user = gl_auth.create_from_omniauth(@auth, true)
+
+ user.should be_valid
+ user.extern_uid.should == @info.uid
+ user.provider.should == 'ldap'
+ end
+
+ it "should create user from Omniauth" do
+ @auth = mock(info: @info, provider: 'twitter')
+ user = gl_auth.create_from_omniauth(@auth, false)
+
+ user.should be_valid
+ user.extern_uid.should == @info.uid
+ user.provider.should == 'twitter'
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index ee022e95..5cb68761 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -14,12 +14,12 @@ describe Event do
it { should respond_to(:commits) }
end
- describe "Push event" do
- before do
+ describe "Push event" do
+ before do
project = Factory :project
@user = project.owner
- data = {
+ data = {
before: "0000000000000000000000000000000000000000",
after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
ref: "refs/heads/master",
@@ -50,25 +50,24 @@ describe Event do
it { @event.author.should == @user }
end
- describe "Joined project team" do
- let(:project) {Factory.create :project}
- let(:new_user) {Factory.create :user}
- it "should create event" do
- UsersProject.observers.enable :users_project_observer
- expect{
- UsersProject.bulk_import(project, [new_user.id], UsersProject::DEVELOPER)
- }.to change{Event.count}.by(1)
+ describe 'Team events' do
+ let(:user_project) { stub.as_null_object }
+ let(:observer) { UsersProjectObserver.instance }
+
+ before {
+ Event.should_receive :create
+ }
+
+ describe "Joined project team" do
+ it "should create event" do
+ observer.after_create user_project
+ end
end
- end
- describe "Left project team" do
- let(:project) {Factory.create :project}
- let(:new_user) {Factory.create :user}
- it "should create event" do
- UsersProject.bulk_import(project, [new_user.id], UsersProject::DEVELOPER)
- UsersProject.observers.enable :users_project_observer
- expect{
- UsersProject.bulk_delete(project, [new_user.id])
- }.to change{Event.count}.by(1)
+
+ describe "Left project team" do
+ it "should create event" do
+ observer.after_destroy user_project
+ end
end
end
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index ca6307e7..34192da9 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -12,7 +12,7 @@ describe Issue do
describe 'modules' do
it { should include_module(IssueCommonality) }
- it { should include_module(Upvote) }
+ it { should include_module(Votes) }
end
subject { Factory.create(:issue) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index d1253b35..523e823d 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -8,6 +8,6 @@ describe MergeRequest do
describe 'modules' do
it { should include_module(IssueCommonality) }
- it { should include_module(Upvote) }
+ it { should include_module(Votes) }
end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index dddfd34c..7809953f 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -24,6 +24,13 @@ describe Note do
it "recognizes a neutral note" do
note = Factory(:note, note: "This is not a +1 note")
note.should_not be_upvote
+ note.should_not be_downvote
+ end
+
+ it "recognizes a neutral emoji note" do
+ note = build(:note, note: "I would :+1: this, but I don't want to")
+ note.should_not be_upvote
+ note.should_not be_downvote
end
it "recognizes a +1 note" do
@@ -31,19 +38,19 @@ describe Note do
note.should be_upvote
end
- it "recognizes a -1 note as no vote" do
- note = Factory(:note, note: "-1 for this")
- note.should_not be_upvote
- end
-
it "recognizes a +1 emoji as a vote" do
note = build(:note, note: ":+1: for this")
note.should be_upvote
end
- it "recognizes a neutral emoji note" do
- note = build(:note, note: "I would :+1: this, but I don't want to")
- note.should_not be_upvote
+ it "recognizes a -1 note" do
+ note = Factory(:note, note: "-1 for this")
+ note.should be_downvote
+ end
+
+ it "recognizes a -1 emoji as a vote" do
+ note = build(:note, note: ":-1: for this")
+ note.should be_downvote
end
end
diff --git a/spec/observers/user_observer_spec.rb b/spec/observers/user_observer_spec.rb
index 23dac98b..0420a250 100644
--- a/spec/observers/user_observer_spec.rb
+++ b/spec/observers/user_observer_spec.rb
@@ -13,7 +13,7 @@ describe UserObserver do
end
context 'when a new user is created' do
- let(:user) { double(:user, id: 42, password: 'P@ssword!') }
+ let(:user) { double(:user, id: 42, password: 'P@ssword!', name: 'John', email: 'u@mail.local') }
let(:notification) { double :notification }
it 'sends an email' do
@@ -22,5 +22,10 @@ describe UserObserver do
subject.after_create(user)
end
+
+ it 'trigger logger' do
+ Gitlab::AppLogger.should_receive(:info)
+ subject.after_create(user)
+ end
end
end
diff --git a/spec/observers/users_project_observer_spec.rb b/spec/observers/users_project_observer_spec.rb
index 650321ce..2009b85f 100644
--- a/spec/observers/users_project_observer_spec.rb
+++ b/spec/observers/users_project_observer_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
describe UsersProjectObserver do
+# let(:users_project) { stub.as_null_object }
let(:user) { Factory.create :user }
let(:project) { Factory.create(:project,
code: "Fuu",
@@ -14,21 +15,23 @@ describe UsersProjectObserver do
it "should called when UsersProject created" do
subject.should_receive(:after_commit).once
UsersProject.observers.enable :users_project_observer do
- Factory.create(:users_project,
- project: project,
- user: user)
+ create(:users_project)
end
end
+
it "should send email to user" do
Notify.should_receive(:project_access_granted_email).with(users_project.id).and_return(double(deliver: true))
subject.after_commit(users_project)
+ Event.stub(:create => true)
end
+
it "should create new event" do
Event.should_receive(:create).with(
- project_id: users_project.project.id,
- action: Event::Joined,
+ project_id: users_project.project.id,
+ action: Event::Joined,
author_id: users_project.user.id
)
+
subject.after_create(users_project)
end
end
@@ -37,9 +40,10 @@ describe UsersProjectObserver do
it "should called when UsersProject updated" do
subject.should_receive(:after_commit).once
UsersProject.observers.enable :users_project_observer do
- users_project.update_attribute(:project_access, 40)
+ create(:users_project).update_attribute(:project_access, UsersProject::MASTER)
end
end
+
it "should send email to user" do
Notify.should_receive(:project_access_granted_email).with(users_project.id).and_return(double(deliver: true))
subject.after_commit(users_project)
@@ -51,20 +55,20 @@ describe UsersProjectObserver do
end
end
end
+
describe "#after_destroy" do
it "should called when UsersProject destroyed" do
subject.should_receive(:after_destroy)
+
UsersProject.observers.enable :users_project_observer do
- UsersProject.bulk_delete(
- users_project.project,
- [users_project.user.id]
- )
+ create(:users_project).destroy
end
end
+
it "should create new event" do
Event.should_receive(:create).with(
- project_id: users_project.project.id,
- action: Event::Left,
+ project_id: users_project.project.id,
+ action: Event::Left,
author_id: users_project.user.id
)
subject.after_destroy(users_project)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 293ea83a..442e9c73 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -9,12 +9,14 @@ describe Gitlab::API do
before { project.add_access(user, :read) }
describe "GET /issues" do
- it "should return authentication error" do
- get api("/issues")
- response.status.should == 401
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/issues")
+ response.status.should == 401
+ end
end
- describe "authenticated GET /issues" do
+ context "when authenticated" do
it "should return an array of issues" do
get api("/issues", user)
response.status.should == 200
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 439aecce..b46380b2 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -6,6 +6,7 @@ describe Gitlab::API do
let(:user) { Factory :user }
let(:user2) { Factory.create(:user) }
let(:user3) { Factory.create(:user) }
+ let!(:hook) { Factory :project_hook, project: project, url: "http://example.com" }
let!(:project) { Factory :project, owner: user }
let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' }
let!(:users_project) { Factory :users_project, user: user, project: project, project_access: UsersProject::MASTER }
@@ -13,12 +14,14 @@ describe Gitlab::API do
before { project.add_access(user, :read) }
describe "GET /projects" do
- it "should return authentication error" do
- get api("/projects")
- response.status.should == 401
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/projects")
+ response.status.should == 401
+ end
end
- describe "authenticated GET /projects" do
+ context "when authenticated" do
it "should return an array of projects" do
get api("/projects", user)
response.status.should == 200
@@ -85,7 +88,7 @@ describe Gitlab::API do
it "should return a 404 error if not found" do
get api("/projects/42", user)
response.status.should == 404
- json_response['message'].should == '404 Not found'
+ json_response['message'].should == '404 Not Found'
end
end
@@ -147,6 +150,36 @@ describe Gitlab::API do
end
end
+ describe "GET /projects/:id/hooks" do
+ it "should return project hooks" do
+ get api("/projects/#{project.code}/hooks", user)
+
+ response.status.should == 200
+
+ json_response.should be_an Array
+ json_response.count.should == 1
+ json_response.first['url'].should == "http://example.com"
+ end
+ end
+
+ describe "POST /projects/:id/users" do
+ it "should add hook to project" do
+ expect {
+ post api("/projects/#{project.code}/hooks", user),
+ "url" => "http://example.com"
+ }.to change {project.hooks.count}.by(1)
+ end
+ end
+
+ describe "DELETE /projects/:id/hooks" do
+ it "should delete hook from project" do
+ expect {
+ delete api("/projects/#{project.code}/hooks", user),
+ hook_id: hook.id
+ }.to change {project.hooks.count}.by(-1)
+ end
+ end
+
describe "GET /projects/:id/repository/tags" do
it "should return an array of project tags" do
get api("/projects/#{project.code}/repository/tags", user)
diff --git a/spec/requests/api/ssh_keys_spec.rb b/spec/requests/api/ssh_keys_spec.rb
new file mode 100644
index 00000000..7fb8c920
--- /dev/null
+++ b/spec/requests/api/ssh_keys_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Gitlab::Keys do
+ include ApiHelpers
+ let(:user) {
+ user = Factory.create :user
+ user.reset_authentication_token!
+ user
+ }
+ let(:key) { Factory.create :key, { user: user}}
+
+ describe "GET /keys" do
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/keys")
+ response.status.should == 401
+ end
+ end
+ context "when authenticated" do
+ it "should return array of ssh keys" do
+ user.keys << key
+ user.save
+ get api("/keys", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first["title"].should == key.title
+ end
+ end
+ end
+
+ describe "GET /keys/:id" do
+ it "should returm single key" do
+ user.keys << key
+ user.save
+ get api("/keys/#{key.id}", user)
+ response.status.should == 200
+ json_response["title"].should == key.title
+ end
+ it "should return 404 Not Found within invalid ID" do
+ get api("/keys/42", user)
+ response.status.should == 404
+ end
+ end
+
+ describe "POST /keys" do
+ it "should not create invalid ssh key" do
+ post api("/keys", user), { title: "invalid key" }
+ response.status.should == 404
+ end
+ it "should create ssh key" do
+ key_attrs = Factory.attributes :key
+ expect {
+ post api("/keys", user), key_attrs
+ }.to change{ user.keys.count }.by(1)
+ end
+ end
+
+ describe "DELETE /keys/:id" do
+ it "should delete existed key" do
+ user.keys << key
+ user.save
+ expect {
+ delete api("/keys/#{key.id}", user)
+ }.to change{user.keys.count}.by(-1)
+ end
+ it "should return 404 Not Found within invalid ID" do
+ delete api("/keys/42", user)
+ response.status.should == 404
+ end
+ end
+
+end
+
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index d791962a..e25fe134 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -6,12 +6,14 @@ describe Gitlab::API do
let(:user) { Factory :user }
describe "GET /users" do
- it "should return authentication error" do
- get api("/users")
- response.status.should == 401
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/users")
+ response.status.should == 401
+ end
end
- describe "authenticated GET /users" do
+ context "when authenticated" do
it "should return an array of users" do
get api("/users", user)
response.status.should == 200
diff --git a/spec/requests/atom/dashboard_issues_spec.rb b/spec/requests/atom/dashboard_issues_spec.rb
index 79a9b8ef..8d1111fc 100644
--- a/spec/requests/atom/dashboard_issues_spec.rb
+++ b/spec/requests/atom/dashboard_issues_spec.rb
@@ -1,42 +1,23 @@
require 'spec_helper'
-describe "User Issues Dashboard" do
+describe "Dashboard Issues Feed" do
describe "GET /issues" do
- before do
+ let!(:user) { Factory :user }
+ let!(:project1) { Factory :project }
+ let!(:project2) { Factory :project }
+ let!(:issue1) { Factory :issue, author: user, assignee: user, project: project1 }
+ let!(:issue2) { Factory :issue, author: user, assignee: user, project: project2 }
- login_as :user
-
- @project1 = Factory :project
-
- @project2 = Factory :project
-
- @project1.add_access(@user, :read, :write)
- @project2.add_access(@user, :read, :write)
-
- @issue1 = Factory :issue,
- author: @user,
- assignee: @user,
- project: @project1
-
- @issue2 = Factory :issue,
- author: @user,
- assignee: @user,
- project: @project2
-
- visit dashboard_issues_path
- end
-
- describe "atom feed", js: false do
+ describe "atom feed" do
it "should render atom feed via private token" do
- logout
- visit dashboard_issues_path(:atom, private_token: @user.private_token)
+ visit dashboard_issues_path(:atom, private_token: user.private_token)
page.response_headers['Content-Type'].should have_content("application/atom+xml")
- page.body.should have_selector("title", text: "#{@user.name} issues")
- page.body.should have_selector("author email", text: @issue1.author_email)
- page.body.should have_selector("entry summary", text: @issue1.title)
- page.body.should have_selector("author email", text: @issue2.author_email)
- page.body.should have_selector("entry summary", text: @issue2.title)
+ page.body.should have_selector("title", text: "#{user.name} issues")
+ page.body.should have_selector("author email", text: issue1.author_email)
+ page.body.should have_selector("entry summary", text: issue1.title)
+ page.body.should have_selector("author email", text: issue2.author_email)
+ page.body.should have_selector("entry summary", text: issue2.title)
end
end
end
diff --git a/spec/requests/atom/dashboard_spec.rb b/spec/requests/atom/dashboard_spec.rb
index 00c7a525..9459dd01 100644
--- a/spec/requests/atom/dashboard_spec.rb
+++ b/spec/requests/atom/dashboard_spec.rb
@@ -1,27 +1,21 @@
require 'spec_helper'
-describe "User Dashboard" do
- before { login_as :user }
-
+describe "Dashboard Feed" do
describe "GET /" do
- before do
- @project = Factory :project, owner: @user
- @project.add_access(@user, :read)
- visit dashboard_path
+ let!(:user) { Factory :user }
+
+ context "projects atom feed via private token" do
+ it "should render projects atom feed" do
+ visit dashboard_path(:atom, private_token: user.private_token)
+ page.body.should have_selector("feed title")
+ end
end
- it "should render projects atom feed via private token" do
- logout
-
- visit dashboard_path(:atom, private_token: @user.private_token)
- page.body.should have_selector("feed title")
- end
-
- it "should not render projects page via private token" do
- logout
-
- visit dashboard_path(private_token: @user.private_token)
- current_path.should == new_user_session_path
+ context "projects page via private token" do
+ it "should redirect to login page" do
+ visit dashboard_path(private_token: user.private_token)
+ current_path.should == new_user_session_path
+ end
end
end
end
diff --git a/spec/requests/atom/issues_spec.rb b/spec/requests/atom/issues_spec.rb
index 468d1b22..c8671979 100644
--- a/spec/requests/atom/issues_spec.rb
+++ b/spec/requests/atom/issues_spec.rb
@@ -1,40 +1,34 @@
require 'spec_helper'
-describe "Issues" do
- let(:project) { Factory :project }
-
- before do
- login_as :user
- project.add_access(@user, :read, :write)
- end
-
+describe "Issues Feed" do
describe "GET /issues" do
- before do
- @issue = Factory :issue,
- author: @user,
- assignee: @user,
- project: project
+ let!(:user) { Factory :user }
+ let!(:project) { Factory :project, owner: user }
+ let!(:issue) { Factory :issue, author: user, project: project }
- visit project_issues_path(project)
+ before { project.add_access(user, :read, :write) }
+
+ context "when authenticated" do
+ it "should render atom feed" do
+ login_with user
+ visit project_issues_path(project, :atom)
+
+ page.response_headers['Content-Type'].should have_content("application/atom+xml")
+ page.body.should have_selector("title", text: "#{project.name} issues")
+ page.body.should have_selector("author email", text: issue.author_email)
+ page.body.should have_selector("entry summary", text: issue.title)
+ end
end
- it "should render atom feed" do
- visit project_issues_path(project, :atom)
+ context "when authenticated via private token" do
+ it "should render atom feed" do
+ visit project_issues_path(project, :atom, private_token: user.private_token)
- page.response_headers['Content-Type'].should have_content("application/atom+xml")
- page.body.should have_selector("title", text: "#{project.name} issues")
- page.body.should have_selector("author email", text: @issue.author_email)
- page.body.should have_selector("entry summary", text: @issue.title)
- end
-
- it "should render atom feed via private token" do
- logout
- visit project_issues_path(project, :atom, private_token: @user.private_token)
-
- page.response_headers['Content-Type'].should have_content("application/atom+xml")
- page.body.should have_selector("title", text: "#{project.name} issues")
- page.body.should have_selector("author email", text: @issue.author_email)
- page.body.should have_selector("entry summary", text: @issue.title)
+ page.response_headers['Content-Type'].should have_content("application/atom+xml")
+ page.body.should have_selector("title", text: "#{project.name} issues")
+ page.body.should have_selector("author email", text: issue.author_email)
+ page.body.should have_selector("entry summary", text: issue.title)
+ end
end
end
end
diff --git a/spec/requests/gitlab_flavored_markdown_spec.rb b/spec/requests/gitlab_flavored_markdown_spec.rb
index 1076e90c..68d354b7 100644
--- a/spec/requests/gitlab_flavored_markdown_spec.rb
+++ b/spec/requests/gitlab_flavored_markdown_spec.rb
@@ -25,6 +25,7 @@ describe "Gitlab Flavored Markdown" do
@tag_name = "gfm-test-tag"
r.git.native(:tag, {}, @tag_name, commit.id)
end
+
after do
# delete test branch and tag
project.repo.git.native(:branch, {D: true}, @branch_name)
diff --git a/spec/requests/security/profile_access_spec.rb b/spec/requests/security/profile_access_spec.rb
index 9f6fe6a2..69c1c29c 100644
--- a/spec/requests/security/profile_access_spec.rb
+++ b/spec/requests/security/profile_access_spec.rb
@@ -28,8 +28,8 @@ describe "Users Security" do
it { should be_denied_for :visitor }
end
- describe "GET /profile/password" do
- subject { profile_password_path }
+ describe "GET /profile/account" do
+ subject { profile_account_path }
it { should be_allowed_for @u1 }
it { should be_allowed_for :admin }
diff --git a/spec/requests/security/project_access_spec.rb b/spec/requests/security/project_access_spec.rb
index 0cdf43bf..af0d5fcd 100644
--- a/spec/requests/security/project_access_spec.rb
+++ b/spec/requests/security/project_access_spec.rb
@@ -70,7 +70,7 @@ describe "Application access" do
end
describe "GET /project_code/team" do
- subject { team_project_path(@project) }
+ subject { project_team_index_path(@project) }
it { should be_allowed_for @u1 }
it { should be_allowed_for @u3 }
diff --git a/spec/roles/upvote_spec.rb b/spec/roles/upvote_spec.rb
deleted file mode 100644
index 24288ada..00000000
--- a/spec/roles/upvote_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require 'spec_helper'
-
-describe Issue, "Upvote" do
- let(:issue) { create(:issue) }
-
- it "with no notes has a 0/0 score" do
- issue.upvotes.should == 0
- end
-
- it "should recognize non-+1 notes" do
- issue.notes << create(:note, note: "No +1 here")
- issue.should have(1).note
- issue.notes.first.upvote?.should be_false
- issue.upvotes.should == 0
- end
-
- it "should recognize a single +1 note" do
- issue.notes << create(:note, note: "+1 This is awesome")
- issue.upvotes.should == 1
- end
-
- it "should recognize multiple +1 notes" do
- issue.notes << create(:note, note: "+1 This is awesome")
- issue.notes << create(:note, note: "+1 I want this")
- issue.upvotes.should == 2
- end
-end
diff --git a/spec/roles/votes_spec.rb b/spec/roles/votes_spec.rb
new file mode 100644
index 00000000..98666022
--- /dev/null
+++ b/spec/roles/votes_spec.rb
@@ -0,0 +1,132 @@
+require 'spec_helper'
+
+describe Issue do
+ let(:issue) { create(:issue) }
+
+ describe "#upvotes" do
+ it "with no notes has a 0/0 score" do
+ issue.upvotes.should == 0
+ end
+
+ it "should recognize non-+1 notes" do
+ issue.notes << create(:note, note: "No +1 here")
+ issue.should have(1).note
+ issue.notes.first.upvote?.should be_false
+ issue.upvotes.should == 0
+ end
+
+ it "should recognize a single +1 note" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.upvotes.should == 1
+ end
+
+ it "should recognize multiple +1 notes" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.notes << create(:note, note: "+1 I want this")
+ issue.upvotes.should == 2
+ end
+ end
+
+ describe "#downvotes" do
+ it "with no notes has a 0/0 score" do
+ issue.downvotes.should == 0
+ end
+
+ it "should recognize non--1 notes" do
+ issue.notes << create(:note, note: "Almost got a -1")
+ issue.should have(1).note
+ issue.notes.first.downvote?.should be_false
+ issue.downvotes.should == 0
+ end
+
+ it "should recognize a single -1 note" do
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.downvotes.should == 1
+ end
+
+ it "should recognize multiple -1 notes" do
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.notes << create(:note, note: "-1 Away with this")
+ issue.downvotes.should == 2
+ end
+ end
+
+ describe "#votes_count" do
+ it "with no notes has a 0/0 score" do
+ issue.votes_count.should == 0
+ end
+
+ it "should recognize non notes" do
+ issue.notes << create(:note, note: "No +1 here")
+ issue.should have(1).note
+ issue.votes_count.should == 0
+ end
+
+ it "should recognize a single +1 note" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.votes_count.should == 1
+ end
+
+ it "should recognize a single -1 note" do
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.votes_count.should == 1
+ end
+
+ it "should recognize multiple notes" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.notes << create(:note, note: "+1 I want this")
+ issue.votes_count.should == 3
+ end
+ end
+
+ describe "#upvotes_in_percent" do
+ it "with no notes has a 0% score" do
+ issue.upvotes_in_percent.should == 0
+ end
+
+ it "should count a single 1 note as 100%" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.upvotes_in_percent.should == 100
+ end
+
+ it "should count multiple +1 notes as 100%" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.notes << create(:note, note: "+1 I want this")
+ issue.upvotes_in_percent.should == 100
+ end
+
+ it "should count fractions for multiple +1 and -1 notes correctly" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.notes << create(:note, note: "+1 I want this")
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.notes << create(:note, note: "+1 me too")
+ issue.upvotes_in_percent.should == 75
+ end
+ end
+
+ describe "#downvotes_in_percent" do
+ it "with no notes has a 0% score" do
+ issue.downvotes_in_percent.should == 0
+ end
+
+ it "should count a single -1 note as 100%" do
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.downvotes_in_percent.should == 100
+ end
+
+ it "should count multiple -1 notes as 100%" do
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.notes << create(:note, note: "-1 Away with this")
+ issue.downvotes_in_percent.should == 100
+ end
+
+ it "should count fractions for multiple +1 and -1 notes correctly" do
+ issue.notes << create(:note, note: "+1 This is awesome")
+ issue.notes << create(:note, note: "+1 I want this")
+ issue.notes << create(:note, note: "-1 This is bad")
+ issue.notes << create(:note, note: "+1 me too")
+ issue.downvotes_in_percent.should == 25
+ end
+ end
+end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
new file mode 100644
index 00000000..60261c7a
--- /dev/null
+++ b/spec/routing/admin_routing_spec.rb
@@ -0,0 +1,166 @@
+require 'spec_helper'
+
+# team_update_admin_user PUT /admin/users/:id/team_update(.:format) admin/users#team_update
+# block_admin_user PUT /admin/users/:id/block(.:format) admin/users#block
+# unblock_admin_user PUT /admin/users/:id/unblock(.:format) admin/users#unblock
+# admin_users GET /admin/users(.:format) admin/users#index
+# POST /admin/users(.:format) admin/users#create
+# new_admin_user GET /admin/users/new(.:format) admin/users#new
+# edit_admin_user GET /admin/users/:id/edit(.:format) admin/users#edit
+# admin_user GET /admin/users/:id(.:format) admin/users#show
+# PUT /admin/users/:id(.:format) admin/users#update
+# DELETE /admin/users/:id(.:format) admin/users#destroy
+describe Admin::UsersController, "routing" do
+ it "to #team_update" do
+ put("/admin/users/1/team_update").should route_to('admin/users#team_update', id: '1')
+ end
+
+ it "to #block" do
+ put("/admin/users/1/block").should route_to('admin/users#block', id: '1')
+ end
+
+ it "to #unblock" do
+ put("/admin/users/1/unblock").should route_to('admin/users#unblock', id: '1')
+ end
+
+ it "to #index" do
+ get("/admin/users").should route_to('admin/users#index')
+ end
+
+ it "to #show" do
+ get("/admin/users/1").should route_to('admin/users#show', id: '1')
+ end
+
+ it "to #create" do
+ post("/admin/users").should route_to('admin/users#create')
+ end
+
+ it "to #new" do
+ get("/admin/users/new").should route_to('admin/users#new')
+ end
+
+ it "to #edit" do
+ get("/admin/users/1/edit").should route_to('admin/users#edit', id: '1')
+ end
+
+ it "to #show" do
+ get("/admin/users/1").should route_to('admin/users#show', id: '1')
+ end
+
+ it "to #update" do
+ put("/admin/users/1").should route_to('admin/users#update', id: '1')
+ end
+
+ it "to #destroy" do
+ delete("/admin/users/1").should route_to('admin/users#destroy', id: '1')
+ end
+end
+
+# team_admin_project GET /admin/projects/:id/team(.:format) admin/projects#team {:id=>/[^\/]+/}
+# team_update_admin_project PUT /admin/projects/:id/team_update(.:format) admin/projects#team_update {:id=>/[^\/]+/}
+# admin_projects GET /admin/projects(.:format) admin/projects#index {:id=>/[^\/]+/}
+# POST /admin/projects(.:format) admin/projects#create {:id=>/[^\/]+/}
+# new_admin_project GET /admin/projects/new(.:format) admin/projects#new {:id=>/[^\/]+/}
+# edit_admin_project GET /admin/projects/:id/edit(.:format) admin/projects#edit {:id=>/[^\/]+/}
+# admin_project GET /admin/projects/:id(.:format) admin/projects#show {:id=>/[^\/]+/}
+# PUT /admin/projects/:id(.:format) admin/projects#update {:id=>/[^\/]+/}
+# DELETE /admin/projects/:id(.:format) admin/projects#destroy {:id=>/[^\/]+/}
+describe Admin::ProjectsController, "routing" do
+ it "to #team" do
+ get("/admin/projects/gitlab/team").should route_to('admin/projects#team', id: 'gitlab')
+ end
+
+ it "to #team_update" do
+ put("/admin/projects/gitlab/team_update").should route_to('admin/projects#team_update', id: 'gitlab')
+ end
+
+ it "to #index" do
+ get("/admin/projects").should route_to('admin/projects#index')
+ end
+
+ it "to #create" do
+ post("/admin/projects").should route_to('admin/projects#create')
+ end
+
+ it "to #new" do
+ get("/admin/projects/new").should route_to('admin/projects#new')
+ end
+
+ it "to #edit" do
+ get("/admin/projects/gitlab/edit").should route_to('admin/projects#edit', id: 'gitlab')
+ end
+
+ it "to #show" do
+ get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab')
+ end
+
+ it "to #update" do
+ put("/admin/projects/gitlab").should route_to('admin/projects#update', id: 'gitlab')
+ end
+
+ it "to #destroy" do
+ delete("/admin/projects/gitlab").should route_to('admin/projects#destroy', id: 'gitlab')
+ end
+end
+
+# edit_admin_team_member GET /admin/team_members/:id/edit(.:format) admin/team_members#edit
+# admin_team_member PUT /admin/team_members/:id(.:format) admin/team_members#update
+# DELETE /admin/team_members/:id(.:format) admin/team_members#destroy
+describe Admin::TeamMembersController, "routing" do
+ it "to #edit" do
+ get("/admin/team_members/1/edit").should route_to('admin/team_members#edit', id: '1')
+ end
+
+ it "to #update" do
+ put("/admin/team_members/1").should route_to('admin/team_members#update', id: '1')
+ end
+
+ it "to #destroy" do
+ delete("/admin/team_members/1").should route_to('admin/team_members#destroy', id: '1')
+ end
+end
+
+# admin_hook_test GET /admin/hooks/:hook_id/test(.:format) admin/hooks#test
+# admin_hooks GET /admin/hooks(.:format) admin/hooks#index
+# POST /admin/hooks(.:format) admin/hooks#create
+# admin_hook DELETE /admin/hooks/:id(.:format) admin/hooks#destroy
+describe Admin::HooksController, "routing" do
+ it "to #test" do
+ get("/admin/hooks/1/test").should route_to('admin/hooks#test', hook_id: '1')
+ end
+
+ it "to #index" do
+ get("/admin/hooks").should route_to('admin/hooks#index')
+ end
+
+ it "to #create" do
+ post("/admin/hooks").should route_to('admin/hooks#create')
+ end
+
+ it "to #destroy" do
+ delete("/admin/hooks/1").should route_to('admin/hooks#destroy', id: '1')
+ end
+
+end
+
+# admin_logs GET /admin/logs(.:format) admin/logs#show
+describe Admin::LogsController, "routing" do
+ it "to #show" do
+ get("/admin/logs").should route_to('admin/logs#show')
+ end
+end
+
+# admin_resque GET /admin/resque(.:format) admin/resque#show
+describe Admin::ResqueController, "routing" do
+ it "to #show" do
+ get("/admin/resque").should route_to('admin/resque#show')
+ end
+end
+
+# admin_root /admin(.:format) admin/dashboard#index
+describe Admin::DashboardController, "routing" do
+ it "to #index" do
+ get("/admin").should route_to('admin/dashboard#index')
+ end
+end
+
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
new file mode 100644
index 00000000..b3f9db01
--- /dev/null
+++ b/spec/routing/project_routing_spec.rb
@@ -0,0 +1,398 @@
+require 'spec_helper'
+
+# Shared examples for a resource inside a Project
+#
+# By default it tests all the default REST actions: index, create, new, edit,
+# show, update, and destroy. You can remove actions by customizing the
+# `actions` variable.
+#
+# It also expects a `controller` variable to be available which defines both
+# the path to the resource as well as the controller name.
+#
+# Examples
+#
+# # Default behavior
+# it_behaves_like "RESTful project resources" do
+# let(:controller) { 'issues' }
+# end
+#
+# # Customizing actions
+# it_behaves_like "RESTful project resources" do
+# let(:actions) { [:index] }
+# let(:controller) { 'issues' }
+# end
+shared_examples "RESTful project resources" do
+ let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
+
+ it "to #index" do
+ get("/gitlabhq/#{controller}").should route_to("#{controller}#index", project_id: 'gitlabhq') if actions.include?(:index)
+ end
+
+ it "to #create" do
+ post("/gitlabhq/#{controller}").should route_to("#{controller}#create", project_id: 'gitlabhq') if actions.include?(:create)
+ end
+
+ it "to #new" do
+ get("/gitlabhq/#{controller}/new").should route_to("#{controller}#new", project_id: 'gitlabhq') if actions.include?(:new)
+ end
+
+ it "to #edit" do
+ get("/gitlabhq/#{controller}/1/edit").should route_to("#{controller}#edit", project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
+ end
+
+ it "to #show" do
+ get("/gitlabhq/#{controller}/1").should route_to("#{controller}#show", project_id: 'gitlabhq', id: '1') if actions.include?(:show)
+ end
+
+ it "to #update" do
+ put("/gitlabhq/#{controller}/1").should route_to("#{controller}#update", project_id: 'gitlabhq', id: '1') if actions.include?(:update)
+ end
+
+ it "to #destroy" do
+ delete("/gitlabhq/#{controller}/1").should route_to("#{controller}#destroy", project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
+ end
+end
+
+# projects POST /projects(.:format) projects#create
+# new_project GET /projects/new(.:format) projects#new
+# wall_project GET /:id/wall(.:format) projects#wall
+# graph_project GET /:id/graph(.:format) projects#graph
+# files_project GET /:id/files(.:format) projects#files
+# edit_project GET /:id/edit(.:format) projects#edit
+# project GET /:id(.:format) projects#show
+# PUT /:id(.:format) projects#update
+# DELETE /:id(.:format) projects#destroy
+describe ProjectsController, "routing" do
+ it "to #create" do
+ post("/projects").should route_to('projects#create')
+ end
+
+ it "to #new" do
+ get("/projects/new").should route_to('projects#new')
+ end
+
+ it "to #wall" do
+ get("/gitlabhq/wall").should route_to('projects#wall', id: 'gitlabhq')
+ end
+
+ it "to #graph" do
+ get("/gitlabhq/graph").should route_to('projects#graph', id: 'gitlabhq')
+ end
+
+ it "to #files" do
+ get("/gitlabhq/files").should route_to('projects#files', id: 'gitlabhq')
+ end
+
+ it "to #edit" do
+ get("/gitlabhq/edit").should route_to('projects#edit', id: 'gitlabhq')
+ end
+
+ it "to #show" do
+ get("/gitlabhq").should route_to('projects#show', id: 'gitlabhq')
+ end
+
+ it "to #update" do
+ put("/gitlabhq").should route_to('projects#update', id: 'gitlabhq')
+ end
+
+ it "to #destroy" do
+ delete("/gitlabhq").should route_to('projects#destroy', id: 'gitlabhq')
+ end
+end
+
+# pages_project_wikis GET /:project_id/wikis/pages(.:format) wikis#pages
+# history_project_wiki GET /:project_id/wikis/:id/history(.:format) wikis#history
+# project_wikis POST /:project_id/wikis(.:format) wikis#create
+# edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) wikis#edit
+# project_wiki GET /:project_id/wikis/:id(.:format) wikis#show
+# DELETE /:project_id/wikis/:id(.:format) wikis#destroy
+describe WikisController, "routing" do
+ it "to #pages" do
+ get("/gitlabhq/wikis/pages").should route_to('wikis#pages', project_id: 'gitlabhq')
+ end
+
+ it "to #history" do
+ get("/gitlabhq/wikis/1/history").should route_to('wikis#history', project_id: 'gitlabhq', id: '1')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:actions) { [:create, :edit, :show, :destroy] }
+ let(:controller) { 'wikis' }
+ end
+end
+
+# branches_project_repository GET /:project_id/repository/branches(.:format) repositories#branches
+# tags_project_repository GET /:project_id/repository/tags(.:format) repositories#tags
+# archive_project_repository GET /:project_id/repository/archive(.:format) repositories#archive
+# project_repository POST /:project_id/repository(.:format) repositories#create
+# new_project_repository GET /:project_id/repository/new(.:format) repositories#new
+# edit_project_repository GET /:project_id/repository/edit(.:format) repositories#edit
+# GET /:project_id/repository(.:format) repositories#show
+# PUT /:project_id/repository(.:format) repositories#update
+# DELETE /:project_id/repository(.:format) repositories#destroy
+describe RepositoriesController, "routing" do
+ it "to #branches" do
+ get("/gitlabhq/repository/branches").should route_to('repositories#branches', project_id: 'gitlabhq')
+ end
+
+ it "to #tags" do
+ get("/gitlabhq/repository/tags").should route_to('repositories#tags', project_id: 'gitlabhq')
+ end
+
+ it "to #archive" do
+ get("/gitlabhq/repository/archive").should route_to('repositories#archive', project_id: 'gitlabhq')
+ end
+
+ it "to #create" do
+ post("/gitlabhq/repository").should route_to('repositories#create', project_id: 'gitlabhq')
+ end
+
+ it "to #new" do
+ get("/gitlabhq/repository/new").should route_to('repositories#new', project_id: 'gitlabhq')
+ end
+
+ it "to #edit" do
+ get("/gitlabhq/repository/edit").should route_to('repositories#edit', project_id: 'gitlabhq')
+ end
+
+ it "to #show" do
+ get("/gitlabhq/repository").should route_to('repositories#show', project_id: 'gitlabhq')
+ end
+
+ it "to #update" do
+ put("/gitlabhq/repository").should route_to('repositories#update', project_id: 'gitlabhq')
+ end
+
+ it "to #destroy" do
+ delete("/gitlabhq/repository").should route_to('repositories#destroy', project_id: 'gitlabhq')
+ end
+end
+
+# project_deploy_keys GET /:project_id/deploy_keys(.:format) deploy_keys#index
+# POST /:project_id/deploy_keys(.:format) deploy_keys#create
+# new_project_deploy_key GET /:project_id/deploy_keys/new(.:format) deploy_keys#new
+# edit_project_deploy_key GET /:project_id/deploy_keys/:id/edit(.:format) deploy_keys#edit
+# project_deploy_key GET /:project_id/deploy_keys/:id(.:format) deploy_keys#show
+# PUT /:project_id/deploy_keys/:id(.:format) deploy_keys#update
+# DELETE /:project_id/deploy_keys/:id(.:format) deploy_keys#destroy
+describe DeployKeysController, "routing" do
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'deploy_keys' }
+ end
+end
+
+# project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index
+# POST /:project_id/protected_branches(.:format) protected_branches#create
+# project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy
+describe ProtectedBranchesController, "routing" do
+ it_behaves_like "RESTful project resources" do
+ let(:actions) { [:index, :create, :destroy] }
+ let(:controller) { 'protected_branches' }
+ end
+end
+
+# switch_project_refs GET /:project_id/switch(.:format) refs#switch
+# tree_project_ref GET /:project_id/:id/tree(.:format) refs#tree
+# logs_tree_project_ref GET /:project_id/:id/logs_tree(.:format) refs#logs_tree
+# blob_project_ref GET /:project_id/:id/blob(.:format) refs#blob
+# tree_file_project_ref GET /:project_id/:id/tree/:path(.:format) refs#tree
+# logs_file_project_ref GET /:project_id/:id/logs_tree/:path(.:format) refs#logs_tree
+# blame_file_project_ref GET /:project_id/:id/blame/:path(.:format) refs#blame
+describe RefsController, "routing" do
+ it "to #switch" do
+ get("/gitlabhq/switch").should route_to('refs#switch', project_id: 'gitlabhq')
+ end
+
+ it "to #tree" do
+ get("/gitlabhq/stable/tree").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable')
+ get("/gitlabhq/stable/tree/foo/bar/baz").should route_to('refs#tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+ end
+
+ it "to #logs_tree" do
+ get("/gitlabhq/stable/logs_tree").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
+ get("/gitlabhq/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+ end
+
+ it "to #blob" do
+ get("/gitlabhq/stable/blob").should route_to('refs#blob', project_id: 'gitlabhq', id: 'stable')
+ end
+
+ it "to #blame" do
+ get("/gitlabhq/stable/blame/foo/bar/baz").should route_to('refs#blame', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
+ end
+end
+
+# diffs_project_merge_request GET /:project_id/merge_requests/:id/diffs(.:format) merge_requests#diffs
+# automerge_project_merge_request GET /:project_id/merge_requests/:id/automerge(.:format) merge_requests#automerge
+# automerge_check_project_merge_request GET /:project_id/merge_requests/:id/automerge_check(.:format) merge_requests#automerge_check
+# raw_project_merge_request GET /:project_id/merge_requests/:id/raw(.:format) merge_requests#raw
+# branch_from_project_merge_requests GET /:project_id/merge_requests/branch_from(.:format) merge_requests#branch_from
+# branch_to_project_merge_requests GET /:project_id/merge_requests/branch_to(.:format) merge_requests#branch_to
+# project_merge_requests GET /:project_id/merge_requests(.:format) merge_requests#index
+# POST /:project_id/merge_requests(.:format) merge_requests#create
+# new_project_merge_request GET /:project_id/merge_requests/new(.:format) merge_requests#new
+# edit_project_merge_request GET /:project_id/merge_requests/:id/edit(.:format) merge_requests#edit
+# project_merge_request GET /:project_id/merge_requests/:id(.:format) merge_requests#show
+# PUT /:project_id/merge_requests/:id(.:format) merge_requests#update
+# DELETE /:project_id/merge_requests/:id(.:format) merge_requests#destroy
+describe MergeRequestsController, "routing" do
+ it "to #diffs" do
+ get("/gitlabhq/merge_requests/1/diffs").should route_to('merge_requests#diffs', project_id: 'gitlabhq', id: '1')
+ end
+
+ it "to #automerge" do
+ get("/gitlabhq/merge_requests/1/automerge").should route_to('merge_requests#automerge', project_id: 'gitlabhq', id: '1')
+ end
+
+ it "to #automerge_check" do
+ get("/gitlabhq/merge_requests/1/automerge_check").should route_to('merge_requests#automerge_check', project_id: 'gitlabhq', id: '1')
+ end
+
+ it "to #raw" do
+ get("/gitlabhq/merge_requests/1/raw").should route_to('merge_requests#raw', project_id: 'gitlabhq', id: '1')
+ end
+
+ it "to #branch_from" do
+ get("/gitlabhq/merge_requests/branch_from").should route_to('merge_requests#branch_from', project_id: 'gitlabhq')
+ end
+
+ it "to #branch_to" do
+ get("/gitlabhq/merge_requests/branch_to").should route_to('merge_requests#branch_to', project_id: 'gitlabhq')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'merge_requests' }
+ end
+end
+
+# raw_project_snippet GET /:project_id/snippets/:id/raw(.:format) snippets#raw
+# project_snippets GET /:project_id/snippets(.:format) snippets#index
+# POST /:project_id/snippets(.:format) snippets#create
+# new_project_snippet GET /:project_id/snippets/new(.:format) snippets#new
+# edit_project_snippet GET /:project_id/snippets/:id/edit(.:format) snippets#edit
+# project_snippet GET /:project_id/snippets/:id(.:format) snippets#show
+# PUT /:project_id/snippets/:id(.:format) snippets#update
+# DELETE /:project_id/snippets/:id(.:format) snippets#destroy
+describe SnippetsController, "routing" do
+ it "to #raw" do
+ get("/gitlabhq/snippets/1/raw").should route_to('snippets#raw', project_id: 'gitlabhq', id: '1')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'snippets' }
+ end
+end
+
+# test_project_hook GET /:project_id/hooks/:id/test(.:format) hooks#test
+# project_hooks GET /:project_id/hooks(.:format) hooks#index
+# POST /:project_id/hooks(.:format) hooks#create
+# project_hook DELETE /:project_id/hooks/:id(.:format) hooks#destroy
+describe HooksController, "routing" do
+ it "to #test" do
+ get("/gitlabhq/hooks/1/test").should route_to('hooks#test', project_id: 'gitlabhq', id: '1')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:actions) { [:index, :create, :destroy] }
+ let(:controller) { 'hooks' }
+ end
+end
+
+# compare_project_commits GET /:project_id/commits/compare(.:format) commits#compare
+# patch_project_commit GET /:project_id/commits/:id/patch(.:format) commits#patch
+# project_commits GET /:project_id/commits(.:format) commits#index
+# POST /:project_id/commits(.:format) commits#create
+# new_project_commit GET /:project_id/commits/new(.:format) commits#new
+# edit_project_commit GET /:project_id/commits/:id/edit(.:format) commits#edit
+# project_commit GET /:project_id/commits/:id(.:format) commits#show
+# PUT /:project_id/commits/:id(.:format) commits#update
+# DELETE /:project_id/commits/:id(.:format) commits#destroy
+describe CommitsController, "routing" do
+ it "to #compare" do
+ get("/gitlabhq/commits/compare").should route_to('commits#compare', project_id: 'gitlabhq')
+ end
+
+ it "to #patch" do
+ get("/gitlabhq/commits/1/patch").should route_to('commits#patch', project_id: 'gitlabhq', id: '1')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'commits' }
+ end
+end
+
+# project_team_members GET /:project_id/team_members(.:format) team_members#index
+# POST /:project_id/team_members(.:format) team_members#create
+# new_project_team_member GET /:project_id/team_members/new(.:format) team_members#new
+# edit_project_team_member GET /:project_id/team_members/:id/edit(.:format) team_members#edit
+# project_team_member GET /:project_id/team_members/:id(.:format) team_members#show
+# PUT /:project_id/team_members/:id(.:format) team_members#update
+# DELETE /:project_id/team_members/:id(.:format) team_members#destroy
+describe TeamMembersController, "routing" do
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'team_members' }
+ end
+end
+
+# project_milestones GET /:project_id/milestones(.:format) milestones#index
+# POST /:project_id/milestones(.:format) milestones#create
+# new_project_milestone GET /:project_id/milestones/new(.:format) milestones#new
+# edit_project_milestone GET /:project_id/milestones/:id/edit(.:format) milestones#edit
+# project_milestone GET /:project_id/milestones/:id(.:format) milestones#show
+# PUT /:project_id/milestones/:id(.:format) milestones#update
+# DELETE /:project_id/milestones/:id(.:format) milestones#destroy
+describe MilestonesController, "routing" do
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'milestones' }
+ end
+end
+
+# project_labels GET /:project_id/labels(.:format) labels#index
+describe LabelsController, "routing" do
+ it "to #index" do
+ get("/gitlabhq/labels").should route_to('labels#index', project_id: 'gitlabhq')
+ end
+end
+
+# sort_project_issues POST /:project_id/issues/sort(.:format) issues#sort
+# bulk_update_project_issues POST /:project_id/issues/bulk_update(.:format) issues#bulk_update
+# search_project_issues GET /:project_id/issues/search(.:format) issues#search
+# project_issues GET /:project_id/issues(.:format) issues#index
+# POST /:project_id/issues(.:format) issues#create
+# new_project_issue GET /:project_id/issues/new(.:format) issues#new
+# edit_project_issue GET /:project_id/issues/:id/edit(.:format) issues#edit
+# project_issue GET /:project_id/issues/:id(.:format) issues#show
+# PUT /:project_id/issues/:id(.:format) issues#update
+# DELETE /:project_id/issues/:id(.:format) issues#destroy
+describe IssuesController, "routing" do
+ it "to #sort" do
+ post("/gitlabhq/issues/sort").should route_to('issues#sort', project_id: 'gitlabhq')
+ end
+
+ it "to #bulk_update" do
+ post("/gitlabhq/issues/bulk_update").should route_to('issues#bulk_update', project_id: 'gitlabhq')
+ end
+
+ it "to #search" do
+ get("/gitlabhq/issues/search").should route_to('issues#search', project_id: 'gitlabhq')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:controller) { 'issues' }
+ end
+end
+
+# preview_project_notes POST /:project_id/notes/preview(.:format) notes#preview
+# project_notes GET /:project_id/notes(.:format) notes#index
+# POST /:project_id/notes(.:format) notes#create
+# project_note DELETE /:project_id/notes/:id(.:format) notes#destroy
+describe NotesController, "routing" do
+ it "to #preview" do
+ post("/gitlabhq/notes/preview").should route_to('notes#preview', project_id: 'gitlabhq')
+ end
+
+ it_behaves_like "RESTful project resources" do
+ let(:actions) { [:index, :create, :destroy] }
+ let(:controller) { 'notes' }
+ end
+end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
new file mode 100644
index 00000000..cb8dbf37
--- /dev/null
+++ b/spec/routing/routing_spec.rb
@@ -0,0 +1,186 @@
+require 'spec_helper'
+
+# search GET /search(.:format) search#show
+describe SearchController, "routing" do
+ it "to #show" do
+ get("/search").should route_to('search#show')
+ end
+end
+
+# gitlab_api /api Gitlab::API
+# resque /info/resque Resque::Server
+# /:path Grack
+describe "Mounted Apps", "routing" do
+ it "to API" do
+ get("/api").should be_routable
+ end
+
+ it "to Resque" do
+ pending
+ get("/info/resque").should be_routable
+ end
+
+ it "to Grack" do
+ get("/gitlabhq.git").should be_routable
+ end
+end
+
+# help GET /help(.:format) help#index
+# help_permissions GET /help/permissions(.:format) help#permissions
+# help_workflow GET /help/workflow(.:format) help#workflow
+# help_api GET /help/api(.:format) help#api
+# help_web_hooks GET /help/web_hooks(.:format) help#web_hooks
+# help_system_hooks GET /help/system_hooks(.:format) help#system_hooks
+# help_markdown GET /help/markdown(.:format) help#markdown
+# help_ssh GET /help/ssh(.:format) help#ssh
+describe HelpController, "routing" do
+ it "to #index" do
+ get("/help").should route_to('help#index')
+ end
+
+ it "to #permissions" do
+ get("/help/permissions").should route_to('help#permissions')
+ end
+
+ it "to #workflow" do
+ get("/help/workflow").should route_to('help#workflow')
+ end
+
+ it "to #api" do
+ get("/help/api").should route_to('help#api')
+ end
+
+ it "to #web_hooks" do
+ get("/help/web_hooks").should route_to('help#web_hooks')
+ end
+
+ it "to #system_hooks" do
+ get("/help/system_hooks").should route_to('help#system_hooks')
+ end
+
+ it "to #markdown" do
+ get("/help/markdown").should route_to('help#markdown')
+ end
+
+ it "to #ssh" do
+ get("/help/ssh").should route_to('help#ssh')
+ end
+end
+
+# errors_githost GET /errors/githost(.:format) errors#githost
+describe ErrorsController, "routing" do
+ it "to #githost" do
+ get("/errors/githost").should route_to('errors#githost')
+ end
+end
+
+# profile_account GET /profile/account(.:format) profile#account
+# profile_history GET /profile/history(.:format) profile#history
+# profile_password PUT /profile/password(.:format) profile#password_update
+# profile_token GET /profile/token(.:format) profile#token
+# profile_reset_private_token PUT /profile/reset_private_token(.:format) profile#reset_private_token
+# profile GET /profile(.:format) profile#show
+# profile_design GET /profile/design(.:format) profile#design
+# profile_update PUT /profile/update(.:format) profile#update
+describe ProfileController, "routing" do
+ it "to #account" do
+ get("/profile/account").should route_to('profile#account')
+ end
+
+ it "to #history" do
+ get("/profile/history").should route_to('profile#history')
+ end
+
+ it "to #password_update" do
+ put("/profile/password").should route_to('profile#password_update')
+ end
+
+ it "to #token" do
+ get("/profile/token").should route_to('profile#token')
+ end
+
+ it "to #reset_private_token" do
+ put("/profile/reset_private_token").should route_to('profile#reset_private_token')
+ end
+
+ it "to #show" do
+ get("/profile").should route_to('profile#show')
+ end
+
+ it "to #design" do
+ get("/profile/design").should route_to('profile#design')
+ end
+
+ it "to #update" do
+ put("/profile/update").should route_to('profile#update')
+ end
+end
+
+# keys GET /keys(.:format) keys#index
+# POST /keys(.:format) keys#create
+# new_key GET /keys/new(.:format) keys#new
+# edit_key GET /keys/:id/edit(.:format) keys#edit
+# key GET /keys/:id(.:format) keys#show
+# PUT /keys/:id(.:format) keys#update
+# DELETE /keys/:id(.:format) keys#destroy
+describe KeysController, "routing" do
+ it "to #index" do
+ get("/keys").should route_to('keys#index')
+ end
+
+ it "to #create" do
+ post("/keys").should route_to('keys#create')
+ end
+
+ it "to #new" do
+ get("/keys/new").should route_to('keys#new')
+ end
+
+ it "to #edit" do
+ get("/keys/1/edit").should route_to('keys#edit', id: '1')
+ end
+
+ it "to #show" do
+ get("/keys/1").should route_to('keys#show', id: '1')
+ end
+
+ it "to #update" do
+ put("/keys/1").should route_to('keys#update', id: '1')
+ end
+
+ it "to #destroy" do
+ delete("/keys/1").should route_to('keys#destroy', id: '1')
+ end
+end
+
+# dashboard GET /dashboard(.:format) dashboard#index
+# dashboard_issues GET /dashboard/issues(.:format) dashboard#issues
+# dashboard_merge_requests GET /dashboard/merge_requests(.:format) dashboard#merge_requests
+# root / dashboard#index
+describe DashboardController, "routing" do
+ it "to #index" do
+ get("/dashboard").should route_to('dashboard#index')
+ get("/").should route_to('dashboard#index')
+ end
+
+ it "to #issues" do
+ get("/dashboard/issues").should route_to('dashboard#issues')
+ end
+
+ it "to #merge_requests" do
+ get("/dashboard/merge_requests").should route_to('dashboard#merge_requests')
+ end
+end
+
+# new_user_session GET /users/sign_in(.:format) devise/sessions#new
+# user_session POST /users/sign_in(.:format) devise/sessions#create
+# destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
+# user_omniauth_authorize /users/auth/:provider(.:format) omniauth_callbacks#passthru
+# user_omniauth_callback /users/auth/:action/callback(.:format) omniauth_callbacks#(?-mix:(?!))
+# user_password POST /users/password(.:format) devise/passwords#create
+# new_user_password GET /users/password/new(.:format) devise/passwords#new
+# edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
+# PUT /users/password(.:format) devise/passwords#update
+describe "Authentication", "routing" do
+ # pending
+end
diff --git a/spec/support/gitolite_stub.rb b/spec/support/gitolite_stub.rb
index 037b09cd..574bb5a1 100644
--- a/spec/support/gitolite_stub.rb
+++ b/spec/support/gitolite_stub.rb
@@ -5,42 +5,16 @@ module GitoliteStub
end
def stub_gitolite_admin
- gitolite_repo = mock(
- clean_permissions: true,
- add_permission: true
- )
-
- gitolite_config = mock(
- add_repo: true,
- get_repo: gitolite_repo,
- has_repo?: true
- )
-
- gitolite_admin = double(
- 'Gitolite::GitoliteAdmin',
- config: gitolite_config,
- save: true,
- )
+ gitolite_admin = double('Gitolite::GitoliteAdmin')
+ gitolite_admin.as_null_object
Gitolite::GitoliteAdmin.stub(new: gitolite_admin)
-
end
def stub_gitlab_gitolite
gitolite_config = double('Gitlab::GitoliteConfig')
- gitolite_config.stub(
- apply: ->() { yield(self) },
- write_key: true,
- rm_key: true,
- update_projects: true,
- update_project: true,
- update_project!: true,
- destroy_project: true,
- destroy_project!: true,
- admin_all_repo: true,
- admin_all_repo!: true,
-
- )
+ gitolite_config.stub(apply: ->() { yield(self) })
+ gitolite_config.as_null_object
Gitlab::GitoliteConfig.stub(new: gitolite_config)
end
diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb
index cb1dcba3..809453c4 100644
--- a/spec/support/matchers.rb
+++ b/spec/support/matchers.rb
@@ -73,11 +73,7 @@ module Shoulda::Matchers::ActiveModel
class EnsureLengthOfMatcher
# Shortcut for is_at_least and is_at_most
def is_within(range)
- if range.exclude_end?
- is_at_least(range.first) && is_at_most(range.last - 1)
- else
- is_at_least(range.first) && is_at_most(range.last)
- end
+ is_at_least(range.min) && is_at_most(range.max)
end
end
end
diff --git a/vendor/assets/images/authbuttons/github_32.png b/vendor/assets/images/authbuttons/github_32.png
new file mode 100644
index 00000000..247e52a5
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_32.png differ
diff --git a/vendor/assets/images/authbuttons/github_64.png b/vendor/assets/images/authbuttons/github_64.png
new file mode 100644
index 00000000..fca7bf44
Binary files /dev/null and b/vendor/assets/images/authbuttons/github_64.png differ
diff --git a/vendor/assets/images/authbuttons/google_32.png b/vendor/assets/images/authbuttons/google_32.png
new file mode 100644
index 00000000..3909e9de
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_32.png differ
diff --git a/vendor/assets/images/authbuttons/google_64.png b/vendor/assets/images/authbuttons/google_64.png
new file mode 100644
index 00000000..e55f34f1
Binary files /dev/null and b/vendor/assets/images/authbuttons/google_64.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_32.png b/vendor/assets/images/authbuttons/twitter_32.png
new file mode 100644
index 00000000..daadcffd
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_32.png differ
diff --git a/vendor/assets/images/authbuttons/twitter_64.png b/vendor/assets/images/authbuttons/twitter_64.png
new file mode 100644
index 00000000..68b74530
Binary files /dev/null and b/vendor/assets/images/authbuttons/twitter_64.png differ