diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 592c57f948ce72cc9a7c5f947b6accad0464c46a..d416fb630c5db5e345e35cea1baaeada78349ffe 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -28,17 +28,9 @@ class Milestone < ActiveRecord::Base
   end
 
   def percent_complete
-    @percent_complete ||= begin
-                            total_i = self.issues.count
-                            closed_i = self.issues.closed.count
-                            if total_i > 0
-                              (closed_i * 100) / total_i
-                            else
-                              100
-                            end
-                          rescue => ex
-                            0
-                          end
+    ((self.issues.closed.count * 100) / self.issues.count).abs
+  rescue ZeroDivisionError
+    100
   end
 
   def expires_at
diff --git a/features/step_definitions/project/projects_steps.rb b/features/step_definitions/project/projects_steps.rb
index 3ff08d584489df7f5e6f8897eebf26d93381a924..d981e1f380290601f301b86698e4ac61fecab54f 100644
--- a/features/step_definitions/project/projects_steps.rb
+++ b/features/step_definitions/project/projects_steps.rb
@@ -1,4 +1,4 @@
-include LoginMacros
+include LoginHelpers
 
 Given /^I signin as a user$/ do
   login_as :user
diff --git a/features/support/env.rb b/features/support/env.rb
index b69a5fe7f072c546c9b92d004c42262aa8a20d94..80a465b472c4fcbbdd49115a0f55fb4b74a17df8 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -7,9 +7,9 @@ require 'cucumber/rails'
 require 'webmock/cucumber'
 WebMock.allow_net_connect!
 
-require Rails.root.join 'spec/monkeypatch'
 require Rails.root.join 'spec/factories'
-require Rails.root.join 'spec/support/login'
+require Rails.root.join 'spec/support/monkeypatch'
+require Rails.root.join 'spec/support/login_helpers'
 require Rails.root.join 'spec/support/valid_commit'
 
 Capybara.default_selector = :css
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 880d3f307a328928d945a4a80bc02e7e67bbb8ee..e9acc4e28159eed0f8a8d854bb5ebfa2445334e8 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -31,24 +31,33 @@ describe Milestone do
 
   it { milestone.should be_valid }
 
-  describe "Issues" do 
-    before do 
+  describe "#percent_complete" do
+    it "should not count open issues" do
       milestone.issues << issue
+      milestone.percent_complete.should == 0
     end
 
-    it { milestone.percent_complete.should == 0 }
+    it "should count closed issues" do
+      issue.update_attributes(closed: true)
+      milestone.issues << issue
+      milestone.percent_complete.should == 100
+    end
 
-    it do 
-      issue.update_attributes closed: true
+    it "should recover from dividing by zero" do
+      milestone.issues.should_receive(:count).and_return(0)
       milestone.percent_complete.should == 100
     end
   end
 
-  describe :expires_at do 
-    before do 
-      milestone.update_attributes due_date: Date.today + 1.day
+  describe "#expires_at" do
+    it "should be nil when due_date is unset" do
+      milestone.update_attributes(due_date: nil)
+      milestone.expires_at.should be_nil
     end
 
-    it { milestone.expires_at.should_not be_nil }
+    it "should not be nil when due_date is set" do
+      milestone.update_attributes(due_date: Date.tomorrow)
+      milestone.expires_at.should be_present
+    end
   end
 end
diff --git a/spec/models/activity_observer_spec.rb b/spec/observers/activity_observer_spec.rb
similarity index 100%
rename from spec/models/activity_observer_spec.rb
rename to spec/observers/activity_observer_spec.rb
diff --git a/spec/models/issue_observer_spec.rb b/spec/observers/issue_observer_spec.rb
similarity index 100%
rename from spec/models/issue_observer_spec.rb
rename to spec/observers/issue_observer_spec.rb
diff --git a/spec/models/user_observer_spec.rb b/spec/observers/user_observer_spec.rb
similarity index 100%
rename from spec/models/user_observer_spec.rb
rename to spec/observers/user_observer_spec.rb
diff --git a/spec/requests/admin/security_spec.rb b/spec/requests/admin/security_spec.rb
index 0c369740cffcd296f12054373f1b94ede8e56ae5..6306832628b8ba6aac2bbcd6b197d501341bccc9 100644
--- a/spec/requests/admin/security_spec.rb
+++ b/spec/requests/admin/security_spec.rb
@@ -2,20 +2,26 @@ require 'spec_helper'
 
 describe "Admin::Projects" do
   describe "GET /admin/projects" do
