diff --git a/Gemfile b/Gemfile
index 34592153c..48524607b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -47,6 +47,8 @@ gem "bootsnap", require: false
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
+gem 'faraday'
+gem 'figaro'
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
@@ -71,4 +73,5 @@ group :test do
gem "launchy"
gem "shoulda-matchers"
gem "simplecov"
+ gem 'webmock'
end
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index a422d9e54..6af843340 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -69,6 +69,7 @@ GEM
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
+ base64 (0.2.0)
bcrypt (3.1.20)
bindex (0.8.1)
bootsnap (1.17.0)
@@ -85,13 +86,23 @@ GEM
xpath (~> 3.2)
coderay (1.1.3)
concurrent-ruby (1.2.2)
+ crack (0.4.5)
+ rexml
crass (1.0.6)
date (3.3.4)
diff-lcs (1.5.0)
docile (1.4.0)
erubi (1.12.0)
+ faraday (2.7.12)
+ base64
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.2)
+ figaro (1.2.0)
+ thor (>= 0.14.0, < 2)
globalid (1.2.1)
activesupport (>= 6.1)
+ hashdiff (1.0.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
importmap-rails (1.2.3)
@@ -216,6 +227,7 @@ GEM
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (1.13.0)
+ ruby2_keywords (0.0.5)
shoulda-matchers (5.3.0)
activesupport (>= 5.2.0)
simplecov (0.22.0)
@@ -247,6 +259,10 @@ GEM
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
+ webmock (3.19.1)
+ addressable (>= 2.8.0)
+ crack (>= 0.3.2)
+ hashdiff (>= 0.4.0, < 2.0.0)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -262,6 +278,8 @@ DEPENDENCIES
bcrypt (~> 3.1.7)
bootsnap
capybara
+ faraday
+ figaro
importmap-rails
jbuilder
launchy
@@ -278,6 +296,7 @@ DEPENDENCIES
turbo-rails
tzinfo-data
web-console
+ webmock
RUBY VERSION
ruby 3.2.2p53
diff --git a/app/controllers/discover_controller.rb b/app/controllers/discover_controller.rb
new file mode 100644
index 000000000..6ef137b41
--- /dev/null
+++ b/app/controllers/discover_controller.rb
@@ -0,0 +1,5 @@
+class DiscoverController < ApplicationController
+ def index
+
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/movies_controller.rb b/app/controllers/movies_controller.rb
new file mode 100644
index 000000000..b1575e12a
--- /dev/null
+++ b/app/controllers/movies_controller.rb
@@ -0,0 +1,18 @@
+class MoviesController < ApplicationController
+ def index
+ if params[:Movie_Title].present?
+ facade = MovieFacade.new
+ @results = facade.search_movies(params[:Movie_Title])
+ else
+ facade = MovieFacade.new
+ @results = facade.top_movies
+ end
+ end
+
+ def show
+ facade = MovieFacade.new
+ @data = facade.movie_details(params[:id])
+ @data2 = facade.movie_cast(params[:id])
+ @data3 = facade.movie_reviews(params[:id])
+ end
+end
\ No newline at end of file
diff --git a/app/facades/movie_facade.rb b/app/facades/movie_facade.rb
new file mode 100644
index 000000000..64110283f
--- /dev/null
+++ b/app/facades/movie_facade.rb
@@ -0,0 +1,34 @@
+class MovieFacade
+ def top_movies
+ service = MovieService.new
+ data = service.top_movies[:results]
+ limit = data[0..20]
+ @results = limit.map do |movie_data|
+ MoviePoro.new(movie_data)
+ end
+ end
+
+ def search_movies(title)
+ service = MovieService.new
+ data = service.search_movies(title)[:results]
+ limit = data[0..20]
+ @results = limit.map do |movie_data|
+ MoviePoro.new(movie_data)
+ end
+ end
+
+ def movie_details(id)
+ service = MovieService.new
+ service.movie_details(id)
+ end
+
+ def movie_cast(id)
+ service = MovieService.new
+ service.movie_cast(id)
+ end
+
+ def movie_reviews(id)
+ service = MovieService.new
+ service.movie_reviews(id)
+ end
+end
\ No newline at end of file
diff --git a/app/poros/movie_poro.rb b/app/poros/movie_poro.rb
new file mode 100644
index 000000000..061c399bd
--- /dev/null
+++ b/app/poros/movie_poro.rb
@@ -0,0 +1,15 @@
+class MoviePoro
+ attr_reader :id, :title, :vote_average, :runtime, :genres, :overview, :cast, :results, :poster_path
+
+ def initialize(data)
+ @id = data[:id]
+ @title = data[:title]
+ @vote_average = data[:vote_average]
+ @runtime = data[:runtime]
+ @genres = data[:genres]
+ @overview = data[:overview]
+ @cast = data[:cast]
+ @results = data[:results]
+ @poster_path = data[:poster_path]
+ end
+end
\ No newline at end of file
diff --git a/app/services/movie_service.rb b/app/services/movie_service.rb
new file mode 100644
index 000000000..9b3a69ac1
--- /dev/null
+++ b/app/services/movie_service.rb
@@ -0,0 +1,32 @@
+class MovieService
+ def get_url(url)
+ response = conn.get(url)
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ def top_movies
+ get_url('/3/movie/popular')
+ end
+
+ def search_movies(title)
+ get_url("/3/search/movie?query=#{title}")
+ end
+
+ def movie_details(id)
+ get_url("/3/movie/#{id}")
+ end
+
+ def movie_cast(id)
+ get_url("/3/movie/#{id}/credits")
+ end
+
+ def movie_reviews(id)
+ get_url("/3/movie/#{id}/reviews")
+ end
+
+ def conn
+ Faraday.new(url: "https://api.themoviedb.org") do |faraday|
+ faraday.params['api_key'] = Rails.application.credentials.tmdb[:key]
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/views/discover/index.html.erb b/app/views/discover/index.html.erb
new file mode 100644
index 000000000..7e7e6425a
--- /dev/null
+++ b/app/views/discover/index.html.erb
@@ -0,0 +1,9 @@
+<%= button_to 'Discover Top Rated Movies', "/users/#{params[:user_id]}/movies", method: :get %>
+
+<%= form_with url: "/users/#{params[:user_id]}/movies" , method: :get, local: true do |f| %>
+
+ <%= f.label :Movie_Title %>
+ <%= f.text_field :Movie_Title %>
+
+ <%= f.submit 'Search by Movie Title' %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/movies/index.html.erb b/app/views/movies/index.html.erb
new file mode 100644
index 000000000..850720d08
--- /dev/null
+++ b/app/views/movies/index.html.erb
@@ -0,0 +1,7 @@
+
Movie Results
+<% @results.each do |result| %>
+
+ - <%= link_to "#{result.title}", "/users/#{params[:user_id]}/movies/#{result.id}" %>
+ - <%= result.vote_average %>
+
+<% end %>
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 262ffd547..bac3be522 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -3,4 +3,9 @@
# Defines the root path route ("/")
# root "articles#index"
+
+ resources :users, only: [:new, :create, :show] do
+ resources :discover, only: [:index]
+ resources :movies, only: [:index, :show]
+ end
end
diff --git a/db/migrate/20231128001844_create_users.rb b/db/migrate/20231128001844_create_users.rb
index 88bc54750..1c96c67ca 100644
--- a/db/migrate/20231128001844_create_users.rb
+++ b/db/migrate/20231128001844_create_users.rb
@@ -3,6 +3,7 @@ def change
create_table :users do |t|
t.string :name
t.string :password_digest
+ t.string :email
t.timestamps
end
diff --git a/db/schema.rb b/db/schema.rb
index d32b0be61..e31e39284 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -37,6 +37,7 @@
create_table "users", force: :cascade do |t|
t.string "name"
t.string "password_digest"
+ t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
diff --git a/spec/features/users/discover/index_spec.rb b/spec/features/users/discover/index_spec.rb
new file mode 100644
index 000000000..f6b5b7ea8
--- /dev/null
+++ b/spec/features/users/discover/index_spec.rb
@@ -0,0 +1,32 @@
+require 'rails_helper'
+
+RSpec.describe 'Discover Movies Page' do
+ before(:each) do
+ load_test_data
+ end
+
+ it 'When a user can get to movie results through movie title search' do
+
+ visit "/users/#{@user1.id}/discover"
+
+ expect(page).to have_button("Discover Top Rated Movies")
+ expect(page).to have_button("Search by Movie Title")
+
+ fill_in 'Movie_Title', with: "Batman"
+ # click_button "Search by Movie Title"
+
+ # expect(current_path).to eq("/users/#{@user1.id}/movies")
+ end
+
+ it 'When a user can get to movie results through top rated movies button' do
+
+ visit "/users/#{@user1.id}/discover"
+
+ expect(page).to have_button("Discover Top Rated Movies")
+ expect(page).to have_button("Search by Movie Title")
+
+ # click_button "Discover Top Rated Movies"
+
+ # expect(current_path).to eq("/users/#{@user1.id}/movies")
+ end
+end
\ No newline at end of file
diff --git a/spec/features/users/movies/index_spec.rb b/spec/features/users/movies/index_spec.rb
new file mode 100644
index 000000000..2a0768f65
--- /dev/null
+++ b/spec/features/users/movies/index_spec.rb
@@ -0,0 +1,57 @@
+require 'rails_helper'
+
+RSpec.describe 'Movie Results' do
+ before(:each) do
+ load_test_data
+ end
+ describe 'happy path' do
+ it 'Get top 20 rated movies' do
+ json_response = File.read('spec/fixtures/top_twenty_movies.json')
+ stub_request(:get, "https://api.themoviedb.org/3/movie/popular?api_key=#{Rails.application.credentials.tmdb[:key]}").
+ with(
+ headers: {
+ 'Accept'=>'*/*',
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
+ 'User-Agent'=>'Faraday v2.7.12'
+ }).
+ to_return(status: 200, body: json_response, headers: {})
+
+ visit "/users/#{@user1.id}/discover"
+
+ expect(page).to have_button("Discover Top Rated Movies")
+ expect(page).to have_button("Search by Movie Title")
+
+ click_button "Discover Top Rated Movies"
+
+ expect(page.status_code).to eq 200
+
+ expect(page).to have_link("Trolls Band Together")
+ expect(page).to have_content(7.215)
+ end
+
+ it 'Get searched movies' do
+ visit "/users/#{@user1.id}/discover"
+
+ expect(page).to have_button("Discover Top Rated Movies")
+ expect(page).to have_button("Search by Movie Title")
+
+ json_response = File.read('spec/fixtures/batman_movies.json')
+ stub_request(:get, "https://api.themoviedb.org/3/search/movie?api_key=#{Rails.application.credentials.tmdb[:key]}&query=Batman").
+ with(
+ headers: {
+ 'Accept'=>'*/*',
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
+ 'User-Agent'=>'Faraday v2.7.12'
+ }).
+ to_return(status: 200, body: json_response, headers: {})
+
+ fill_in 'Movie_Title', with: "Batman"
+ click_button "Search by Movie Title"
+
+ expect(page.status_code).to eq 200
+
+ expect(page).to have_link("Batman Begins")
+ expect(page).to have_content(7.2)
+ end
+ end
+end
\ No newline at end of file
diff --git a/spec/features/users/movies/show_spec.rb b/spec/features/users/movies/show_spec.rb
new file mode 100644
index 000000000..e69de29bb
diff --git a/spec/fixtures/batman_movies.json b/spec/fixtures/batman_movies.json
new file mode 100644
index 000000000..495a0fea8
--- /dev/null
+++ b/spec/fixtures/batman_movies.json
@@ -0,0 +1,418 @@
+{
+ "page": 1,
+ "results": [
+ {
+ "adult": false,
+ "backdrop_path": "/frDS8A5vIP927KYAxTVVKRIbqZw.jpg",
+ "genre_ids": [
+ 14,
+ 28,
+ 80
+ ],
+ "id": 268,
+ "original_language": "en",
+ "original_title": "Batman",
+ "overview": "Batman must face his most ruthless nemesis when a deformed madman calling himself \"The Joker\" seizes control of Gotham's criminal underworld.",
+ "popularity": 55.624,
+ "poster_path": "/cij4dd21v2Rk2YtUQbV5kW69WB2.jpg",
+ "release_date": "1989-06-21",
+ "title": "Batman",
+ "video": false,
+ "vote_average": 7.22,
+ "vote_count": 7237
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/bxxupqG6TBLKC60M6L8iOvbQEr6.jpg",
+ "genre_ids": [
+ 28,
+ 35,
+ 80
+ ],
+ "id": 2661,
+ "original_language": "en",
+ "original_title": "Batman",
+ "overview": "The Dynamic Duo faces four super-villains who plan to hold the world for ransom with the help of a secret invention that instantly dehydrates people.",
+ "popularity": 29.989,
+ "poster_path": "/zzoPxWHnPa0eyfkMLgwbNvdEcVF.jpg",
+ "release_date": "1966-07-30",
+ "title": "Batman",
+ "video": false,
+ "vote_average": 6.301,
+ "vote_count": 791
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/xEG5iP1qZCiDt4BefSpLy1d54zE.jpg",
+ "genre_ids": [
+ 28,
+ 12,
+ 80,
+ 878,
+ 53,
+ 10752
+ ],
+ "id": 125249,
+ "original_language": "en",
+ "original_title": "Batman",
+ "overview": "Japanese master spy Daka operates a covert espionage-sabotage organization located in Gotham City's now-deserted Little Tokyo, which turns American scientists into pliable zombies. The great crime-fighters Batman and Robin, with the help of their allies, are in pursuit.",
+ "popularity": 10.352,
+ "poster_path": "/AvzD3mrtokIzZOiV6zAG7geIo6F.jpg",
+ "release_date": "1943-07-16",
+ "title": "Batman",
+ "video": false,
+ "vote_average": 6.4,
+ "vote_count": 59
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/p2aiSLQZx7AVZrY9cfOOPv1u5Zk.jpg",
+ "genre_ids": [
+ 27,
+ 53,
+ 878
+ ],
+ "id": 1160196,
+ "original_language": "en",
+ "original_title": "Batman",
+ "overview": "A young man learns the consequence of tempting with the underworld",
+ "popularity": 5.072,
+ "poster_path": "/qIvTMHX2MIYG2Ij4jP5dkKgMqUo.jpg",
+ "release_date": "2023-07-28",
+ "title": "Batman",
+ "video": false,
+ "vote_average": 6.0,
+ "vote_count": 3
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/tRS6jvPM9qPrrnx2KRp3ew96Yot.jpg",
+ "genre_ids": [
+ 80,
+ 9648,
+ 53
+ ],
+ "id": 414906,
+ "original_language": "en",
+ "original_title": "The Batman",
+ "overview": "In his second year of fighting crime, Batman uncovers corruption in Gotham City that connects to his own family while facing a serial killer known as the Riddler.",
+ "popularity": 204.53,
+ "poster_path": "/74xTEgt7R36Fpooo50r9T25onhq.jpg",
+ "release_date": "2022-03-01",
+ "title": "The Batman",
+ "video": false,
+ "vote_average": 7.7,
+ "vote_count": 8819
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/5fX1oSGuYdKgwWmUTAN5MNSQGzr.jpg",
+ "genre_ids": [
+ 28,
+ 12,
+ 14
+ ],
+ "id": 209112,
+ "original_language": "en",
+ "original_title": "Batman v Superman: Dawn of Justice",
+ "overview": "Fearing the actions of a god-like Super Hero left unchecked, Gotham City’s own formidable, forceful vigilante takes on Metropolis’s most revered, modern-day savior, while the world wrestles with what sort of hero it really needs. And with Batman and Superman at war with one another, a new threat quickly arises, putting mankind in greater danger than it’s ever known before.",
+ "popularity": 93.975,
+ "poster_path": "/5UsK3grJvtQrtzEgqNlDljJW96w.jpg",
+ "release_date": "2016-03-23",
+ "title": "Batman v Superman: Dawn of Justice",
+ "video": false,
+ "vote_average": 5.956,
+ "vote_count": 17210
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/8pOUmMgVnl1tYNtTRTE5TeyGBGD.jpg",
+ "genre_ids": [
+ 16,
+ 28,
+ 878
+ ],
+ "id": 485942,
+ "original_language": "ja",
+ "original_title": "ニンジャバットマン",
+ "overview": "Batman, along with many of his allies and adversaries, finds himself transported to feudal Japan by Gorilla Grodd's time displacement machine.",
+ "popularity": 28.396,
+ "poster_path": "/5xSB0Npkc9Fd9kahKBsq9P4Cdzp.jpg",
+ "release_date": "2018-06-15",
+ "title": "Batman Ninja",
+ "video": false,
+ "vote_average": 5.8,
+ "vote_count": 785
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/lh5lbisD4oDbEKgUxoRaZU8HVrk.jpg",
+ "genre_ids": [
+ 28,
+ 80,
+ 18
+ ],
+ "id": 272,
+ "original_language": "en",
+ "original_title": "Batman Begins",
+ "overview": "Driven by tragedy, billionaire Bruce Wayne dedicates his life to uncovering and defeating the corruption that plagues his home, Gotham City. Unable to work within the system, he instead creates a new identity, a symbol of fear for the criminal underworld - The Batman.",
+ "popularity": 79.782,
+ "poster_path": "/4MpN4kIEqUjW8OPtOQJXlTdHiJV.jpg",
+ "release_date": "2005-06-10",
+ "title": "Batman Begins",
+ "video": false,
+ "vote_average": 7.7,
+ "vote_count": 19783
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/7eccX0xay9pDj6ZQvU4cu3whw18.jpg",
+ "genre_ids": [
+ 16,
+ 14,
+ 27,
+ 28,
+ 9648
+ ],
+ "id": 1003579,
+ "original_language": "en",
+ "original_title": "Batman: The Doom That Came to Gotham",
+ "overview": "Explorer Bruce Wayne accidentally unleashes an ancient evil, and returns to Gotham after being away for two decades. There, Batman battles Lovecraftian supernatural forces and encounters allies and enemies such as Green Arrow, Ra's al Ghul, Mr. Freeze, Killer Croc, Two-Face and James Gordon.",
+ "popularity": 46.754,
+ "poster_path": "/dzPNQXI8FlpXTGGp1082RJ8OQoT.jpg",
+ "release_date": "2023-03-10",
+ "title": "Batman: The Doom That Came to Gotham",
+ "video": false,
+ "vote_average": 6.726,
+ "vote_count": 157
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/3WP0RObZ2t7ShHfqQpKPljF9B22.jpg",
+ "genre_ids": [
+ 28,
+ 14
+ ],
+ "id": 364,
+ "original_language": "en",
+ "original_title": "Batman Returns",
+ "overview": "While Batman deals with a deformed man calling himself the Penguin, an employee of a corrupt businessman transforms into the Catwoman.",
+ "popularity": 52.985,
+ "poster_path": "/jKBjeXM7iBBV9UkUcOXx3m7FSHY.jpg",
+ "release_date": "1992-06-19",
+ "title": "Batman Returns",
+ "video": false,
+ "vote_average": 6.919,
+ "vote_count": 6051
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/tgPFZxhDuxWd4VXYaz8eAUznGTF.jpg",
+ "genre_ids": [
+ 28,
+ 878,
+ 12
+ ],
+ "id": 415,
+ "original_language": "en",
+ "original_title": "Batman & Robin",
+ "overview": "Batman and Robin deal with relationship issues while preventing Mr. Freeze and Poison Ivy from attacking Gotham City.",
+ "popularity": 45.997,
+ "poster_path": "/cGRDufDDSrFrv7VI4YnmWnslne0.jpg",
+ "release_date": "1997-06-20",
+ "title": "Batman & Robin",
+ "video": false,
+ "vote_average": 4.336,
+ "vote_count": 4667
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/eoMushgujydxFplE9yPZ54lwOvo.jpg",
+ "genre_ids": [
+ 16,
+ 28,
+ 35,
+ 10751
+ ],
+ "id": 324849,
+ "original_language": "en",
+ "original_title": "The Lego Batman Movie",
+ "overview": "A cooler-than-ever Bruce Wayne must deal with the usual suspects as they plan to rule Gotham City, while discovering that he has accidentally adopted a teenage orphan who wishes to become his sidekick.",
+ "popularity": 73.499,
+ "poster_path": "/snGwr2gag4Fcgx2OGmH9otl6ofW.jpg",
+ "release_date": "2017-02-08",
+ "title": "The Lego Batman Movie",
+ "video": false,
+ "vote_average": 7.225,
+ "vote_count": 4639
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/98kbLdg6rDqhYySxROTluRbLy5t.jpg",
+ "genre_ids": [
+ 28,
+ 80,
+ 14
+ ],
+ "id": 414,
+ "original_language": "en",
+ "original_title": "Batman Forever",
+ "overview": "Batman must battle a disfigured district attorney and a disgruntled former employee with help from an amorous psychologist and a young circus acrobat.",
+ "popularity": 38.719,
+ "poster_path": "/mzzNBVwTiiY94xAXDMWJpNPW2US.jpg",
+ "release_date": "1995-06-16",
+ "title": "Batman Forever",
+ "video": false,
+ "vote_average": 5.408,
+ "vote_count": 4826
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/sA50fD5aLbYPRU0fMCHIZ88gc5g.jpg",
+ "genre_ids": [
+ 16,
+ 28,
+ 10751
+ ],
+ "id": 581997,
+ "original_language": "en",
+ "original_title": "Batman vs Teenage Mutant Ninja Turtles",
+ "overview": "Batman, Batgirl and Robin forge an alliance with the Teenage Mutant Ninja Turtles to fight against the Turtles' sworn enemy, The Shredder, who has apparently teamed up with Ra's Al Ghul and The League of Assassins.",
+ "popularity": 29.836,
+ "poster_path": "/yP3h0Pu8htyb9450mWJ9Vu1rU.jpg",
+ "release_date": "2019-03-31",
+ "title": "Batman vs Teenage Mutant Ninja Turtles",
+ "video": false,
+ "vote_average": 7.126,
+ "vote_count": 432
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/iQJ1gC2p6yn5wnBEklhPaEFJ3n1.jpg",
+ "genre_ids": [
+ 16,
+ 28,
+ 878
+ ],
+ "id": 886396,
+ "original_language": "en",
+ "original_title": "Batman and Superman: Battle of the Super Sons",
+ "overview": "After discovering he has powers, 11-year-old Jonathan Kent and assassin-turned-Boy-Wonder Damian Wayne must join forces to rescue their fathers (Superman & Batman) and save the planet from the malevolent alien force known as Starro.",
+ "popularity": 31.009,
+ "poster_path": "/mvffaexT5kA3chOnGxwBSlRoshh.jpg",
+ "release_date": "2022-10-17",
+ "title": "Batman and Superman: Battle of the Super Sons",
+ "video": false,
+ "vote_average": 7.687,
+ "vote_count": 252
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/niRgVCgvDVxD67u6gjKZnkBO1AD.jpg",
+ "genre_ids": [
+ 878,
+ 16,
+ 28,
+ 80,
+ 53
+ ],
+ "id": 13851,
+ "original_language": "en",
+ "original_title": "Batman: Gotham Knight",
+ "overview": "A chronicle of Bruce Wayne's establishment and progression into Gotham City’s legendary caped crusader through 6 standalone episodes.",
+ "popularity": 34.653,
+ "poster_path": "/3i1o0sHBP0VUpuSVmkdCRKYoDBC.jpg",
+ "release_date": "2008-07-08",
+ "title": "Batman: Gotham Knight",
+ "video": false,
+ "vote_average": 6.67,
+ "vote_count": 616
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/bNMw3onveTYU7PpLQRK0HQK8JRb.jpg",
+ "genre_ids": [
+ 28,
+ 16,
+ 80
+ ],
+ "id": 69735,
+ "original_language": "en",
+ "original_title": "Batman: Year One",
+ "overview": "A wealthy playboy named Bruce Wayne and a Chicago cop named Jim Gordon both return to Gotham City where their lives unexpectedly intersect.",
+ "popularity": 32.523,
+ "poster_path": "/mLZRhulJcDsxZWTdfx0trtk6y07.jpg",
+ "release_date": "2011-09-27",
+ "title": "Batman: Year One",
+ "video": false,
+ "vote_average": 7.284,
+ "vote_count": 873
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/74H4XXU0q22TSrkPmlqkcWoX5ZZ.jpg",
+ "genre_ids": [
+ 878,
+ 28,
+ 12,
+ 16
+ ],
+ "id": 45162,
+ "original_language": "en",
+ "original_title": "Superman/Batman: Apocalypse",
+ "overview": "Batman discovers a mysterious teen-aged girl with superhuman powers and a connection to Superman. When the girl comes to the attention of Darkseid, the evil overlord of Apokolips, events take a decidedly dangerous turn.",
+ "popularity": 20.1,
+ "poster_path": "/d7gHmsA2o5Z1MhcuspMyOSO48KB.jpg",
+ "release_date": "2010-09-28",
+ "title": "Superman/Batman: Apocalypse",
+ "video": false,
+ "vote_average": 7.2,
+ "vote_count": 639
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/2Li2vaWeCIMYwcgC9yU3Z99LDVL.jpg",
+ "genre_ids": [
+ 12,
+ 14,
+ 16,
+ 28,
+ 878
+ ],
+ "id": 21683,
+ "original_language": "en",
+ "original_title": "Batman: Mystery of the Batwoman",
+ "overview": "As if the Penguin wasn't enough to contend with, a new vigilante has surfaced in Gotham City, and her strong-arm tactics give Batman cause for concern.",
+ "popularity": 34.176,
+ "poster_path": "/mlmhpUArJdpRPO211v3lETe3uzg.jpg",
+ "release_date": "2003-10-21",
+ "title": "Batman: Mystery of the Batwoman",
+ "video": false,
+ "vote_average": 6.687,
+ "vote_count": 352
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/9Eh5xzWTpJeZM1FGCblWKZ8GTpw.jpg",
+ "genre_ids": [
+ 878,
+ 28,
+ 16,
+ 9648
+ ],
+ "id": 142061,
+ "original_language": "en",
+ "original_title": "Batman: The Dark Knight Returns, Part 2",
+ "overview": "Batman has stopped the reign of terror that The Mutants had cast upon his city. Now an old foe wants a reunion and the government wants The Man of Steel to put a stop to Batman.",
+ "popularity": 39.477,
+ "poster_path": "/arEZYd6uMOFTILne9Ux0A8qctMe.jpg",
+ "release_date": "2013-01-03",
+ "title": "Batman: The Dark Knight Returns, Part 2",
+ "video": false,
+ "vote_average": 7.923,
+ "vote_count": 1361
+ }
+ ],
+ "total_pages": 8,
+ "total_results": 157
+}
\ No newline at end of file
diff --git a/spec/fixtures/top_twenty_movies.json b/spec/fixtures/top_twenty_movies.json
new file mode 100644
index 000000000..858df9945
--- /dev/null
+++ b/spec/fixtures/top_twenty_movies.json
@@ -0,0 +1,405 @@
+{
+ "page": 1,
+ "results": [
+ {
+ "adult": false,
+ "backdrop_path": "/xgGGinKRL8xeRkaAR9RMbtyk60y.jpg",
+ "genre_ids": [
+ 16,
+ 10751,
+ 10402,
+ 14,
+ 35
+ ],
+ "id": 901362,
+ "original_language": "en",
+ "original_title": "Trolls Band Together",
+ "overview": "Rylan McFadden is awesome",
+ "popularity": 1839.78,
+ "poster_path": "/qV4fdXXUm5xNlEJ2jw7af3XxuQB.jpg",
+ "release_date": "2023-10-12",
+ "title": "Trolls Band Together",
+ "video": false,
+ "vote_average": 7.215,
+ "vote_count": 195
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/fm6KqXpk3M2HVveHwCrBSSBaO0V.jpg",
+ "genre_ids": [
+ 18,
+ 36
+ ],
+ "id": 872585,
+ "original_language": "en",
+ "original_title": "Oppenheimer",
+ "overview": "The story of J. Robert Oppenheimer's role in the development of the atomic bomb during World War II.",
+ "popularity": 1672.982,
+ "poster_path": "/8Gxv8gSFCU0XGDykEGv7zR1n2ua.jpg",
+ "release_date": "2023-07-19",
+ "title": "Oppenheimer",
+ "video": false,
+ "vote_average": 8.163,
+ "vote_count": 4984
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/kjQBrc00fB2RjHZB3PGR4w9ibpz.jpg",
+ "genre_ids": [
+ 878,
+ 28,
+ 53
+ ],
+ "id": 670292,
+ "original_language": "en",
+ "original_title": "The Creator",
+ "overview": "Amid a future war between the human race and the forces of artificial intelligence, a hardened ex-special forces agent grieving the disappearance of his wife, is recruited to hunt down and kill the Creator, the elusive architect of advanced AI who has developed a mysterious weapon with the power to end the war—and mankind itself.",
+ "popularity": 1335.428,
+ "poster_path": "/vBZ0qvaRxqEhZwl6LWmruJqWE8Z.jpg",
+ "release_date": "2023-09-27",
+ "title": "The Creator",
+ "video": false,
+ "vote_average": 7.153,
+ "vote_count": 1184
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/9PqD3wSIjntyJDBzMNuxuKHwpUD.jpg",
+ "genre_ids": [
+ 16,
+ 35,
+ 10751
+ ],
+ "id": 1075794,
+ "original_language": "en",
+ "original_title": "Leo",
+ "overview": "Rylan McFadden is awesome",
+ "popularity": 1267.179,
+ "poster_path": "/pD6sL4vntUOXHmuvJPPZAgvyfd9.jpg",
+ "release_date": "2023-11-17",
+ "title": "Leo",
+ "video": false,
+ "vote_average": 7.943,
+ "vote_count": 237
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/t5zCBSB5xMDKcDqe91qahCOUYVV.jpg",
+ "genre_ids": [
+ 27,
+ 9648
+ ],
+ "id": 507089,
+ "original_language": "en",
+ "original_title": "Five Nights at Freddy's",
+ "overview": "Recently fired and desperate for work, a troubled young man named Mike agrees to take a position as a night security guard at an abandoned theme restaurant: Freddy Fazbear's Pizzeria. But he soon discovers that nothing at Freddy's is what it seems.",
+ "popularity": 1077.066,
+ "poster_path": "/j9mH1pr3IahtraTWxVEMANmPSGR.jpg",
+ "release_date": "2023-10-25",
+ "title": "Five Nights at Freddy's",
+ "video": false,
+ "vote_average": 7.864,
+ "vote_count": 2564
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/wl4NWiZwpzZH67HiDgpDImLyds9.jpg",
+ "genre_ids": [
+ 28,
+ 12,
+ 53
+ ],
+ "id": 299054,
+ "original_language": "en",
+ "original_title": "Expend4bles",
+ "overview": "Armed with every weapon they can get their hands on and the skills to use them, The Expendables are the world’s last line of defense and the team that gets called when all other options are off the table. But new team members with new styles and tactics are going to give “new blood” a whole new meaning.",
+ "popularity": 889.087,
+ "poster_path": "/iwsMu0ehRPbtaSxqiaUDQB9qMWT.jpg",
+ "release_date": "2023-09-15",
+ "title": "Expend4bles",
+ "video": false,
+ "vote_average": 6.431,
+ "vote_count": 810
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/28er4p7B5zMSxUDQKPF1hBsgnys.jpg",
+ "genre_ids": [
+ 28,
+ 12,
+ 53
+ ],
+ "id": 872906,
+ "original_language": "hi",
+ "original_title": "जवान",
+ "overview": "An emotional journey of a prison warden, driven by a personal vendetta while keeping up to a promise made years ago, recruits inmates to commit outrageous crimes that shed light on corruption and injustice, in an attempt to get even with his past, and that leads him to an unexpected reunion.",
+ "popularity": 784.233,
+ "poster_path": "/jFt1gS4BGHlK8xt76Y81Alp4dbt.jpg",
+ "release_date": "2023-09-07",
+ "title": "Jawan",
+ "video": false,
+ "vote_average": 7.146,
+ "vote_count": 120
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/4XM8DUTQb3lhLemJC51Jx4a2EuA.jpg",
+ "genre_ids": [
+ 28,
+ 80,
+ 53
+ ],
+ "id": 385687,
+ "original_language": "en",
+ "original_title": "Fast X",
+ "overview": "Over many missions and against impossible odds, Dom Toretto and his family have outsmarted, out-nerved and outdriven every foe in their path. Now, they confront the most lethal opponent they've ever faced: A terrifying threat emerging from the shadows of the past who's fueled by blood revenge, and who is determined to shatter this family and destroy everything—and everyone—that Dom loves, forever.",
+ "popularity": 759.254,
+ "poster_path": "/fiVW06jE7z9YnO4trhaMEdclSiC.jpg",
+ "release_date": "2023-05-17",
+ "title": "Fast X",
+ "video": false,
+ "vote_average": 7.203,
+ "vote_count": 4348
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/628Dep6AxEtDxjZoGP78TsOxYbK.jpg",
+ "genre_ids": [
+ 28,
+ 53
+ ],
+ "id": 575264,
+ "original_language": "en",
+ "original_title": "Mission: Impossible - Dead Reckoning Part One",
+ "overview": "Ethan Hunt and his IMF team embark on their most dangerous mission yet: To track down a terrifying new weapon that threatens all of humanity before it falls into the wrong hands. With control of the future and the world's fate at stake and dark forces from Ethan's past closing in, a deadly race around the globe begins. Confronted by a mysterious, all-powerful enemy, Ethan must consider that nothing can matter more than his mission—not even the lives of those he cares about most.",
+ "popularity": 720.588,
+ "poster_path": "/NNxYkU70HPurnNCSiCjYAmacwm.jpg",
+ "release_date": "2023-07-08",
+ "title": "Mission: Impossible - Dead Reckoning Part One",
+ "video": false,
+ "vote_average": 7.6,
+ "vote_count": 2562
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/f1AQhx6ZfGhPZFTVKgxG91PhEYc.jpg",
+ "genre_ids": [
+ 18,
+ 36,
+ 10752
+ ],
+ "id": 753342,
+ "original_language": "en",
+ "original_title": "Napoleon",
+ "overview": "An epic that details the checkered rise and fall of French Emperor Napoleon Bonaparte and his relentless journey to power through the prism of his addictive, volatile relationship with his wife, Josephine.",
+ "popularity": 670.48,
+ "poster_path": "/jE5o7y9K6pZtWNNMEw3IdpHuncR.jpg",
+ "release_date": "2023-11-22",
+ "title": "Napoleon",
+ "video": false,
+ "vote_average": 6.443,
+ "vote_count": 333
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/7dCzb1oa7ACYi66VIrE1wqmftAa.jpg",
+ "genre_ids": [
+ 28
+ ],
+ "id": 660521,
+ "original_language": "en",
+ "original_title": "The Mercenary",
+ "overview": "When a mission in South America goes wrong a mercenary is left for dead, but he is nursed back to health and reborn with a new outlook on life. But his peaceful days are short-lived when mercenaries he used to work with cross his path again and he is forced to revisit and face his own demons.",
+ "popularity": 562.037,
+ "poster_path": "/p3wgefagejlefFEDsLRHiXU7NGu.jpg",
+ "release_date": "2020-01-07",
+ "title": "The Mercenary",
+ "video": false,
+ "vote_average": 6.25,
+ "vote_count": 22
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/jAW3L7N5ePEnIsBQP5vnmhw1qbl.jpg",
+ "genre_ids": [
+ 80,
+ 28,
+ 53
+ ],
+ "id": 958263,
+ "original_language": "ko",
+ "original_title": "독전 2",
+ "overview": "A determined detective continues his search for the truth behind Asia's largest drug organization and its elusive boss he has unfinished business with.",
+ "popularity": 559.335,
+ "poster_path": "/g9aDZSqH5KmsHbMurhni5d2wq6q.jpg",
+ "release_date": "2023-10-05",
+ "title": "Believer 2",
+ "video": false,
+ "vote_average": 7.0,
+ "vote_count": 36
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/tC78Pck2YCsUAtEdZwuHYUFYtOj.jpg",
+ "genre_ids": [
+ 28,
+ 53,
+ 80
+ ],
+ "id": 926393,
+ "original_language": "en",
+ "original_title": "The Equalizer 3",
+ "overview": "Robert McCall finds himself at home in Southern Italy but he discovers his friends are under the control of local crime bosses. As events turn deadly, McCall knows what he has to do: become his friends' protector by taking on the mafia.",
+ "popularity": 555.986,
+ "poster_path": "/b0Ej6fnXAP8fK75hlyi2jKqdhHz.jpg",
+ "release_date": "2023-08-30",
+ "title": "The Equalizer 3",
+ "video": false,
+ "vote_average": 7.424,
+ "vote_count": 1742
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/5a4JdoFwll5DRtKMe7JLuGQ9yJm.jpg",
+ "genre_ids": [
+ 28,
+ 12,
+ 878
+ ],
+ "id": 695721,
+ "original_language": "en",
+ "original_title": "The Hunger Games: The Ballad of Songbirds & Snakes",
+ "overview": "64 years before he becomes the tyrannical president of Panem, Coriolanus Snow sees a chance for a change in fortunes when he mentors Lucy Gray Baird, the female tribute from District 12.",
+ "popularity": 553.155,
+ "poster_path": "/mBaXZ95R2OxueZhvQbcEWy2DqyO.jpg",
+ "release_date": "2023-11-15",
+ "title": "The Hunger Games: The Ballad of Songbirds & Snakes",
+ "video": false,
+ "vote_average": 7.297,
+ "vote_count": 454
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/2X7BAu7x2oMB3cTMF38uJhGSqoB.jpg",
+ "genre_ids": [
+ 36,
+ 28,
+ 18
+ ],
+ "id": 606870,
+ "original_language": "en",
+ "original_title": "The Survivor",
+ "overview": "Harry Haft is a boxer who fought fellow prisoners in the concentration camps to survive. Haunted by the memories and his guilt, he attempts to use high-profile fights against boxing legends like Rocky Marciano as a way to find his first love again.",
+ "popularity": 503.03,
+ "poster_path": "/oZWJ20tGWZ5xO9CrTCVavmDRy7J.jpg",
+ "release_date": "2022-04-07",
+ "title": "The Survivor",
+ "video": false,
+ "vote_average": 7.215,
+ "vote_count": 114
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/5mzr6JZbrqnqD8rCEvPhuCE5Fw2.jpg",
+ "genre_ids": [
+ 28,
+ 878,
+ 27
+ ],
+ "id": 615656,
+ "original_language": "en",
+ "original_title": "Meg 2: The Trench",
+ "overview": "An exploratory dive into the deepest depths of the ocean of a daring research team spirals into chaos when a malevolent mining operation threatens their mission and forces them into a high-stakes battle for survival.",
+ "popularity": 498.577,
+ "poster_path": "/4m1Au3YkjqsxF8iwQy0fPYSxE0h.jpg",
+ "release_date": "2023-08-02",
+ "title": "Meg 2: The Trench",
+ "video": false,
+ "vote_average": 6.744,
+ "vote_count": 2594
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/3H9NA1KWEQN0ItL3Wl3SFZYP6yV.jpg",
+ "genre_ids": [
+ 28,
+ 878,
+ 12
+ ],
+ "id": 565770,
+ "original_language": "en",
+ "original_title": "Blue Beetle",
+ "overview": "Recent college grad Jaime Reyes returns home full of aspirations for his future, only to find that home is not quite as he left it. As he searches to find his purpose in the world, fate intervenes when Jaime unexpectedly finds himself in possession of an ancient relic of alien biotechnology: the Scarab.",
+ "popularity": 493.911,
+ "poster_path": "/mXLOHHc1Zeuwsl4xYKjKh2280oL.jpg",
+ "release_date": "2023-08-16",
+ "title": "Blue Beetle",
+ "video": false,
+ "vote_average": 6.945,
+ "vote_count": 1750
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/feSiISwgEpVzR1v3zv2n2AU4ANJ.jpg",
+ "genre_ids": [
+ 878,
+ 12,
+ 28
+ ],
+ "id": 609681,
+ "original_language": "en",
+ "original_title": "The Marvels",
+ "overview": "Carol Danvers, aka Captain Marvel, has reclaimed her identity from the tyrannical Kree and taken revenge on the Supreme Intelligence. But unintended consequences see Carol shouldering the burden of a destabilized universe. When her duties send her to an anomalous wormhole linked to a Kree revolutionary, her powers become entangled with that of Jersey City super-fan Kamala Khan, aka Ms. Marvel, and Carol’s estranged niece, now S.A.B.E.R. astronaut Captain Monica Rambeau. Together, this unlikely trio must team up and learn to work in concert to save the universe.",
+ "popularity": 492.065,
+ "poster_path": "/Ag3D9qXjhJ2FUkrlJ0Cv1pgxqYQ.jpg",
+ "release_date": "2023-11-08",
+ "title": "The Marvels",
+ "video": false,
+ "vote_average": 6.582,
+ "vote_count": 564
+ },
+ {
+ "adult": false,
+ "backdrop_path": null,
+ "genre_ids": [
+ 28,
+ 16
+ ],
+ "id": 116776,
+ "original_language": "ja",
+ "original_title": "ドラゴンボール 魔訶不思議大冒険",
+ "overview": "Master Roshi has succeeded at the one mission he valued most: to train Goku and Krillin to become ultimate fighters. So, he arranges for them to test their mettle at a competition hosted by Emperor Chiaotzu. Not everyone's playing by the rules, however, as a member of the ruler's household schemes to use the Dragonballs to extort money and power from the royal.",
+ "popularity": 490.916,
+ "poster_path": "/5aXG0B3TYTpQsodXzvYCkKQfpB1.jpg",
+ "release_date": "1988-07-09",
+ "title": "Dragon Ball: Mystical Adventure",
+ "video": false,
+ "vote_average": 6.803,
+ "vote_count": 223
+ },
+ {
+ "adult": false,
+ "backdrop_path": "/9n2tJBplPbgR2ca05hS5CKXwP2c.jpg",
+ "genre_ids": [
+ 16,
+ 10751,
+ 12,
+ 14,
+ 35
+ ],
+ "id": 502356,
+ "original_language": "en",
+ "original_title": "The Super Mario Bros. Movie",
+ "overview": "While working underground to fix a water main, Brooklyn plumbers—and brothers—Mario and Luigi are transported down a mysterious pipe and wander into a magical new world. But when the brothers are separated, Mario embarks on an epic quest to find Luigi.",
+ "popularity": 490.291,
+ "poster_path": "/qNBAXBIQlnOThrVvA6mA2B5ggV6.jpg",
+ "release_date": "2023-04-05",
+ "title": "The Super Mario Bros. Movie",
+ "video": false,
+ "vote_average": 7.747,
+ "vote_count": 7265
+ }
+ ],
+ "total_pages": 41539,
+ "total_results": 830768
+}
\ No newline at end of file
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 327b58ea1..6352e7421 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -3,6 +3,7 @@
# The generated `.rspec` file contains `--require spec_helper` which will cause
# this file to always be loaded, without a need to explicitly require it in any
# files.
+require 'webmock/rspec'
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file