diff --git a/Gemfile b/Gemfile index 390999a..8ada858 100644 --- a/Gemfile +++ b/Gemfile @@ -39,4 +39,5 @@ group :development, :test do gem 'capybara' gem 'launchy' gem 'rspec-rails' + gem 'factory_girl_rails' end diff --git a/Gemfile.lock b/Gemfile.lock index cd1145d..2f2e612 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -48,6 +48,11 @@ GEM diff-lcs (1.2.5) erubis (2.7.0) execjs (2.7.0) + factory_girl (4.8.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.8.0) + factory_girl (~> 4.8.0) + railties (>= 3.0.0) faraday (0.9.2) multipart-post (>= 1.2, < 3) font-awesome-rails (4.6.3.1) @@ -171,6 +176,7 @@ DEPENDENCIES byebug capybara coffee-rails (~> 4.0.0) + factory_girl_rails font-awesome-rails foundation-rails jquery-rails @@ -189,4 +195,4 @@ RUBY VERSION ruby 2.2.2p95 BUNDLED WITH - 1.14.3 + 1.14.5 diff --git a/app/models/user.rb b/app/models/user.rb index d547333..c2a09ea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -15,6 +15,10 @@ def admin_button_class admin? ? "success" : "secondary" end + def user_button_class + approved? ? "approved" : "not-approved" + end + def approved? approval_at.present? end diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 1f88c66..197c8a8 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -19,8 +19,8 @@ <%= user.created_at_string %> - <%= link_to("No", [:approve, user], class: "button tiny secondary") unless user.approved? %> - <%= link_to("Yes", [:remove_approval, user], class: "button tiny success") if user.approved? %> + <%= link_to("No", [:approve, user], class: "button tiny secondary #{user.user_button_class}") unless user.approved? %> + <%= link_to("Yes", [:remove_approval, user], class: "button tiny success #{user.user_button_class}") if user.approved? %> <%= user.approval_at_string %> diff --git a/spec/factories/users.rb b/spec/factories/users.rb new file mode 100644 index 0000000..16dba07 --- /dev/null +++ b/spec/factories/users.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :user do + provider "google_oauth2" + sequence(:uid) { |n| n } + sequence(:name) { |n| "Fake User#{n}" } + end +end diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index d783e19..a5c5157 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,9 +1,10 @@ -feature "User management" do +feature "user management" do let(:users_index_path) { polymorphic_path([:users]) } - context "when an admin user visits the users index" do - let!(:admin_user) { login_new_admin_user } - subject { admin_user } + context "when an admin visits the users index" do + let!(:admin) { login_new_admin_user } + let!(:users) { create_list(:user, 2, approval_at: "01/01/2001") } + let!(:unapproved_user) { create(:user) } before { visit users_index_path } @@ -11,80 +12,61 @@ expect(page).to have_table("users_table") end - it "fills the table with the right headers and rows" do - check_headers_and_values_on_generic_index_page( - "users_table", { - "Name" => "Example User", - "Created At" => subject.created_at_string, - "Approval At" => subject.approval_at_string, - "Admin" => "true", - "Actions" => "Remove Approval Delete", - } - ) + it "displays a table with proper headers and admin row data" do + page.find("#user_#{admin.id} td:nth-of-type(1)", text: admin.name) + page.find("#user_#{admin.id} td:nth-of-type(2)", text: admin.created_at_string) + page.find("#user_#{admin.id} td:nth-of-type(3)", text: "Yes") + page.find("#user_#{admin.id} td:nth-of-type(4)", text: admin.approval_at_string) + page.find("#user_#{admin.id} td:nth-of-type(5)", text: "Yes") + page.find("#user_#{admin.id} td:nth-of-type(6)", text: "Delete") end - context "and a new non-admin user is added" do - subject! { User.create!(name: "Joe") } + it "displays a table with proper headers and user row data" do + page.find("#user_#{users.first.id} td:nth-of-type(1)", text: users.first.name) + page.find("#user_#{users.first.id} td:nth-of-type(2)", text: users.first.created_at_string) + page.find("#user_#{users.first.id} td:nth-of-type(3)", text: "Yes") + page.find("#user_#{users.first.id} td:nth-of-type(4)", text: users.first.approval_at_string) + page.find("#user_#{users.first.id} td:nth-of-type(5)", text: "No") + page.find("#user_#{users.first.id} td:nth-of-type(6)", text: "Delete") + end - before { visit users_index_path } + context "and admin clicks No for user approval" do + before do + find('.not-approved').click - it "fills the table with that user\"s information too" do - check_headers_and_values_on_generic_index_page( - "users_table", { - "Name" => "Joe", - "Created At" => subject.created_at_string, - "Approval At" => "", - "Admin" => "", - "Actions" => "Approve Delete", - } - ) end - context "and the current user clicks the approve link for that user" do - before do - within(:row_for, subject) do - click_link "Approve" - end - end + it "approves the user" do + expect(unapproved_user.reload).to be_approved + end - it "approves the user" do - expect(subject.reload).to be_approved - end + it "displays an approval time" do + expect(page).to have_content(unapproved_user.approval_at_string) + end - it "displays an approval time" do - within(:row_for, subject) do - expect(find(:value_under_header, "Approval At").text).to_not be_blank - end - end + it "shows Yes instead of No button" do + expect(page).to have_link('Yes', href: remove_approval_user_path(unapproved_user)) + end - it "no longer shows the approve link" do - within(:row_for, subject) do - expect(find(:value_under_header, "Actions").text).to eq "Remove Approval Delete" - end + context "and the admin clicks No for user approval for same user" do + before do + find(:xpath, "//a[@href='/users/#{unapproved_user.id}/remove_approval']").click end - context "and the current user clicks the Remove Approval link for that user" do - before do - within(:row_for, subject) do - click_link "Remove Approval" - end - end - - it "removes the user's approval" do - expect(subject.reload).to_not be_approved - end + it "removes the user's approval" do + expect(unapproved_user.reload).to_not be_approved end end - context "and the current user clicks the delete link for that user" do + context "and the admin clicks the delete link for same user" do before do - within(:row_for, subject) do + within(:css, "#user_#{unapproved_user.id}") do click_link "Delete" end end it "deletes the user" do - expect(User.find_by_id(subject.id)).to be_nil + expect(User.find_by_id(unapproved_user.id)).to be_nil end end end diff --git a/spec/support/factory_girl.rb b/spec/support/factory_girl.rb new file mode 100644 index 0000000..eec437f --- /dev/null +++ b/spec/support/factory_girl.rb @@ -0,0 +1,3 @@ +RSpec.configure do |config| + config.include FactoryGirl::Syntax::Methods +end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 72a18d1..406f941 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -1,7 +1,9 @@ module FeatureHelpers def login_new_user(options = {}) visit "/" - click_link "Sign in" + within(".super-button") do + click_link "Sign in or sign up" + end user = User.last user.admin = options[:admin] || false user.approval_at = options[:approval_at] || Time.now @@ -22,7 +24,7 @@ def check_headers_and_values_on_generic_index_page(table_locator, headers_and_va end end - within(:row_for, subject) do + within(:row_for, headers_and_values_hash) do headers_and_values_hash.each do |header, value| expect({ header => find(:value_under_header, header).text }).to eq({ header => value }) end