diff --git a/.gitignore b/.gitignore index 48fb168f..d869f9f9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ # Ignore Byebug command history file. .byebug_history +.env diff --git a/Gemfile b/Gemfile index c029c6da..734b0142 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ git_source(:github) do |repo_name| end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.0.2' +gem 'rails', '~> 5.1.6' # Use postgresql as the database for Active Record gem 'pg', '~> 0.18' # Use Puma as the app server @@ -40,6 +40,9 @@ gem 'jbuilder', '~> 2.5' gem 'foundation-rails' gem 'autoprefixer-rails' +gem 'omniauth' +gem 'omniauth-github' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platform: :mri @@ -65,6 +68,8 @@ group :development do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' + + gem 'dotenv-rails' end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem diff --git a/Gemfile.lock b/Gemfile.lock index f03db854..06923d6e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,45 +1,45 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.0.7) - actionpack (= 5.0.7) - nio4r (>= 1.2, < 3.0) + actioncable (5.1.6) + actionpack (= 5.1.6) + nio4r (~> 2.0) websocket-driver (~> 0.6.1) - actionmailer (5.0.7) - actionpack (= 5.0.7) - actionview (= 5.0.7) - activejob (= 5.0.7) + actionmailer (5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.0.7) - actionview (= 5.0.7) - activesupport (= 5.0.7) + actionpack (5.1.6) + actionview (= 5.1.6) + activesupport (= 5.1.6) rack (~> 2.0) - rack-test (~> 0.6.3) + rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.0.7) - activesupport (= 5.0.7) + actionview (5.1.6) + activesupport (= 5.1.6) builder (~> 3.1) - erubis (~> 2.7.0) + erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.0.7) - activesupport (= 5.0.7) + activejob (5.1.6) + activesupport (= 5.1.6) globalid (>= 0.3.6) - activemodel (5.0.7) - activesupport (= 5.0.7) - activerecord (5.0.7) - activemodel (= 5.0.7) - activesupport (= 5.0.7) - arel (~> 7.0) - activesupport (5.0.7) + activemodel (5.1.6) + activesupport (= 5.1.6) + activerecord (5.1.6) + activemodel (= 5.1.6) + activesupport (= 5.1.6) + arel (~> 8.0) + activesupport (5.1.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) ansi (1.5.0) - arel (7.1.4) + arel (8.0.0) autoprefixer-rails (8.2.0) execjs babel-source (5.8.35) @@ -62,10 +62,15 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - crass (1.0.3) + crass (1.0.4) + dotenv (2.2.2) + dotenv-rails (2.2.2) + dotenv (= 2.2.2) + railties (>= 3.2, < 6.0) erubi (1.7.1) - erubis (2.7.0) execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) ffi (1.9.23) foundation-rails (6.4.3.0) railties (>= 3.1.0) @@ -73,7 +78,8 @@ GEM sprockets-es6 (>= 0.9.0) globalid (0.4.1) activesupport (>= 4.2.0) - i18n (1.0.0) + hashie (3.5.7) + i18n (1.0.1) concurrent-ruby (~> 1.0) jbuilder (2.7.0) activesupport (>= 4.2.0) @@ -82,6 +88,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jwt (1.5.6) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -108,9 +115,26 @@ GEM minitest (~> 5.0) rails (>= 4.1) multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) nio4r (2.3.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.8.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) pg (0.21.0) pry (0.11.3) coderay (~> 1.1.0) @@ -118,29 +142,29 @@ GEM pry-rails (0.3.6) pry (>= 0.10.4) puma (3.11.3) - rack (2.0.4) - rack-test (0.6.3) - rack (>= 1.0) - rails (5.0.7) - actioncable (= 5.0.7) - actionmailer (= 5.0.7) - actionpack (= 5.0.7) - actionview (= 5.0.7) - activejob (= 5.0.7) - activemodel (= 5.0.7) - activerecord (= 5.0.7) - activesupport (= 5.0.7) + rack (2.0.5) + rack-test (1.0.0) + rack (>= 1.0, < 3) + rails (5.1.6) + actioncable (= 5.1.6) + actionmailer (= 5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + activemodel (= 5.1.6) + activerecord (= 5.1.6) + activesupport (= 5.1.6) bundler (>= 1.3.0) - railties (= 5.0.7) + railties (= 5.1.6) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - railties (5.0.7) - actionpack (= 5.0.7) - activesupport (= 5.0.7) + railties (5.1.6) + actionpack (= 5.1.6) + activesupport (= 5.1.6) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) @@ -199,6 +223,7 @@ DEPENDENCIES better_errors byebug coffee-rails (~> 4.2) + dotenv-rails foundation-rails jbuilder (~> 2.5) jquery-rails @@ -207,10 +232,12 @@ DEPENDENCIES minitest-reporters minitest-skip minitest-spec-rails + omniauth + omniauth-github pg (~> 0.18) pry-rails puma (~> 3.0) - rails (~> 5.0.2) + rails (~> 5.1.6) sass-rails (~> 5.0) spring spring-watcher-listen (~> 2.0.0) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c12c7c17..a8b54748 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,16 +2,26 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :find_user + # before_action :require_login #____WHY IS THIS NOT WORKING____ def render_404 # DPR: this will actually render a 404 page in production raise ActionController::RoutingError.new('Not Found') end + private + # def require_login + # unless session[:user_id] + # flash[:failure] = 'You must be logged in to do that' + # redirect_to root_path + # end + # end + def find_user if session[:user_id] @login_user = User.find_by(id: session[:user_id]) end end + end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 5bce99e6..c0ac0d48 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,27 +1,22 @@ class SessionsController < ApplicationController - def login_form - end - def login - username = params[:username] - if username and user = User.find_by(username: username) - session[:user_id] = user.id - flash[:status] = :success - flash[:result_text] = "Successfully logged in as existing user #{user.username}" - else - user = User.new(username: username) - if user.save - session[:user_id] = user.id - flash[:status] = :success - flash[:result_text] = "Successfully created new user #{user.username} with ID #{user.id}" - else - flash.now[:status] = :failure - flash.now[:result_text] = "Could not log in" - flash.now[:messages] = user.errors.messages - render "login_form", status: :bad_request + def create + auth_hash = request.env['omniauth.auth'] + + if auth_hash['uid'] + user = User.get_user(auth_hash) + if user.nil? + flash[:result_text] = 'Could not log in' + flash[:messages] = user.errors.messages + redirect_to root_path return end + session[:user_id] = user.id + flash[:success] = 'Successfully logged in' + else + flash[:result_text] = "Could not log in" end + redirect_to root_path end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 73b42652..618391bf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,6 @@ class UsersController < ApplicationController + before_action :require_login + def index @users = User.all end @@ -7,4 +9,12 @@ def show @user = User.find_by(id: params[:id]) render_404 unless @user end + + private + + def require_login + unless session[:user_id] + redirect_to root_path + end + end end diff --git a/app/controllers/works_controller.rb b/app/controllers/works_controller.rb index 2020bee4..81168cb0 100644 --- a/app/controllers/works_controller.rb +++ b/app/controllers/works_controller.rb @@ -3,6 +3,8 @@ class WorksController < ApplicationController # of work we're dealing with before_action :category_from_work, except: [:root, :index, :new, :create] + before_action :require_login, except: [:root] + def root @albums = Work.best_albums @books = Work.best_books @@ -91,4 +93,12 @@ def category_from_work render_404 unless @work @media_category = @work.category.downcase.pluralize end + + def require_login + unless session[:user_id] + flash[:failure] = 'You must be logged in to do that' + redirect_to root_path + end + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 51b55d86..98b4f082 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -2,4 +2,8 @@ module ApplicationHelper def render_date(date) date.strftime("%b %e, %Y") end + + def email_or_name(user) + return user.name ? user.name : user.email + end end diff --git a/app/models/user.rb b/app/models/user.rb index 4cac8fe0..7ca99007 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,25 @@ class User < ApplicationRecord - has_many :votes + has_many :votes, dependent: :destroy has_many :ranked_works, through: :votes, source: :work - validates :username, uniqueness: true, presence: true + validates :uid, presence: true, uniqueness: true + validates :provider, presence: true + validates :email, presence: true # might be redundant with github needing an email + + def self.get_user(data_hash) + user = User.find_by(uid: data_hash[:uid], provider: data_hash[:provider]) + if user.nil? + user_data = { + uid: data_hash['uid'], + provider: data_hash['provider'], + name: data_hash['info']['name'], + email: data_hash['info']['email'] + } + user = User.new(user_data) + return user.save ? user : nil + end + return user + end + + end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 82ca0fdc..04e21ed2 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -26,10 +26,10 @@
<% if @login_user %> - <%= link_to "Logged in as #{@login_user.username}", user_path(@login_user), class: "button" %> + <%= link_to "Logged in as #{email_or_name(@login_user)}", user_path(@login_user), class: "button" %> <%= link_to "Log Out", logout_path, method: :post, class: "button" %> <% else %> - <%= link_to "Log In", login_path, class: "button" %> + <%= link_to "Log In", '/auth/github', class: "button" %> <% end %>
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 83570de1..4cce0922 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -2,7 +2,7 @@ - + @@ -10,7 +10,7 @@ <% @users.each do |user| %> - + diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index d6185ad7..e03820e2 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,4 +1,4 @@ -

