node-csfd-api-racintom 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintrc.json +33 -0
  3. package/.gitattributes +2 -0
  4. package/.github/FUNDING.yml +8 -0
  5. package/.github/pull_request_template.md +19 -0
  6. package/.github/workflows/main.yml +40 -0
  7. package/.github/workflows/publish.yml +73 -0
  8. package/.github/workflows/test.yml +43 -0
  9. package/.husky/pre-commit +1 -0
  10. package/.idea/codeStyles/Project.xml +72 -0
  11. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  12. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  13. package/.idea/misc.xml +6 -0
  14. package/.idea/modules.xml +8 -0
  15. package/.idea/node-csfd-api.iml +9 -0
  16. package/.idea/prettier.xml +6 -0
  17. package/.idea/vcs.xml +7 -0
  18. package/.nvmrc +1 -0
  19. package/.prettierignore +8 -0
  20. package/.prettierrc +10 -0
  21. package/.vscode/settings.json +16 -0
  22. package/Dockerfile +19 -0
  23. package/demo.ts +35 -0
  24. package/eslint.config.mjs +55 -0
  25. package/package.json +86 -62
  26. package/server.ts +66 -0
  27. package/src/fetchers/fetch.polyfill.ts +7 -0
  28. package/src/fetchers/index.ts +25 -0
  29. package/src/helpers/creator.helper.ts +95 -0
  30. package/src/helpers/global.helper.ts +70 -0
  31. package/src/helpers/movie.helper.ts +276 -0
  32. package/src/helpers/search-user.helper.ts +19 -0
  33. package/src/helpers/search.helper.ts +66 -0
  34. package/src/helpers/user-ratings.helper.ts +62 -0
  35. package/src/index.ts +50 -0
  36. package/src/interfaces/creator.interface.ts +14 -0
  37. package/src/interfaces/global.ts +36 -0
  38. package/src/interfaces/movie.interface.ts +157 -0
  39. package/src/interfaces/search.interface.ts +32 -0
  40. package/src/interfaces/season.interface.ts +12 -0
  41. package/src/interfaces/user-ratings.interface.ts +21 -0
  42. package/src/services/creator.service.ts +34 -0
  43. package/src/services/movie.service.ts +89 -0
  44. package/src/services/search.service.ts +101 -0
  45. package/src/services/season.service.ts +55 -0
  46. package/src/services/user-ratings.service.ts +106 -0
  47. package/src/vars.ts +16 -0
  48. package/tests/creator.test.ts +182 -0
  49. package/tests/fetchers.test.ts +109 -0
  50. package/tests/global.test.ts +35 -0
  51. package/tests/helpers.test.ts +59 -0
  52. package/tests/mocks/creator-actor.html.ts +2244 -0
  53. package/tests/mocks/creator-composer-empty.html.ts +683 -0
  54. package/tests/mocks/creator-director.html.ts +3407 -0
  55. package/tests/mocks/movie1.html.ts +1430 -0
  56. package/tests/mocks/movie2.html.ts +740 -0
  57. package/tests/mocks/movie3.html.ts +1843 -0
  58. package/tests/mocks/movie4.html.ts +1568 -0
  59. package/tests/mocks/search.html.ts +838 -0
  60. package/tests/mocks/series1.html.ts +1540 -0
  61. package/tests/mocks/userRatings.html.ts +1354 -0
  62. package/tests/movie.test.ts +606 -0
  63. package/tests/search.test.ts +379 -0
  64. package/tests/season.test.ts +115 -0
  65. package/tests/services.test.ts +106 -0
  66. package/tests/user-ratings.test.ts +142 -0
  67. package/tests/vars.test.ts +34 -0
  68. package/tsconfig.json +23 -0
  69. package/vitest.config.mts +10 -0
  70. package/fetchers/fetch.polyfill.d.ts +0 -1
  71. package/fetchers/fetch.polyfill.js +0 -9
  72. package/fetchers/index.d.ts +0 -1
  73. package/fetchers/index.js +0 -27
  74. package/helpers/creator.helper.d.ts +0 -17
  75. package/helpers/creator.helper.js +0 -87
  76. package/helpers/global.helper.d.ts +0 -17
  77. package/helpers/global.helper.js +0 -68
  78. package/helpers/movie.helper.d.ts +0 -26
  79. package/helpers/movie.helper.js +0 -270
  80. package/helpers/search-user.helper.d.ts +0 -5
  81. package/helpers/search-user.helper.js +0 -22
  82. package/helpers/search.helper.d.ts +0 -11
  83. package/helpers/search.helper.js +0 -62
  84. package/helpers/user-ratings.helper.d.ts +0 -13
  85. package/helpers/user-ratings.helper.js +0 -61
  86. package/index.d.ts +0 -24
  87. package/index.js +0 -39
  88. package/interfaces/creator.interface.d.ts +0 -12
  89. package/interfaces/creator.interface.js +0 -2
  90. package/interfaces/global.d.ts +0 -22
  91. package/interfaces/global.js +0 -2
  92. package/interfaces/movie.interface.d.ts +0 -73
  93. package/interfaces/movie.interface.js +0 -2
  94. package/interfaces/search.interface.d.ts +0 -27
  95. package/interfaces/search.interface.js +0 -2
  96. package/interfaces/season.interface.d.ts +0 -11
  97. package/interfaces/season.interface.js +0 -2
  98. package/interfaces/user-ratings.interface.d.ts +0 -18
  99. package/interfaces/user-ratings.interface.js +0 -2
  100. package/services/creator.service.d.ts +0 -6
  101. package/services/creator.service.js +0 -32
  102. package/services/movie.service.d.ts +0 -6
  103. package/services/movie.service.js +0 -59
  104. package/services/search.service.d.ts +0 -5
  105. package/services/search.service.js +0 -80
  106. package/services/season.service.d.ts +0 -9
  107. package/services/season.service.js +0 -42
  108. package/services/user-ratings.service.d.ts +0 -7
  109. package/services/user-ratings.service.js +0 -84
  110. package/vars.d.ts +0 -5
  111. package/vars.js +0 -13