-    it { admin_projects_path.should be_allowed_for :admin }
-    it { admin_projects_path.should be_denied_for :user }
-    it { admin_projects_path.should be_denied_for :visitor }
+    subject { admin_projects_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 
   describe "GET /admin/users" do
-    it { admin_users_path.should be_allowed_for :admin }
-    it { admin_users_path.should be_denied_for :user }
-    it { admin_users_path.should be_denied_for :visitor }
+    subject { admin_users_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 
   describe "GET /admin/hooks" do
-    it { admin_hooks_path.should be_allowed_for :admin }
-    it { admin_hooks_path.should be_denied_for :user }
-    it { admin_hooks_path.should be_denied_for :visitor }
+    subject { admin_hooks_path }
+
+    it { should be_allowed_for :admin }
+    it { should be_denied_for :user }
+    it { should be_denied_for :visitor }
   end
 end
diff --git a/spec/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
similarity index 75%
rename from spec/api/issues_spec.rb
rename to spec/requests/api/issues_spec.rb
index f6d8e3792c2bf7fd24ce2309af80670c5caf47c8..c00a056d0798ca3468bb849bf31bec935f9e9b27 100644
--- a/spec/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -1,6 +1,8 @@
 require 'spec_helper'
 
 describe Gitlab::API do
+  include ApiHelpers
+
   let(:user) { Factory :user }
   let!(:project) { Factory :project, owner: user }
   let!(:issue) { Factory :issue, author: user, assignee: user, project: project }
@@ -8,13 +10,13 @@ describe Gitlab::API do
 
   describe "GET /issues" do
     it "should return authentication error" do
-      get "#{api_prefix}/issues"
+      get api("/issues")
       response.status.should == 401
     end
 
     describe "authenticated GET /issues" do
       it "should return an array of issues" do
-        get "#{api_prefix}/issues?private_token=#{user.private_token}"
+        get api("/issues", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['title'].should == issue.title
@@ -24,7 +26,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/issues" do
     it "should return project issues" do
-      get "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/issues", user)
       response.status.should == 200
       json_response.should be_an Array
       json_response.first['title'].should == issue.title
@@ -33,7 +35,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/issues/:issue_id" do
     it "should return a project issue by id" do
-      get "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/issues/#{issue.id}", user)
       response.status.should == 200
       json_response['title'].should == issue.title
     end
@@ -41,7 +43,7 @@ describe Gitlab::API do
 
   describe "POST /projects/:id/issues" do
     it "should create a new project issue" do
-      post "#{api_prefix}/projects/#{project.code}/issues?private_token=#{user.private_token}",
+      post api("/projects/#{project.code}/issues", user),
         title: 'new issue', labels: 'label, label2'
       response.status.should == 201
       json_response['title'].should == 'new issue'
@@ -52,7 +54,7 @@ describe Gitlab::API do
 
   describe "PUT /projects/:id/issues/:issue_id" do
     it "should update a project issue" do
-      put "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}",
+      put api("/projects/#{project.code}/issues/#{issue.id}", user),
         title: 'updated title', labels: 'label2', closed: 1
       response.status.should == 200
       json_response['title'].should == 'updated title'
@@ -64,7 +66,7 @@ describe Gitlab::API do
   describe "DELETE /projects/:id/issues/:issue_id" do
     it "should delete a project issue" do
       expect {
-        delete "#{api_prefix}/projects/#{project.code}/issues/#{issue.id}?private_token=#{user.private_token}"
+        delete api("/projects/#{project.code}/issues/#{issue.id}", user)
       }.to change { Issue.count }.by(-1)
     end
   end
diff --git a/spec/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
similarity index 67%
rename from spec/api/projects_spec.rb
rename to spec/requests/api/projects_spec.rb
index ff45619e58af31069ca412e32638ea62e94619ea..0cbc12af53bb493c373df58c6a6a8b7ca1add76a 100644
--- a/spec/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1,6 +1,8 @@
 require 'spec_helper'
 
 describe Gitlab::API do
+  include ApiHelpers
+
   let(:user) { Factory :user }
   let!(:project) { Factory :project, owner: user }
   let!(:snippet) { Factory :snippet, author: user, project: project, title: 'example' }
@@ -8,13 +10,13 @@ describe Gitlab::API do
 
   describe "GET /projects" do
     it "should return authentication error" do
-      get "#{api_prefix}/projects"
+      get api("/projects")
       response.status.should == 401
     end
 
     describe "authenticated GET /projects" do
       it "should return an array of projects" do
-        get "#{api_prefix}/projects?private_token=#{user.private_token}"
+        get api("/projects", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['name'].should == project.name
@@ -25,20 +27,20 @@ describe Gitlab::API do
 
   describe "GET /projects/:id" do
     it "should return a project by id" do
-      get "#{api_prefix}/projects/#{project.id}?private_token=#{user.private_token}"
+      get api("/projects/#{project.id}", user)
       response.status.should == 200
       json_response['name'].should == project.name
       json_response['owner']['email'].should == user.email
     end
 
     it "should return a project by code name" do
-      get "#{api_prefix}/projects/#{project.code}?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}", user)
       response.status.should == 200
       json_response['name'].should == project.name
     end
 
     it "should return a 404 error if not found" do
-      get "#{api_prefix}/projects/42?private_token=#{user.private_token}"
+      get api("/projects/42", user)
       response.status.should == 404
       json_response['message'].should == '404 Not found'
     end
@@ -46,7 +48,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/repository/branches" do
     it "should return an array of project branches" do
-      get "#{api_prefix}/projects/#{project.code}/repository/branches?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/repository/branches", user)
       response.status.should == 200
       json_response.should be_an Array
       json_response.first['name'].should == project.repo.heads.sort_by(&:name).first.name
