trakt_rs/api/
movies.rs

1//! Movie related endpoints
2//!
3//! <https://trakt.docs.apiary.io/#reference/movies>
4
5pub mod favorited {
6    //! Get the most favorited movies.
7    //!
8    //! <https://trakt.docs.apiary.io/#reference/movies/favorited>
9
10    use serde::Deserialize;
11    use trakt_core::{Pagination, PaginationResponse};
12
13    use crate::smo::{Movie, Period};
14
15    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
16    #[trakt(
17    response = Response,
18    endpoint = "/movies/favorited/{period}",
19    )]
20    pub struct Request {
21        pub period: Period,
22        #[serde(flatten)]
23        pub pagination: Pagination,
24    }
25
26    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
27    pub struct Response {
28        #[trakt(pagination)]
29        pub items: PaginationResponse<ResponseItem>,
30    }
31
32    #[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
33    pub struct ResponseItem {
34        pub user_count: usize,
35        pub movie: Movie,
36    }
37}
38
39pub mod popular {
40    //! Get popular movies.
41    //!
42    //! <https://trakt.docs.apiary.io/#reference/movies/popular/get-popular-movies>
43    use trakt_core::PaginationResponse;
44
45    use crate::smo::Movie;
46
47    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)]
48    #[trakt(
49    response = Response,
50    endpoint = "/movies/popular",
51    )]
52    pub struct Request {
53        #[serde(flatten)]
54        pub pagination: trakt_core::Pagination,
55    }
56
57    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
58    pub struct Response {
59        #[trakt(pagination)]
60        pub items: PaginationResponse<Movie>,
61    }
62}
63
64pub mod trending {
65    //! Get trending movies.
66    //!
67    //! <https://trakt.docs.apiary.io/#reference/movies/trending/get-trending-movies>
68    use http::StatusCode;
69    use serde::Deserialize;
70    use trakt_core::{
71        error::FromHttpError, handle_response_body, parse_from_header, Pagination,
72        PaginationResponse,
73    };
74
75    use crate::smo::Movie;
76
77    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)]
78    #[trakt(
79    response = Response,
80    endpoint = "/movies/trending",
81    )]
82    pub struct Request {
83        #[serde(flatten)]
84        pub pagination: Pagination,
85    }
86
87    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Paginated)]
88    pub struct Response {
89        #[trakt(pagination)]
90        pub items: PaginationResponse<ResponseItem>,
91        pub trending_user_count: usize,
92    }
93
94    #[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
95    pub struct ResponseItem {
96        pub watchers: usize,
97        pub movie: Movie,
98    }
99
100    impl trakt_core::Response for Response {
101        fn try_from_http_response<T: AsRef<[u8]>>(
102            response: http::Response<T>,
103        ) -> Result<Self, FromHttpError> {
104            let body: Vec<ResponseItem> = handle_response_body(&response, StatusCode::OK)?;
105
106            let items = PaginationResponse::from_headers(body, response.headers())?;
107
108            Ok(Self {
109                items,
110                trending_user_count: parse_from_header(
111                    response.headers(),
112                    "X-Trending-User-Count",
113                )?,
114            })
115        }
116    }
117}
118
119pub mod played {
120    //! Get the most played movies in a specific time period.
121    //!
122    //! <https://trakt.docs.apiary.io/#reference/movies/played/get-the-most-played-movies>
123    use trakt_core::{Pagination, PaginationResponse};
124
125    use crate::smo::{Movie, Period};
126
127    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
128    #[trakt(
129    response = Response,
130    endpoint = "/movies/played/{period}",
131    )]
132    pub struct Request {
133        pub period: Period,
134        #[serde(flatten)]
135        pub pagination: Pagination,
136    }
137
138    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
139    pub struct Response {
140        #[trakt(pagination)]
141        pub items: PaginationResponse<ResponseItem>,
142    }
143
144    #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize)]
145    pub struct ResponseItem {
146        pub watcher_count: usize,
147        pub play_count: usize,
148        pub collected_count: usize,
149        pub movie: Movie,
150    }
151}
152
153pub mod watched {
154    //! Get the most watched movies in a specific time period.
155    //!
156    //! <https://trakt.docs.apiary.io/#reference/movies/watched/get-the-most-watched-movies>
157    use trakt_core::{Pagination, PaginationResponse};
158
159    use crate::smo::{Movie, Period};
160
161    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
162    #[trakt(
163    response = Response,
164    endpoint = "/movies/watched/{period}",
165    )]
166    pub struct Request {
167        pub period: Period,
168        #[serde(flatten)]
169        pub pagination: Pagination,
170    }
171
172    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
173    pub struct Response {
174        #[trakt(pagination)]
175        pub items: PaginationResponse<ResponseItem>,
176    }
177
178    #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize)]
179    pub struct ResponseItem {
180        pub watcher_count: usize,
181        pub play_count: usize,
182        pub collected_count: usize,
183        pub movie: Movie,
184    }
185}
186
187pub mod collected {
188    //! Get the most collected movies in a specific time period.
189    //!
190    //! <https://trakt.docs.apiary.io/#reference/movies/collected/get-the-most-collected-movies>
191    use trakt_core::{Pagination, PaginationResponse};
192
193    use crate::smo::{Movie, Period};
194
195    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
196    #[trakt(
197    response = Response,
198    endpoint = "/movies/collected/{period}",
199    )]
200    pub struct Request {
201        pub period: Period,
202        #[serde(flatten)]
203        pub pagination: Pagination,
204    }
205
206    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
207    pub struct Response {
208        #[trakt(pagination)]
209        pub items: PaginationResponse<ResponseItem>,
210    }
211
212    #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize)]
213    pub struct ResponseItem {
214        pub watcher_count: usize,
215        pub play_count: usize,
216        pub collected_count: usize,
217        pub movie: Movie,
218    }
219}
220
221pub mod anticipated {
222    //! Get the most anticipated movies.
223    //!
224    //! <https://trakt.docs.apiary.io/#reference/movies/anticipated/get-the-most-anticipated-movies>
225    use trakt_core::{Pagination, PaginationResponse};
226
227    use crate::smo::Movie;
228
229    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
230    #[trakt(
231    response = Response,
232    endpoint = "/movies/anticipated",
233    )]
234    pub struct Request {
235        #[serde(flatten)]
236        pub pagination: Pagination,
237    }
238
239    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
240    pub struct Response {
241        #[trakt(pagination)]
242        pub items: PaginationResponse<ResponseItem>,
243    }
244
245    #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize)]
246    pub struct ResponseItem {
247        pub list_count: usize,
248        pub movie: Movie,
249    }
250}
251
252pub mod boxoffice {
253    //! Get the top 10 box office movies.
254    //!
255    //! <https://trakt.docs.apiary.io/#reference/movies/box-office/get-the-weekend-box-office>
256
257    use crate::smo::Movie;
258
259    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default, trakt_macros::Request)]
260    #[trakt(
261    response = Response,
262    endpoint = "/movies/boxoffice",
263    )]
264    pub struct Request;
265
266    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
267    pub struct Response(pub Vec<ResponseItem>);
268
269    #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize)]
270    pub struct ResponseItem {
271        pub revenue: usize,
272        pub movie: Movie,
273    }
274}
275
276pub mod updates {
277    //! Get all movies updated since a specific date.
278    //!
279    //! <https://trakt.docs.apiary.io/#reference/movies/box-office/get-recently-updated-movies>
280    use time::OffsetDateTime;
281    use trakt_core::{Pagination, PaginationResponse};
282
283    use crate::smo::Movie;
284
285    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
286    #[trakt(
287    response = Response,
288    endpoint = "/movies/updates/{start_date}",
289    )]
290    pub struct Request {
291        #[serde(with = "time::serde::iso8601")]
292        pub start_date: OffsetDateTime,
293        #[serde(flatten)]
294        pub pagination: Pagination,
295    }
296
297    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
298    #[trakt(expected = OK)]
299    pub struct Response {
300        #[trakt(pagination)]
301        pub items: PaginationResponse<Movie>,
302    }
303}
304
305pub mod updates_id {
306    //! Get recently update movie IDs since a specific date.
307    //!
308    //! <https://trakt.docs.apiary.io/#reference/movies/updated-ids/get-recently-updated-movie-trakt-ids>
309
310    use time::OffsetDateTime;
311    use trakt_core::{Pagination, PaginationResponse};
312
313    #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
314    #[trakt(
315    response = Response,
316    endpoint = "/movies/updates/id/{start_date}",
317    )]
318    pub struct Request {
319        #[serde(with = "time::serde::iso8601")]
320        pub start_date: OffsetDateTime,
321        #[serde(flatten)]
322        pub pagination: Pagination,
323    }
324
325    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Response)]
326    #[trakt(expected = OK)]
327    pub struct Response {
328        #[trakt(pagination)]
329        pub items: PaginationResponse<u32>,
330    }
331}
332
333pub mod summary {
334    //! Get a single movie's details.
335    //!
336    //! <https://trakt.docs.apiary.io/#reference/movies/summary/get-a-movie>
337
338    use crate::smo::{Id, Movie};
339
340    #[derive(Debug, Clone, Eq, PartialEq, trakt_macros::Request)]
341    #[trakt(response = Response, endpoint = "/movies/{id}")]
342    pub struct Request {
343        pub id: Id,
344    }
345
346    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
347    pub struct Response(pub Movie);
348}
349
350pub mod aliases {
351    //! Get all title aliases for a movie.
352    //!
353    //! <https://trakt.docs.apiary.io/#reference/movies/aliases/get-all-movie-aliases>
354
355    use serde::Deserialize;
356
357    use crate::smo::Id;
358
359    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
360    #[trakt(
361    response = Response,
362    endpoint = "/movies/{id}/aliases",
363    )]
364    pub struct Request {
365        pub id: Id,
366    }
367
368    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
369    pub struct Response(pub Vec<ResponseItem>);
370
371    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
372    pub struct ResponseItem {
373        pub title: String,
374        pub country: String,
375    }
376}
377
378pub mod releases {
379    //! Get all releases for a movie.
380    //!
381    //! <https://trakt.docs.apiary.io/#reference/movies/releases/get-all-movie-releases>
382
383    use serde::Deserialize;
384
385    use crate::smo::{Country, Id};
386
387    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
388    #[trakt(
389    response = Response,
390    endpoint = "/movies/{id}/releases/{country}",
391    )]
392    pub struct Request {
393        pub id: Id,
394        pub country: Country,
395    }
396
397    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
398    pub struct Response(pub Vec<ResponseItem>);
399
400    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
401    pub struct ResponseItem {
402        pub country: Country,
403        pub certification: String,
404        pub release_date: String,
405        pub release_type: ReleaseType,
406        pub note: Option<String>,
407    }
408
409    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
410    #[serde(rename_all = "lowercase")]
411    pub enum ReleaseType {
412        Unknown,
413        Premiere,
414        Limited,
415        Theatrical,
416        Digital,
417        Physical,
418        TV,
419    }
420}
421
422pub mod translations {
423    //! Get all translations for a movie.
424    //!
425    //! <https://trakt.docs.apiary.io/#reference/movies/translations/get-all-movie-translations>
426
427    use serde::Deserialize;
428
429    use crate::smo::{Country, Id, Language};
430
431    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
432    #[trakt(
433    response = Response,
434    endpoint = "/movies/{id}/translations/{language}",
435    )]
436    pub struct Request {
437        pub id: Id,
438        pub language: Language,
439    }
440
441    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
442    pub struct Response(pub Vec<ResponseItem>);
443
444    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
445    pub struct ResponseItem {
446        pub title: String,
447        pub overview: String,
448        pub tagline: String,
449        pub language: Language,
450        pub country: Country,
451    }
452}
453
454pub mod comments {
455    //! Get all comments for a movie.
456    //!
457    //! If oauth is provided, comments from blocked users will be filtered out.
458    //!
459    //! <https://trakt.docs.apiary.io/#reference/movies/comments/get-all-movie-comments>
460    use trakt_core::{Pagination, PaginationResponse};
461
462    use crate::smo::{Comment, Sort};
463
464    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
465    #[trakt(
466    response = Response,
467    endpoint = "/movies/{id}/comments/{sort}",
468    auth = Optional,
469    )]
470    pub struct Request {
471        pub id: String,
472        pub sort: Sort,
473        #[serde(flatten)]
474        pub pagination: Pagination,
475    }
476
477    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
478    #[trakt(expected = OK)]
479    pub struct Response {
480        #[trakt(pagination)]
481        pub items: PaginationResponse<Comment>,
482    }
483}
484
485pub mod lists {
486    //! TODO: Implement
487    // use serde::Serialize;
488    //
489    // #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
490    // #[trakt(
491    // response = Response,
492    // endpoint = "/movies/{id}/lists/{tp}/{sort}",
493    // )]
494    // pub struct Request {
495    //     pub id: String,
496    //     pub tp: Type,
497    //     pub sort: Sort,
498    //     pub pagination: Pagination,
499    // }
500    //
501    // #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize)]
502    // #[serde(rename_all = "lowercase")]
503    // pub enum Type {
504    //     All,
505    //     #[default]
506    //     Personal,
507    //     Official,
508    //     Watchlist,
509    //     Favorite,
510    // }
511    //
512    // #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Serialize)]
513    // #[serde(rename_all = "lowercase")]
514    // pub enum Sort {
515    //     #[default]
516    //     Popular,
517    //     Likes,
518    //     Comments,
519    //     Items,
520    //     Added,
521    //     Updated,
522    // }
523}
524
525pub mod people {
526    //! Get all people for a movie.
527    //!
528    //! <https://trakt.docs.apiary.io/#reference/movies/lists/get-all-people-for-a-movie>
529
530    use serde::Deserialize;
531
532    use crate::smo::{Id, Person};
533
534    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
535    #[trakt(
536    response = Response,
537    endpoint = "/movies/{id}/people",
538    )]
539    pub struct Request {
540        pub id: Id,
541    }
542
543    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, trakt_macros::Response)]
544    pub struct Response {
545        pub cast: Vec<Character>,
546        pub crew: Crew,
547    }
548
549    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
550    pub struct Character {
551        pub characters: Vec<String>,
552        pub person: Person,
553    }
554
555    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
556    pub struct Crew {
557        pub production: Vec<CrewMember>,
558        pub art: Vec<CrewMember>,
559        pub crew: Vec<CrewMember>,
560        #[serde(rename = "costume & make-up")]
561        pub costume_and_make_up: Vec<CrewMember>,
562        pub directing: Vec<CrewMember>,
563        pub writing: Vec<CrewMember>,
564        pub sound: Vec<CrewMember>,
565        pub camera: Vec<CrewMember>,
566        #[serde(rename = "visual effects")]
567        pub visual_effects: Vec<CrewMember>,
568        pub lighting: Vec<CrewMember>,
569        pub editing: Vec<CrewMember>,
570    }
571
572    #[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize)]
573    pub struct CrewMember {
574        pub jobs: Vec<String>,
575        pub person: Person,
576    }
577}
578
579pub mod ratings {
580    //! Get rating distribution for a movie.
581    //!
582    //! <https://trakt.docs.apiary.io/#reference/movies/ratings/get-movie-ratings>
583
584    use serde::Deserialize;
585
586    use crate::smo::{Id, Ratings};
587
588    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
589    #[trakt(
590    response = Response,
591    endpoint = "/movies/{id}/ratings",
592    )]
593    pub struct Request {
594        pub id: Id,
595    }
596
597    #[derive(Debug, Clone, PartialEq, Deserialize, trakt_macros::Response)]
598    pub struct Response(pub Ratings);
599}
600
601pub mod related {
602    //! Get related movies.
603    //!
604    //! <https://trakt.docs.apiary.io/#reference/movies/related/get-related-movies>
605
606    use trakt_core::PaginationResponse;
607
608    use crate::smo::{Id, Movie};
609
610    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
611    #[trakt(
612    response = Response,
613    endpoint = "/movies/{id}/related",
614    )]
615    pub struct Request {
616        pub id: Id,
617    }
618
619    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
620    #[trakt(expected = OK)]
621    pub struct Response {
622        #[trakt(pagination)]
623        pub items: PaginationResponse<Movie>,
624    }
625}
626
627pub mod stats {
628    //! Get stats for a movie.
629    //!
630    //! <https://trakt.docs.apiary.io/#reference/movies/related/get-movie-stats>
631    use crate::smo::Id;
632
633    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
634    #[trakt(
635    response = Response,
636    endpoint = "/movies/{id}/stats",
637    )]
638    pub struct Request {
639        pub id: Id,
640    }
641
642    #[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Deserialize, trakt_macros::Response)]
643    pub struct Response {
644        pub watchers: u32,
645        pub plays: u32,
646        pub collectors: u32,
647        pub comments: u32,
648        pub lists: u32,
649        pub votes: u32,
650        pub favorited: u32,
651    }
652}
653
654pub mod studio {
655    //! Get movie studios
656    //!
657    //! <https://trakt.docs.apiary.io/#reference/movies/studios/get-movie-studios>
658
659    use crate::smo::{Id, Studio};
660
661    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
662    #[trakt(
663    response = Response,
664    endpoint = "/movies/{id}/studios",
665    )]
666    pub struct Request {
667        pub id: Id,
668    }
669
670    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
671    pub struct Response(pub Vec<Studio>);
672}
673
674pub mod watching {
675    //! Get users currently watching a movie.
676    //!
677    //! <https://trakt.docs.apiary.io/#reference/movies/watching/get-users-currently-watching-a-movie>
678    use crate::smo::{Id, User};
679
680    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Request)]
681    #[trakt(
682    response = Response,
683    endpoint = "/movies/{id}/watching",
684    )]
685    pub struct Request {
686        pub id: Id,
687    }
688
689    #[derive(Debug, Clone, Eq, PartialEq, Hash, trakt_macros::Response)]
690    pub struct Response(pub Vec<User>);
691}
692
693#[cfg(test)]
694mod tests {
695    use httpmock::prelude::*;
696    use serde_json::json;
697    use trakt_core::{Context, PaginatedResponse, Request};
698
699    use super::*;
700
701    #[test]
702    pub fn test_popular() {
703        let server = MockServer::start();
704
705        let popular_mock = server.mock(|when, then| {
706            when.method(GET)
707                .path("/movies/popular")
708                .header("Content-Type", "application/json")
709                .header("trakt-api-key", "abc")
710                .header("trakt-api-version", "2")
711                .query_param("page", "1")
712                .query_param("limit", "10");
713            then.status(200)
714                .header("Content-Type", "application/json")
715                .header("X-Pagination-Page", "1")
716                .header("X-Pagination-Limit", "10")
717                .header("X-Pagination-Page-Count", "1")
718                .header("X-Pagination-Item-Count", "2")
719                .json_body(json!([
720                    {
721                        "title": "The Dark Knight",
722                        "year": 2008,
723                        "ids": {
724                            "trakt": 16,
725                            "slug": "the-dark-knight-2008",
726                            "imdb": "tt0468569",
727                            "tmdb": 155
728                        }
729                    },
730                    {
731                        "title": "Fight Club",
732                        "year": 1999,
733                        "ids": {
734                            "trakt": 727,
735                            "slug": "fight-club-1999",
736                            "imdb": "tt0137523",
737                            "tmdb": 550
738                        }
739                    }
740                ]));
741        });
742
743        let ctx = Context {
744            base_url: &server.base_url(),
745            client_id: "abc",
746            oauth_token: None,
747        };
748
749        let request = popular::Request::default();
750        let http_req: http::Request<Vec<u8>> = request.try_into_http_request(ctx).unwrap();
751
752        assert_eq!(
753            http_req.uri(),
754            &*format!("{}/movies/popular?page=1&limit=10", server.base_url())
755        );
756        assert_eq!(http_req.method(), http::Method::GET);
757        assert_eq!(
758            http_req.headers().get("Content-Type").unwrap(),
759            "application/json"
760        );
761        assert_eq!(http_req.headers().get("trakt-api-key").unwrap(), "abc");
762        assert_eq!(http_req.headers().get("trakt-api-version").unwrap(), "2");
763        assert_eq!(http_req.headers().get("Authorization"), None);
764        assert!(http_req.body().is_empty());
765
766        let response = crate::test::execute(ctx, request).unwrap();
767
768        assert_eq!(response.items().len(), 2);
769        assert_eq!(response.items()[0].title, "The Dark Knight");
770        assert_eq!(response.items()[0].year, 2008);
771        assert_eq!(response.items()[0].ids.trakt, Some(16));
772        assert_eq!(response.items()[1].title, "Fight Club");
773        assert_eq!(response.items()[1].year, 1999);
774        assert_eq!(response.items()[1].ids.trakt, Some(727));
775
776        assert_eq!(response.next_page(), None);
777
778        popular_mock.assert();
779    }
780}