@@ -0,0 +1,32 @@
1
+ import { CSFDScreening } from './global';
2
+ import { CSFDCreator } from './movie.interface';
3
+
4
+ export interface CSFDSearch {
5
+ movies: CSFDSearchMovie[];
6
+ tvSeries: CSFDSearchMovie[];
7
+ creators: CSFDSearchCreator[];
8
+ users: CSFDSearchUser[];
9
+ }
10
+
11
+ export interface CSFDSearchMovie extends CSFDScreening {
12
+ poster: string;
13
+ origins: string[];
14
+ creators: CSFDSearchCreators;
15
+ }
16
+
17
+ export interface CSFDSearchUser {
18
+ id: number;
19
+ user: string;
20
+ userRealName: string;
21
+ avatar: string;
22
+ url: string;
23
+ }
24
+
25
+ export interface CSFDSearchCreator extends CSFDCreator {
26
+ image: string;
27
+ }
28
+
29
+ export interface CSFDSearchCreators {
30
+ directors: CSFDCreator[];
31
+ actors: CSFDCreator[];
32
+ }
@@ -0,0 +1,12 @@
1
+ export type CSFDSeason = {
2
+ description: string | undefined;
3
+ thumbnail: string;
4
+ episodeList: CSFDEpisodeInfo[]
5
+ origin: string;
6
+ }
7
+
8
+ export type CSFDEpisodeInfo = {
9
+ name: string
10
+ seasonEpisodeIdentifier: string;
11
+ linkToDetail: string
12
+ }
@@ -0,0 +1,21 @@
1
+ import { CSFDFilmTypes, CSFDScreening, CSFDStars } from './global';
2
+
3
+ export interface CSFDUserRatings extends CSFDScreening {
4
+ userRating: CSFDStars;
5
+ userDate: string; // TODO datetime
6
+ }
7
+
8
+ export interface CSFDUserRatingConfig {
9
+ includesOnly?: CSFDFilmTypes[];
10
+ excludes?: CSFDFilmTypes[];
11
+ /**
12
+ * Fetch all ratings. (Warning: Use it wisely. Can be detected and banned. Consider using it together with `allPagesDelay` attribute)
13
+ */
14
+ allPages?: boolean;
15
+ /**
16
+ * Delay on each page request. In milliseconds
17
+ */
18
+ allPagesDelay?: number;
19
+ }
20
+
21
+ export type Colors = 'lightgrey' | 'blue' | 'red' | 'grey';
@@ -0,0 +1,34 @@
1
+ import { HTMLElement, parse } from 'node-html-parser';
2
+ import { fetchPage } from '../fetchers';
3
+ import { getBio, getBirthdayInfo, getFilms, getName, getPhoto } from '../helpers/creator.helper';
4
+ import { CSFDCreator } from '../interfaces/creator.interface';
5
+ import { creatorUrl } from '../vars';
6
+
7
+ export class CreatorScraper {
8
+ private person: CSFDCreator;
9
+
10
+ public async creator(creatorId: number): Promise<CSFDCreator> {
11
+ const url = creatorUrl(+creatorId);
12
+ const response = await fetchPage(url);
13
+
14
+ const creatorHtml = parse(response);
15
+
16
+ const asideNode = creatorHtml.querySelector('.creator-about');
17
+ const filmsNode = creatorHtml.querySelector('.creator-filmography');
18
+ this.buildCreator(+creatorId, asideNode, filmsNode);
19
+ return this.person;
20
+ }
21
+
22
+ private buildCreator(id: number, asideEl: HTMLElement, filmsNode: HTMLElement) {
23
+ this.person = {
24
+ id,
25
+ name: getName(asideEl),
26
+ birthday: getBirthdayInfo(asideEl)?.birthday,
27
+ birthplace: getBirthdayInfo(asideEl)?.birthPlace,
28
+ photo: getPhoto(asideEl),
29
+ age: getBirthdayInfo(asideEl)?.age || null,
30
+ bio: getBio(asideEl),
31
+ films: getFilms(filmsNode)
32
+ };
33
+ }
34
+ }
@@ -0,0 +1,89 @@
1
+ import { HTMLElement, parse } from 'node-html-parser';
2
+ import { fetchPage } from '../fetchers';
3
+ import {
4
+ getBoxMovies,
5
+ getColorRating,
6
+ getDescriptions,
7
+ getDuration,
8
+ getGenres,
9
+ getGroup,
10
+ getOrigins,
11
+ getPoster,
12
+ getPremieres,
13
+ getRandomPhoto,
14
+ getRating,
15
+ getRatingCount, getSeasonsInfo,
16
+ getTags,
17
+ getTitle,
18
+ getTitlesOther,
19
+ getTrivia,
20
+ getType,
21
+ getVods,
22
+ getYear
23
+ } from '../helpers/movie.helper';
24
+ import { CSFDFilmTypes } from '../interfaces/global';
25
+ import { CSFDMovie } from '../interfaces/movie.interface';
26
+ import { movieUrl } from '../vars';
27
+
28
+ export class MovieScraper {
29
+ private film: CSFDMovie;
30
+
31
+ public async movie(movieId: number): Promise<CSFDMovie> {
32
+ const url = movieUrl(+movieId);
33
+ const response = await fetchPage(url);
34
+
35
+ const movieHtml = parse(response);
36
+
37
+ const pageClasses = movieHtml.querySelector('.page-content').classNames.split(' ');
38
+ const asideNode = movieHtml.querySelector('.aside-movie-profile');
39
+ const movieNode = movieHtml.querySelector('.main-movie-profile');
40
+ const jsonLd = movieHtml.querySelector('script[type="application/ld+json"]').innerText;
41
+ this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd);
42
+ return this.film;
43
+ }
44
+
45
+ private buildMovie(
46
+ movieId: number,
47
+ el: HTMLElement,
48
+ asideEl: HTMLElement,
49
+ pageClasses: string[],
50
+ jsonLd: string
51
+ ) {
52
+ this.film = {
53
+ id: movieId,
54
+ title: getTitle(el),
55
+ year: getYear(jsonLd),
56
+ duration: getDuration(jsonLd, el),
57
+ descriptions: getDescriptions(el),
58
+ genres: getGenres(el),
59
+ type: getType(el) as CSFDFilmTypes,
60
+ url: movieUrl(movieId),
61
+ origins: getOrigins(el),
62
+ colorRating: getColorRating(pageClasses),
63
+ rating: getRating(asideEl),
64
+ ratingCount: getRatingCount(asideEl),
65
+ titlesOther: getTitlesOther(el),
66
+ poster: getPoster(el),
67
+ photo: getRandomPhoto(el),
68
+ trivia: getTrivia(el),
69
+ creators: {
70
+ directors: getGroup(el, 'Režie'),
71
+ writers: getGroup(el, 'Scénář'),
72
+ cinematography: getGroup(el, 'Kamera'),
73
+ music: getGroup(el, 'Hudba'),
74
+ actors: getGroup(el, 'Hrají'),
75
+ basedOn: getGroup(el, 'Předloha'),
76
+ producers: getGroup(el, 'Produkce'),
77
+ filmEditing: getGroup(el, 'Střih'),
78
+ costumeDesign: getGroup(el, 'Kostýmy'),
79
+ productionDesign: getGroup(el, 'Scénografie')
80
+ },
81
+ vod: getVods(asideEl),
82
+ tags: getTags(asideEl),
83
+ premieres: getPremieres(asideEl),
84
+ related: getBoxMovies(asideEl, 'Související'),
85
+ similar: getBoxMovies(asideEl, 'Podobné'),
86
+ seasons: getSeasonsInfo(el)
87
+ };
88
+ }
89
+ }
@@ -0,0 +1,101 @@
1
+ import { HTMLElement, parse } from 'node-html-parser';
2
+ import { fetchPage } from '../fetchers';
3
+ import { parseIdFromUrl } from '../helpers/global.helper';
4
+ import { getAvatar, getUser, getUserRealName, getUserUrl } from '../helpers/search-user.helper';
5
+ import {
6
+ getColorRating,
7
+ getOrigins,
8
+ getPoster,
9
+ getTitle,
10
+ getType,
11
+ getUrl,
12
+ getYear,
13
+ parsePeople
14
+ } from '../helpers/search.helper';
15
+ import { CSFDSearch, CSFDSearchMovie, CSFDSearchUser } from '../interfaces/search.interface';
16
+ import { searchUrl } from '../vars';
17
+
18
+ export class SearchScraper {
19
+ public async search(text: string): Promise<CSFDSearch> {
20
+ const url = searchUrl(text);
21
+ const response = await fetchPage(url);
22
+
23
+ const html = parse(response);
24
+ const moviesNode = html.querySelectorAll('.main-movies article');
25
+ const usersNode = html.querySelectorAll('.main-users article');
26
+ const tvSeriesNode = html.querySelectorAll('.main-series article');
27
+
28
+ return this.parseSearch(moviesNode, usersNode, tvSeriesNode);
29
+ }
30
+
31
+ private parseSearch(
32
+ moviesNode: HTMLElement[],
33
+ usersNode: HTMLElement[],
34
+ tvSeriesNode: HTMLElement[]
35
+ ) {
36
+ const movies: CSFDSearchMovie[] = [];
37
+ const users: CSFDSearchUser[] = [];
38
+ const tvSeries: CSFDSearchMovie[] = [];
39
+
40
+ moviesNode.map((m) => {
41
+ const url = getUrl(m);
42
+
43
+ const movie: CSFDSearchMovie = {
44
+ id: parseIdFromUrl(url),
45
+ title: getTitle(m),
46
+ year: getYear(m),
47
+ url: `https://www.csfd.cz${url}`,
48
+ type: getType(m),
49
+ colorRating: getColorRating(m),
50
+ poster: getPoster(m),
51
+ origins: getOrigins(m),
52
+ creators: {
53
+ directors: parsePeople(m, 'directors'),
54
+ actors: parsePeople(m, 'actors')
55
+ }
56
+ };
57
+ movies.push(movie);
58
+ });
59
+
60
+ usersNode.map((m) => {
61
+ const url = getUserUrl(m);
62
+
63
+ const user: CSFDSearchUser = {
64
+ id: parseIdFromUrl(url),
65
+ user: getUser(m),
66
+ userRealName: getUserRealName(m),
67
+ avatar: getAvatar(m),
68
+ url: `https://www.csfd.cz${url}`
69
+ };
70
+ users.push(user);
71
+ });
72
+
73
+ tvSeriesNode.map((m) => {
74
+ const url = getUrl(m);
75
+
76
+ const user: CSFDSearchMovie = {
77
+ id: parseIdFromUrl(url),
78
+ title: getTitle(m),
79
+ year: getYear(m),
80
+ url: `https://www.csfd.cz${url}`,
81
+ type: getType(m),
82
+ colorRating: getColorRating(m),
83
+ poster: getPoster(m),
84
+ origins: getOrigins(m),
85
+ creators: {
86
+ directors: parsePeople(m, 'directors'),
87
+ actors: parsePeople(m, 'actors')
88
+ }
89
+ };
90
+ tvSeries.push(user);
91
+ });
92
+
93
+ const search: CSFDSearch = {
94
+ movies: movies,
95
+ users: users,
96
+ tvSeries: tvSeries,
97
+ creators: []
98
+ };
99
+ return search;
100
+ }
101
+ }
@@ -0,0 +1,55 @@
1
+ import { fetchPage } from '../fetchers';
2
+ import { HTMLElement, parse } from 'node-html-parser';
3
+ import { seasonUrl } from '../vars';
4
+ import { CSFDEpisodeInfo, CSFDSeason } from '../interfaces/season.interface';
5
+
6
+ export class SeasonScraper {
7
+ public async season(url: string): Promise<CSFDSeason> {
8
+ const response = await fetchPage(seasonUrl(url));
9
+
10
+ const seasonHtml = parse(response);
11
+
12
+ const movieNode = seasonHtml.querySelector('.main-movie-profile');
13
+
14
+ return this.buildSeason(movieNode);
15
+ }
16
+
17
+ private buildSeason(
18
+ movieNode: HTMLElement
19
+ ): CSFDSeason {
20
+ return {
21
+ origin: this.getOriginFromHtml(movieNode),
22
+ description: this.getDescriptionFromHtml(movieNode),
23
+ thumbnail: this.getThumbnailFromHtml(movieNode),
24
+ episodeList: this.getEpisodeListFromHtml(movieNode),
25
+ }
26
+ }
27
+
28
+ private getOriginFromHtml(movieNode: HTMLElement): string {
29
+ return movieNode.querySelector('.film-info-content .origin').textContent;
30
+ }
31
+
32
+ private getDescriptionFromHtml(movieNode: HTMLElement): string | undefined {
33
+ return movieNode.querySelector('.plot-full')?.textContent;
34
+ }
35
+
36
+ private getThumbnailFromHtml(movieNode: HTMLElement): string {
37
+ return movieNode.querySelector('.film-posters img').getAttribute('src');
38
+ }
39
+
40
+ private getEpisodeListFromHtml(movieNode: HTMLElement): CSFDEpisodeInfo[] {
41
+ return movieNode.querySelectorAll('.film-episodes-list li').map(container => {
42
+ const nameContainer = container.querySelector('.film-title-name')
43
+
44
+ return {
45
+ name: nameContainer.textContent,
46
+ seasonEpisodeIdentifier: container.querySelector('.film-title-info').textContent,
47
+ linkToDetail: nameContainer.getAttribute('href'),
48
+ }
49
+ })
50
+ }
51
+
52
+
53
+
54
+ }
55
+
@@ -0,0 +1,106 @@
1
+ import { HTMLElement, parse } from 'node-html-parser';
2
+ import { fetchPage } from '../fetchers';
3
+ import {
4
+ getColorRating,
5
+ getDate,
6
+ getId,
7
+ getTitle,
8
+ getType,
9
+ getUrl,
10
+ getUserRating,
11
+ getYear,
12
+ sleep
13
+ } from '../helpers/user-ratings.helper';
14
+ import { CSFDColorRating, CSFDStars } from '../interfaces/global';
15
+ import { CSFDUserRatingConfig, CSFDUserRatings } from '../interfaces/user-ratings.interface';
16
+ import { userRatingsUrl } from '../vars';
17
+
18
+ export class UserRatingsScraper {
19
+ private films: CSFDUserRatings[] = [];
20
+
21
+ public async userRatings(
22
+ user: string | number,
23
+ config?: CSFDUserRatingConfig
24
+ ): Promise<CSFDUserRatings[]> {
25
+ let allMovies: CSFDUserRatings[] = [];
26
+ const url = userRatingsUrl(user);
27
+ const response = await fetchPage(url);
28
+
29
+ const items = parse(response);
30
+ const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');
31
+
32
+ // Get number of pages
33
+ const pagesNode = items.querySelector('.pagination');
34
+ const pages = +pagesNode?.childNodes[pagesNode.childNodes.length - 4].rawText || 1;
35
+
36
+ allMovies = this.getPage(config, movies);
37
+
38
+ if (config?.allPages) {
39
+ console.log('User', user, url);
40
+ console.log('Fetching all pages', pages);
41
+ for (let i = 2; i <= pages; i++) {
42
+ console.log('Fetching page', i, 'out of', pages, '...');
43
+ const url = userRatingsUrl(user, i);
44
+ const response = await fetchPage(url);
45
+
46
+ const items = parse(response);
47
+ const movies = items.querySelectorAll('.box-user-rating .table-container tbody tr');
48
+ allMovies = [...this.getPage(config, movies)];
49
+
50
+ // Sleep
51
+ if (config.allPagesDelay) {
52
+ await sleep(config.allPagesDelay);
53
+ }
54
+ }
55
+ return allMovies;
56
+ }
57
+
58
+ return allMovies;
59
+ }
60
+
61
+ private getPage(config: CSFDUserRatingConfig, movies: HTMLElement[]) {
62
+ if (config) {
63
+ if (config.includesOnly?.length && config.excludes?.length) {
64
+ console.warn(
65
+ `node-csfd-api:
66
+ You can not use both parameters 'includesOnly' and 'excludes'.
67
+ Parameter 'includesOnly' will be used now:`,
68
+ config.includesOnly
69
+ );
70
+ }
71
+ }
72
+
73
+ for (const el of movies) {
74
+ const type = getType(el);
75
+
76
+ // Filtering includesOnly
77
+ if (config?.includesOnly?.length) {
78
+ if (config.includesOnly.some((include) => type === include)) {
79
+ this.buildUserRatings(el);
80
+ }
81
+ // Filter exludes
82
+ } else if (config?.excludes?.length) {
83
+ if (!config.excludes.some((exclude) => type === exclude)) {
84
+ this.buildUserRatings(el);
85
+ }
86
+ } else {
87
+ // Without filtering
88
+ this.buildUserRatings(el);
89
+ }
90
+ }
91
+ return this.films;
92
+ }
93
+
94
+ private buildUserRatings(el: HTMLElement) {
95
+ this.films.push({
96
+ id: getId(el),
97
+ title: getTitle(el),
98
+ year: getYear(el),
99
+ type: getType(el),
100
+ url: getUrl(el),
101
+ colorRating: getColorRating(el) as CSFDColorRating,
102
+ userDate: getDate(el),
103
+ userRating: getUserRating(el) as CSFDStars
104
+ });
105
+ }
106
+ }
package/src/vars.ts ADDED
@@ -0,0 +1,16 @@
1
+ export const userRatingsUrl = (user: string | number, page?: number): string =>
2
+ `https://www.csfd.cz/uzivatel/${encodeURIComponent(user)}/hodnoceni/${
3
+ page ? '?page=' + page : ''
4
+ }`;
5
+
6
+ export const movieUrl = (movie: number): string =>
7
+ `https://www.csfd.cz/film/${encodeURIComponent(movie)}/prehled/`;
8
+
9
+ export const creatorUrl = (creator: number | string): string =>
10
+ `https://www.csfd.cz/tvurce/${encodeURIComponent(creator)}`;
11
+
12
+ export const searchUrl = (text: string): string =>
13
+ `https://www.csfd.cz/hledat/?q=${encodeURIComponent(text)}`;
14
+
15
+ export const seasonUrl = (url: string): string =>
16
+ `https://www.csfd.cz/${url}`;
@@ -0,0 +1,182 @@
1
+ import { parse } from 'node-html-parser';
2
+ import { describe, expect, test } from 'vitest';
3
+ import {
4
+ getBio,
5
+ getBirthdayInfo,
6
+ getFilms,
7
+ getName,
8
+ getPhoto
9
+ } from '../src/helpers/creator.helper';
10
+ import { CSFDCreatorScreening } from '../src/interfaces/creator.interface';
11
+ import { actorMock } from './mocks/creator-actor.html';
12
+ import { composerMock } from './mocks/creator-composer-empty.html';
13
+ import { directorMock } from './mocks/creator-director.html';
14
+
15
+ const html = parse(directorMock);
16
+ const asideNode = html.querySelector('.creator-about');
17
+ const filmsNode = html.querySelector('.creator-filmography');
18
+
19
+ const htmlActor = parse(actorMock);
20
+ const asideNodeActor = htmlActor.querySelector('.creator-about');
21
+ const filmsNodeActor = htmlActor.querySelector('.creator-filmography');
22
+
23
+ const htmlComposer = parse(composerMock);
24
+ const asideNodeComposer = htmlComposer.querySelector('.creator-about');
25
+ const filmsNodeComposer = htmlComposer.querySelector('.creator-filmography');
26
+
27
+ describe('Creator info', () => {
28
+ test('Name', () => {
29
+ const creator = getName(asideNode);
30
+ expect(creator).toEqual<string>('Quentin Tarantino');
31
+ });
32
+
33
+ test('Bio', () => {
34
+ const creator = getBio(asideNode);
35
+ expect(creator).toEqual<string>(
36
+ 'Narodil se teprve šestnáctileté Connii McHugh, která mu dala křestní jméno podle své oblíbené postavy Quinta ze seriálu Gunsmoke. Jeho biologickým otcem byl jistý Tony Tarantino, který rodinu opustil když byl Quentin ještě malinký a nikdy o syna nejevil zájem (přesněji řečeno jen do doby, než se potomek stal slavným – pak se na jeho úspěchu pokoušel parazitovat). Jeho náhradním tatínkem se stal hudebník s československými kořeny, který si Connii vzal a Quentina…'
37
+ );
38
+ });
39
+
40
+ test('Photo', () => {
41
+ const creator = getPhoto(asideNode);
42
+ expect(creator).toEqual<string>(
43
+ 'https://image.pmgstatic.com/cache/resized/w100h132crop/files/images/creator/photos/164/515/164515525_b98f8a.jpg'
44
+ );
45
+ });
46
+ });
47
+
48
+ describe('Creator birthday info', () => {
49
+ test('Birthday', () => {
50
+ const creator = getBirthdayInfo(asideNode)?.birthday;
51
+ expect(creator).toEqual<string>('27.03.1963');
52
+ });
53
+
54
+ test('Birthplace', () => {
55
+ const creator = getBirthdayInfo(asideNode)?.birthPlace;
56
+ expect(creator).toEqual<string>('Knoxville, Tennessee, USA');
57
+ });
58
+
59
+ test('Age', () => {
60
+ const creator = getBirthdayInfo(asideNode)?.age;
61
+ expect(creator).toEqual<number>(61);
62
+ });
63
+ });
64
+
65
+ describe("Creator's films", () => {
66
+ test('First film from first section', () => {
67
+ const films = getFilms(filmsNode) as CSFDCreatorScreening[];
68
+ expect(films[0].title).toEqual<string>('The Movie Critic');
69
+ });
70
+
71
+ test('Last film from first section', () => {
72
+ const films = getFilms(filmsNode) as CSFDCreatorScreening[];
73
+ expect(films[films.length - 1].id).toEqual<number>(1051715);
74
+ });
75
+
76
+ test('Year second movie', () => {
77
+ const films = getFilms(filmsNode) as CSFDCreatorScreening[];
78
+ expect(films[1].year).toEqual<number>(2019);
79
+ });
80
+ });
81
+
82
+ // actor
83
+
84
+ describe('Actor info', () => {
85
+ test('Name', () => {
86
+ const creator = getName(asideNodeActor);
87
+ expect(creator).toEqual<string>('Mads Mikkelsen');
88
+ });
89
+
90
+ test('Bio', () => {
91
+ const creator = getBio(asideNodeActor);
92
+ expect(creator).toEqual<string>(
93
+ 'Dánský herec, celým jménem Mads Dittmann Mikkelsen, se narodil v roce 1965 v kodaňské čtvrti Østerbro. Dříve než se vrhl na hereckou dráhu, pracoval 8 let jako profesionální tanečník. Herecké vzdělání získal Mikkelsen na herecké škole při divadle v Århusu. Školu zakončil v roce 1996. Co se týká soukromého života je Mads Mikkelsen, který za svůj nejoblíbenější film považuje Taxikáře od Martina Scorseseho, od roku 1987 ženatý s dánskou choreografkou Hanne Jacobsen.…'
94
+ );
95
+ });
96
+
97
+ test('Photo', () => {
98
+ const creator = getPhoto(asideNodeActor);
99
+ expect(creator).toEqual<string>(
100
+ 'https://image.pmgstatic.com/cache/resized/w100h132crop/files/images/creator/photos/166/233/166233274_298dbd.jpg'
101
+ );
102
+ });
103
+ });
104
+
105
+ describe('Actor birthday info', () => {
106
+ test('Birthday', () => {
107
+ const creator = getBirthdayInfo(asideNodeActor)?.birthday;
108
+ expect(creator).toEqual<string>('22.11.1965');
109
+ });
110
+
111
+ test('Birthplace', () => {
112
+ const creator = getBirthdayInfo(asideNodeActor)?.birthPlace;
113
+ expect(creator).toEqual<string>('Østerbro, København, Dánsko');
114
+ });
115
+
116
+ test('Age', () => {
117
+ const creator = getBirthdayInfo(asideNodeActor)?.age;
118
+ expect(creator).toEqual<number>(58);
119
+ });
120
+ });
121
+
122
+ describe("Creator's films", () => {
123
+ test('First film from first section', () => {
124
+ const films = getFilms(filmsNodeActor) as CSFDCreatorScreening[];
125
+ expect(films[0].title).toEqual<string>('The Billion Dollar Spy');
126
+ });
127
+
128
+ test('Last film from first section', () => {
129
+ const films = getFilms(filmsNodeActor) as CSFDCreatorScreening[];
130
+ expect(films[films.length - 1].id).toEqual<number>(88874);
131
+ });
132
+
133
+ test('Year second movie', () => {
134
+ const films = getFilms(filmsNodeActor) as CSFDCreatorScreening[];
135
+ expect(films[1].year).toEqual<number>(2025);
136
+ });
137
+ });
138
+
139
+ // composer
140
+
141
+ describe('Composer info', () => {
142
+ test('Name', () => {
143
+ const creator = getName(asideNodeComposer);
144
+ expect(creator).toEqual<string>('Sven Mikkelsen');
145
+ });
146
+
147
+ test('Bio', () => {
148
+ const creator = getBio(asideNodeComposer);
149
+ expect(creator).toEqual<string>(null);
150
+ });
151
+
152
+ test('Photo', () => {
153
+ const creator = getPhoto(asideNodeComposer);
154
+ expect(creator).toEqual<string>(
155
+ 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
156
+ );
157
+ });
158
+ });
159
+
160
+ describe('Composer birthday info', () => {
161
+ test('Birthday', () => {
162
+ const creator = getBirthdayInfo(asideNodeComposer)?.birthday;
163
+ expect(creator).toEqual<string>('');
164
+ });
165
+
166
+ test('Birthplace', () => {
167
+ const creator = getBirthdayInfo(asideNodeComposer)?.birthPlace;
168
+ expect(creator).toEqual<string>('');
169
+ });
170
+
171
+ test('Birthplace', () => {
172
+ const creator = getBirthdayInfo(asideNodeComposer)?.age;
173
+ expect(creator).toEqual(null);
174
+ });
175
+ });
176
+
177
+ describe("Creator's films", () => {
178
+ test('First film from first section', () => {
179
+ const films = getFilms(filmsNodeComposer) as CSFDCreatorScreening[];
180
+ expect(films[0].title).toEqual<string>('Spolu');
181
+ });
182
+ });