User Summary: <%= link_to @user.username, user_path(@user) %>

+

User Summary: <%= link_to email_or_name(@user), user_path(@user) %>

Joined site <%= render_date @user.created_at %>

Votes

diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 00000000..fd441612 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end diff --git a/config/routes.rb b/config/routes.rb index a7e8af1d..0b59789e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,12 +1,14 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html root 'works#root' - get '/login', to: 'sessions#login_form', as: 'login' - post '/login', to: 'sessions#login' + get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' post '/logout', to: 'sessions#logout', as: 'logout' + resources :works post '/works/:id/upvote', to: 'works#upvote', as: 'upvote' resources :users, only: [:index, :show] + + end diff --git a/db/migrate/20180417193410_update_user_table.rb b/db/migrate/20180417193410_update_user_table.rb new file mode 100644 index 00000000..5d5f1644 --- /dev/null +++ b/db/migrate/20180417193410_update_user_table.rb @@ -0,0 +1,10 @@ +class UpdateUserTable < ActiveRecord::Migration[5.0] + def change + remove_column :users, :username + + add_column :users, :name, :string + add_column :users, :email, :string + add_column :users, :uid, :integer + add_column :users, :provider, :string + end +end diff --git a/db/migrate/20180417194103_users_not_null_columns.rb b/db/migrate/20180417194103_users_not_null_columns.rb new file mode 100644 index 00000000..fb7f00f4 --- /dev/null +++ b/db/migrate/20180417194103_users_not_null_columns.rb @@ -0,0 +1,6 @@ +class UsersNotNullColumns < ActiveRecord::Migration[5.0] + def change + change_column_null :users, :uid, false + change_column_null :users, :provider, false + end +end diff --git a/db/schema.rb b/db/schema.rb index 6bc8ba5c..cf306c92 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,15 +10,18 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170407164321) do +ActiveRecord::Schema.define(version: 20180417194103) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" create_table "users", force: :cascade do |t| - t.string "username" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "name" + t.string "email" + t.integer "uid", null: false + t.string "provider", null: false end create_table "votes", force: :cascade do |t| diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb index f641d15c..19a5f9f1 100644 --- a/test/controllers/sessions_controller_test.rb +++ b/test/controllers/sessions_controller_test.rb @@ -1,5 +1,82 @@ require "test_helper" describe SessionsController do + describe 'auth_callback' do + it 'signs in an existing user' do + user = User.first + old_user_count = User.count + login(user) + + must_redirect_to root_path + User.count.must_equal old_user_count + session[:user_id].must_equal user.id + end + + it 'creates a new DB entry for a new user' do + user_data = { + name: 'A Name', + email: 'name@anemail.com', + uid: 99999, + provider: 'github' + } + user = User.new(user_data) + user.valid?.must_equal true + + old_user_count = User.count + + + login(user) + + must_redirect_to root_path + User.count.must_equal old_user_count + 1 + session[:user_id] = User.last.id + end + + it 'will not login a user if not enough information is returned from provider' do + user_data = { + name: 'A Name', + email: 'name@anemail.com', + provider: 'github' + } + user = User.new(user_data) + user.valid?.must_equal false + + old_user_count = User.count + + + login(user) + + must_redirect_to root_path + User.count.must_equal old_user_count + session[:user_id].must_be_nil + end + + it 'will sign in a user that is already signed in' do + user = User.first + old_user_count = User.count + + login(user) + session[:user_id].must_equal user.id + + login(user) + + must_redirect_to root_path + User.count.must_equal old_user_count + session[:user_id].must_equal user.id + end + end + + describe 'logout' do + it 'logs out a logged in user' do + user = User.first + + login(user) + session[:user_id].must_equal user.id + + post logout_path + + session[:user_id].must_be_nil + end + end end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index d2c5cfbb..703e26e8 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -1,5 +1,42 @@ require 'test_helper' describe UsersController do + before do + user = users(:dan) + login(user) + end + + describe 'index' do + it 'must respond with success if there is more than one user' do + get users_path + must_respond_with :success + end + + it 'must respond with success if there are no users' do + User.destroy_all + + get users_path + + must_respond_with :success + end + end + + describe 'show' do + it 'must respond with success if the user is found' do + user = User.first + + get user_path(user.id) + + must_respond_with :success + end + + it 'must respond with 404 not found if the user is not found' do + user_id = User.last.id + 1 + + get user_path(user_id) + + must_respond_with :not_found + end + end end diff --git a/test/controllers/works_controller_test.rb b/test/controllers/works_controller_test.rb index 0945ca47..bc3a9d7d 100644 --- a/test/controllers/works_controller_test.rb +++ b/test/controllers/works_controller_test.rb @@ -1,116 +1,307 @@ require 'test_helper' describe WorksController do - describe "root" do - it "succeeds with all media types" do - # Precondition: there is at least one media of each category - + describe 'guest user' do + describe 'root' do + it 'succeeds with all media types' do + albums = Work.where(category: 'album') + books = Work.where(category: 'book') + movies = Work.where(category: 'movie') + + albums.count.must_be :>, 0 + books.count.must_be :>, 0 + movies.count.must_be :>, 0 + + get root_path + + must_respond_with :success + end + describe 'show' do + it 'redirects back to root if user is not logged in' do + get work_path(Work.first.id) + + must_redirect_to root_path + end + end + + describe 'upvote' do + it "redirects to the work page if no user is logged in" do + work = Work.first + old_count = work.vote_count + + post upvote_path(work.id) + + must_redirect_to root_path + Work.first.vote_count.must_equal old_count + end + end end - it "succeeds with one media type absent" do - # Precondition: there is at least one media in two of the categories + end + describe 'logged in user' do + before do + user = users(:dan) + login(user) + puts session[:user_id] end - it "succeeds with no media" do + describe "root" do + it "succeeds with all media types" do + # Precondition: there is at least one media of each category - end - end + albums = Work.where(category: 'album') + books = Work.where(category: 'book') + movies = Work.where(category: 'movie') - CATEGORIES = %w(albums books movies) - INVALID_CATEGORIES = ["nope", "42", "", " ", "albumstrailingtext"] + albums.count.must_be :>, 0 + books.count.must_be :>, 0 + movies.count.must_be :>, 0 - describe "index" do - it "succeeds when there are works" do + get root_path - end + must_respond_with :success - it "succeeds when there are no works" do + end - end - end + it "succeeds with one media type absent" do + # Precondition: there is at least one media in two of the categories + albums = Work.where(category: 'album') + albums.destroy_all - describe "new" do - it "succeeds" do + albums.count.must_equal 0 - end - end + get root_path - describe "create" do - it "creates a work with valid data for a real category" do + must_respond_with :success - end + end - it "renders bad_request and does not update the DB for bogus data" do + it "succeeds with no media" do + Work.destroy_all + get root_path + + must_respond_with :success + end end - it "renders 400 bad_request for bogus categories" do + CATEGORIES = %w(albums books movies) + INVALID_CATEGORIES = ["nope", "42", "", " ", "albumstrailingtext"] - end + describe "index" do + it "succeeds when there are works" do + Work.count.must_be :>, 0 - end + get works_path - describe "show" do - it "succeeds for an extant work ID" do + must_respond_with :success + end - end + it "succeeds when there are no works" do + Work.destroy_all + + Work.count.must_equal 0 - it "renders 404 not_found for a bogus work ID" do + get works_path + must_respond_with :success + end end - end - describe "edit" do - it "succeeds for an extant work ID" do + describe "new" do + it "succeeds" do + get new_work_path + must_respond_with :success + end end - it "renders 404 not_found for a bogus work ID" do + describe "create" do + it "creates a work with valid data for a real category" do + work_data = { + title: 'A Test Title', + category: 'albums' + } - end - end + before_count = Work.count + Work.new(work_data).must_be :valid? - describe "update" do - it "succeeds for valid data and an extant work ID" do + post works_path, params: {work: work_data} - end + work = Work.last + must_redirect_to work_path(work.id) + Work.count.must_equal before_count + 1 + end - it "renders bad_request for bogus data" do + it "renders bad_request and does not update the DB for bogus data" do + work_data = { + title: nil, + category: 'albums' + } - end + before_count = Work.count + Work.new(work_data).wont_be :valid? - it "renders 404 not_found for a bogus work ID" do + post works_path, params: {work: work_data} - end - end + must_respond_with :bad_request + Work.count.must_equal before_count + end - describe "destroy" do - it "succeeds for an extant work ID" do + it "renders 400 bad_request for bogus categories" do + work_data = { + title: 'Test Title', + category: INVALID_CATEGORIES[0] + } + + before_count = Work.count + + post works_path, params: {work: work_data} + + must_respond_with :bad_request + Work.count.must_equal before_count + end end - it "renders 404 not_found and does not update the DB for a bogus work ID" do + describe "show" do + it "succeeds for an extant work ID" do + work = Work.first + + get work_path(work.id) + + must_respond_with :success + end + + it "renders 404 not_found for a bogus work ID" do + work_id = Work.last.id + 1 + + get work_path(work_id) + must_respond_with :not_found + end end - end - describe "upvote" do + describe "edit" do + it "succeeds for an extant work ID" do + work = Work.first + + get edit_work_path(work.id) + + must_respond_with :success + end + + it "renders 404 not_found for a bogus work ID" do + work_id = Work.last.id + 1 - it "redirects to the work page if no user is logged in" do + get work_path(work_id) + must_respond_with :not_found + end end - it "redirects to the work page after the user has logged out" do + describe "update" do + let (:work) { Work.first } + + it "succeeds for valid data and an extant work ID" do + work_params = { + title: 'my_title' + } + work.assign_attributes(work_params) + + work.valid?.must_equal true + + patch work_path(work.id), params: {work: work_params} + + must_redirect_to work_path(work.id) + Work.first.title.must_equal 'my_title' + end + + it "renders not_found for bogus data" do + work_params = { + category: INVALID_CATEGORIES[-1] + } + + work.assign_attributes(work_params) + + work.valid?.must_equal false + + patch work_path(work.id), params: {work: work_params} + + must_respond_with :not_found + work.category.must_equal work_params[:category] + work.errors.messages.must_include :category + end + + it "renders 404 not_found for a bogus work ID" do + work_id = Work.last.id + 1 + work_params = { + title: 'my_title' + } + work.assign_attributes(work_params) + patch work_path(work_id), params: {work: work_params} + + must_respond_with :not_found + end end - it "succeeds for a logged-in user and a fresh user-vote pair" do + describe "destroy" do + it "succeeds for an extant work ID" do + work = Work.first + old_count = Work.count + + delete work_path(work.id) + + must_redirect_to root_path + Work.count.must_equal old_count - 1 + end + + it "renders 404 not_found and does not update the DB for a bogus work ID" do + work_id = Work.last.id + 1 + old_count = Work.count + delete work_path(work_id) + + must_respond_with :not_found + Work.count.must_equal old_count + + end end - it "redirects to the work page if the user has already voted for that work" do + describe "upvote" do + + it "succeeds for a logged-in user and a fresh user-vote pair" do + user = User.first + work = Work.create!(title: 'A new work', category: 'books') + + login(user) + session[:user_id].must_equal user.id + + post upvote_path(work.id) + + must_redirect_to work_path(work.id) + work.reload + work.vote_count.must_equal 1 + end + + it "redirects to the work page if the user has already voted for that work" do + work = works(:another_album) + user = users(:dan) + + login(user) + session[:user_id].must_equal user.id + + old_vote_count = work.vote_count + + # Act + post upvote_path(work.id) + # Assert + works(:another_album).vote_count.must_equal old_vote_count + must_redirect_to work_path(work.id) + end end end end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index e2968d78..b129b75b 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -1,7 +1,13 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html dan: - username: dan + name: dan + email: dan@adadev.org + uid: 11111 + provider: github kari: - username: kari + name: kari + email: kari@adadev.org + uid: 123456 + provider: github diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 793ce7e6..00655a56 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -20,25 +20,29 @@ end describe "validations" do - it "requires a username" do - user = User.new + it "requires an email" do + user = User.new(uid: 99999, provider: 'github') user.valid?.must_equal false - user.errors.messages.must_include :username + user.errors.messages.must_include :email end - it "requires a unique username" do - username = "test username" - user1 = User.new(username: username) + it "requires a unique uid" do + user1 = User.new(uid: 12345, provider: 'github', email: 'fake@fake.com') # This must go through, so we use create! user1.save! - user2 = User.new(username: username) + user2 = User.new(uid: 12345, provider: 'github', email: 'fake2@fake.com') result = user2.save result.must_equal false - user2.errors.messages.must_include :username + user2.errors.messages.must_include :uid end + it 'requires a provider' do + user = User.new(uid: 99999, email: '29394@ghghgh.com') + user.valid?.must_equal false + user.errors.messages.must_include :provider + end end end diff --git a/test/models/vote_test.rb b/test/models/vote_test.rb index f2615aa1..7c2ec3bb 100644 --- a/test/models/vote_test.rb +++ b/test/models/vote_test.rb @@ -16,8 +16,8 @@ end describe "validations" do - let (:user1) { User.new(username: 'chris') } - let (:user2) { User.new(username: 'chris') } + let (:user1) { User.new(email: 'chris@email.com', uid: 12345, provider: 'github') } + let (:user2) { User.new(email: 'chris@email.com2', uid: 11111, provider: 'github') } let (:work1) { Work.new(category: 'book', title: 'House of Leaves') } let (:work2) { Work.new(category: 'book', title: 'For Whom the Bell Tolls') } diff --git a/test/models/work_test.rb b/test/models/work_test.rb index d9c00073..e809683c 100644 --- a/test/models/work_test.rb +++ b/test/models/work_test.rb @@ -83,7 +83,7 @@ it "tracks the number of votes" do work = Work.create!(title: "test title", category: "movie") 4.times do |i| - user = User.create!(username: "user#{i}") + user = User.create!(email: "user#{i}", uid: i, provider: 'github') Vote.create!(user: user, work: work) end work.vote_count.must_equal 4 @@ -97,7 +97,7 @@ # Create users to do the voting test_users = [] 20.times do |i| - test_users << User.create!(username: "user#{i}") + test_users << User.create!(email: "user#{i}", uid: i, provider: 'github') end # Create media to vote upon diff --git a/test/test_helper.rb b/test/test_helper.rb index 5b4fb667..d2a819b0 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -23,4 +23,24 @@ class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all # Add more helper methods to be used by all tests here... + + def setup + OmniAuth.config.test_mode = true + end + + def mock_auth_hash(user) + return { + provider: user.provider, + uid: user.uid, + info: { + email: user.email, + nickname: user.name + } + } + end + + def login(user) + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(:github) + end end
UsernameName Votes Joined
<%= link_to user.username, user_path(user) %><%= link_to user.name, user_path(user) %> <%= user.votes.count %> <%= render_date user.created_at %>