Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-07-24 11:54:42 +0400
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-07-24 11:54:42 +0400
commite21ca9f8b140476f93eaa2c2a0d6bf96f28b6995 (patch)
treeecaa584f33ed4d5231d07d6dddc8675feb8f19ad
parent4a1e98e4b69800c0044110c1aff6cfdf972b57b6 (diff)
parente1d307bf4b88afa59d851918c29ffbb61b01e8c5 (diff)
Merge branch 'star' of https://github.com/cirosantilli/gitlabhq into cirosantilli-star
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Conflicts: CHANGELOG
-rw-r--r--CHANGELOG3
-rw-r--r--app/assets/javascripts/project.js.coffee5
-rw-r--r--app/assets/stylesheets/behaviors.scss6
-rw-r--r--app/assets/stylesheets/generic/buttons.scss3
-rw-r--r--app/assets/stylesheets/main/variables.scss2
-rw-r--r--app/assets/stylesheets/sections/projects.scss16
-rw-r--r--app/controllers/projects_controller.rb8
-rw-r--r--app/helpers/projects_helper.rb22
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/user.rb16
-rw-r--r--app/models/users_star_project.rb19
-rw-r--r--app/views/projects/_home_panel.html.haml12
-rw-r--r--config/routes.rb1
-rw-r--r--db/migrate/20140625115202_create_users_star_projects.rb15
-rw-r--r--db/schema.rb15
-rw-r--r--features/project/star.feature38
-rw-r--r--features/steps/explore/projects.rb24
-rw-r--r--features/steps/project/star.rb29
-rw-r--r--features/steps/shared/authentication.rb4
-rw-r--r--features/steps/shared/paths.rb32
-rw-r--r--features/steps/shared/project.rb8
-rw-r--r--spec/controllers/projects_controller_spec.rb19
-rw-r--r--spec/features/issues_spec.rb4
-rw-r--r--spec/models/project_spec.rb69
-rw-r--r--spec/models/user_spec.rb40
-rw-r--r--spec/support/login_helpers.rb3
26 files changed, 380 insertions, 37 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 2675db90543..4ca3f997f84 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+v 7.2.0
+ - Add project stars (Ciro Santilli)
+
v 7.1.0
- Remove observers
- Improve MR discussions
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index 4262418fd5e..d81cc087df9 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -46,3 +46,8 @@ $ ->
$.cookie('hide_no_ssh_message', 'false', { path: path })
$(@).parents('.no-ssh-key-message').hide()
e.preventDefault()
+
+ $('.project-home-panel .star').on 'ajax:success', (e, data, status, xhr) ->
+ $(@).toggleClass('on').find('.count').html(data.star_count)
+ .on 'ajax:error', (e, xhr, status, error) ->
+ new Flash('Star toggle failed. Try again later.', 'alert')
diff --git a/app/assets/stylesheets/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 23f206ce3dc..034692a67e1 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -4,3 +4,9 @@
.js-details-container .content.hide { display: block; }
.js-details-container.open .content { display: block; }
.js-details-container.open .content.hide { display: none; }
+
+// Toggle between two states.
+.js-toggler-container .turn-on { display: inline-block; }
+.js-toggler-container .turn-off { display: none; }
+.js-toggler-container.on .turn-on { display: none; }
+.js-toggler-container.on .turn-off { display: inline-block; }
diff --git a/app/assets/stylesheets/generic/buttons.scss b/app/assets/stylesheets/generic/buttons.scss
index 046e5040fb2..d098f1ecaa2 100644
--- a/app/assets/stylesheets/generic/buttons.scss
+++ b/app/assets/stylesheets/generic/buttons.scss
@@ -6,7 +6,7 @@
vertical-align: middle;
cursor: pointer;
background-image: none;
- border: 1px solid transparent;
+ border: $btn-border;
white-space: nowrap;
padding: 6px 12px;
font-size: 13px;
@@ -19,7 +19,6 @@
user-select: none;
color: #444444;
background-color: #fff;
- border-color: #ccc;
text-shadow: none;
&.hover,
diff --git a/app/assets/stylesheets/main/variables.scss b/app/assets/stylesheets/main/variables.scss
index c49f7db788e..02ce2c8338f 100644
--- a/app/assets/stylesheets/main/variables.scss
+++ b/app/assets/stylesheets/main/variables.scss
@@ -10,6 +10,8 @@ $hover: #D9EDF7;
$link_color: #446e9b;
$link_hover_color: #2FA0BB;
+$btn-border: 1px solid #ccc;
+
/*
* Success colors (green)
*/
diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss
index c9188fb751c..eecc49620fd 100644
--- a/app/assets/stylesheets/sections/projects.scss
+++ b/app/assets/stylesheets/sections/projects.scss
@@ -50,6 +50,22 @@
margin-left: 10px;
font-weight: 500;
}
+
+ .star .btn {
+ font-weight: bold;
+ line-height: 22px;
+ padding: 0px;
+ $margin-x: 6px;
+ .toggle {
+ display: inline-block;
+ padding: 0px $margin-x;
+ }
+ .count {
+ border-left: $btn-border;
+ display: inline-block;
+ padding: 0px $margin-x;
+ }
+ }
}
}
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 3d012b7e164..1b1b0eb7ad1 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -60,6 +60,8 @@ class ProjectsController < ApplicationController
@events = event_filter.apply_filter(@events)
@events = @events.limit(limit).offset(params[:offset] || 0)
+ @show_star = !(current_user && current_user.starred?(@project))
+
respond_to do |format|
format.html do
if @project.empty_repo?
@@ -167,6 +169,12 @@ class ProjectsController < ApplicationController
end
end
+ def toggle_star
+ current_user.toggle_star(@project)
+ @project.reload
+ render json: { star_count: @project.star_count }
+ end
+
private
def upload_path
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index bc2ec84302d..1304e2dea23 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -122,6 +122,28 @@ module ProjectsHelper
options_for_select(values, current_tracker)
end
+ def link_to_toggle_star(title, starred, signed_in)
+ cls = 'btn'
+ cls += ' disabled' unless signed_in
+ content_tag 'span', class: starred ? 'turn-on' : 'turn-off' do
+ link_to toggle_star_project_path(@project),
+ title: title, class: cls, method: :post, remote: true,
+ data: {type: 'json'} do
+ content_tag('span', class: 'toggle') do
+ content_tag('i', ' ', class: 'icon-star') <<
+ if starred
+ 'Unstar'
+ else
+ 'Star'
+ end
+ end <<
+ content_tag('span', class: 'count') do
+ @project.star_count.to_s
+ end
+ end
+ end
+ end
+
private
def get_project_nav_tabs(project, current_user)
diff --git a/app/models/project.rb b/app/models/project.rb
index 339143196a7..10882ea97cc 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -22,6 +22,7 @@
# visibility_level :integer default(0), not null
# archived :boolean default(FALSE), not null
# import_status :string(255)
+# star_count :integer
#
class Project < ActiveRecord::Base
@@ -81,6 +82,8 @@ class Project < ActiveRecord::Base
has_many :users, through: :users_projects
has_many :deploy_keys_projects, dependent: :destroy
has_many :deploy_keys, through: :deploy_keys_projects
+ has_many :users_star_projects, dependent: :destroy
+ has_many :starrers, through: :users_star_projects, source: :user
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
@@ -107,6 +110,7 @@ class Project < ActiveRecord::Base
validates :import_url,
format: { with: URI::regexp(%w(git http https)), message: "should be a valid url" },
if: :import?
+ validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
# Scopes
diff --git a/app/models/user.rb b/app/models/user.rb
index 350e30f1618..9ab3ea025c3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -91,6 +91,8 @@ class User < ActiveRecord::Base
has_many :personal_projects, through: :namespace, source: :projects
has_many :projects, through: :users_projects
has_many :created_projects, foreign_key: :creator_id, class_name: 'Project'
+ has_many :users_star_projects, dependent: :destroy
+ has_many :starred_projects, through: :users_star_projects, source: :project
has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet"
has_many :users_projects, dependent: :destroy
@@ -517,4 +519,18 @@ class User < ActiveRecord::Base
def system_hook_service
SystemHooksService.new
end
+
+ def starred?(project)
+ starred_projects.exists?(project)
+ end
+
+ def toggle_star(project)
+ user_star_project = users_star_projects.
+ where(project: project, user: self).take
+ if user_star_project
+ user_star_project.destroy
+ else
+ UsersStarProject.create!(project: project, user: self)
+ end
+ end
end
diff --git a/app/models/users_star_project.rb b/app/models/users_star_project.rb
new file mode 100644
index 00000000000..80e756bd00c
--- /dev/null
+++ b/app/models/users_star_project.rb
@@ -0,0 +1,19 @@
+# == Schema Information
+#
+# Table name: users_star_projects
+#
+# id :integer not null, primary key
+# starrer_id :integer not null
+# project_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+#
+
+class UsersStarProject < ActiveRecord::Base
+ belongs_to :project, counter_cache: :star_count
+ belongs_to :user
+
+ validates :user, presence: true
+ validates :user_id, uniqueness: { scope: [:project_id] }
+ validates :project, presence: true
+end
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index ddf815ebd99..bf9301d70c4 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -27,10 +27,16 @@
= link_to project_blob_path(@project, tree_join(@repository.root_ref, readme.name)) do
= readme.name
- - unless empty_repo
- .col-md-5
- .project-home-links
+ .col-md-5
+ .project-home-links
+ - unless empty_repo
= link_to pluralize(number_with_delimiter(@repository.commit_count), 'commit'), project_commits_path(@project, @ref || @repository.root_ref)
= link_to pluralize(number_with_delimiter(@repository.branch_names.count), 'branch'), project_branches_path(@project)
= link_to pluralize(number_with_delimiter(@repository.tag_names.count), 'tag'), project_tags_path(@project)
%span.light.prepend-left-20= repository_size
+ %span.star.js-toggler-container{class: @show_star ? 'on' : ''}
+ - if current_user
+ = link_to_toggle_star('Star this project.', false, true)
+ = link_to_toggle_star('Unstar this project.', true, true)
+ - else
+ = link_to_toggle_star('You must sign in to star a project.', false, false)
diff --git a/config/routes.rb b/config/routes.rb
index f54f9ea5341..f8c68eb11a1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -185,6 +185,7 @@ Gitlab::Application.routes.draw do
post :archive
post :unarchive
post :upload_image
+ post :toggle_star
get :autocomplete_sources
get :import
put :retry_import
diff --git a/db/migrate/20140625115202_create_users_star_projects.rb b/db/migrate/20140625115202_create_users_star_projects.rb
new file mode 100644
index 00000000000..412f0f6f34b
--- /dev/null
+++ b/db/migrate/20140625115202_create_users_star_projects.rb
@@ -0,0 +1,15 @@
+class CreateUsersStarProjects < ActiveRecord::Migration
+ def change
+ create_table :users_star_projects do |t|
+ t.integer :project_id, null: false
+ t.integer :user_id, null: false
+ t.timestamps
+ end
+ add_index :users_star_projects, :user_id
+ add_index :users_star_projects, :project_id
+ add_index :users_star_projects, [:user_id, :project_id], unique: true
+
+ add_column :projects, :star_count, :integer, default: 0, null: false
+ add_index :projects, :star_count, using: :btree
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 345b6fd3b68..e4dcdf5bea2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20140611135229) do
+ActiveRecord::Schema.define(version: 20140625115202) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -224,11 +224,13 @@ ActiveRecord::Schema.define(version: 20140611135229) do
t.boolean "archived", default: false, null: false
t.string "import_status"
t.float "repository_size", default: 0.0
+ t.integer "star_count", default: 0, null: false
end
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
add_index "projects", ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree
add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree
+ add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree
create_table "protected_branches", force: true do |t|
t.integer "project_id", null: false
@@ -369,6 +371,17 @@ ActiveRecord::Schema.define(version: 20140611135229) do
add_index "users_projects", ["project_id"], name: "index_users_projects_on_project_id", using: :btree
add_index "users_projects", ["user_id"], name: "index_users_projects_on_user_id", using: :btree
+ create_table "users_star_projects", force: true do |t|
+ t.integer "project_id", null: false
+ t.integer "user_id", null: false
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ add_index "users_star_projects", ["project_id"], name: "index_users_star_projects_on_project_id", using: :btree
+ add_index "users_star_projects", ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree
+ add_index "users_star_projects", ["user_id"], name: "index_users_star_projects_on_user_id", using: :btree
+
create_table "web_hooks", force: true do |t|
t.string "url"
t.integer "project_id"
diff --git a/features/project/star.feature b/features/project/star.feature
new file mode 100644
index 00000000000..d8d898155fe
--- /dev/null
+++ b/features/project/star.feature
@@ -0,0 +1,38 @@
+Feature: Project Star
+ Scenario: New projects have 0 stars
+ Given public project "Community"
+ When I visit project "Community" page
+ Then The project has 0 stars
+
+ Scenario: Empty projects show star count
+ Given public empty project "Empty Public Project"
+ When I visit empty project page
+ Then The project has 0 stars
+
+ Scenario: Signed off users can't star projects
+ Given public project "Community"
+ And I visit project "Community" page
+ When I click on the star toggle button
+ Then The project has 0 stars
+
+ @javascript
+ Scenario: Signed in users can toggle star
+ Given I sign in as "John Doe"
+ And public project "Community"
+ And I visit project "Community" page
+ When I click on the star toggle button
+ Then The project has 1 star
+ When I click on the star toggle button
+ Then The project has 0 stars
+
+ @javascript
+ Scenario: Star count sums stars
+ Given I sign in as "John Doe"
+ And public project "Community"
+ And I visit project "Community" page
+ And I click on the star toggle button
+ And I logout
+ And I sign in as "Mary Jane"
+ And I visit project "Community" page
+ When I click on the star toggle button
+ Then The project has 2 stars
diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb
index 8aa2916014b..dfd51060738 100644
--- a/features/steps/explore/projects.rb
+++ b/features/steps/explore/projects.rb
@@ -3,10 +3,6 @@ class Spinach::Features::ExploreProjectsFeature < Spinach::FeatureSteps
include SharedPaths
include SharedProject
- step 'public empty project "Empty Public Project"' do
- create :empty_project, :public, name: 'Empty Public Project'
- end
-
step 'I should see project "Empty Public Project"' do
page.should have_content "Empty Public Project"
end
@@ -20,16 +16,6 @@ class Spinach::Features::ExploreProjectsFeature < Spinach::FeatureSteps
page.should have_content 'README.md'
end
- step 'I visit empty project page' do
- project = Project.find_by(name: 'Empty Public Project')
- visit project_path(project)
- end
-
- step 'I visit project "Community" page' do
- project = Project.find_by(name: 'Community')
- visit project_path(project)
- end
-
step 'I should see empty public project details' do
page.should have_content 'Git global setup'
end
@@ -48,22 +34,12 @@ class Spinach::Features::ExploreProjectsFeature < Spinach::FeatureSteps
end
end
- step 'I visit project "Enterprise" page' do
- project = Project.find_by(name: 'Enterprise')
- visit project_path(project)
- end
-
step 'I should see project "Community" home page' do
within '.project-home-title' do
page.should have_content 'Community'
end
end
- step 'I visit project "Internal" page' do
- project = Project.find_by(name: 'Internal')
- visit project_path(project)
- end
-
step 'I should see project "Internal" home page' do
within '.project-home-title' do
page.should have_content 'Internal'
diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb
new file mode 100644
index 00000000000..11102900ed4
--- /dev/null
+++ b/features/steps/project/star.rb
@@ -0,0 +1,29 @@
+class Spinach::Features::ProjectStar < Spinach::FeatureSteps
+ include SharedAuthentication
+ include SharedProject
+ include SharedPaths
+ include SharedUser
+
+ step "The project has 0 stars" do
+ has_n_stars(0)
+ end
+
+ step "The project has 1 star" do
+ has_n_stars(1)
+ end
+
+ step "The project has 2 stars" do
+ has_n_stars(2)
+ end
+
+ # Requires @javascript
+ step "I click on the star toggle button" do
+ page.find(".star .toggle", visible: true).click
+ end
+
+ protected
+
+ def has_n_stars(n)
+ expect(page).to have_css(".star .count", text: /^#{n}$/, visible: true)
+ end
+end
diff --git a/features/steps/shared/authentication.rb b/features/steps/shared/authentication.rb
index b8c11ce0a23..b48021dc146 100644
--- a/features/steps/shared/authentication.rb
+++ b/features/steps/shared/authentication.rb
@@ -24,6 +24,10 @@ module SharedAuthentication
current_path.should == new_user_session_path
end
+ step "I logout" do
+ logout
+ end
+
def current_user
@user || User.first
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index a0b4099ab3e..111d40c0e1b 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -320,6 +320,34 @@ module SharedPaths
end
# ----------------------------------------
+ # Visibility Projects
+ # ----------------------------------------
+
+ step 'I visit project "Community" page' do
+ project = Project.find_by(name: "Community")
+ visit project_path(project)
+ end
+
+ step 'I visit project "Internal" page' do
+ project = Project.find_by(name: "Internal")
+ visit project_path(project)
+ end
+
+ step 'I visit project "Enterprise" page' do
+ project = Project.find_by(name: "Enterprise")
+ visit project_path(project)
+ end
+
+ # ----------------------------------------
+ # Empty Projects
+ # ----------------------------------------
+
+ step "I visit empty project page" do
+ project = Project.find_by(name: "Empty Public Project")
+ visit project_path(project)
+ end
+
+ # ----------------------------------------
# Public Projects
# ----------------------------------------
@@ -327,10 +355,6 @@ module SharedPaths
visit explore_projects_path
end
- step 'I visit public page for "Community" project' do
- visit public_project_path(Project.find_by(name: "Community"))
- end
-
# ----------------------------------------
# Public Groups
# ----------------------------------------
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index ddb87daeeb7..ba6f090a706 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -122,4 +122,12 @@ module SharedProject
project ||= create :empty_project, :public, name: 'Community', namespace: user.namespace
project.team << [user, :master]
end
+
+ # ----------------------------------------
+ # Empty projects
+ # ----------------------------------------
+
+ step 'public empty project "Empty Public Project"' do
+ create :empty_project, :public, name: "Empty Public Project"
+ end
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 944df5314bd..71bc49787cc 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -2,6 +2,7 @@ require('spec_helper')
describe ProjectsController do
let(:project) { create(:project) }
+ let(:public_project) { create(:project, :public) }
let(:user) { create(:user) }
let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') }
let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') }
@@ -40,4 +41,22 @@ describe ProjectsController do
end
end
end
+
+ describe "POST #toggle_star" do
+ it "toggles star if user is signed in" do
+ sign_in(user)
+ expect(user.starred?(public_project)).to be_false
+ post :toggle_star, id: public_project.to_param
+ expect(user.starred?(public_project)).to be_true
+ post :toggle_star, id: public_project.to_param
+ expect(user.starred?(public_project)).to be_false
+ end
+
+ it "does nothing if user is not signed in" do
+ post :toggle_star, id: public_project.to_param
+ expect(user.starred?(public_project)).to be_false
+ post :toggle_star, id: public_project.to_param
+ expect(user.starred?(public_project)).to be_false
+ end
+ end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index d7f3f3a302c..f0daf081018 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -226,7 +226,7 @@ describe "Issues", feature: true do
issue.save
end
- it 'shows assignee text' do
+ it "shows assignee text", js: true do
logout
login_with guest
@@ -262,7 +262,7 @@ describe "Issues", feature: true do
issue.save
end
- it 'shows milestone text' do
+ it "shows milestone text", js: true do
logout
login_with guest
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index c3263ed0fe7..bc537b7312b 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -240,4 +240,73 @@ describe Project do
it { project.open_branches.map(&:name).should include('bootstrap') }
it { project.open_branches.map(&:name).should_not include('master') }
end
+
+ describe '#star_count' do
+ it 'counts stars from multiple users' do
+ user1 = create :user
+ user2 = create :user
+ project = create :project, :public
+
+ expect(project.star_count).to eq(0)
+
+ user1.toggle_star(project)
+ expect(project.reload.star_count).to eq(1)
+
+ user2.toggle_star(project)
+ project.reload
+ expect(project.reload.star_count).to eq(2)
+
+ user1.toggle_star(project)
+ project.reload
+ expect(project.reload.star_count).to eq(1)
+
+ user2.toggle_star(project)
+ project.reload
+ expect(project.reload.star_count).to eq(0)
+ end
+
+ it 'counts stars on the right project' do
+ user = create :user
+ project1 = create :project, :public
+ project2 = create :project, :public
+
+ expect(project1.star_count).to eq(0)
+ expect(project2.star_count).to eq(0)
+
+ user.toggle_star(project1)
+ project1.reload
+ project2.reload
+ expect(project1.star_count).to eq(1)
+ expect(project2.star_count).to eq(0)
+
+ user.toggle_star(project1)
+ project1.reload
+ project2.reload
+ expect(project1.star_count).to eq(0)
+ expect(project2.star_count).to eq(0)
+
+ user.toggle_star(project2)
+ project1.reload
+ project2.reload
+ expect(project1.star_count).to eq(0)
+ expect(project2.star_count).to eq(1)
+
+ user.toggle_star(project2)
+ project1.reload
+ project2.reload
+ expect(project1.star_count).to eq(0)
+ expect(project2.star_count).to eq(0)
+ end
+
+ it 'is decremented when an upvoter account is deleted' do
+ user = create :user
+ project = create :project, :public
+ user.toggle_star(project)
+ project.reload
+ expect(project.star_count).to eq(1)
+ user.destroy
+ project.reload
+ expect(project.star_count).to eq(0)
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index a36b57a95de..ef6b8a94502 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -355,4 +355,44 @@ describe User do
expect(user.short_website_url).to eq 'test.com'
end
end
+
+ describe "#starred?" do
+ it "determines if user starred a project" do
+ user = create :user
+ project1 = create :project, :public
+ project2 = create :project, :public
+
+ expect(user.starred?(project1)).to be_false
+ expect(user.starred?(project2)).to be_false
+
+ star1 = UsersStarProject.create!(project: project1, user: user)
+ expect(user.starred?(project1)).to be_true
+ expect(user.starred?(project2)).to be_false
+
+ star2 = UsersStarProject.create!(project: project2, user: user)
+ expect(user.starred?(project1)).to be_true
+ expect(user.starred?(project2)).to be_true
+
+ star1.destroy
+ expect(user.starred?(project1)).to be_false
+ expect(user.starred?(project2)).to be_true
+
+ star2.destroy
+ expect(user.starred?(project1)).to be_false
+ expect(user.starred?(project2)).to be_false
+ end
+ end
+
+ describe "#toggle_star" do
+ it "toggles stars" do
+ user = create :user
+ project = create :project, :public
+
+ expect(user.starred?(project)).to be_false
+ user.toggle_star(project)
+ expect(user.starred?(project)).to be_true
+ user.toggle_star(project)
+ expect(user.starred?(project)).to be_false
+ end
+ end
end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index 7713e9f17d7..238ac7c6611 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -19,7 +19,8 @@ module LoginHelpers
Thread.current[:current_user] = user
end
+ # Requires Javascript driver.
def logout
- click_link "Logout" rescue nil
+ page.find(:css, ".icon-signout").click
end
end