using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Moq;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using Ombi.Api.External.ExternalApis.RottenTomatoes.Models;
using Ombi.Api.External.ExternalApis.TheMovieDb.Models;
using Ombi.Api.IntegrationTests.Harness;
using Ombi.Core.Models.Search;
using Ombi.Core.Models.Search.V2;
namespace Ombi.Api.IntegrationTests.Tests
{
///
/// Contract tests for the V2 Search endpoints the mobile app consumes. The engines are mocked so
/// the test pins the serialized HTTP shape (route + camelCase JSON) rather than TheMovieDb data.
///
[TestFixture]
public class SearchContractTests : IntegrationTestBase
{
[Test]
public async Task PopularMovies_Paged_ReturnsExpectedShape()
{
Factory.MovieEngineV2
.Setup(x => x.PopularMovies(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()))
.ReturnsAsync(new List
{
new SearchMovieViewModel
{
Id = 123,
Title = "Test Movie",
Overview = "An overview",
PosterPath = "/poster.jpg",
BackdropPath = "/backdrop.jpg",
VoteAverage = 8.1,
VoteCount = 100,
Available = true,
Approved = true,
Requested = true,
}
});
var (status, body) = await GetAsync("/api/v2/search/movie/popular/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
var array = AsArray(body);
Assert.That(array.Count, Is.EqualTo(1));
var item = (JObject)array[0];
AssertHasProperties(item,
"id", "title", "overview", "posterPath", "backdropPath",
"releaseDate", "popularity", "voteCount", "voteAverage",
"available", "approved", "denied", "requested", "requestId",
"type", "quality", "plexUrl", "embyUrl", "jellyfinUrl", "imdbId");
}
[Test]
public async Task MovieDetails_ReturnsExpectedShape()
{
Factory.MovieEngineV2
.Setup(x => x.GetFullMovieInformation(It.IsAny(), It.IsAny(), It.IsAny()))
.ReturnsAsync(new MovieFullInfoViewModel
{
Id = 555,
Title = "Full Movie",
Overview = "Detailed overview",
PosterPath = "/p.jpg",
BackdropPath = "/b.jpg",
Runtime = 120,
VoteAverage = 7.5,
Available = false,
Requested = false,
});
var (status, body) = await GetAsync("/api/v2/search/movie/555");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
var obj = AsObject(body);
AssertHasProperties(obj,
"id", "title", "overview", "posterPath", "backdropPath",
"runtime", "releaseDate", "voteAverage", "genres",
"available", "requested", "type");
}
[Test]
public async Task TvDetails_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2
.Setup(x => x.GetShowInformation(It.IsAny(), It.IsAny()))
.ReturnsAsync(new SearchFullInfoTvShowViewModel
{
Id = 777,
Title = "Test Show",
Overview = "Show overview",
Status = "Continuing",
FirstAired = "2020-01-01",
Available = false,
Requested = false,
});
var (status, body) = await GetAsync("/api/v2/search/tv/777");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
var obj = AsObject(body);
AssertHasProperties(obj,
"id", "title", "overview", "status", "firstAired",
"genres", "available", "requested", "type");
}
[Test]
public async Task MultiSearch_ReturnsExpectedShape()
{
Factory.MultiSearchEngine
.Setup(x => x.MultiSearch(It.IsAny(), It.IsAny(), It.IsAny()))
.ReturnsAsync(new List
{
new MultiSearchResult
{
Id = "123",
MediaType = "movie",
Title = "Result",
Poster = "/poster.jpg",
Overview = "Overview",
}
});
var (status, body) = await PostJsonAsync("/api/v2/search/multi/star", new { movies = true, tvShows = true });
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
var array = AsArray(body);
Assert.That(array.Count, Is.EqualTo(1));
var item = (JObject)array[0];
AssertHasProperties(item, "id", "mediaType", "title", "poster", "overview");
}
private static readonly string[] MovieListProps =
{
"id", "title", "overview", "posterPath", "backdropPath", "releaseDate",
"voteAverage", "voteCount", "available", "approved", "requested", "type"
};
private static readonly string[] TvListProps =
{
"id", "title", "status", "firstAired", "banner", "available",
"approved", "requested", "type"
};
private static List OneMovie() => new List
{
new SearchMovieViewModel { Id = 1, Title = "M", Overview = "o", PosterPath = "/p", BackdropPath = "/b", VoteAverage = 5 }
};
private static List OneShow() => new List
{
new SearchTvShowViewModel { Id = 1, Title = "S", Status = "Continuing", FirstAired = "2020", Banner = "/banner" }
};
[Test]
public async Task TopRatedMovies_ReturnsExpectedShape()
{
Factory.MovieEngineV2.Setup(x => x.TopRatedMovies(It.IsAny(), It.IsAny())).ReturnsAsync(OneMovie());
var (status, body) = await GetAsync("/api/v2/search/movie/toprated/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], MovieListProps);
}
[Test]
public async Task UpcomingMovies_ReturnsExpectedShape()
{
Factory.MovieEngineV2.Setup(x => x.UpcomingMovies(It.IsAny(), It.IsAny())).ReturnsAsync(OneMovie());
var (status, body) = await GetAsync("/api/v2/search/movie/upcoming/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], MovieListProps);
}
[Test]
public async Task NowPlayingMovies_ReturnsExpectedShape()
{
Factory.MovieEngineV2.Setup(x => x.NowPlayingMovies(It.IsAny(), It.IsAny())).ReturnsAsync(OneMovie());
var (status, body) = await GetAsync("/api/v2/search/movie/nowplaying/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], MovieListProps);
}
[Test]
public async Task PopularTv_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2.Setup(x => x.Popular(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(OneShow());
var (status, body) = await GetAsync("/api/v2/search/tv/popular/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], TvListProps);
}
[Test]
public async Task TrendingTv_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2.Setup(x => x.Trending(It.IsAny(), It.IsAny())).ReturnsAsync(OneShow());
var (status, body) = await GetAsync("/api/v2/search/tv/trending/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], TvListProps);
}
[Test]
public async Task AnticipatedTv_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2.Setup(x => x.Anticipated(It.IsAny(), It.IsAny())).ReturnsAsync(OneShow());
var (status, body) = await GetAsync("/api/v2/search/tv/anticipated/0/10");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], TvListProps);
}
[Test]
public async Task MovieStreams_ReturnsExpectedShape()
{
Factory.MovieEngineV2.Setup(x => x.GetStreamInformation(It.IsAny(), It.IsAny()))
.ReturnsAsync(new List { new StreamingData { Order = 1, StreamingProvider = "Netflix", Logo = "/logo" } });
var (status, body) = await GetAsync("/api/v2/search/stream/movie/123");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], "order", "streamingProvider", "logo");
}
[Test]
public async Task TvStreams_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2.Setup(x => x.GetStreamInformation(It.IsAny(), It.IsAny()))
.ReturnsAsync(new List { new StreamingData { Order = 1, StreamingProvider = "Hulu", Logo = "/logo" } });
var (status, body) = await GetAsync("/api/v2/search/stream/tv/123");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties((JObject)AsArray(body)[0], "order", "streamingProvider", "logo");
}
[Test]
public async Task ActorMovieCredits_ReturnsExpectedShape()
{
Factory.MovieEngineV2.Setup(x => x.GetMoviesByActor(It.IsAny(), It.IsAny()))
.ReturnsAsync(new ActorCredits { id = 1, cast = new[] { new Cast { id = 2, character = "Hero", poster_path = "/p" } } });
var (status, body) = await GetAsync("/api/v2/search/actor/1/movie");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties(AsObject(body), "id", "cast", "crew");
}
[Test]
public async Task ActorTvCredits_ReturnsExpectedShape()
{
Factory.TvSearchEngineV2.Setup(x => x.GetTvByActor(It.IsAny(), It.IsAny()))
.ReturnsAsync(new ActorCredits { id = 1, cast = new[] { new Cast { id = 2, character = "Hero", poster_path = "/p" } } });
var (status, body) = await GetAsync("/api/v2/search/actor/1/tv");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties(AsObject(body), "id", "cast", "crew");
}
[Test]
public async Task MovieRatings_ReturnsExpectedShape()
{
Factory.RottenTomatoesApi.Setup(x => x.GetMovieRatings(It.IsAny(), It.IsAny()))
.ReturnsAsync(new MovieRatings { critics_rating = "Certified Fresh", critics_score = 98, audience_rating = "Upright", audience_score = 90 });
var (status, body) = await GetAsync("/api/v2/search/ratings/movie/Up/2009");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties(AsObject(body), "critics_rating", "critics_score", "audience_rating", "audience_score");
}
[Test]
public async Task TvRatings_ReturnsExpectedShape()
{
Factory.RottenTomatoesApi.Setup(x => x.GetTvRatings(It.IsAny(), It.IsAny()))
.ReturnsAsync(new TvRatings { Class = "fresh", Score = 90 });
var (status, body) = await GetAsync("/api/v2/search/ratings/tv/Lost/2004");
Assert.That(status, Is.EqualTo(HttpStatusCode.OK));
AssertHasProperties(AsObject(body), "class", "score");
}
}
}