diff options
Diffstat (limited to 'spec')
34 files changed, 1778 insertions, 0 deletions
diff --git a/spec/factories.rb b/spec/factories.rb new file mode 100644 index 00000000000..457c08ba87d --- /dev/null +++ b/spec/factories.rb @@ -0,0 +1,43 @@ +require File.join(Rails.root, 'spec', 'factory') + +Factory.add(:project, Project) do |obj| + obj.name = Faker::Internet.user_name + obj.path = 'legit' + obj.code = 'LGT' +end + +Factory.add(:public_project, Project) do |obj| + obj.name = Faker::Internet.user_name + obj.path = 'legit' + obj.private_flag = false + obj.code = 'LGT' +end + +Factory.add(:user, User) do |obj| + obj.email = Faker::Internet.email + obj.password = "123456" + obj.name = Faker::Name.name + obj.password_confirmation = "123456" +end + +Factory.add(:admin, User) do |obj| + obj.email = Faker::Internet.email + obj.password = "123456" + obj.name = Faker::Name.name + obj.password_confirmation = "123456" + obj.admin = true +end + +Factory.add(:issue, Issue) do |obj| + obj.title = Faker::Lorem.sentence + obj.content = Faker::Lorem.sentences +end + +Factory.add(:note, Note) do |obj| + obj.note = Faker::Lorem.sentence +end + +Factory.add(:key, Key) do |obj| + obj.title = "Example key" + obj.key = File.read(File.join(Rails.root, "db", "pkey.example")) +end diff --git a/spec/factory.rb b/spec/factory.rb new file mode 100644 index 00000000000..29e552b1474 --- /dev/null +++ b/spec/factory.rb @@ -0,0 +1,29 @@ +class Factory + @factories = {} + + class << self + def add(name, klass, &block) + @factories[name] = [klass, block] + end + + def create(name, opts = {}) + new(name, opts).tap(&:save!) + end + + def new(name, opts) + factory = @factories[name] + factory[0].new.tap do |obj| + factory[1].call(obj) + end.tap do |obj| + opts.each do |k, opt| + obj.send("#{k}=", opt) + end + end + end + end +end + +def Factory(name, opts={}) + Factory.create name, opts +end + diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb new file mode 100644 index 00000000000..23609023c50 --- /dev/null +++ b/spec/models/issue_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Issue do + describe "Associations" do + it { should belong_to(:project) } + it { should belong_to(:author) } + it { should belong_to(:assignee) } + end + + describe "Validation" do + it { should validate_presence_of(:title) } + it { should validate_presence_of(:author_id) } + it { should validate_presence_of(:project_id) } + it { should validate_presence_of(:assignee_id) } + end + + describe "Scope" do + it { Issue.should respond_to :closed } + it { Issue.should respond_to :opened } + end + + it { Factory.create(:issue, + :author => Factory(:user), + :assignee => Factory(:user), + :project => Factory.create(:project)).should be_valid } + +end +# == Schema Information +# +# Table name: issues +# +# id :integer not null, primary key +# title :string(255) +# content :text +# assignee_id :integer +# author_id :integer +# project_id :integer +# created_at :datetime +# updated_at :datetime +# closed :boolean default(FALSE), not null +# + diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb new file mode 100644 index 00000000000..8515f19b2f2 --- /dev/null +++ b/spec/models/key_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe Key do + describe "Associations" do + it { should belong_to(:user) } + end + + describe "Validation" do + it { should validate_presence_of(:title) } + it { should validate_presence_of(:key) } + end + + describe "Methods" do + it { should respond_to :projects } + end + + it { Factory.create(:key, + :user => Factory(:user)).should be_valid } +end +# == Schema Information +# +# Table name: keys +# +# id :integer not null, primary key +# user_id :integer not null +# created_at :datetime +# updated_at :datetime +# key :text +# title :string(255) +# identifier :string(255) +# + diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb new file mode 100644 index 00000000000..20bd41adc29 --- /dev/null +++ b/spec/models/note_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe Note do + describe "Associations" do + it { should belong_to(:project) } + end + + describe "Validation" do + it { should validate_presence_of(:note) } + it { should validate_presence_of(:project) } + end + + it { Factory.create(:note, + :project => Factory.create(:project)).should be_valid } + + describe :authorization do + before do + @p1 = Factory :project + @p2 = Factory :project, :code => "alien", :path => "legit_1" + @u1 = Factory :user + @u2 = Factory :user + @u3 = Factory :user + @abilities = Six.new + @abilities << Ability + end + + describe :read do + before do + @p1.users_projects.create(:user => @u1, :read => false) + @p1.users_projects.create(:user => @u2, :read => true) + @p2.users_projects.create(:user => @u3, :read => true) + end + + it { @abilities.allowed?(@u1, :read_note, @p1).should be_false } + it { @abilities.allowed?(@u2, :read_note, @p1).should be_true } + it { @abilities.allowed?(@u3, :read_note, @p1).should be_false } + end + + describe :write do + before do + @p1.users_projects.create(:user => @u1, :write => false) + @p1.users_projects.create(:user => @u2, :write => true) + @p2.users_projects.create(:user => @u3, :write => true) + end + + it { @abilities.allowed?(@u1, :write_note, @p1).should be_false } + it { @abilities.allowed?(@u2, :write_note, @p1).should be_true } + it { @abilities.allowed?(@u3, :write_note, @p1).should be_false } + end + + describe :admin do + before do + @p1.users_projects.create(:user => @u1, :admin => false) + @p1.users_projects.create(:user => @u2, :admin => true) + @p2.users_projects.create(:user => @u3, :admin => true) + end + + it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false } + it { @abilities.allowed?(@u2, :admin_note, @p1).should be_true } + it { @abilities.allowed?(@u3, :admin_note, @p1).should be_false } + end + end +end +# == Schema Information +# +# Table name: notes +# +# id :integer not null, primary key +# note :string(255) +# noteable_id :string(255) +# noteable_type :string(255) +# author_id :integer +# created_at :datetime +# updated_at :datetime +# project_id :integer +# attachment :string(255) +# + diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb new file mode 100644 index 00000000000..8eb8ee80f6c --- /dev/null +++ b/spec/models/project_security_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe Project do + describe :authorization do + before do + @p1 = Factory :project + @u1 = Factory :user + @u2 = Factory :user + @abilities = Six.new + @abilities << Ability + end + + describe :read do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :read => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :read => true) + end + + it { @abilities.allowed?(@u1, :read_project, @p1).should be_false } + it { @abilities.allowed?(@u2, :read_project, @p1).should be_true } + end + + describe :write do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :write => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :write => true) + end + + it { @abilities.allowed?(@u1, :write_project, @p1).should be_false } + it { @abilities.allowed?(@u2, :write_project, @p1).should be_true } + end + + describe :admin do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :admin => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :admin => true) + end + + it { @abilities.allowed?(@u1, :admin_project, @p1).should be_false } + it { @abilities.allowed?(@u2, :admin_project, @p1).should be_true } + end + end +end +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) +# path :string(255) +# description :text +# created_at :datetime +# updated_at :datetime +# private_flag :boolean default(TRUE), not null +# code :string(255) +# + diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb new file mode 100644 index 00000000000..8f41b525286 --- /dev/null +++ b/spec/models/project_spec.rb @@ -0,0 +1,126 @@ +require 'spec_helper' + +describe Project do + describe "Associations" do + it { should have_many(:users) } + it { should have_many(:users_projects) } + end + + describe "Validation" do + it { should validate_presence_of(:name) } + it { should validate_presence_of(:path) } + end + + describe "Respond to" do + it { should respond_to(:readers) } + it { should respond_to(:writers) } + it { should respond_to(:gitosis_writers) } + it { should respond_to(:admins) } + it { should respond_to(:add_access) } + it { should respond_to(:reset_access) } + it { should respond_to(:update_gitosis_project) } + it { should respond_to(:destroy_gitosis_project) } + it { should respond_to(:public?) } + it { should respond_to(:private?) } + it { should respond_to(:url_to_repo) } + it { should respond_to(:path_to_repo) } + it { should respond_to(:valid_repo?) } + it { should respond_to(:repo_exists?) } + it { should respond_to(:repo) } + it { should respond_to(:tags) } + it { should respond_to(:commit) } + end + + it "should return valid url to repo" do + project = Project.new(:path => "somewhere") + project.url_to_repo.should == "git@localhost:somewhere.git" + end + + it "should return path to repo" do + project = Project.new(:path => "somewhere") + project.path_to_repo.should == "/tmp/somewhere" + end + + describe :valid_repo? do + it "should be valid repo" do + project = Factory :project + project.valid_repo?.should be_true + end + + it "should be invalid repo" do + project = Project.new(:name => "ok_name", :path => "/INVALID_PATH/", :code => "NEOK") + project.valid_repo?.should be_false + end + end + + describe "Git methods" do + let(:project) { Factory :project } + + describe :repo do + it "should return valid repo" do + project.repo.should be_kind_of(Grit::Repo) + end + + it "should return nil" do + lambda { Project.new(:path => "invalid").repo }.should raise_error(Grit::NoSuchPathError) + end + + it "should return nil" do + lambda { Project.new.repo }.should raise_error(TypeError) + end + end + + describe :commit do + it "should return first head commit if without params" do + project.commit.id.should == project.repo.commits.first.id + end + + it "should return valid commit" do + project.commit(ValidCommit::ID).should be_valid_commit + end + + it "should return nil" do + project.commit("+123_4532530XYZ").should be_nil + end + end + + describe :tree do + before do + @commit = project.commit(ValidCommit::ID) + end + + it "should raise error w/o arguments" do + lambda { project.tree }.should raise_error + end + + it "should return root tree for commit" do + tree = project.tree(@commit) + tree.contents.size.should == ValidCommit::FILES_COUNT + tree.contents.map(&:name).should == ValidCommit::FILES + end + + it "should return root tree for commit with correct path" do + tree = project.tree(@commit, ValidCommit::C_FILE_PATH) + tree.contents.map(&:name).should == ValidCommit::C_FILES + end + + it "should return root tree for commit with incorrect path" do + project.tree(@commit, "invalid_path").should be_nil + end + end + end +end +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# name :string(255) +# path :string(255) +# description :text +# created_at :datetime +# updated_at :datetime +# private_flag :boolean default(TRUE), not null +# code :string(255) +# + diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb new file mode 100644 index 00000000000..aedfd20ade0 --- /dev/null +++ b/spec/models/user_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe User do + describe "Associations" do + it { should have_many(:projects) } + it { should have_many(:users_projects) } + it { should have_many(:issues) } + it { should have_many(:assigned_issues) } + end + + describe "Respond to" do + it { should respond_to(:is_admin?) } + it { should respond_to(:identifier) } + it { should respond_to(:name) } + end + + it "should return valid identifier" do + user = User.new(:email => "test@mail.com") + user.identifier.should == "test_mail.com" + end +end +# == Schema Information +# +# Table name: users +# +# id :integer not null, primary key +# email :string(255) default(""), not null +# encrypted_password :string(128) default(""), not null +# reset_password_token :string(255) +# reset_password_sent_at :datetime +# remember_created_at :datetime +# sign_in_count :integer default(0) +# current_sign_in_at :datetime +# last_sign_in_at :datetime +# current_sign_in_ip :string(255) +# last_sign_in_ip :string(255) +# created_at :datetime +# updated_at :datetime +# name :string(255) +# admin :boolean default(FALSE), not null +# + diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb new file mode 100644 index 00000000000..d6a4d02b6e2 --- /dev/null +++ b/spec/models/users_project_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe UsersProject do + describe "Associations" do + it { should belong_to(:project) } + it { should belong_to(:user) } + end + + describe "Validation" do + it { should validate_presence_of(:user_id) } + it { should validate_presence_of(:project_id) } + end + + describe "Delegate methods" do + it { should respond_to(:user_name) } + it { should respond_to(:user_email) } + end +end +# == Schema Information +# +# Table name: users_projects +# +# id :integer not null, primary key +# user_id :integer not null +# project_id :integer not null +# read :boolean default(FALSE) +# write :boolean default(FALSE) +# admin :boolean default(FALSE) +# created_at :datetime +# updated_at :datetime +# + diff --git a/spec/monkeypatch.rb b/spec/monkeypatch.rb new file mode 100644 index 00000000000..e630cc10d31 --- /dev/null +++ b/spec/monkeypatch.rb @@ -0,0 +1,31 @@ +# Stubbing Project <-> gitosis path +# create project using Factory only +class Project + def update_gitosis_project + true + end + + def update_gitosis + true + end + + def path_to_repo + "/tmp/" + path + end +end + +class Key + def update_gitosis + true + end + + def gitosis_delete_key + true + end +end + +class UsersProject + def update_gitosis_project + true + end +end diff --git a/spec/requests/admin/admin_projects_spec.rb b/spec/requests/admin/admin_projects_spec.rb new file mode 100644 index 00000000000..8aa311e8442 --- /dev/null +++ b/spec/requests/admin/admin_projects_spec.rb @@ -0,0 +1,106 @@ +require 'spec_helper' + +describe "Admin::Projects" do + before do + @project = Factory :project, + :name => "LeGiT", + :code => "LGT" + login_as :admin + end + + describe "GET /admin/projects" do + before do + visit admin_projects_path + end + + it "should be ok" do + current_path.should == admin_projects_path + end + + it "should have projects list" do + page.should have_content(@project.code) + page.should have_content(@project.name) + end + end + + describe "GET /admin/projects/:id" do + before do + visit admin_projects_path + click_link "Show" + end + + it "should have project info" do + page.should have_content(@project.code) + page.should have_content(@project.name) + end + end + + describe "GET /admin/projects/:id/edit" do + before do + visit admin_projects_path + click_link "edit_project_#{@project.id}" + end + + it "should have project edit page" do + page.should have_content("Name") + page.should have_content("Code") + end + + describe "Update project" do + before do + fill_in "project_name", :with => "Big Bang" + fill_in "project_code", :with => "BB1" + click_button "Save" + @project.reload + end + + it "should show page with new data" do + page.should have_content("BB1") + page.should have_content("Big Bang") + end + + it "should change project entry" do + @project.name.should == "Big Bang" + @project.code.should == "BB1" + end + end + end + + describe "GET /admin/projects/new" do + before do + visit admin_projects_path + click_link "New Project" + end + + it "should be correct path" do + current_path.should == new_admin_project_path + end + + it "should have labels for new project" do + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") + end + end + + describe "POST /admin/projects" do + before do + visit new_admin_project_path + fill_in 'Name', :with => 'NewProject' + fill_in 'Code', :with => 'NPR' + fill_in 'Path', :with => '/tmp/legit_test/legit' + expect { click_button "Save" }.to change { Project.count }.by(1) + @project = Project.last + end + + it "should be correct path" do + current_path.should == admin_project_path(@project) + end + + it "should show project" do + page.should have_content(@project.name) + page.should have_content(@project.path) + page.should have_content(@project.description) + end + end +end diff --git a/spec/requests/admin/admin_users_spec.rb b/spec/requests/admin/admin_users_spec.rb new file mode 100644 index 00000000000..8d9cbcae2ac --- /dev/null +++ b/spec/requests/admin/admin_users_spec.rb @@ -0,0 +1,102 @@ +require 'spec_helper' + +describe "Admin::Users" do + before { login_as :admin } + + describe "GET /admin/users" do + before do + visit admin_users_path + end + + it "should be ok" do + current_path.should == admin_users_path + end + + it "should have users list" do + page.should have_content(@user.email) + page.should have_content(@user.name) + end + end + + describe "GET /admin/users/new" do + before do + @password = "123ABC" + visit new_admin_user_path + fill_in "user_name", :with => "Big Bang" + fill_in "user_email", :with => "bigbang@mail.com" + fill_in "user_password", :with => @password + fill_in "user_password_confirmation", :with => @password + end + + it "should create new user" do + expect { click_button "Save" }.to change {User.count}.by(1) + end + + it "should create user with valid data" do + click_button "Save" + user = User.last + user.name.should == "Big Bang" + user.email.should == "bigbang@mail.com" + end + + it "should call send mail" do + Notify.should_receive(:new_user_email).and_return(stub(:deliver => true)) + click_button "Save" + end + + it "should send valid email to user with email & password" do + click_button "Save" + user = User.last + email = ActionMailer::Base.deliveries.last + email.subject.should have_content("Account was created") + email.body.should have_content(user.email) + email.body.should have_content(@password) + end + end + + describe "GET /admin/users/:id" do + before do + visit admin_users_path + click_link "Show" + end + + it "should have user info" do + page.should have_content(@user.email) + page.should have_content(@user.name) + page.should have_content(@user.is_admin?) + end + end + + describe "GET /admin/users/:id/edit" do + before do + @simple_user = Factory :user + visit admin_users_path + click_link "edit_user_#{@simple_user.id}" + end + + it "should have user edit page" do + page.should have_content("Name") + page.should have_content("Password") + end + + describe "Update user" do + before do + fill_in "user_name", :with => "Big Bang" + fill_in "user_email", :with => "bigbang@mail.com" + check "user_admin" + click_button "Save" + end + + it "should show page with new data" do + page.should have_content("bigbang@mail.com") + page.should have_content("Big Bang") + end + + it "should change user entry" do + @simple_user.reload + @simple_user.name.should == "Big Bang" + @simple_user.is_admin?.should be_true + end + end + end +end diff --git a/spec/requests/admin/security_spec.rb b/spec/requests/admin/security_spec.rb new file mode 100644 index 00000000000..743f9f08cef --- /dev/null +++ b/spec/requests/admin/security_spec.rb @@ -0,0 +1,27 @@ +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 } + 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 } + end + + describe "GET /admin/team_members" do + it { admin_team_members_path.should be_allowed_for :admin } + it { admin_team_members_path.should be_denied_for :user } + it { admin_team_members_path.should be_denied_for :visitor } + end + + describe "GET /admin/emails" do + it { admin_emails_path.should be_allowed_for :admin } + it { admin_emails_path.should be_denied_for :user } + it { admin_emails_path.should be_denied_for :visitor } + end +end diff --git a/spec/requests/commits_notes_spec.rb b/spec/requests/commits_notes_spec.rb new file mode 100644 index 00000000000..522fe51824b --- /dev/null +++ b/spec/requests/commits_notes_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe "Issues" do + let(:project) { Factory :project } + let!(:commit) { project.repo.commits.first } + + before do + login_as :user + project.add_access(@user, :read, :write) + end + + describe "add new note", :js => true do + before do + visit project_commit_path(project, commit) + click_link "Comments" # notes tab + fill_in "note_note", :with => "I commented this commit" + click_button "Add note" + end + + it "should conatin new note" do + page.should have_content("I commented this commit") + end + end +end diff --git a/spec/requests/commits_spec.rb b/spec/requests/commits_spec.rb new file mode 100644 index 00000000000..cd7314f9812 --- /dev/null +++ b/spec/requests/commits_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe "Commits" do + let(:project) { Factory :project } + let!(:commit) { project.repo.commits.first } + before do + login_as :user + project.add_access(@user, :read) + end + + describe "GET /commits" do + before do + visit project_commits_path(project) + end + + it "should have valid path" do + current_path.should == project_commits_path(project) + end + + it "should have project name" do + page.should have_content(project.name) + end + + it "should list commits" do + page.should have_content(commit.author) + page.should have_content(commit.message) + end + end + + describe "GET /commits/:id" do + before do + visit project_commit_path(project, commit) + end + + it "should have valid path" do + current_path.should == project_commit_path(project, commit) + end + end +end diff --git a/spec/requests/issues_notes_spec.rb b/spec/requests/issues_notes_spec.rb new file mode 100644 index 00000000000..95eb2f35d79 --- /dev/null +++ b/spec/requests/issues_notes_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe "Issues" do + let(:project) { Factory :project } + + before do + login_as :user + project.add_access(@user, :read, :write) + + @issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project + end + + describe "add new note", :js => true do + before do + visit project_issue_path(project, @issue) + fill_in "note_note", :with => "I commented this issue" + click_button "Add note" + end + + it "should conatin new note" do + page.should have_content("I commented this issue") + end + end +end diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb new file mode 100644 index 00000000000..79fdf5efbb5 --- /dev/null +++ b/spec/requests/issues_spec.rb @@ -0,0 +1,147 @@ +require 'spec_helper' + +describe "Issues" do + let(:project) { Factory :project } + + before do + login_as :user + project.add_access(@user, :read, :write) + end + + describe "GET /issues" do + before do + @issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project + + visit project_issues_path(project) + end + + subject { page } + + it { should have_content(@issue.title) } + it { should have_content(@issue.project.name) } + it { should have_content(@issue.assignee.name) } + + describe "Destroy" do + before do + # admin access to remove issue + @user.users_projects.destroy_all + project.add_access(@user, :read, :write, :admin) + visit project_issues_path(project) + end + + it "should remove entry" do + expect { + click_link "destroy_issue_#{@issue.id}" + }.to change { Issue.count }.by(-1) + end + end + + describe "statuses", :js => true do + before do + @closed_issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project, + :closed => true + end + + it "should show only open" do + should have_content(@issue.title) + should have_no_content(@closed_issue.title) + end + + it "should show only closed" do + choose "closed_issues" + should have_no_content(@issue.title) + should have_content(@closed_issue.title) + end + + it "should show all" do + choose "all_issues" + should have_content(@issue.title) + should have_content(@closed_issue.title) + end + end + end + + describe "New issue", :js => true do + before do + visit project_issues_path(project) + click_link "New Issue" + end + + it "should open new issue popup" do + page.should have_content("Add new issue") + end + + describe "fill in" do + before do + fill_in "issue_title", :with => "bug 345" + fill_in "issue_content", :with => "app bug 345" + click_link "Select user" + click_link @user.name + end + + it { expect { click_button "Save" }.to change {Issue.count}.by(1) } + + it "should add new issue to table" do + click_button "Save" + + page.should_not have_content("Add new issue") + page.should have_content @user.name + page.should have_content "bug 345" + page.should have_content project.name + end + + it "should call send mail" do + Notify.should_receive(:new_issue_email).and_return(stub(:deliver => true)) + click_button "Save" + end + + it "should send valid email to user with email & password" do + click_button "Save" + issue = Issue.last + email = ActionMailer::Base.deliveries.last + email.subject.should have_content("New Issue was created") + email.body.should have_content(issue.title) + email.body.should have_content(issue.assignee.name) + end + end + end + + describe "Edit issue", :js => true do + before do + @issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project + visit project_issues_path(project) + click_link "Edit" + end + + it "should open new issue popup" do + page.should have_content("Issue ##{@issue.id}") + end + + describe "fill in" do + before do + fill_in "issue_title", :with => "bug 345" + fill_in "issue_content", :with => "app bug 345" + end + + it { expect { click_button "Save" }.to_not change {Issue.count} } + + it "should update issue fields" do + click_button "Save" + + page.should_not have_content("Issue ##{@issue.id}") + page.should have_content @user.name + page.should have_content "bug 345" + page.should have_content project.name + end + end + end +end diff --git a/spec/requests/keys_spec.rb b/spec/requests/keys_spec.rb new file mode 100644 index 00000000000..316115f9234 --- /dev/null +++ b/spec/requests/keys_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe "Issues" do + before do + login_as :user + end + + describe "GET /keys" do + before do + @key = Factory :key, :user => @user + visit keys_path + end + + subject { page } + + it { should have_content(@key.title) } + + describe "Destroy" do + it "should remove entry" do + expect { + click_link "destroy_key_#{@key.id}" + }.to change { @user.keys.count }.by(-1) + end + end + end + + describe "New key", :js => true do + before do + visit keys_path + click_link "Add new" + end + + it "should open new key popup" do + page.should have_content("Add new public key") + end + + describe "fill in" do + before do + fill_in "key_title", :with => "laptop" + fill_in "key_key", :with => "publickey234=" + end + + it { expect { click_button "Save" }.to change {Key.count}.by(1) } + + it "should add new key to table" do + click_button "Save" + + page.should_not have_content("Add new public key") + page.should have_content "laptop" + page.should have_content "publickey234=" + end + end + end +end diff --git a/spec/requests/profile_spec.rb b/spec/requests/profile_spec.rb new file mode 100644 index 00000000000..07fdc4abdc6 --- /dev/null +++ b/spec/requests/profile_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe "Profile" do + before do + login_as :user + end + + describe "Show profile" do + before do + visit profile_path + end + + it { page.should have_content(@user.name) } + it { page.should have_content(@user.email) } + end + + describe "Password update" do + before do + visit profile_password_path + end + + it { page.should have_content("Password") } + it { page.should have_content("Password confirmation") } + + describe "change password" do + before do + @old_pwd = @user.encrypted_password + fill_in "user_password", :with => "777777" + fill_in "user_password_confirmation", :with => "777777" + click_button "Save" + @user.reload + end + + it "should redirect to signin page" do + current_path.should == new_user_session_path + end + + it "should change password" do + @user.encrypted_password.should_not == @old_pwd + end + + describe "login with new password" do + before do + fill_in "user_email", :with => @user.email + fill_in "user_password", :with => "777777" + click_button "Sign in" + end + + it "should login user" do + current_path.should == root_path + end + end + end + end +end diff --git a/spec/requests/projects_security_spec.rb b/spec/requests/projects_security_spec.rb new file mode 100644 index 00000000000..a725a49c2d8 --- /dev/null +++ b/spec/requests/projects_security_spec.rb @@ -0,0 +1,111 @@ +require 'spec_helper' + +describe "Projects" do + describe "GET /projects" do + it { projects_path.should be_allowed_for :admin } + it { projects_path.should be_allowed_for :user } + it { projects_path.should be_denied_for :visitor } + end + + describe "GET /projects/new" do + it { projects_path.should be_allowed_for :admin } + it { projects_path.should be_allowed_for :user } + it { projects_path.should be_denied_for :visitor } + end + + describe "Project" do + before do + @project = Factory :project + @u1 = Factory :user + @u2 = Factory :user + @u3 = Factory :user + # full access + @project.users_projects.create(:user => @u1, :read => true, :write => true, :admin => true) + # no access + @project.users_projects.create(:user => @u2, :read => false, :write => false, :admin => false) + # readonly + @project.users_projects.create(:user => @u3, :read => true, :write => false, :admin => false) + 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 } + end + + describe "GET /project_code/tree" do + it { tree_project_path(@project).should be_allowed_for @u1 } + it { tree_project_path(@project).should be_allowed_for @u3 } + it { tree_project_path(@project).should be_denied_for :admin } + it { tree_project_path(@project).should be_denied_for @u2 } + it { tree_project_path(@project).should be_denied_for :user } + it { tree_project_path(@project).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 } + end + + describe "GET /project_code/commit" do + it { project_commit_path(@project, @project.commit).should be_allowed_for @u1 } + it { project_commit_path(@project, @project.commit).should be_allowed_for @u3 } + it { project_commit_path(@project, @project.commit).should be_denied_for :admin } + it { project_commit_path(@project, @project.commit).should be_denied_for @u2 } + it { project_commit_path(@project, @project.commit).should be_denied_for :user } + it { project_commit_path(@project, @project.commit).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 } + 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 } + end + + describe "GET /project_code/blob" do + it { blob_project_path(@project).should be_allowed_for @u1 } + it { blob_project_path(@project).should be_allowed_for @u3 } + it { blob_project_path(@project).should be_denied_for :admin } + it { blob_project_path(@project).should be_denied_for @u2 } + it { blob_project_path(@project).should be_denied_for :user } + it { blob_project_path(@project).should be_denied_for :visitor } + 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 } + 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 } + end + end +end diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb new file mode 100644 index 00000000000..329f0a50435 --- /dev/null +++ b/spec/requests/projects_spec.rb @@ -0,0 +1,152 @@ +require 'spec_helper' + +describe "Projects" do + before { login_as :user } + + describe "GET /projects" do + before do + visit projects_path + end + + it "should be on projects page" do + current_path.should == projects_path + end + + it "should have link to new project" do + page.should have_content("New Project") + end + end + + describe "GET /projects/new" do + before do + visit projects_path + click_link "New Project" + end + + it "should be correct path" do + current_path.should == new_project_path + end + + it "should have labels for new project" do + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") + end + end + + describe "POST /projects" do + before do + visit new_project_path + fill_in 'Name', :with => 'NewProject' + fill_in 'Code', :with => 'NPR' + fill_in 'Path', :with => '/tmp/legit_test/legit' + expect { click_button "Create Project" }.to change { Project.count }.by(1) + @project = Project.last + end + + it "should be correct path" do + current_path.should == project_path(@project) + end + + it "should show project" do + page.should have_content(@project.name) + page.should have_content(@project.path) + page.should have_content(@project.description) + end + + it "should init repo instructions" do + page.should have_content("git remote") + page.should have_content(@project.url_to_repo) + end + end + + describe "GET /projects/show" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit project_path(@project) + end + + it "should be correct path" do + current_path.should == project_path(@project) + end + + it_behaves_like :tree_view + end + + describe "GET /projects/team" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit team_project_path(@project, + :path => ValidCommit::BLOB_FILE_PATH, + :commit_id => ValidCommit::ID) + end + + it "should be correct path" do + current_path.should == team_project_path(@project) + end + + it "should have as as team member" do + page.should have_content(@user.name) + end + end + + describe "GET /projects/:id/edit" do + before do + @project = Factory :project + @project.add_access(@user, :admin, :read) + + visit edit_project_path(@project) + end + + it "should be correct path" do + current_path.should == edit_project_path(@project) + end + + it "should have labels for new project" do + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") + end + end + + describe "PUT /projects/:id" do + before do + @project = Factory :project + @project.add_access(@user, :admin, :read) + + visit edit_project_path(@project) + + fill_in 'Name', :with => 'Awesome' + fill_in 'Path', :with => 'legit' + fill_in 'Description', :with => 'Awesome project' + click_button "Update Project" + @project = @project.reload + end + + it "should be correct path" do + current_path.should == project_path(@project) + end + + it "should show project" do + page.should have_content("Awesome") + end + + it_behaves_like :tree_view + end + + #describe "DELETE /projects/:id", :js => true do + #before do + #@project = Factory :project + #@project.add_access(@user, :read, :admin) + #visit projects_path + #end + + #it "should be correct path" do + #expect { click_link "Destroy" }.to change {Project.count}.by(1) + #end + #end +end diff --git a/spec/requests/projects_tree_spec.rb b/spec/requests/projects_tree_spec.rb new file mode 100644 index 00000000000..4e3176bbdc3 --- /dev/null +++ b/spec/requests/projects_tree_spec.rb @@ -0,0 +1,92 @@ +require 'spec_helper' + +describe "Projects" do + before { login_as :user } + + describe "GET /projects/tree" do + describe "head" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit tree_project_path(@project) + end + + it "should be correct path" do + current_path.should == tree_project_path(@project) + end + + it_behaves_like :tree_view + end + + describe ValidCommit::ID do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit tree_project_path(@project, :commit_id => ValidCommit::ID) + end + + it "should be correct path" do + current_path.should == tree_project_path(@project) + end + + it_behaves_like :tree_view + it_behaves_like :project_side_pane + end + + describe "branch passed" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit tree_project_path(@project, :branch => "master") + end + + it "should be correct path" do + current_path.should == tree_project_path(@project) + end + + it_behaves_like :tree_view + it_behaves_like :project_side_pane + end + + # TREE FILE PREVIEW + describe "file preview" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit tree_project_path(@project, :path => ".rvmrc") + end + + it "should be correct path" do + current_path.should == tree_project_path(@project) + end + + it "should contain file view" do + page.should have_content("rvm use 1.9.2@legit") + end + end + end + + # RAW FILE + describe "GET /projects/blob" do + before do + @project = Factory :project + @project.add_access(@user, :read) + + visit blob_project_path(@project, + :path => ValidCommit::BLOB_FILE_PATH, + :commit_id => ValidCommit::ID) + end + + it "should be correct path" do + current_path.should == blob_project_path(@project) + end + + it "raw file response" do + page.source.should == ValidCommit::BLOB_FILE + end + end +end diff --git a/spec/requests/projects_wall_spec.rb b/spec/requests/projects_wall_spec.rb new file mode 100644 index 00000000000..a7387f9326d --- /dev/null +++ b/spec/requests/projects_wall_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe "Projects", "Wall" do + let(:project) { Factory :project } + + before do + login_as :user + project.add_access(@user, :read, :write) + end + + describe "View notes on wall" do + before do + Factory :note, :project => project, :note => "Project specs", :author => @user + visit wall_project_path(project) + end + + it { page.should have_content("Project specs") } + it { page.should have_content(@user.name) } + it { page.should have_content("less than a minute ago") } + end + + describe "add new note", :js => true do + before do + visit wall_project_path(project) + fill_in "note_note", :with => "my post on wall" + click_button "Add note" + end + + it "should conatin new note" do + page.should have_content("my post on wall") + end + end +end diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb new file mode 100644 index 00000000000..db7513ae956 --- /dev/null +++ b/spec/requests/team_members_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe "TeamMembers" do + before do + login_as :user + @project = Factory :project + @project.add_access(@user, :read, :admin) + end + + describe "New Team member", :js => true do + before do + @user_1 = Factory :user + visit team_project_path(@project) + click_link "Add new" + end + + it "should open new team member popup" do + page.should have_content("Add new member to project") + end + + describe "fill in" do + before do + check "team_member_read" + click_link "Select user" + click_link @user_1.name + #select @user_1.name, :from => "team_member_user_id" + end + + it { expect { click_button "Save" }.to change {UsersProject.count}.by(1) } + + it "should add new member to table" do + click_button "Save" + + page.should_not have_content("Add new member") + page.should have_content @user_1.name + end + end + end + + describe "Cancel membership" do + it "should cancel membership" do + visit team_project_path(@project) + expect { click_link "Cancel" }.to change { UsersProject.count }.by(-1) + end + end +end diff --git a/spec/requests/top_panel_spec.rb b/spec/requests/top_panel_spec.rb new file mode 100644 index 00000000000..bd4d2047796 --- /dev/null +++ b/spec/requests/top_panel_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe "Top Panel", :js => true do + before { login_as :user } + + describe "Search autocomplete" do + before do + visit projects_path + fill_in "search", :with => "Ke" + sleep(2) + find(:xpath, "//ul[contains(@class,'ui-autocomplete')]/li/a[.=\"Keys\"]").click + end + + it "should be on projects page" do + current_path.should == keys_path + end + end + + describe "with project" do + before do + @project = Factory :project + @project.add_access(@user, :read) + visit project_path(@project) + + fill_in "search", :with => "Commi" + sleep(2) + find(:xpath, "//ul[contains(@class,'ui-autocomplete')]/li/a[.=\"#{@project.code} / Commits\"]").click + end + + it "should be on projects page" do + current_path.should == project_commits_path(@project) + end + end +end diff --git a/spec/requests/user_security_spec.rb b/spec/requests/user_security_spec.rb new file mode 100644 index 00000000000..3c923870e86 --- /dev/null +++ b/spec/requests/user_security_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +describe "Users Security" do + describe "Project" do + before do + @u1 = Factory :user + end + + describe "GET /login" do + it { new_user_session_path.should be_denied_for @u1 } + it { new_user_session_path.should be_denied_for :admin } + it { new_user_session_path.should be_denied_for :user } + it { new_user_session_path.should be_allowed_for :visitor } + 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 } + 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 } + 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 } + end + end +end diff --git a/spec/seed_project.tar.gz b/spec/seed_project.tar.gz Binary files differnew file mode 100644 index 00000000000..6474c324f07 --- /dev/null +++ b/spec/seed_project.tar.gz diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000000..0c2545e3380 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,56 @@ +require 'simplecov' +SimpleCov.start 'rails' + +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'capybara/rails' +require 'capybara/rspec' +require 'capybara/dsl' +require 'factories' +require 'monkeypatch' + + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + +RSpec.configure do |config| + # == Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + config.mock_with :rspec + + config.include LoginMacros + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # 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 + # instead of true. + config.use_transactional_fixtures = false + + config.before :each, :type => :integration do + DeviseSessionMock.disable + end + + config.before do + if example.metadata[:js] + DatabaseCleaner.strategy = :truncation + 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 new file mode 100644 index 00000000000..0d4ab264e85 --- /dev/null +++ b/spec/support/js_patch.rb @@ -0,0 +1,6 @@ +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 new file mode 100644 index 00000000000..09f64f9e3c3 --- /dev/null +++ b/spec/support/login.rb @@ -0,0 +1,29 @@ +module LoginMacros + def login_as role + @user = User.create(:email => "user#{User.count}@mail.com", + :name => "John Smith", + :password => "123456", + :password_confirmation => "123456") + + if role == :admin + @user.admin = true + @user.save! + end + + visit new_user_session_path + fill_in "Email", :with => @user.email + fill_in "Password", :with => "123456" + click_button "Sign in" + end + + def login_with(user) + visit new_user_session_path + fill_in "Email", :with => user.email + fill_in "Password", :with => "123456" + click_button "Sign in" + end + + def logout + click_link "Logout" rescue nil + end +end diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb new file mode 100644 index 00000000000..953b535698d --- /dev/null +++ b/spec/support/matchers.rb @@ -0,0 +1,46 @@ +RSpec::Matchers.define :be_valid_commit do + match do |actual| + actual != nil + actual.id == ValidCommit::ID + actual.message == ValidCommit::MESSAGE + actual.author.name == ValidCommit::AUTHOR_FULL_NAME + end +end + +RSpec::Matchers.define :be_allowed_for do |user| + match do |url| + include UrlAccess + url_allowed?(user, url) + end +end + +RSpec::Matchers.define :be_denied_for do |user| + match do |url| + include UrlAccess + url_denied?(user, url) + end +end + +module UrlAccess + def url_allowed?(user, url) + emulate_user(user) + visit url + result = (current_path == url) + end + + def url_denied?(user, url) + emulate_user(user) + visit url + result = (current_path != url) + end + + def emulate_user(user) + user = case user + when :user then Factory(:user) + when :visitor then nil + when :admin then Factory(:admin) + else user + end + login_with(user) if user + end +end diff --git a/spec/support/security.rb b/spec/support/security.rb new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/spec/support/security.rb diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb new file mode 100644 index 00000000000..a2e94ac109b --- /dev/null +++ b/spec/support/shared_examples.rb @@ -0,0 +1,18 @@ +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("Team") } + it { should have_content("Tree") } +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 diff --git a/spec/support/valid_commit.rb b/spec/support/valid_commit.rb new file mode 100644 index 00000000000..a4d3496e241 --- /dev/null +++ b/spec/support/valid_commit.rb @@ -0,0 +1,25 @@ +module ValidCommit + ID = "eaffbe556ec3a8dc84ef15892a9f12d84dde7e1d" + MESSAGE = "style" + AUTHOR_FULL_NAME = "Dmitriy Zaporozhets" + + FILES = [".gitignore", ".rspec", ".rvmrc", "Gemfile", "Gemfile.lock", "LICENSE", "README.rdoc", "Rakefile", "app", "config.ru", "config", "db", "doc", "lib", "log", "public", "script", "spec", "vendor"] + FILES_COUNT = 19 + + C_FILE_PATH = "app/models" + C_FILES = [".gitkeep", "project.rb", "user.rb"] + + BLOB_FILE = <<-blob +<div class="span-14 colborder"> + <h2>Tree / <%= link_to "Commits", project_commits_path(@project) %></h2> + <%= render :partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @commit.tree} %> +</div> + +<div class="span-8 right"> + <%= render "side_panel" %> +</div> +blob + + BLOB_FILE_PATH = "app/views/projects/show.html.erb" +end + |