@@ -55,7 +57,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/repository/branches/:branch" do
     it "should return the branch information for a single branch" do
-      get "#{api_prefix}/projects/#{project.code}/repository/branches/new_design?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/repository/branches/new_design", user)
       response.status.should == 200
 
       json_response['name'].should == 'new_design'
@@ -65,7 +67,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/repository/tags" do
     it "should return an array of project tags" do
-      get "#{api_prefix}/projects/#{project.code}/repository/tags?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/repository/tags", user)
       response.status.should == 200
       json_response.should be_an Array
       json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name
@@ -74,7 +76,7 @@ describe Gitlab::API do
 
   describe "GET /projects/:id/snippets/:snippet_id" do
     it "should return a project snippet" do
-      get "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/snippets/#{snippet.id}", user)
       response.status.should == 200
       json_response['title'].should == snippet.title
     end
@@ -82,7 +84,7 @@ describe Gitlab::API do
 
   describe "POST /projects/:id/snippets" do
     it "should create a new project snippet" do
-      post "#{api_prefix}/projects/#{project.code}/snippets?private_token=#{user.private_token}",
+      post api("/projects/#{project.code}/snippets", user),
         title: 'api test', file_name: 'sample.rb', code: 'test'
       response.status.should == 201
       json_response['title'].should == 'api test'
@@ -91,7 +93,7 @@ describe Gitlab::API do
 
   describe "PUT /projects/:id/snippets" do
     it "should update an existing project snippet" do
-      put "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}",
+      put api("/projects/#{project.code}/snippets/#{snippet.id}", user),
         code: 'updated code'
       response.status.should == 200
       json_response['title'].should == 'example'
