diff --git a/spec/factories/photo.rb b/spec/factories/photo.rb index 496d02b..79eb79c 100644 --- a/spec/factories/photo.rb +++ b/spec/factories/photo.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :photo do - image { Faker::Avatar.image } - caption "Lake Bondhus" + sequence(:image) { |n| "https://some.url/image#{n}.png" } + sequence(:caption) { |n| "Some caption #{n}" } end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index ca715af..5816c85 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -1,8 +1,9 @@ FactoryBot.define do factory :user do sequence(:email) { |n| "test#{n}@example.com" } - password 'f4k3p455w0rd' - sequence(:username) { |n| "president#{n}" } + password "password" + sequence(:username) { |n| "person#{n}" } + factory :user_with_photos do transient do photos_count 1 diff --git a/spec/features/1_setup_spec.rb b/spec/features/1_setup_spec.rb index 264577b..9fb43b5 100644 --- a/spec/features/1_setup_spec.rb +++ b/spec/features/1_setup_spec.rb @@ -1,10 +1,11 @@ require "rails_helper" -feature "Devise" do +feature "Setup:" do scenario "root url set to photos index", points: 1 do user = create(:user) visit "/" + if page.has_selector?("label", text: "Email") fill_in("Email", :with => user.email) fill_in("Password", :with => user.password) @@ -16,11 +17,7 @@ scenario "user authentication required for home page", points: 2 do visit "/" - expect(page.current_path).to eq("/users/sign_in") - end - scenario "user authentication required for likes page", points: 1 do - visit "/likes" expect(page.current_path).to eq("/users/sign_in") end @@ -34,5 +31,4 @@ expect(page).to have_content("Signed in successfully.") end - end diff --git a/spec/features/2_header_spec.rb b/spec/features/2_header_spec.rb deleted file mode 100644 index 59d0900..0000000 --- a/spec/features/2_header_spec.rb +++ /dev/null @@ -1,59 +0,0 @@ -require "rails_helper" - -feature "Header:" do - - scenario "edit profile link is just username", points: 2 do - user = create(:user) - login_as(user, :scope => :user) - - visit "/" - - within('nav') do - expect(page).to have_link(user.username, href: '/users/edit') - end - end - - scenario "no 'dummy' text in sign-out link", points: 1 do - user = create(:user) - login_as(user, :scope => :user) - - visit "/" - - within('nav') do - expect(find(:xpath, "//a[@href='/users/sign_out']").text).not_to eq('Dummy Sign Out Link') - end - end - - scenario "shows sign-up link if logged out", points: 1 do - visit "/" - - within('nav') do - expect(page).to have_link(nil, href: '/users/sign_up') - end - end - - scenario "shows sign-in link if logged out", points: 1 do - visit "/" - - within('nav') do - expect(page).to have_link(nil, href: '/users/sign_in') - end - end - - scenario "not shows sign-out link if logged out", points: 1 do - visit "/" - - within('nav') do - expect(page).not_to have_link(nil, href: '/users/sign_out') - end - end - - scenario "not shows edit link if logged out", points: 1 do - visit "/" - - within('nav') do - expect(page).not_to have_link(nil, href: '/users/edit') - end - end - -end diff --git a/spec/features/2_navbar_spec.rb b/spec/features/2_navbar_spec.rb new file mode 100644 index 0000000..fdfbc7c --- /dev/null +++ b/spec/features/2_navbar_spec.rb @@ -0,0 +1,58 @@ +require "rails_helper" + +feature "Navbar:" do + scenario "edit profile link's text is username", points: 3 do + user = create(:user) + login_as(user, :scope => :user) + + visit "/" + + within("nav") do + expect(page).to have_link(user.username, href: "/users/edit") + end + end + + scenario "no 'dummy' text in sign out link", points: 1 do + user = create(:user) + login_as(user, :scope => :user) + + visit "/" + + within("nav") do + expect(find(:xpath, "//a[@href='/users/sign_out']").text).not_to eq("Dummy Sign Out Link") + end + end + + scenario "shows sign-up link if signed out", points: 2 do + visit "/" + + within("nav") do + expect(page).to have_link(nil, href: "/users/sign_up") + end + end + + scenario "shows sign-in link if signed out", points: 2 do + visit "/" + + within("nav") do + expect(page).to have_link(nil, href: "/users/sign_in") + end + end + + scenario "does not show sign-out link if signed out", points: 2 do + visit "/" + + within("nav") do + expect(page).not_to have_link(nil, href: "/users/sign_out") + end + end + + scenario "does not show edit link if signed out", points: 1 do + visit "/" + + within("nav") do + expect(page).not_to have_link(nil, href: "/users/edit") + end + end + +end diff --git a/spec/features/3_users_spec.rb b/spec/features/3_users_spec.rb index 7173da1..52f361c 100644 --- a/spec/features/3_users_spec.rb +++ b/spec/features/3_users_spec.rb @@ -1,78 +1,79 @@ require "rails_helper" feature "Users:" do - - scenario "for new photo form, user ID prepopulated or in hidden field", points: 2 do + scenario "in routes.rb, 'get /users/:id' below 'devise_for :users'", points: 1 do user = create(:user) login_as(user, :scope => :user) - visit "/photos/new" + visit "/users/sign_in" - if page.has_selector?("label", text: "User") - expect(page).to have_selector("input[value='#{user.id}']") - expect(page).to have_field('User', with: "#{user.id}") - else - expect(page).not_to have_selector("label", text: "User") - end + expect(page.current_path).to eq "/" end - scenario "RCAV set for /users", points: 1 do + scenario "user_id pre-populated in new photo form", points: 2 do user = create(:user) + login_as(user, :scope => :user) + visit "/photos/new" + expect(page).to have_selector("input[value='#{user.id}']", visible: false) + end + + scenario "RCAV dots connected for /users", points: 1 do + user = create(:user) + + login_as(user, :scope => :user) visit "/users" expect(page.status_code).to be(200) # 200 is "OK" end - scenario "/users lists all users", points: 2 do - user_1 = create(:user) - user_2 = create(:user) - login_as(user_1, :scope => :user) + scenario "/users lists all users", points: 3 do + users = create_list(:user, 2) + login_as(users.first, :scope => :user) visit "/users" - users = User.all users.each do |user| expect(page).to have_content(user.username) end end - scenario "header includes link to /users", points: 1 do + scenario "navbar includes link to /users", points: 1 do user = create(:user) - login_as(user, :scope => :user) + login_as(user, :scope => :user) visit "/" - within('nav') do - expect(page).to have_link(nil, href: '/users') + within("nav") do + expect(page).to have_link(nil, href: "/users") end end - scenario "RCAV set for /users/:id", points: 1 do + scenario "RCAV dots connected for /users/:id", points: 1 do user = create(:user) - login_as(user, :scope => :user) + login_as(user, :scope => :user) visit "/users/#{user.id}" expect(page.status_code).to be(200) # 200 is "OK" end - scenario "/users/:id lists user's details", points: 1 do + scenario "/users/:id lists user's details", points: 2 do user = create(:user) - login_as(user, :scope => :user) + login_as(user, :scope => :user) visit "/users/#{user.id}" expect(page).to have_content(user.username) end - scenario "/users/:id lists user's photos caption", points: 2 do + scenario "/users/:id lists user's photos captions", points: 3 do user = create(:user) - photo_1 = FactoryBot.create(:photo, :user_id => user.id) - photo_2 = FactoryBot.create(:photo, :user_id => user.id) - login_as(user, :scope => :user) + photo_1 = create(:photo, :user_id => user.id) + photo_2 = create(:photo, :user_id => user.id) + login_as(user, :scope => :user) visit "/users/#{user.id}" photos = Photo.all @@ -83,8 +84,8 @@ scenario "/users/:id lists user's photos", points: 2 do user = create(:user) - photo_1 = FactoryBot.create(:photo, :user_id => user.id) - photo_2 = FactoryBot.create(:photo, :user_id => user.id) + photo_1 = create(:photo, :user_id => user.id) + photo_2 = create(:photo, :user_id => user.id) login_as(user, :scope => :user) visit "/users/#{user.id}" @@ -95,13 +96,13 @@ end end - scenario "when signed in header has link to /users/:id", points: 2 do + scenario "when signed in navbar has link to /users/:id", points: 2 do user = create(:user) login_as(user, :scope => :user) visit "/" - within('nav') do + within("nav") do expect(page).to have_link(nil, href: "/users/#{user.id}") end end @@ -111,18 +112,8 @@ visit "/" - within('nav') do + within("nav") do expect(page).not_to have_link(nil, href: "/users/#{user.id}") end end - - scenario "in routes.rb, /users/:id below 'devise_for :users'", points: 1 do - user = create(:user) - login_as(user, :scope => :user) - - visit "/users/sign_in" - - expect(page.current_path).to eq "/" - end - end diff --git a/spec/features/4_mylikes_spec.rb b/spec/features/4_mylikes_spec.rb index 268b9f1..fe83c8a 100644 --- a/spec/features/4_mylikes_spec.rb +++ b/spec/features/4_mylikes_spec.rb @@ -1,8 +1,18 @@ require "rails_helper" -feature "My_likes:" do +feature "My Likes:" do + scenario "navbar has link to /my_likes", points: 1 do + user = create(:user) + login_as(user, :scope => :user) + + visit "/" - scenario "RCAV set for /my_likes", points: 1 do + within('nav') do + expect(page).to have_link(nil, href: '/my_likes') + end + end + + scenario "RCAV dots connected for /my_likes", points: 1 do user = create(:user) login_as(user, :scope => :user) @@ -11,69 +21,63 @@ expect(page.status_code).to be(200) # 200 is "OK" end - scenario "shows photos caption a user has liked", points: 1 do - user_1, user_2, user_3 = create_list(:user_with_photos, 3) + scenario "shows the captions of photos a user has liked", points: 3 do + alice = create(:user_with_photos) + bob = create(:user_with_photos) + carol = create(:user_with_photos) - like_1 = FactoryBot.create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) - like_2 = FactoryBot.create(:like, :user_id => user_3.id, :photo_id => user_3.photos.first.id) - login_as(user_2, :scope => :user) + create(:like, :user => alice, :photo => bob.photos.first) + create(:like, :user => alice, :photo => carol.photos.first) + + login_as(alice, :scope => :user) visit "/my_likes" - user_2.likes.each do |like| + alice.likes.each do |like| expect(page).to have_content(like.photo.caption) end end - scenario "shows photos a user has liked", points: 1 do - user_1, user_2, user_3 = create_list(:user_with_photos, 3) + scenario "shows the images a user has liked", points: 2 do + alice = create(:user_with_photos) + bob = create(:user_with_photos) + carol = create(:user_with_photos) + + create(:like, :user => alice, :photo => bob.photos.first) + create(:like, :user => alice, :photo => carol.photos.first) - like_1 = FactoryBot.create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) - like_2 = FactoryBot.create(:like, :user_id => user_3.id, :photo_id => user_3.photos.first.id) - login_as(user_2, :scope => :user) + login_as(alice, :scope => :user) visit "/my_likes" - user_2.likes.each do |like| + alice.likes.each do |like| expect(page).to have_css("img[src*='#{like.photo.image}']") end end - scenario "does not show photos caption a user hasn't liked", points: 1 do - user_1, user_2, user_3 = create_list(:user_with_photos, 3) + scenario "does not show the captions of photos a user hasn't liked", points: 3 do + alice = create(:user_with_photos) + bob = create(:user_with_photos) + carol = create(:user_with_photos) - like_1 = FactoryBot.create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) - like_2 = FactoryBot.create(:like, :user_id => user_3.id, :photo_id => user_3.photos.first.id) + create(:like, :user => alice, :photo => bob.photos.first) + create(:like, :user => alice, :photo => carol.photos.first) - login_as(user_2, :scope => :user) + login_as(alice, :scope => :user) visit "/my_likes" - user_1.likes.each do |like| - expect(page).not_to have_content(like.photo.caption) - end + expect(page).not_to have_content(alice.photos.first.caption) end - scenario "does not show photos a user hasn't liked", points: 1 do - user_1, user_2, user_3 = create_list(:user_with_photos, 3) + scenario "does not show images a user hasn't liked", points: 2 do + alice = create(:user_with_photos) + bob = create(:user_with_photos) + carol = create(:user_with_photos) - like_1 = FactoryBot.create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) - like_2 = FactoryBot.create(:like, :user_id => user_3.id, :photo_id => user_3.photos.first.id) + create(:like, :user => alice, :photo => bob.photos.first) + create(:like, :user => alice, :photo => carol.photos.first) - login_as(user_2, :scope => :user) + login_as(alice, :scope => :user) visit "/my_likes" - user_1.likes.each do |like| - expect(page).not_to have_css("img[src*='#{like.photo.image}']") - end + expect(page).not_to have_css("img[src*='#{alice.photos.first.image}']") end - - scenario "header has link to /my_likes", points: 1 do - user = create(:user) - login_as(user, :scope => :user) - - visit "/" - - within('nav') do - expect(page).to have_link(nil, href: '/my_likes') - end - end - end diff --git a/spec/features/5_photos_spec.rb b/spec/features/5_photos_spec.rb index af2518b..a52cf7c 100644 --- a/spec/features/5_photos_spec.rb +++ b/spec/features/5_photos_spec.rb @@ -1,10 +1,9 @@ require "rails_helper" -feature "Photos Index Page:" do - - scenario "only show edit link for signed-in user's photos", points: 1 do - owner = create(:user) - non_owner = create(:user) +feature "Photos Index:" do + it "only shows edit link for signed-in user's photos", points: 3 do + owner = create(:user_with_photos) + non_owner = create(:user_with_photos) login_as(owner, :scope => :user) visit "/photos" @@ -18,9 +17,9 @@ end end - scenario "only show delete link for signed-in user's photos", points: 1 do - owner = create(:user) - non_owner = create(:user) + it "only shows delete link for signed-in user's photos", points: 2 do + owner = create(:user_with_photos) + non_owner = create(:user_with_photos) login_as(owner, :scope => :user) visit "/photos" @@ -34,78 +33,65 @@ end end - scenario "ADD PHOTO link should present", points: 1 do + it "has 'Add Photo' link", points: 1 do user = create(:user) - photo = create(:photo, :user_id => user.id) - login_as(user, :scope => :user) + login_as(user, :scope => :user) visit "/photos" expect(page).to have_link("Add Photo", href: "/photos/new") end - scenario "'Photos' h1 tag should not present", points: 1 do + it "'Photos' h1 element should not present", points: 1 do user = create(:user) - photo = create(:photo, :user_id => user.id) - login_as(user, :scope => :user) + login_as(user, :scope => :user) visit "/photos" expect(page).not_to have_selector("h1", text: "Photos") end - scenario "displays per-photo username", points: 1 do - user = create(:user) - login_as(user, :scope => :user) - - visit "/photos" + it "displays photos", points: 2 do + users = create_list(:user_with_photos, 3) photos = Photo.all - photos.each do |photo| - expect(page).to have_content("#{photo.user.username}") - end - end - - scenario "displays photo", points: 1 do - user = create(:user) - login_as(user, :scope => :user) - + login_as(users.first, :scope => :user) visit "/photos" - photos = Photo.all photos.each do |photo| expect(page).to have_css("img[src*='#{photo.image}']") end end - scenario "displays per-photo time elapsed", points: 1, hint: h("time_in_words") do - user = create(:user) - login_as(user, :scope => :user) + it "displays submitters' usernames", points: 3 do + users = create_list(:user_with_photos, 3) + photos = Photo.all + login_as(users.first, :scope => :user) visit "/photos" - photos = Photo.all photos.each do |photo| - expect(page).to have_content(ApplicationController.helpers.time_ago_in_words(photo.created_at)) + expect(page).to have_content("#{photo.user.username}") end end - scenario "header have Sign Out link", points: 1 do - user = create(:user) - login_as(user, :scope => :user) + it "displays time elapsed since posting photos", points: 1, hint: h("time_in_words") do + users = create_list(:user_with_photos, 3) + photos = Photo.all + login_as(users.first, :scope => :user) visit "/photos" - within('nav') do - expect(page).to have_link("Sign Out", href: "/users/sign_out") + photos.each do |photo| + expect(page).to have_content(ApplicationController.helpers.time_ago_in_words(photo.created_at)) end end - scenario "lists comments with authors", points: 1 do + it "lists comments in each photo", points: 1 do user_1, user_2, user_3 = create_list(:user_with_photos, 3) - comment_1 = FactoryBot.create(:comment, :user_id => user_1.id, :body => "comment_1", :photo_id => user_1.photos.first.id) - comment_2 = FactoryBot.create(:comment, :user_id => user_2.id, :body => "comment_two", :photo_id => user_2.photos.first.id) + comment_1 = create(:comment, :user_id => user_1.id, :body => "comment_1", :photo_id => user_1.photos.first.id) + comment_2 = create(:comment, :user_id => user_2.id, :body => "comment_two", :photo_id => user_2.photos.first.id) login_as(user_3, :scope => :user) visit "/photos" @@ -113,16 +99,16 @@ photos = Photo.all photos.each do |photo| photo.comments.each do |comment| - expect(page).to have_content(comment.user.username) + expect(page).to have_content(comment.body) end end end - scenario "lists comments in each photo", points: 1 do + it "lists comments with authors", points: 1 do user_1, user_2, user_3 = create_list(:user_with_photos, 3) - comment_1 = FactoryBot.create(:comment, :user_id => user_1.id, :body => "comment_1", :photo_id => user_1.photos.first.id) - comment_2 = FactoryBot.create(:comment, :user_id => user_2.id, :body => "comment_two", :photo_id => user_2.photos.first.id) + comment_1 = create(:comment, :user_id => user_1.id, :body => "comment_1", :photo_id => user_1.photos.first.id) + comment_2 = create(:comment, :user_id => user_2.id, :body => "comment_two", :photo_id => user_2.photos.first.id) login_as(user_3, :scope => :user) visit "/photos" @@ -130,43 +116,28 @@ photos = Photo.all photos.each do |photo| photo.comments.each do |comment| - expect(page).to have_content(comment.body) + expect(page).to have_content(comment.user.username) end end end - scenario "shows LIKE/UNLIKE button", points: 1 do - user_1 = create(:user_with_photos) - user_2 = create(:user_with_photos) - - like_1 = FactoryBot.create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) - like_2 = FactoryBot.create(:like, :user_id => user_2.id, :photo_id => user_2.photos.first.id) - login_as(user_1, :scope => :user) - - visit "/photos" - - expect(page).to have_css("button", text: 'Like') - - expect(page).to have_link("Unlike", href: "/delete_like/#{like_1.id}") - end - - scenario "includes form field with placeholder 'Add a comment...'", points: 1 do + it "includes form field with placeholder 'Add a comment...'", points: 1 do user = create(:user) login_as(user, :scope => :user) - photo = FactoryBot.create(:photo, :user_id => user.id) + photo = create(:photo, :user_id => user.id) visit "/photos" expect(page).to have_selector("input[placeholder='Add a comment...']") end - scenario "quick-add a comment should add comment", points: 2 do + it "quick-add a comment should add comment", points: 2 do user_1 = create(:user_with_photos) user_2 = create(:user) login_as(user_2, :scope => :user) visit "/photos" - + new_comment = "Just added a comment at #{Time.now.to_f}" fill_in("Add a comment...", with: new_comment) find("button", text: 'Add Comment').click @@ -174,13 +145,13 @@ expect(page).to have_content(new_comment) end - scenario "after adding a comment page it should leads back to /photos", points: 2 do + it "after adding a comment page it should leads back to /photos", points: 2 do user_1 = create(:user_with_photos) user_2 = create(:user) login_as(user_2, :scope => :user) visit "/photos" - + new_comment = "Just added a comment at #{Time.now.to_f}" fill_in("Add a comment...", with: new_comment) find("button", text: 'Add Comment').click @@ -188,10 +159,10 @@ expect(page).to have_current_path("/photos") end - scenario "quick-add a comment sets the author correctly", points: 1, hint: h("display_id_or_username") do + it "quick-add a comment sets the author correctly", points: 1, hint: h("display_id_or_username") do user_1 = create(:user_with_photos) user_2 = create(:user) - + login_as(user_2, :scope => :user) visit "/photos" @@ -210,9 +181,24 @@ end end - scenario "displays a link to unlike a photo after liking a photo", points: 2 do + it "shows Like/Unlike buttons", points: 1 do + user_1 = create(:user_with_photos) + user_2 = create(:user_with_photos) + + like_1 = create(:like, :user_id => user_1.id, :photo_id => user_1.photos.first.id) + like_2 = create(:like, :user_id => user_2.id, :photo_id => user_2.photos.first.id) + login_as(user_1, :scope => :user) + + visit "/photos" + + expect(page).to have_css("button", text: 'Like') + + expect(page).to have_link("Unlike", href: "/delete_like/#{like_1.id}") + end + + it "displays a link to unlike a photo after liking a photo", points: 2 do user = create(:user) - photo = FactoryBot.create(:photo, :user_id => user.id) + photo = create(:photo, :user_id => user.id) login_as(user, :scope => :user) visit "/photos" @@ -221,10 +207,10 @@ expect(page).to have_link("Unlike", href: "/delete_like/#{photo.likes.first.id}") end - scenario "displays a link to like a photo after unliking a photo", points: 1 do + it "displays a link to like a photo after unliking a photo", points: 1 do user = create(:user_with_photos) - - like = FactoryBot.create(:like, :user_id => user.id, :photo_id => user.photos.first.id) + + like = create(:like, :user_id => user.id, :photo_id => user.photos.first.id) login_as(user, :scope => :user) visit "/photos" @@ -233,5 +219,4 @@ expect(page).to have_css("button", text: 'Like') end - end diff --git a/spec/features/6_devise_spec.rb b/spec/features/6_devise_spec.rb index b0ea04e..b6c08de 100644 --- a/spec/features/6_devise_spec.rb +++ b/spec/features/6_devise_spec.rb @@ -20,7 +20,7 @@ fill_in("Username", :with => sample_username) click_on("Sign up") - within('nav') do + within("nav") do expect(page).to have_content(sample_username) end end @@ -44,15 +44,8 @@ fill_in("Current password", :with => user.password) click_on("Update") - within('nav') do + within("nav") do expect(page).to have_content(new_username) end end - - scenario "sign-in form modified with Bootstrap class", points: 1, hint: h("class_must_match") do - visit "/" - - expect(page).to have_selector(".form-group") - end - end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 454e5f3..17c2678 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -29,6 +29,8 @@ ActiveRecord::Migration.maintain_test_schema! RSpec.configure do |config| + config.backtrace_exclusion_patterns << /rvm/ + config.include FactoryBot::Syntax::Methods # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures"