+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class ApplicationController < ActionController::Base
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class DiscoverController < ApplicationController
+
+
+
+
+
-
+ 1
+
+
+
+
+
def index
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class LandingPageController < ApplicationController
+
+
+
+
+
-
+ 1
+
+
+
+
+
def index
+
+
+
+
+
-
+ 2
+
+
+
+
+
@users = User.all
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class MoviesController < ApplicationController
+
+
+
+
+
-
+ 1
+
+
+
+
+
def index
+
+
+
+
+
-
+ 4
+
+
+
+
+
@user = User.find(session[:user_id])
+
+
+
+
+
-
+ 4
+
+
+
+
+
if params[:search_by_movie_title]
+
+
+
+
+
-
+ 2
+
+
+
+
+
@movies = MovieFacade.search(params[:search_by_movie_title])
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+ 2
+
+
+
+
+
@movies = MovieFacade.top_rated_movies
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def show
+
+
+
+
+
-
+ 3
+
+
+
+
+
@user = User.find(session[:user_id])
+
+
+
+
+
-
+ 3
+
+
+
+
+
id = params[:id]
+
+
+
+
+
-
+ 3
+
+
+
+
+
@movie = MovieFacade.find_by_id(params[:id])
+
+
+
+
+
-
+ 3
+
+
+
+
+
@cast = MovieFacade.find_cast(params[:id]).first(10)
+
+
+
+
+
-
+ 3
+
+
+
+
+
@reviews = MovieFacade.find_reviews(params[:id])
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class UsersController < ApplicationController
+
+
+
+
+
-
+ 1
+
+
+
+
+
def show
+
+
+
+
+
-
+ 14
+
+
+
+
+
@user = User.find(params[:id])
+
+
+
+
+
-
+ 14
+
+
+
+
+
session[:user_id] = @user.id
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def new
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def create
+
+
+
+
+
-
+ 3
+
+
+
+
+
@user = User.new(name: params[:name], email: params[:email])
+
+
+
+
+
-
+ 3
+
+
+
+
+
if @user.save
+
+
+
+
+
-
+ 2
+
+
+
+
+
redirect_to user_path(@user)
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+ 1
+
+
+
+
+
render :new
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class ViewingPartiesController < ApplicationController
+
+
+
+
+
-
+ 1
+
+
+
+
+
def new
+
+
+
+
+
-
+ 1
+
+
+
+
+
@user = User.find_by_id(session[:user_id])
+
+
+
+
+
-
+ 1
+
+
+
+
+
@users = User.all
+
+
+
+
+
-
+ 1
+
+
+
+
+
id = params[:id]
+
+
+
+
+
-
+ 1
+
+
+
+
+
@movie = MovieFacade.find_by_id(params[:id])
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def create
+
+
+
+
+
-
+
+
+
+
+
+
@user = User.find_by_id(session[:user_id])
+
+
+
+
+
-
+
+
+
+
+
+
# if params[:duration].present? && params[:start_time].present? && params[:movie_id].present?
+
+
+
+
+
-
+
+
+
+
+
+
# @user.viewingparty.create(movie_title: params[:name]
+
+
+
+
+
-
+
+
+
+
+
+
# description:params[:description]
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class MovieFacade
+
+
+
+
+
-
+ 1
+
+
+
+
+
attr_reader :movie_details, :url, :movie_id
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def initialize(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
@movie_id = movie_id
+
+
+
+
+
-
+ 1
+
+
+
+
+
@url = 'https://api.themoviedb.org'
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.top_rated_movies
+
+
+
+
+
-
+ 3
+
+
+
+
+
conn = Faraday.new(url: 'https://api.themoviedb.org') do |faraday|
+
+
+
+
+
-
+ 3
+
+
+
+
+
faraday.params['api_key'] = Rails.application.credentials.api_key
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
response = conn.get("/3/movie/top_rated")
+
+
+
+
+
-
+ 3
+
+
+
+
+
json = JSON.parse(response.body, symbolize_names: true)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
if json[:results].present?
+
+
+
+
+
-
+ 3
+
+
+
+
+
@movies = json[:results].map do |movie_data|
+
+
+
+
+
-
+ 60
+
+
+
+
+
Movie.new(movie_data)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+
+
+
+
+
+
@movies = []
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
@movies
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.search(search_string)
+
+
+
+
+
-
+ 3
+
+
+
+
+
conn = Faraday.new(url: 'https://api.themoviedb.org') do |faraday|
+
+
+
+
+
-
+ 3
+
+
+
+
+
faraday.params['api_key'] = Rails.application.credentials.api_key
+
+
+
+
+
-
+ 3
+
+
+
+
+
faraday.params['query'] = search_string
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
response = conn.get("/3/search/movie")
+
+
+
+
+
-
+ 3
+
+
+
+
+
json = JSON.parse(response.body, symbolize_names: true)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
if json[:results].present?
+
+
+
+
+
-
+ 3
+
+
+
+
+
@movies = json[:results].map do |movie_data|
+
+
+
+
+
-
+ 60
+
+
+
+
+
Movie.new(movie_data)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+
+
+
+
+
+
@movies = []
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 3
+
+
+
+
+
@movies
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.find_by_id(id)
+
+
+
+
+
-
+ 5
+
+
+
+
+
conn = Faraday.new(url: 'https://api.themoviedb.org') do |faraday|
+
+
+
+
+
-
+ 5
+
+
+
+
+
faraday.params['api_key'] = Rails.application.credentials.api_key
+
+
+
+
+
-
+ 5
+
+
+
+
+
faraday.params['movie_id'] = id
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 5
+
+
+
+
+
response = conn.get("/3/movie/#{id}")
+
+
+
+
+
-
+ 5
+
+
+
+
+
json = JSON.parse(response.body, symbolize_names: true)
+
+
+
+
+
-
+ 5
+
+
+
+
+
Movie.new(json)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.find_cast(id)
+
+
+
+
+
-
+ 4
+
+
+
+
+
conn = Faraday.new(url: 'https://api.themoviedb.org') do |faraday|
+
+
+
+
+
-
+ 4
+
+
+
+
+
faraday.params['api_key'] = Rails.application.credentials.api_key
+
+
+
+
+
-
+ 4
+
+
+
+
+
faraday.params['movie_id'] = id
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+ 4
+
+
+
+
+
response = conn.get("/3/movie/#{id}/credits")
+
+
+
+
+
-
+ 4
+
+
+
+
+
json = JSON.parse(response.body, symbolize_names: true)
+
+
+
+
+
-
+ 4
+
+
+
+
+
json[:cast].map do |cast_member|
+
+
+
+
+
-
+ 16
+
+
+
+
+
CastMember.new(cast_member)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.find_reviews(id)
+
+
+
+
+
-
+ 4
+
+
+
+
+
conn = Faraday.new(url: 'https://api.themoviedb.org') do |faraday|
+
+
+
+
+
-
+ 4
+
+
+
+
+
faraday.params['api_key'] = Rails.application.credentials.api_key
+
+
+
+
+
-
+ 4
+
+
+
+
+
faraday.params['movie_id'] = id
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+ 4
+
+
+
+
+
response = conn.get("/3/movie/#{id}/reviews")
+
+
+
+
+
-
+ 4
+
+
+
+
+
json = JSON.parse(response.body, symbolize_names: true)
+
+
+
+
+
-
+ 4
+
+
+
+
+
json[:results].map do |review|
+
+
+
+
+
-
+ 8
+
+
+
+
+
Review.new(review)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
module ApplicationHelper
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
module LandingPageHelper
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class ApplicationRecord < ActiveRecord::Base
+
+
+
+
+
-
+ 1
+
+
+
+
+
primary_abstract_class
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class User < ApplicationRecord
+
+
+
+
+
-
+ 1
+
+
+
+
+
validates_presence_of :name, :email
+
+
+
+
+
-
+ 1
+
+
+
+
+
validates :email, uniqueness: { case_sensitive: false }
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
has_many :user_viewing_parties
+
+
+
+
+
-
+ 1
+
+
+
+
+
has_many :viewing_parties, through: :user_viewing_parties
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class UserViewingParty < ApplicationRecord
+
+
+
+
+
-
+ 1
+
+
+
+
+
belongs_to :user
+
+
+
+
+
-
+ 1
+
+
+
+
+
belongs_to :viewing_party
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class ViewingParty < ApplicationRecord
+
+
+
+
+
-
+ 1
+
+
+
+
+
validates_presence_of :movie_title, :movie_image, :start_time
+
+
+
+
+
-
+ 1
+
+
+
+
+
validates_numericality_of :movie_id, :duration
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
has_many :user_viewing_parties
+
+
+
+
+
-
+ 1
+
+
+
+
+
has_many :users, through: :user_viewing_parties
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class CastMember
+
+
+
+
+
-
+ 1
+
+
+
+
+
attr_reader :name, :character
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def initialize(member_data)
+
+
+
+
+
-
+ 17
+
+
+
+
+
@name = member_data[:name]
+
+
+
+
+
-
+ 17
+
+
+
+
+
@character = member_data[:character]
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class Movie
+
+
+
+
+
-
+ 1
+
+
+
+
+
attr_reader :title, :vote_average, :runtime, :genres, :summary, :id
+
+
+
+
+
-
+ 1
+
+
+
+
+
attr_accessor :cast, :reviews
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def initialize(movie_data)
+
+
+
+
+
-
+ 138
+
+
+
+
+
@title = movie_data[:original_title]
+
+
+
+
+
-
+ 138
+
+
+
+
+
@vote_average = movie_data[:vote_average]
+
+
+
+
+
-
+ 138
+
+
+
+
+
@runtime = movie_data[:runtime]
+
+
+
+
+
-
+ 138
+
+
+
+
+
@genres = parse_genres(movie_data[:genres])
+
+
+
+
+
-
+ 138
+
+
+
+
+
@summary = movie_data[:overview]
+
+
+
+
+
-
+ 138
+
+
+
+
+
@id = movie_data[:id]
+
+
+
+
+
-
+ 138
+
+
+
+
+
@cast = []
+
+
+
+
+
-
+ 138
+
+
+
+
+
@reviews = []
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def parse_genres(genres)
+
+
+
+
+
-
+ 141
+
+
+
+
+
if genres.nil?
+
+
+
+
+
-
+ 123
+
+
+
+
+
'N/A'
+
+
+
+
+
-
+ 18
+
+
+
+
+
elsif genres.first.is_a?(Hash)
+
+
+
+
+
-
+ 51
+
+
+
+
+
genres.map { |genre| genre[:name] }.join(', ')
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+ 1
+
+
+
+
+
genres.join(', ')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.all
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.from_api_response(movie_data)
+
+
+
+
+
-
+
+
+
+
+
+
Movie.new(
+
+
+
+
+
-
+
+
+
+
+
+
title: movie_data[:original_title],
+
+
+
+
+
-
+
+
+
+
+
+
vote_average: movie_data[:vote_average],
+
+
+
+
+
-
+
+
+
+
+
+
runtime: movie_data[:runtime],
+
+
+
+
+
-
+
+
+
+
+
+
genres: movie_data[:genres],
+
+
+
+
+
-
+
+
+
+
+
+
summary: movie_data[:overview],
+
+
+
+
+
-
+
+
+
+
+
+
id: movie_data[:id]
+
+
+
+
+
-
+
+
+
+
+
+
)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def add_cast(member)
+
+
+
+
+
-
+ 1
+
+
+
+
+
@cast << member
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def add_review(review)
+
+
+
+
+
-
+ 1
+
+
+
+
+
@reviews << review
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def formatted_runtime
+
+
+
+
+
-
+ 4
+
+
+
+
+
return 'N/A' if @runtime.nil?
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 4
+
+
+
+
+
total_minutes = @runtime
+
+
+
+
+
-
+ 4
+
+
+
+
+
hours = total_minutes / 60
+
+
+
+
+
-
+ 4
+
+
+
+
+
minutes = total_minutes % 60
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 4
+
+
+
+
+
if hours.positive? && minutes.positive?
+
+
+
+
+
-
+ 1
+
+
+
+
+
"#{hours} hours #{minutes} minutes"
+
+
+
+
+
-
+ 3
+
+
+
+
+
elsif hours.positive?
+
+
+
+
+
-
+ 1
+
+
+
+
+
"#{hours} hours"
+
+
+
+
+
-
+
+
+
+
+
+
else
+
+
+
+
+
-
+ 2
+
+
+
+
+
"#{minutes} minutes"
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
class Review
+
+
+
+
+
-
+ 1
+
+
+
+
+
attr_accessor :author, :username, :content
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def initialize(data)
+
+
+
+
+
-
+ 11
+
+
+
+
+
@author = data[:author]
+
+
+
+
+
-
+ 11
+
+
+
+
+
@username = data[:author_details][:username]
+
+
+
+
+
-
+ 11
+
+
+
+
+
@content = data[:content]
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
def self.from_api_response(response)
+
+
+
+
+
-
+ 2
+
+
+
+
+
reviews_data = response['results']
+
+
+
+
+
-
+ 4
+
+
+
+
+
reviews_data.map { |data| new(data) }
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require_relative 'boot'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails'
+
+
+
+
+
-
+
+
+
+
+
+
# Pick the frameworks you want:
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'active_model/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'active_job/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'active_record/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'active_storage/engine'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_controller/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_mailer/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_mailbox/engine'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_text/engine'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_view/railtie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'action_cable/engine'
+
+
+
+
+
-
+
+
+
+
+
+
# require "rails/test_unit/railtie"
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Require the gems listed in Gemfile, including any gems
+
+
+
+
+
-
+
+
+
+
+
+
# you've limited to :test, :development, or :production.
+
+
+
+
+
-
+ 1
+
+
+
+
+
Bundler.require(*Rails.groups)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
module ViewingPartyLite7
+
+
+
+
+
-
+ 1
+
+
+
+
+
class Application < Rails::Application
+
+
+
+
+
-
+
+
+
+
+
+
# Initialize configuration defaults for originally generated Rails version.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.load_defaults 7.0
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Configuration for the application, engines, and railties goes here.
+
+
+
+
+
-
+
+
+
+
+
+
#
+
+
+
+
+
-
+
+
+
+
+
+
# These settings can be overridden in specific environments using the files
+
+
+
+
+
-
+
+
+
+
+
+
# in config/environments, which are processed later.
+
+
+
+
+
-
+
+
+
+
+
+
#
+
+
+
+
+
-
+
+
+
+
+
+
# config.time_zone = "Central Time (US & Canada)"
+
+
+
+
+
-
+
+
+
+
+
+
# config.eager_load_paths << Rails.root.join("extras")
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Don't generate system test files.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.generators.system_tests = nil
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'bundler/setup' # Set up gems listed in the Gemfile.
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'bootsnap/setup' # Speed up boot time by caching expensive operations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Load the Rails application.
+
+
+
+
+
-
+ 1
+
+
+
+
+
require_relative 'application'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Initialize the Rails application.
+
+
+
+
+
-
+ 1
+
+
+
+
+
Rails.application.initialize!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'active_support/core_ext/integer/time'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# The test environment is used exclusively to run your application's
+
+
+
+
+
-
+
+
+
+
+
+
# test suite. You never need to work with it otherwise. Remember that
+
+
+
+
+
-
+
+
+
+
+
+
# your test database is "scratch space" for the test suite and is wiped
+
+
+
+
+
-
+
+
+
+
+
+
# and recreated between test runs. Don't rely on the data there!
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
Rails.application.configure do
+
+
+
+
+
-
+
+
+
+
+
+
# Settings specified here will take precedence over those in config/application.rb.
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Turn false under Spring and add config.action_view.cache_template_loading = true.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.cache_classes = true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Eager loading loads your whole application. When running a single test locally,
+
+
+
+
+
-
+
+
+
+
+
+
# this probably isn't necessary. It's a good idea to do in a continuous integration
+
+
+
+
+
-
+
+
+
+
+
+
# system, or in some way before deploying your code.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.eager_load = ENV['CI'].present?
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Configure public file server for tests with Cache-Control for performance.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.public_file_server.enabled = true
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.public_file_server.headers = {
+
+
+
+
+
-
+
+
+
+
+
+
'Cache-Control' => "public, max-age=#{1.hour.to_i}"
+
+
+
+
+
-
+
+
+
+
+
+
}
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Show full error reports and disable caching.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.consider_all_requests_local = true
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.action_controller.perform_caching = false
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.cache_store = :null_store
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Raise exceptions instead of rendering exception templates.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.action_dispatch.show_exceptions = false
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Disable request forgery protection in test environment.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.action_controller.allow_forgery_protection = false
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Store uploaded files on the local file system in a temporary directory.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.active_storage.service = :test
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.action_mailer.perform_caching = false
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Tell Action Mailer not to deliver emails to the real world.
+
+
+
+
+
-
+
+
+
+
+
+
# The :test delivery method accumulates sent emails in the
+
+
+
+
+
-
+
+
+
+
+
+
# ActionMailer::Base.deliveries array.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.action_mailer.delivery_method = :test
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Print deprecation notices to the stderr.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.active_support.deprecation = :stderr
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Raise exceptions for disallowed deprecations.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.active_support.disallowed_deprecation = :raise
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Tell Active Support which deprecation messages to disallow.
+
+
+
+
+
-
+ 1
+
+
+
+
+
config.active_support.disallowed_deprecation_warnings = []
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Raises error for missing translations.
+
+
+
+
+
-
+
+
+
+
+
+
# config.i18n.raise_on_missing_translations = true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Annotate rendered view with file names.
+
+
+
+
+
-
+
+
+
+
+
+
# config.action_view.annotate_rendered_view_with_filenames = true
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Be sure to restart your server when you modify this file.
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Version of your assets, change this if you want to expire all your assets.
+
+
+
+
+
-
+ 1
+
+
+
+
+
Rails.application.config.assets.version = '1.0'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Add additional assets to the asset load path.
+
+
+
+
+
-
+
+
+
+
+
+
# Rails.application.config.assets.paths << Emoji.images_path
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Precompile additional assets.
+
+
+
+
+
-
+
+
+
+
+
+
# application.js, application.css, and all non-JS/CSS in the app/assets
+
+
+
+
+
-
+
+
+
+
+
+
# folder are already added.
+
+
+
+
+
-
+
+
+
+
+
+
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
# Be sure to restart your server when you modify this file.
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Define an application-wide content security policy.
+
+
+
+
+
-
+
+
+
+
+
+
# See the Securing Rails Applications Guide for more information:
+
+
+
+
+
-
+
+
+
+
+
+
# https://guides.rubyonrails.org/security.html#content-security-policy-header
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Rails.application.configure do
+
+
+
+
+
-
+
+
+
+
+
+
# config.content_security_policy do |policy|
+
+
+
+
+
-
+
+
+
+
+
+
# policy.default_src :self, :https
+
+
+
+
+
-
+
+
+
+
+
+
# policy.font_src :self, :https, :data
+
+
+
+
+
-
+
+
+
+
+
+
# policy.img_src :self, :https, :data
+
+
+
+
+
-
+
+
+
+
+
+
# policy.object_src :none
+
+
+
+
+
-
+
+
+
+
+
+
# policy.script_src :self, :https
+
+
+
+
+
-
+
+
+
+
+
+
# policy.style_src :self, :https
+
+
+
+
+
-
+
+
+
+
+
+
# # Specify URI for violation reports
+
+
+
+
+
-
+
+
+
+
+
+
# # policy.report_uri "/csp-violation-report-endpoint"
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
-
+
+
+
+
+
+
#
+
+
+
+
+
-
+
+
+
+
+
+
# # Generate session nonces for permitted importmap and inline scripts
+
+
+
+
+
-
+
+
+
+
+
+
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
+
+
+
+
+
-
+
+
+
+
+
+
# config.content_security_policy_nonce_directives = %w(script-src)
+
+
+
+
+
-
+
+
+
+
+
+
#
+
+
+
+
+
-
+
+
+
+
+
+
# # Report violations without enforcing the policy.
+
+
+
+
+
-
+
+
+
+
+
+
# # config.content_security_policy_report_only = true
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Be sure to restart your server when you modify this file.
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Configure parameters to be filtered from the log file. Use this to limit dissemination of
+
+
+
+
+
-
+
+
+
+
+
+
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
+
+
+
+
+
-
+
+
+
+
+
+
# notations and behaviors.
+
+
+
+
+
-
+ 1
+
+
+
+
+
Rails.application.config.filter_parameters += %i[
+
+
+
+
+
-
+
+
+
+
+
+
passw secret token _key crypt salt certificate otp ssn
+
+
+
+
+
-
+
+
+
+
+
+
]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
# Be sure to restart your server when you modify this file.
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Add new inflection rules using the following format. Inflections
+
+
+
+
+
-
+
+
+
+
+
+
# are locale specific, and you may define rules for as many different
+
+
+
+
+
-
+
+
+
+
+
+
# locales as you wish. All of these examples are active by default:
+
+
+
+
+
-
+
+
+
+
+
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
+
+
+
+
+
-
+
+
+
+
+
+
# inflect.plural /^(ox)$/i, "\\1en"
+
+
+
+
+
-
+
+
+
+
+
+
# inflect.singular /^(ox)en/i, "\\1"
+
+
+
+
+
-
+
+
+
+
+
+
# inflect.irregular "person", "people"
+
+
+
+
+
-
+
+
+
+
+
+
# inflect.uncountable %w( fish sheep )
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# These inflection rules are supported but not enabled by default:
+
+
+
+
+
-
+
+
+
+
+
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
+
+
+
+
+
-
+
+
+
+
+
+
# inflect.acronym "RESTful"
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
# Define an application-wide HTTP permissions policy. For further
+
+
+
+
+
-
+
+
+
+
+
+
# information see https://developers.google.com/web/updates/2018/06/feature-policy
+
+
+
+
+
-
+
+
+
+
+
+
#
+
+
+
+
+
-
+
+
+
+
+
+
# Rails.application.config.permissions_policy do |f|
+
+
+
+
+
-
+
+
+
+
+
+
# f.camera :none
+
+
+
+
+
-
+
+
+
+
+
+
# f.gyroscope :none
+
+
+
+
+
-
+
+
+
+
+
+
# f.microphone :none
+
+
+
+
+
-
+
+
+
+
+
+
# f.usb :none
+
+
+
+
+
-
+
+
+
+
+
+
# f.fullscreen :self
+
+
+
+
+
-
+
+
+
+
+
+
# f.payment :self, "https://secure.example.com"
+
+
+
+
+
-
+
+
+
+
+
+
# end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# frozen_string_literal: true
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
Rails.application.routes.draw do
+
+
+
+
+
-
+
+
+
+
+
+
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# Defines the root path route ("/")
+
+
+
+
+
-
+
+
+
+
+
+
# root "articles#index"
+
+
+
+
+
-
+ 1
+
+
+
+
+
root to: 'landing_page#index'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
resources :users, only: %i[show new create] do
+
+
+
+
+
-
+ 1
+
+
+
+
+
resources :discover, only: [:index]
+
+
+
+
+
-
+ 1
+
+
+
+
+
resources :movies, only: [:index, :show] do
+
+
+
+
+
-
+ 1
+
+
+
+
+
resources :viewing_parties
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe MovieFacade do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 6
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/search/movie?api_key=#{Rails.application.credentials.api_key}&query=Star%20Wars").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/search_movie_results.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 6
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/top_rated?api_key=#{Rails.application.credentials.api_key}").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_results.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 6
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/123?api_key=#{Rails.application.credentials.api_key}&movie_id=123").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 6
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/123/credits?api_key=#{Rails.application.credentials.api_key}&movie_id=123").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_cast.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 6
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/123/reviews?api_key=#{Rails.application.credentials.api_key}&movie_id=123").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/reviews.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'initialize' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'exists' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_id = 123
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_facade = MovieFacade.new(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(MovieFacade).to be_a(Class)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie_facade.movie_id).to eq(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie_facade.url).to eq('https://api.themoviedb.org')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe '.top_rated_movies' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns an array of top-rated movies' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movies = MovieFacade.top_rated_movies
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies).not_to be_empty
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies.first).to be_a(Movie)
+
+
+
+
+
-
+ 21
+
+
+
+
+
expect(movies.all? { |movie| movie.is_a?(Movie)}).to be_truthy
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe '.search' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns an array of movies matching the search query' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
query = 'Star Wars'
+
+
+
+
+
-
+ 1
+
+
+
+
+
movies = MovieFacade.search(query)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies).not_to be_empty
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movies.first).to be_a(Movie)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe '.find_by_id' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns a movie by its ID' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_id = 123
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie = MovieFacade.find_by_id(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie).to be_a(Movie)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe '.find_cast' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns an array of cast members for a movie by its ID' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_id = 123
+
+
+
+
+
-
+ 1
+
+
+
+
+
cast = MovieFacade.find_cast(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(cast).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(cast.first).to be_a(CastMember)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe '.find_reviews' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns an array of reviews for a movie by its ID' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_id = 123
+
+
+
+
+
-
+ 1
+
+
+
+
+
reviews = MovieFacade.find_reviews(movie_id)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews.first).to be_a(Review)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe 'Discover Movies Page' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u1 = User.create!(name: 'Brian', email: 'brian@brian.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u2 = User.create!(name: 'Lorien', email: 'lorienlorienl.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u3 = User.create!(name: 'Rachel', email: 'rachel@rachel.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
visit user_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'has a button to discover movies' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/top_rated?api_key=#{Rails.application.credentials.api_key}").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_results.json"), headers: {})
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_discover_index_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
within('#top_movies') do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_button('Discover Top Rated Movies')
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Discover Top Rated Movies'
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq user_movies_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'has a search field to search by movie title' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/search/movie?api_key=#{Rails.application.credentials.api_key}&query=Barbie").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200,body: File.read("spec/features/fixtures/search_movie_results.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_discover_index_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
within('#movie_search') do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_field('Search By Movie Title')
+
+
+
+
+
-
+ 1
+
+
+
+
+
fill_in 'Search By Movie Title', with: 'Barbie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Search'
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq user_movies_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe 'landing page', type: :feature do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'landing page has title, new user button, and links' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
u1 = User.create!(name: 'Sean', email: 'championlyfe@gmail.com')
+
+
+
+
+
-
+ 1
+
+
+
+
+
u2 = User.create!(name: 'Volk', email: 'primeathlete@gmail.com')
+
+
+
+
+
-
+ 1
+
+
+
+
+
u3 = User.create!(name: 'Izzy', email: 'animeever@gmail.com')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit root_path
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Viewing Party Lite')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_button('New User')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link('Landing Page')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
within('#users') do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link(u1.name.to_s)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link(u2.name.to_s)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link(u3.name.to_s)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_link(u1.name.to_s)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq(user_path(u1))
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_link('Landing Page')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq(root_path)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button('New User')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq(new_user_path)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe 'Movie Details Page', type: :feature do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 3
+
+
+
+
+
@u1 = User.create!(name: 'Tim', email: 'tim@brayn10.com')
+
+
+
+
+
-
+ 3
+
+
+
+
+
visit user_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'displays movie details by id and buttons' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5142?api_key=#{Rails.application.credentials.api_key}&movie_id=5142").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5142/credits?api_key=#{Rails.application.credentials.api_key}&movie_id=5142").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_cast.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5142/reviews?api_key=#{Rails.application.credentials.api_key}&movie_id=5142").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/reviews.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_movie_path(user_id: @u1.id, id: 5142)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Movie Title: Santo')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Vote Average: 6.114')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Runtime: 95')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Genre(s): Horror, Action')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Summary description: Innocent')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "displays the first 10 cast members" do
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124/credits?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_cast.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124/reviews?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/reviews.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_movie_path(user_id: @u1.id, id: 5124)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Cast')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Actor Name: Anup Jagdale')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Charater Name: Bob Jagdale')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page.all('li').count).to be <= 10
+
+
+
+
+
-
+
+
+
+
+
+
# expect(page).to have_link('Create a Viewing Party')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link('Return to Discover Page')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "can display the total number of reviews, and each reviews author and information" do
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124/credits?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_cast.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/5124/reviews?api_key=#{Rails.application.credentials.api_key}&movie_id=5124").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/reviews.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_movie_path(user_id: @u1.id, id: 5124)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Total Reviews')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Author: MovieGuys')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Author Username: MovieGuys')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Content: Anyone remember the little')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page.all('li').count).to be <= 1000
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe 'Movies Results Page', type: :feature do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u1 = User.create!(name: 'Brian', email: 'brian@brian.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u2 = User.create!(name: 'Lorien', email: 'lorien@lorien.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
@u3 = User.create!(name: 'Rachel', email: 'rachel@rachel.com')
+
+
+
+
+
-
+ 2
+
+
+
+
+
@movie1 = Movie.new(title: 'Movie Title 1', vote_average: 9.5, runtime: 100, api_id: 1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'displays top-rated movie results and a return button' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/top_rated?api_key=#{Rails.application.credentials.api_key}").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_results.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Discover Movies'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_current_path(user_discover_index_path(@u1.id))
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Discover Top Rated Movies'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq(user_movies_path(@u1.id))
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link('Return to Discover Page', href: user_discover_index_path(user_id: @u1.id))
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "can search for movies by title and have a return button" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/search/movie?api_key=#{Rails.application.credentials.api_key}&query=Barbie").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/search_movie_results.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Discover Movies'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_current_path(user_discover_index_path(@u1.id))
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
fill_in 'Search By Movie Title', with: 'Barbie'
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button 'Search'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq(user_movies_path(@u1.id))
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Barbie')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('Vote Average')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content('7.3')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_link('Return to Discover Page', href: user_discover_index_path(user_id: @u1.id))
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe "User Show Page/ Dashboard" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 3
+
+
+
+
+
@u1 = User.create!(name: 'Brian', email: 'brian@brian.com')
+
+
+
+
+
-
+ 3
+
+
+
+
+
@u2 = User.create!(name: 'Lorien', email: 'lorienlorienl.com')
+
+
+
+
+
-
+ 3
+
+
+
+
+
@u3 = User.create!(name: 'Rachel', email: 'rachel@rachel.com')
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
# @vp1 = @u1.viewingparties.create!(title: "Movie 1", movie_id: 1, movie_image:,duration: 119, date: "10-31-2023", start_time: "09:00" )
+
+
+
+
+
-
+
+
+
+
+
+
# @vp2 = @u1.viewingparties.create!(title: "Movie 2", movie_id: 2, movie_image:,duration: 100, date: "11-13-2023", start_time: "13:00" )
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "shows the User's information on the page" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_path(@u1)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content("Brian's Dashboard")
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content("brian@brian.com")
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to_not have_content("Rachel's Dashboard")
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to_not have_content("rachel@rachel.com")
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "has a section for the viewing parties that a user has signed up for" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_path(@u2)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
within("#viewing_parties") do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content("My Viewing Parties")
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it "has a button to take the user to discover movies" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit user_path(@u3)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_button("Discover Movies")
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
click_button "Discover Movies"
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(current_path).to eq user_discover_index_path(@u3)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require "rails_helper"
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe "New Viewing Party Page" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
before :each do
+
+
+
+
+
-
+ 1
+
+
+
+
+
@user1 = User.create!(name: "Haley M", email: "haley@haley.com")
+
+
+
+
+
-
+ 1
+
+
+
+
+
@user2 = User.create!(name: "Camila T", email: "camila@camila.com")
+
+
+
+
+
-
+ 1
+
+
+
+
+
@user3 = User.create!(name: "Rachel V", email: "rachel@rachel.com")
+
+
+
+
+
-
+ 1
+
+
+
+
+
@user4 = User.create!(name: "Bret M", email: "bret@bret.com")
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'the new viewing party form' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'has all the proper fields to create a new viewing party' do
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/3214?api_key=#{Rails.application.credentials.api_key}&movie_id=3214").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/3214/credits?api_key=#{Rails.application.credentials.api_key}&movie_id=3214").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_cast.json"), headers: {})
+
+
+
+
+
-
+ 1
+
+
+
+
+
stub_request(:get, "https://api.themoviedb.org/3/movie/?api_key=#{Rails.application.credentials.api_key}&movie_id").
+
+
+
+
+
-
+
+
+
+
+
+
to_return(status: 200, body: File.read("spec/features/fixtures/movie_details.json"), headers: {})
+
+
+
+
+
-
+ 1
+
+
+
+
+
visit new_user_movie_viewing_party_path(user_id: @user1.id, movie_id: 3214)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_content("Movie Title: Santo")
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
within(".new_party") do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_field('Duration', with: "95 minutes")
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_field :start_time
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_unchecked_field('Camila T')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_unchecked_field('Rachel V')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_unchecked_field('Bret M')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(page).to have_button('Create Party')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe User, type: :model do
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "validations" do
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_presence_of :name }
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_presence_of :email}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_uniqueness_of(:email).case_insensitive}
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "relationships" do
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should have_many(:user_viewing_parties) }
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should have_many(:viewing_parties).through(:user_viewing_parties) }
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe UserViewingParty, type: :model do
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "relationships" do
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should belong_to :user}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should belong_to :viewing_party}
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe ViewingParty, type: :model do
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "validations" do
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_presence_of :movie_title}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_numericality_of :movie_id}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_presence_of :movie_image}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_numericality_of :duration}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should validate_presence_of :start_time}
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "relationships" do
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should have_many :user_viewing_parties}
+
+
+
+
+
-
+ 2
+
+
+
+
+
it { should have_many(:users).through(:user_viewing_parties)}
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe CastMember do
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'initialize' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'sets attributes correctly' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
member_data = { name: 'John Smith', character: 'Character 1' }
+
+
+
+
+
-
+ 1
+
+
+
+
+
cast_member = CastMember.new(member_data)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(cast_member.name).to eq('John Smith')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(cast_member.character).to eq('Character 1')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe Movie do
+
+
+
+
+
-
+ 1
+
+
+
+
+
let(:movie_data) do
+
+
+
+
+
-
+
+
+
+
+
+
{
+
+
+
+
+
-
+ 11
+
+
+
+
+
original_title: 'Test Movie',
+
+
+
+
+
-
+
+
+
+
+
+
vote_average: 7.5,
+
+
+
+
+
-
+
+
+
+
+
+
runtime: 120,
+
+
+
+
+
-
+
+
+
+
+
+
genres: [{ name: 'Drama' }, { name: 'Action' }],
+
+
+
+
+
-
+
+
+
+
+
+
overview: 'A test movie overview',
+
+
+
+
+
-
+
+
+
+
+
+
id: 1
+
+
+
+
+
-
+
+
+
+
+
+
}
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 9
+
+
+
+
+
let(:movie) { Movie.new(movie_data) }
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'initialization' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'correctly initializes movie attributes' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.title).to eq('Test Movie')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.vote_average).to eq(7.5)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.runtime).to eq(120)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.genres).to eq('Drama, Action')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.summary).to eq('A test movie overview')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.id).to eq(1)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.cast).to be_empty
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.reviews).to be_empty
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'formatted_runtime' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'returns a formatted runtime' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.formatted_runtime).to eq('2 hours')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'handles zero minutes' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_with_zero_minutes = Movie.new(movie_data.merge(runtime: 120 - 30))
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie_with_zero_minutes.formatted_runtime).to eq('1 hours 30 minutes')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'handles zero hours' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_with_zero_hours = Movie.new(movie_data.merge(runtime: 30))
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie_with_zero_hours.formatted_runtime).to eq('30 minutes')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'handles zero hours and zero minutes' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie_with_no_runtime = Movie.new(movie_data.merge(runtime: 0))
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie_with_no_runtime.formatted_runtime).to eq('0 minutes')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'parse_genres' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'correctly parses genres from an array of hashes' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
genres = movie.parse_genres([{ name: 'Adventure' }, { name: 'Comedy' }])
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(genres).to eq('Adventure, Comedy')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'correctly parses genres from an array of strings' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
genres = movie.parse_genres(['Action', 'Thriller'])
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(genres).to eq('Action, Thriller')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'handles nil genres' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
genres = movie.parse_genres(nil)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(genres).to eq('N/A')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'add_cast' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'adds a cast member to the movie' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
actor = 'Test Actor'
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie.add_cast(actor)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.cast).to include(actor)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'add_review' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'adds a review to the movie' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
review = 'A great test review'
+
+
+
+
+
-
+ 1
+
+
+
+
+
movie.add_review(review)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.reviews).to include(review)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe "creates ojbect from API data" do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'creates a movie from an API response' do
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.title).to eq('Test Movie')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.vote_average).to eq(7.5)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.runtime).to eq(120)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.genres).to eq('Drama, Action')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.summary).to eq('A test movie overview')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(movie.id).to eq(1)
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'rails_helper'
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
RSpec.describe Review do
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'initialize' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'sets attributes correctly' do
+
+
+
+
+
-
+
+
+
+
+
+
data = {
+
+
+
+
+
-
+ 1
+
+
+
+
+
author: 'John Doe',
+
+
+
+
+
-
+
+
+
+
+
+
author_details: { username: 'johndoe123' },
+
+
+
+
+
-
+
+
+
+
+
+
content: 'A great movie!',
+
+
+
+
+
-
+
+
+
+
+
+
}
+
+
+
+
+
-
+ 1
+
+
+
+
+
review = Review.new(data)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(review.author).to eq('John Doe')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(review.username).to eq('johndoe123')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(review.content).to eq('A great movie!')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
describe 'from_api_response' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'creates an array of reviews from API response' do
+
+
+
+
+
-
+
+
+
+
+
+
response_data = {
+
+
+
+
+
-
+ 1
+
+
+
+
+
'results' => [
+
+
+
+
+
-
+
+
+
+
+
+
{
+
+
+
+
+
-
+
+
+
+
+
+
author: 'User1',
+
+
+
+
+
-
+
+
+
+
+
+
author_details: { username: 'user1' },
+
+
+
+
+
-
+
+
+
+
+
+
content: 'Review 1',
+
+
+
+
+
-
+
+
+
+
+
+
},
+
+
+
+
+
-
+
+
+
+
+
+
{
+
+
+
+
+
-
+
+
+
+
+
+
author: 'User2',
+
+
+
+
+
-
+
+
+
+
+
+
author_details: { username: 'user2' },
+
+
+
+
+
-
+
+
+
+
+
+
content: 'Review 2',
+
+
+
+
+
-
+
+
+
+
+
+
},
+
+
+
+
+
-
+
+
+
+
+
+
],
+
+
+
+
+
-
+
+
+
+
+
+
}
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
reviews = Review.from_api_response(response_data)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews.size).to eq(2)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews[0]).to be_a(Review)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews[0].author).to eq('User1')
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews[1]).to be_a(Review)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews[1].content).to eq('Review 2')
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
it 'handles empty API response' do
+
+
+
+
+
-
+ 1
+
+
+
+
+
response_data = { 'results' => [] }
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
reviews = Review.from_api_response(response_data)
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews).to be_an(Array)
+
+
+
+
+
-
+ 1
+
+
+
+
+
expect(reviews).to be_empty
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
-
+
+
+
+
+
+
end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ 1
+
+
+
+
+
require 'webmock/rspec'
+
+
+
+
+
+
+
+
+