@@ -102,34 +104,31 @@ describe Gitlab::API do
   describe "DELETE /projects/:id/snippets/:snippet_id" do
     it "should delete existing project snippet" do
       expect {
-        delete "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}?private_token=#{user.private_token}"
+        delete api("/projects/#{project.code}/snippets/#{snippet.id}", user)
       }.to change { Snippet.count }.by(-1)
     end
   end
 
   describe "GET /projects/:id/snippets/:snippet_id/raw" do
     it "should get a raw project snippet" do
-      get "#{api_prefix}/projects/#{project.code}/snippets/#{snippet.id}/raw?private_token=#{user.private_token}"
+      get api("/projects/#{project.code}/snippets/#{snippet.id}/raw", user)
       response.status.should == 200
     end
   end
 
   describe "GET /projects/:id/:sha/blob" do
     it "should get the raw file contents" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/master/blob?filepath=README.md&private_token=#{user.private_token}"
-      
+      get api("/projects/#{project.code}/repository/commits/master/blob?filepath=README.md", user)
       response.status.should == 200
     end
 
     it "should return 404 for invalid branch_name" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/invalid_branch_name/blob?filepath=README.md&private_token=#{user.private_token}"
-      
+      get api("/projects/#{project.code}/repository/commits/invalid_branch_name/blob?filepath=README.md", user)
       response.status.should == 404
     end
 
     it "should return 404 for invalid file" do
-      get "#{api_prefix}/projects/#{project.code}/repository/commits/master/blob?filepath=README.invalid&private_token=#{user.private_token}"
-      
+      get api("/projects/#{project.code}/repository/commits/master/blob?filepath=README.invalid", user)
       response.status.should == 404
     end
   end
diff --git a/spec/api/users_spec.rb b/spec/requests/api/users_spec.rb
similarity index 76%
rename from spec/api/users_spec.rb
rename to spec/requests/api/users_spec.rb
index 32b9379d212969d789b529bff5cca9380351eca4..d791962adc269eb1b74ad3ab4c9fc64fe57cf91a 100644
--- a/spec/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1,17 +1,19 @@
 require 'spec_helper'
 
 describe Gitlab::API do
+  include ApiHelpers
+
   let(:user) { Factory :user }
 
   describe "GET /users" do
     it "should return authentication error" do
-      get "#{api_prefix}/users"
+      get api("/users")
       response.status.should == 401
     end
 
     describe "authenticated GET /users" do
       it "should return an array of users" do
-        get "#{api_prefix}/users?private_token=#{user.private_token}"
+        get api("/users", user)
         response.status.should == 200
         json_response.should be_an Array
         json_response.first['email'].should == user.email
@@ -21,7 +23,7 @@ describe Gitlab::API do
 
   describe "GET /users/:id" do
     it "should return a user by id" do
-      get "#{api_prefix}/users/#{user.id}?private_token=#{user.private_token}"
+      get api("/users/#{user.id}", user)
       response.status.should == 200
       json_response['email'].should == user.email
     end
@@ -29,7 +31,7 @@ describe Gitlab::API do
 
   describe "GET /user" do
     it "should return current user" do
-      get "#{api_prefix}/user?private_token=#{user.private_token}"
+      get api("/user", user)
       response.status.should == 200
       json_response['email'].should == user.email
     end
diff --git a/spec/requests/security/profile_access_spec.rb b/spec/requests/security/profile_access_spec.rb
index b8ed27f031ca1a1648f30abb178d88a1f5692304..9f6fe6a2b50353d6b2f99bca1e14287bae37e366 100644
--- a/spec/requests/security/profile_access_spec.rb
+++ b/spec/requests/security/profile_access_spec.rb
@@ -11,24 +11,30 @@ describe "Users Security" do
     end
 
     describe "GET /keys" do
-      it { keys_path.should be_allowed_for @u1 }
-      it { keys_path.should be_allowed_for :admin }
-      it { keys_path.should be_allowed_for :user }
-      it { keys_path.should be_denied_for :visitor }
+      subject { keys_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /profile" do
-      it { profile_path.should be_allowed_for @u1 }
-      it { profile_path.should be_allowed_for :admin }
-      it { profile_path.should be_allowed_for :user }
-      it { profile_path.should be_denied_for :visitor }
+      subject { profile_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /profile/password" do
-      it { profile_password_path.should be_allowed_for @u1 }
-      it { profile_password_path.should be_allowed_for :admin }
-      it { profile_password_path.should be_allowed_for :user }
-      it { profile_password_path.should be_denied_for :visitor }
+      subject { profile_password_path }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for :admin }
+      it { should be_allowed_for :user }
+      it { should be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/requests/security/project_access_spec.rb b/spec/requests/security/project_access_spec.rb
index d503cf857b54ce0695cc1f1ca2d0e910c30510a5..0cdf43bf84eb86a036bcb39122d05a311718b72b 100644
--- a/spec/requests/security/project_access_spec.rb
+++ b/spec/requests/security/project_access_spec.rb
@@ -26,64 +26,76 @@ describe "Application access" do
     end
 
     describe "GET /project_code" do
-      it { project_path(@project).should be_allowed_for @u1 }
-      it { project_path(@project).should be_allowed_for @u3 }
-      it { project_path(@project).should be_denied_for :admin }
-      it { project_path(@project).should be_denied_for @u2 }
-      it { project_path(@project).should be_denied_for :user }
-      it { project_path(@project).should be_denied_for :visitor }
+      subject { project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/master/tree" do
-      it { tree_project_ref_path(@project, @project.root_ref).should be_allowed_for @u1 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_allowed_for @u3 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :admin }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for @u2 }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :user }
-      it { tree_project_ref_path(@project, @project.root_ref).should be_denied_for :visitor }
+      subject { tree_project_ref_path(@project, @project.root_ref) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/commits" do
-      it { project_commits_path(@project).should be_allowed_for @u1 }
-      it { project_commits_path(@project).should be_allowed_for @u3 }
-      it { project_commits_path(@project).should be_denied_for :admin }
-      it { project_commits_path(@project).should be_denied_for @u2 }
-      it { project_commits_path(@project).should be_denied_for :user }
-      it { project_commits_path(@project).should be_denied_for :visitor }
+      subject { project_commits_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/commit" do
-      it { project_commit_path(@project, @project.commit.id).should be_allowed_for @u1 }
-      it { project_commit_path(@project, @project.commit.id).should be_allowed_for @u3 }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :admin }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for @u2 }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :user }
-      it { project_commit_path(@project, @project.commit.id).should be_denied_for :visitor }
+      subject { project_commit_path(@project, @project.commit.id) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/team" do
-      it { team_project_path(@project).should be_allowed_for @u1 }
-      it { team_project_path(@project).should be_allowed_for @u3 }
-      it { team_project_path(@project).should be_denied_for :admin }
-      it { team_project_path(@project).should be_denied_for @u2 }
-      it { team_project_path(@project).should be_denied_for :user }
-      it { team_project_path(@project).should be_denied_for :visitor }
+      subject { team_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/wall" do
-      it { wall_project_path(@project).should be_allowed_for @u1 }
-      it { wall_project_path(@project).should be_allowed_for @u3 }
-      it { wall_project_path(@project).should be_denied_for :admin }
-      it { wall_project_path(@project).should be_denied_for @u2 }
-      it { wall_project_path(@project).should be_denied_for :user }
-      it { wall_project_path(@project).should be_denied_for :visitor }
+      subject { wall_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/blob" do
       before do
-        @commit = @project.commit
-        @path = @commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
-        @blob_path = blob_project_ref_path(@project, @commit.id, path: @path)
+        commit = @project.commit
+        path = commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name
+        @blob_path = blob_project_ref_path(@project, commit.id, path: path)
       end
 
       it { @blob_path.should be_allowed_for @u1 }
@@ -95,93 +107,113 @@ describe "Application access" do
     end
 
     describe "GET /project_code/edit" do
-      it { edit_project_path(@project).should be_allowed_for @u1 }
-      it { edit_project_path(@project).should be_denied_for @u3 }
-      it { edit_project_path(@project).should be_denied_for :admin }
-      it { edit_project_path(@project).should be_denied_for @u2 }
-      it { edit_project_path(@project).should be_denied_for :user }
-      it { edit_project_path(@project).should be_denied_for :visitor }
+      subject { edit_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_denied_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/deploy_keys" do
-      it { project_deploy_keys_path(@project).should be_allowed_for @u1 }
-      it { project_deploy_keys_path(@project).should be_denied_for @u3 }
-      it { project_deploy_keys_path(@project).should be_denied_for :admin }
-      it { project_deploy_keys_path(@project).should be_denied_for @u2 }
-      it { project_deploy_keys_path(@project).should be_denied_for :user }
-      it { project_deploy_keys_path(@project).should be_denied_for :visitor }
+      subject { project_deploy_keys_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_denied_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/issues" do
-      it { project_issues_path(@project).should be_allowed_for @u1 }
-      it { project_issues_path(@project).should be_allowed_for @u3 }
-      it { project_issues_path(@project).should be_denied_for :admin }
-      it { project_issues_path(@project).should be_denied_for @u2 }
-      it { project_issues_path(@project).should be_denied_for :user }
-      it { project_issues_path(@project).should be_denied_for :visitor }
+      subject { project_issues_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/snippets" do
-      it { project_snippets_path(@project).should be_allowed_for @u1 }
-      it { project_snippets_path(@project).should be_allowed_for @u3 }
-      it { project_snippets_path(@project).should be_denied_for :admin }
-      it { project_snippets_path(@project).should be_denied_for @u2 }
-      it { project_snippets_path(@project).should be_denied_for :user }
-      it { project_snippets_path(@project).should be_denied_for :visitor }
+      subject { project_snippets_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/merge_requests" do
-      it { project_merge_requests_path(@project).should be_allowed_for @u1 }
-      it { project_merge_requests_path(@project).should be_allowed_for @u3 }
-      it { project_merge_requests_path(@project).should be_denied_for :admin }
-      it { project_merge_requests_path(@project).should be_denied_for @u2 }
-      it { project_merge_requests_path(@project).should be_denied_for :user }
-      it { project_merge_requests_path(@project).should be_denied_for :visitor }
+      subject { project_merge_requests_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository" do
-      it { project_repository_path(@project).should be_allowed_for @u1 }
-      it { project_repository_path(@project).should be_allowed_for @u3 }
-      it { project_repository_path(@project).should be_denied_for :admin }
-      it { project_repository_path(@project).should be_denied_for @u2 }
-      it { project_repository_path(@project).should be_denied_for :user }
-      it { project_repository_path(@project).should be_denied_for :visitor }
+      subject { project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository/branches" do
-      it { branches_project_repository_path(@project).should be_allowed_for @u1 }
-      it { branches_project_repository_path(@project).should be_allowed_for @u3 }
-      it { branches_project_repository_path(@project).should be_denied_for :admin }
-      it { branches_project_repository_path(@project).should be_denied_for @u2 }
-      it { branches_project_repository_path(@project).should be_denied_for :user }
-      it { branches_project_repository_path(@project).should be_denied_for :visitor }
+      subject { branches_project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/repository/tags" do
-      it { tags_project_repository_path(@project).should be_allowed_for @u1 }
-      it { tags_project_repository_path(@project).should be_allowed_for @u3 }
-      it { tags_project_repository_path(@project).should be_denied_for :admin }
-      it { tags_project_repository_path(@project).should be_denied_for @u2 }
-      it { tags_project_repository_path(@project).should be_denied_for :user }
-      it { tags_project_repository_path(@project).should be_denied_for :visitor }
+      subject { tags_project_repository_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/hooks" do
-      it { project_hooks_path(@project).should be_allowed_for @u1 }
-      it { project_hooks_path(@project).should be_allowed_for @u3 }
-      it { project_hooks_path(@project).should be_denied_for :admin }
-      it { project_hooks_path(@project).should be_denied_for @u2 }
-      it { project_hooks_path(@project).should be_denied_for :user }
-      it { project_hooks_path(@project).should be_denied_for :visitor }
+      subject { project_hooks_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
 
     describe "GET /project_code/files" do
-      it { files_project_path(@project).should be_allowed_for @u1 }
-      it { files_project_path(@project).should be_allowed_for @u3 }
-      it { files_project_path(@project).should be_denied_for :admin }
-      it { files_project_path(@project).should be_denied_for @u2 }
-      it { files_project_path(@project).should be_denied_for :user }
-      it { files_project_path(@project).should be_denied_for :visitor }
+      subject { files_project_path(@project) }
+
+      it { should be_allowed_for @u1 }
+      it { should be_allowed_for @u3 }
+      it { should be_denied_for :admin }
+      it { should be_denied_for @u2 }
+      it { should be_denied_for :user }
+      it { should be_denied_for :visitor }
     end
   end
 end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index cd931475486b92a766b1e6be86f26636bad20700..9fb0ad7e24979f31382792ddc12491eb682098a1 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -9,10 +9,8 @@ require File.expand_path("../../config/environment", __FILE__)
 require 'rspec/rails'
 require 'capybara/rails'
 require 'capybara/rspec'
-require 'capybara/dsl'
 require 'webmock/rspec'
 require 'factories'
-require 'monkeypatch'
 require 'email_spec'
 require 'headless'
 
@@ -23,10 +21,12 @@ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
 # Use capybara-webkit
 Capybara.javascript_driver = :webkit
 
+WebMock.disable_net_connect!(allow_localhost: true)
+
 RSpec.configure do |config|
   config.mock_with :rspec
 
-  config.include LoginMacros
+  config.include LoginHelpers, type: :request
 
   # If you're not using ActiveRecord, or you'd prefer not to run each of your
   # examples within a transaction, remove the following line or assign false
@@ -38,35 +38,9 @@ RSpec.configure do |config|
     headless.start
   end
 
-  config.before :each, type: :integration do
-    DeviseSessionMock.disable
-  end
-
   config.before do
-    if example.metadata[:js]
-      DatabaseCleaner.strategy = :truncation
-      Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true
-    else
-      DatabaseCleaner.strategy = :transaction
-    end
-
-    DatabaseCleaner.start
-
-    WebMock.disable_net_connect!(allow_localhost: true)
-
     # !!! Observers disabled by default in tests
-    #
-    #   Use next code to enable observers
-    #   before(:each) { ActiveRecord::Base.observers.enable(:all) }
-    #
-    ActiveRecord::Base.observers.disable :all
-  end
-
-  config.after do
-    DatabaseCleaner.clean
+    ActiveRecord::Base.observers.disable(:all)
+    # ActiveRecord::Base.observers.enable(:all)
   end
-
-  config.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: {
-    file_path: /spec\/api/
-  }
 end
diff --git a/spec/support/api.rb b/spec/support/api.rb
deleted file mode 100644
index d363d8b9a578eae234c0e049f0b4f03e83ce14a2..0000000000000000000000000000000000000000
--- a/spec/support/api.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-def api_prefix
-  "/api/#{Gitlab::API::VERSION}"
-end
-
-def json_response
-  JSON.parse(response.body)
-end
diff --git a/spec/support/api_helpers.rb b/spec/support/api_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7d9011971dd1a91482ff11c2d63ac156993fbdbc
--- /dev/null
+++ b/spec/support/api_helpers.rb
@@ -0,0 +1,34 @@
+module ApiHelpers
+  # Public: Prepend a request path with the path to the API
+  #
+  # path - Path to append
+  # user - User object - If provided, automatically appends private_token query
+  #          string for authenticated requests
+  #
+  # Examples
+  #
+  #   >> api('/issues')
+  #   => "/api/v2/issues"
+  #
+  #   >> api('/issues', User.last)
+  #   => "/api/v2/issues?private_token=..."
+  #
+  #   >> api('/issues?foo=bar', User.last)
+  #   => "/api/v2/issues?foo=bar&private_token=..."
+  #
+  # Returns the relative path to the requested API resource
+  def api(path, user = nil)
+    "/api/#{Gitlab::API::VERSION}#{path}" +
+
+      # Normalize query string
+      (path.index('?') ? '' : '?') +
+
+      # Append private_token if given a User object
+      (user.respond_to?(:private_token) ?
+        "&private_token=#{user.private_token}" : "")
+  end
+
+  def json_response
+    JSON.parse(response.body)
+  end
+end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f1e072aa15f7f71974cb4633cf9fc1da4c42e39d
--- /dev/null
+++ b/spec/support/db_cleaner.rb
@@ -0,0 +1,18 @@
+require 'database_cleaner'
+
+RSpec.configure do |config|
+  config.before do
+    if example.metadata[:js]
+      DatabaseCleaner.strategy = :truncation
+      Capybara::Selenium::Driver::DEFAULT_OPTIONS[:resynchronize] = true
+    else
+      DatabaseCleaner.strategy = :transaction
+    end
+
+    DatabaseCleaner.start
+  end
+
+  config.after do
+    DatabaseCleaner.clean
+  end
+end
diff --git a/spec/support/js_patch.rb b/spec/support/js_patch.rb
deleted file mode 100644
index 0d4ab264e858956c04146a28f001d670646362ad..0000000000000000000000000000000000000000
--- a/spec/support/js_patch.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module JsPatch
-  def confirm_js_popup
-    page.evaluate_script("window.alert = function(msg) { return true; }")
-    page.evaluate_script("window.confirm = function(msg) { return true; }")
-  end
-end
diff --git a/spec/support/login.rb b/spec/support/login.rb
deleted file mode 100644
index 78a907bad0b196f176811588df88b714072f1874..0000000000000000000000000000000000000000
--- a/spec/support/login.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-module LoginMacros
-  def login_as role
-    @user = User.create(email: "user#{User.count}@mail.com",
-                        name: "John Smith",
-                        password: "123456",
-                        password_confirmation: "123456",
-                        skype: 'user_skype')
-
-    if role == :admin
-      @user.admin = true
-      @user.save!
-    end
-
-    visit new_user_session_path
-    fill_in "user_email", with: @user.email
-    fill_in "user_password", with: "123456"
-    click_button "Sign in"
-  end
-
-  def login_with(user)
-    visit new_user_session_path
-    fill_in "user_email", with: user.email
-    fill_in "user_password", with: "123456"
-    click_button "Sign in"
-  end
-
-  def logout
-    click_link "Logout" rescue nil
-  end
-end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..769034e2286ddc8bad23d613c775d0b6b0f46051
--- /dev/null
+++ b/spec/support/login_helpers.rb
@@ -0,0 +1,23 @@
+module LoginHelpers
+  # Internal: Create and log in as a user of the specified role
+  #
+  # role - User role (e.g., :admin, :user)
+  def login_as(role)
+    @user = Factory(role)
+    login_with(@user)
+  end
+
+  # Internal: Login as the specified user
+  #
+  # user - User instance to login with
+  def login_with(user)
+    visit new_user_session_path
+    fill_in "user_email", with: user.email
+    fill_in "user_password", with: "123456"
+    click_button "Sign in"
+  end
+
+  def logout
+    click_link "Logout" rescue nil
+  end
+end
diff --git a/spec/monkeypatch.rb b/spec/support/monkeypatch.rb
similarity index 100%
rename from spec/monkeypatch.rb
rename to spec/support/monkeypatch.rb
diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb
deleted file mode 100644
index 9fd207d0db25771e7410edac89654f6dbf0c36ae..0000000000000000000000000000000000000000
--- a/spec/support/shared_examples.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-shared_examples_for :project_side_pane do
-  subject { page }
-  it { should have_content((@project || project).name) }
-  it { should have_content("Commits") }
-  it { should have_content("Files") }
-end
-
-shared_examples_for :tree_view do
-  subject { page }
-
-  it "should have Tree View of project" do
-    should have_content("app")
-    should have_content("History")
-    should have_content("Gemfile")
-  end
-end