Пример #1
0
    def test_main_no_errors(self, mock_player):
        mock_player.get_current_url = mock.MagicMock()
        mock_player.dialog_ok = mock.MagicMock()

        addon.main()

        mock_player.dialog_ok.assert_not_called()
Пример #2
0
def test_index(mocker, index, main, xbmcplugin, ExtendedListItem):
    main()
    expected_results = [
        (handle, plugin.format("profile"), u"Профиль", False),
        (handle, plugin.format("search?type=None"), u"Поиск", False),
        (handle, plugin.format("items?type=None"), u"Последние", True),
        (handle, plugin.format("items?type=None&shortcut=%2Fpopular"),
         u"Популярные", True),
        (handle, plugin.format("items?type=None&shortcut=%2Fhot"),
         u"Популярные", True), (handle, plugin.format("tv"), u"ТВ", True),
        (handle, plugin.format("bookmarks"), u"Закладки", True),
        (handle, plugin.format("watching"), u"Я смотрю", True),
        (handle, plugin.format("watching_movies"), u"Недосмотренные", True),
        (handle, plugin.format("collections"), u"Подборки", True),
        (handle, plugin.format("item_index?type=movie"), u"Фильмы", True),
        (handle, plugin.format("item_index?type=serial"), u"Сериалы", True),
        (handle, plugin.format("item_index?type=tvshow"), u"ТВ шоу", True),
        (handle, plugin.format("item_index?type=4k"), u"4K", True),
        (handle, plugin.format("item_index?type=3d"), u"3D", True),
        (handle, plugin.format("item_index?type=concert"), u"Концерты", True),
        (handle, plugin.format("item_index?type=documovie"),
         u"Документальные фильмы", True),
        (handle, plugin.format("item_index?type=docuserial"),
         u"Документальные сериалы", True)
    ]
    for result in expected_results:
        handle_, link, title, is_directory = result
        ExtendedListItem.assert_any_call(title.encode("utf-8"))
        li = ExtendedListItem()
        xbmcplugin.addDirectoryItem.assert_any_call(handle_, link, li,
                                                    is_directory)
    xbmcplugin.endOfDirectory.assert_called_once_with(handle)
Пример #3
0
def test_view_seasons(main, view_seasons, ExtendedListItem, xbmcplugin):
    from resources.lib.utils import video_info

    main()
    item = actionView_seasons_response["item"]
    i = actionView_seasons_response["item"]["id"]
    seasons = actionView_seasons_response["item"]["seasons"]
    for season in seasons:
        ExtendedListItem.assert_any_call(
            "Сезон {}".format(season["number"]),
            video_info=video_info(item, {
                "season": season["number"],
                "playcount": -1,
                "mediatype": "season"
            }),
            poster=item["posters"]["big"],
            properties={"id": item["id"]},
            addContextMenuItems=True,
        )
        link = plugin.format(
            "view_season_episodes?season_number={}&id={}".format(
                season["number"], i))
        xbmcplugin.addDirectoryItem.assert_any_call(handle, link,
                                                    ExtendedListItem(), True)
    xbmcplugin.endOfDirectory.assert_called_once_with(handle,
                                                      cacheToDisc=False)
Пример #4
0
def test_index(mocker, index, main, xbmcplugin, ExtendedListItem):
    from resources.lib.utils import build_icon_path

    main()
    expected_results = [
        (handle, plugin.format("profile"), u"Профиль", "profile", False),
        (handle, plugin.format("search?type=None"), u"Поиск", "search", False),
        (handle, plugin.format("bookmarks"), u"Закладки", "bookmarks", True),
        (handle, plugin.format("watching"), u"Я смотрю", "watching", True),
        (handle, plugin.format("watching_movies"), u"Недосмотренные",
         "watching_movies", True),
        (handle, plugin.format("items?type=None"), u"Последние", "new", True),
        (
            handle,
            plugin.format("items?type=None&shortcut=%2Fpopular"),
            u"Популярные",
            "popular",
            True,
        ),
        (handle, plugin.format("items?type=None&shortcut=%2Fhot"), u"Горячие",
         "hot", True),
        (handle, plugin.format("tv"), u"ТВ", "tv", True),
        (handle, plugin.format("collections"), u"Подборки", "collections",
         True),
        (handle, plugin.format("item_index?type=movie"), u"Фильмы", "movie",
         True),
        (handle, plugin.format("item_index?type=serial"), u"Сериалы", "serial",
         True),
        (handle, plugin.format("item_index?type=tvshow"), u"ТВ шоу", "tvshow",
         True),
        (handle, plugin.format("item_index?type=4k"), u"4K", "4k", True),
        (handle, plugin.format("item_index?type=3d"), u"3D", "3d", True),
        (handle, plugin.format("item_index?type=concert"), u"Концерты",
         "concert", True),
        (
            handle,
            plugin.format("item_index?type=documovie"),
            u"Документальные фильмы",
            "documovie",
            True,
        ),
        (
            handle,
            plugin.format("item_index?type=docuserial"),
            u"Документальные сериалы",
            "docuserial",
            True,
        ),
    ]
    for result in expected_results:
        handle_, link, title, icon, is_directory = result
        img = build_icon_path(icon)
        ExtendedListItem.assert_any_call(title.encode("utf-8"),
                                         iconImage=img,
                                         thumbnailImage=img)
        li = ExtendedListItem()
        xbmcplugin.addDirectoryItem.assert_any_call(handle_, link, li,
                                                    is_directory)
    xbmcplugin.endOfDirectory.assert_called_once_with(handle)
Пример #5
0
    def test_main_error_network(self, mock_player, mock_resolve):
        mock_resolve.side_effect = addon.kinoman_api.NetworkError
        mock_player.get_current_url = mock.MagicMock()
        mock_player.dialog_ok = mock.MagicMock()

        addon.main()

        mock_player.dialog_ok.assert_called_once_with(
            "Kinoman.Uz", "Проблема сети, попробуйте позже")
Пример #6
0
    def test_main_error_missing_video(self, mock_player, mock_resolve):
        mock_resolve.side_effect = addon.kinoman_api.MissingVideoError
        mock_player.get_current_url = mock.MagicMock()
        mock_player.dialog_ok = mock.MagicMock()

        addon.main()

        mock_player.dialog_ok.assert_called_once_with("Kinoman.Uz",
                                                      "Видео отсутствует")
Пример #7
0
    def test_main_error_login_error(self, mock_player, mock_kinoman,
                                    mock_resolve):
        mock_kinoman.LoginError = Exception
        mock_resolve.side_effect = mock_kinoman.LoginError("test login error")
        mock_player.get_current_url = mock.MagicMock()
        mock_player.dialog_ok = mock.MagicMock()

        addon.main()

        mock_player.dialog_ok.assert_called_once_with(
            "Kinoman.Uz", "Ошибка авторизации: test login error")
Пример #8
0
def test_view_season_episodes(request, main, view_season_episodes,
                              ExtendedListItem, xbmcplugin):
    from resources.lib.utils import video_info

    main()
    item = actionView_seasons_response["item"]
    season = item["seasons"][0]
    watching_season = watching_info_response_with_seasons["item"]["seasons"][
        season["number"] - 1]
    i = item["id"]
    for episode in season["episodes"]:
        watching_episode = watching_season["episodes"][episode["number"] - 1]
        episode_title = "s{:02d}e{:02d}".format(season["number"],
                                                episode["number"])
        if episode["title"]:
            episode_title = "{} | {}".format(episode_title,
                                             episode["title"].encode("utf-8"))
        info = video_info(
            item,
            {
                "season": season["number"],
                "episode": episode["number"],
                "tvshowtitle": episode["title"],
                "time": watching_episode["time"],
                "duration": watching_episode["duration"],
                "playcount": watching_episode["status"],
                "mediatype": "episode",
            },
        )
        link = plugin.format("play?{}".format(
            urlencode({
                "id": i,
                "index": episode["number"]
            })))
        ExtendedListItem.assert_any_call(
            episode_title,
            thumbnailImage=episode["thumbnail"],
            poster=item["posters"]["big"],
            video_info=info,
            properties={
                "id": item["id"],
                "isPlayable": "true"
            },
            addContextMenuItems=True,
        )
        xbmcplugin.addDirectoryItem.assert_any_call(handle, link,
                                                    ExtendedListItem(), False)
    xbmcplugin.setContent.assert_called_once_with(handle, "episodes")
    xbmcplugin.endOfDirectory.assert_called_once_with(handle,
                                                      cacheToDisc=False)
    def test_search(self, mock_print):
        with mock.patch(
            "sys.argv", ["plugin://test.plugin", "1", "/search/мастер и маргарита/"]
        ):
            addon.main()

        search_results = mock_print.call_args[0][0]

        for video in search_results:
            if video["path"] == "/movie/166/":
                self.assertEqual(video["label"], "Мастер и Маргарита (2005)")
                break
        else:
            self.fail("Test video not found in the listing, probably something wrong")
    def test_search_filter(self, mock_print):
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/search_filter/"]):
            addon.main()

        # 4 steps -> video category, age rating, genre, year
        for i in range(1, 5):
            next_menu = mock_print.call_args[0][0][1]

            with mock.patch(
                "sys.argv", ["plugin://test.plugin", "1", next_menu["path"]]
            ):
                mock_print.reset_mock()
                addon.main()

            if i <= 3:
                self.assertRegexpMatches(
                    next_menu["path"], r"^/search_filter/{}/.*$".format(i)
                )
            else:
                self.assertRegexpMatches(next_menu["path"], r"^/list_movies/.*$")
Пример #11
0
def test_view_episodes(request, main, view_episodes, ExtendedListItem,
                       xbmcplugin):
    from resources.lib.addonutils import video_info
    main()
    item = actionView_without_seasons_response["item"]
    watching_info = watching_info_response_without_seasons["item"]
    for video in item["videos"]:
        watching_episode = watching_info["videos"][video["number"] - 1]
        episode_title = "e{:02d}".format(video["number"])
        if video["title"]:
            episode_title = "{} | {}".format(episode_title,
                                             video["title"].encode("utf-8"))
        info = video_info(
            item, {
                "episode": video["number"],
                "playcount": video["watched"],
                "time": watching_episode["time"],
                "duration": watching_episode["duration"],
                "mediatype": "episode"
            })
        link = plugin.format("play?{}".format(
            urlencode({
                "id": item["id"],
                "title": episode_title,
                "video_data": json.dumps(video),
                "video_info": json.dumps(info),
                "poster": item["posters"]["big"]
            })))
        ExtendedListItem.assert_any_call(episode_title,
                                         thumbnailImage=video["thumbnail"],
                                         video_info=info,
                                         poster=item["posters"]["big"],
                                         properties={
                                             "id": item["id"],
                                             "isPlayable": "true"
                                         },
                                         addContextMenuItems=True)
        xbmcplugin.addDirectoryItem.assert_any_call(handle, link,
                                                    ExtendedListItem(), False)
    xbmcplugin.setContent.assert_called_once_with(handle, "episodes")
    xbmcplugin.endOfDirectory.assert_called_once_with(handle)
Пример #12
0
def test_play(play, main, ExtendedListItem, xbmcplugin):
    stream, video_quality = play
    main()
    title = actionPlay_response["item"]["title"].encode("utf-8")
    link = "https://example.com/{}/{}".format(stream,
                                              video_quality.rstrip("p"))
    ExtendedListItem.assert_called_with(
        title,
        path=link,
        properties={
            "id": str(actionPlay_response["item"]["id"]),
            "play_duration": 0,
            "play_resumetime": 0,
            "video_number": 1,
            "season_number": "",
            "playcount": 0
        },
        poster=None,
        subtitles=[])
    li = ExtendedListItem(title, path=link)
    xbmcplugin.setResolvedUrl.assert_called_once_with(handle, True, li)
    def test_movie_playback(self, mock_print, mock_play):
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/movie/73/"]):
            addon.main()

        video_types = mock_print.call_args[0][0]

        for video in video_types:
            self.assertRegexpMatches(video["path"], r"^/play/73/.*$")
            self.assertRegexpMatches(video["label"], r"^Воспроизвести \(.*\)$")

            with mock.patch("sys.argv", ["plugin://test.plugin", "1", video["path"]]):
                mock_play.reset_mock()
                addon.main()

                playback_url = mock_play.call_args[0][0]

                self.assertRegexpMatches(
                    playback_url,
                    r"^https://(online|dl)[0-9]+\.kinoman\.uz/dl/(online|movie)"
                    r"/[0-9]+/.*\..*?$",
                )
    def test_search_history(self, mock_print):
        addon.player.set_setting("search_history_status", True)
        addon.search_clear()

        with mock.patch(
            "sys.argv", ["plugin://test.plugin", "1", "/search/test search/"]
        ):
            addon.main()

        mock_print.reset_mock()
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/"]):
            addon.main()

        main_menu = mock_print.call_args[0][0]

        for item in main_menu:
            if item["path"] == "/search_history/":
                break
        else:
            self.fail("Search history menu is missing with nonempty history")

        mock_print.reset_mock()
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/search_history/"]):
            addon.main()

        search_menu = mock_print.call_args[0][0]

        self.assertEqual(search_menu[-1]["path"], "/search/test%20search/")
        self.assertEqual(search_menu[-1]["label"], "test search")

        addon.search_clear()
        addon.player.set_setting("search_history_status", False)
    def test_series_playback(self, mock_print, mock_play):
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/movie/166/"]):
            addon.main()

        video_types = mock_print.call_args[0][0]

        for video in video_types:
            self.assertRegexpMatches(video["path"], r"^/movie/166/[a-z]+/$")
            self.assertRegexpMatches(video["label"], r"^Смотреть серии \(.*\)$")

            with mock.patch("sys.argv", ["plugin://test.plugin", "1", video["path"]]):
                mock_print.reset_mock()
                addon.main()

                episodes_list = mock_print.call_args[0][0]

                for e_video in [episodes_list[0], episodes_list[-1]]:
                    self.assertRegexpMatches(
                        e_video["path"], r"^/play/166/.*?$",
                    )

                    with mock.patch(
                        "sys.argv", ["plugin://test.plugin", "1", e_video["path"]]
                    ):
                        mock_play.reset_mock()
                        addon.main()

                        playback_url = mock_play.call_args[0][0]

                        self.assertRegexpMatches(
                            playback_url,
                            r"^https://(online|dl)[0-9]+\.kinoman\.uz/dl/(online|movie)"
                            r"/[0-9]+/.*\..*?$",
                        )
Пример #16
0
def test_items(main, items, ExtendedListItem, xbmcplugin, mocker):
    from resources.lib.addonutils import video_info, trailer_link
    from resources.lib.addonworker import mediatype_map
    main()

    def make_info(item):
        extra_info = {
            "trailer": trailer_link(item),
            "mediatype": mediatype_map[item["type"]]
        }
        if item["type"] not in ["serial", "docuserial", "tvshow"]:
            extra_info.update({"time": 0, "duration": 1, "playcount": 0})
        return json.dumps(video_info(item, extra_info))

    expected_results = []
    for item in actionItems_response["items"]:
        expected_results.append({
            "title": item["title"].encode("utf-8"),
            "id": item["id"],
            "poster": item["posters"]["big"],
            "video_info": make_info(item)
        })
    links = [
        plugin.format("play?{}".format(urlencode(expected_results[0]))),
        plugin.format("play?{}".format(urlencode(expected_results[1]))),
        plugin.format("view_seasons?id={}".format(expected_results[2]["id"])),
        plugin.format("view_seasons?id={}".format(expected_results[3]["id"])),
        plugin.format("view_seasons?id={}".format(expected_results[4]["id"])),
    ]
    is_dirs = [False, False, True, True, True]
    for result, link, is_dir in zip(expected_results, links, is_dirs):
        ExtendedListItem.assert_any_call(
            result["title"],
            poster=result["poster"],
            properties={"id": result["id"]},
        )
        li = ExtendedListItem()
        xbmcplugin.addDirectoryItem.assert_any_call(handle, link, li, is_dir)
    xbmcplugin.endOfDirectory.assert_called_once_with(handle)
    def test_movie_sections(self, mock_print):
        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/"]):
            addon.main()

        movie_sections = mock_print.call_args[0][0]

        for section in movie_sections:
            if section["label"] == "Избранное":
                break

            with mock.patch("sys.argv", ["plugin://test.plugin", "1", section["path"]]):
                mock_print.reset_mock()
                addon.main()

                movies_list = mock_print.call_args[0][0]

                self.assertRegexpMatches(movies_list[0]["path"], r"^/movie/[0-9]+/$")

                # Checking if paginator works by going to last two pages
                # of the list (if this list has multiple pages)
                if movies_list[-1]["label"].startswith("-->"):
                    last_page = int(
                        re.search(
                            r"^--> \(2 / ([0-9]+)\)$", movies_list[-1]["label"]
                        ).group(1)
                    )

                    for page_n in range(last_page - 1, last_page + 1):
                        with mock.patch(
                            "sys.argv",
                            [
                                "plugin://test.plugin",
                                "1",
                                section["path"] + "&page={}".format(page_n),
                            ],
                        ):
                            mock_print.reset_mock()
                            addon.main()

                            page_movies = mock_print.call_args[0][0]

                            # I think there is an off-by-one error somewhere on server
                            # side, it glitched once, so putting this special case here
                            if not page_movies and page_n == last_page:
                                continue

                            if page_n == last_page - 1:
                                self.assertRegexpMatches(
                                    page_movies[-1]["label"],
                                    r"^--> \({} / {}\)$".format(last_page, last_page),
                                )
                            elif page_n == last_page:
                                self.assertNotRegexpMatches(
                                    page_movies[-1]["label"],
                                    r"^--> \([0-9]+ / [0-9]+\)$",
                                )
Пример #18
0
# import the kodi python modules we are going to use
# see the kodi api docs to find out what functionality each module provides
import xbmc
import xbmcaddon
import sys
import addon

# getting the assetTYPE so we can later confirm that it's a movie or tvshow

assetTYPE = xbmc.getInfoLabel('ListItem.DBtype')

#calling the main function if assetTYPE is movie or tvshow

if assetTYPE == 'movie' or assetTYPE == 'tvshow':
    addon.main()
else:
    assetMsg = "Invalid item selected: '%s'" % assetTYPE
    xbmc.executebuiltin("Notification(\"Tag Quick Edit\", \"%s\")" % assetMsg)
Пример #19
0
def exploration_loop(log):
    import addon
    start_time = time.time()
    entry_point_reached = False

    # Init Route to root
    root = Route(label='Root menu', path=[1])
    Route.add_route_to_explore(root)

    while (Route.continue_epxloration()):
        log.debug('Loop entry')

        current_route = Route.get_route_to_explore()

        # Check if the entry point was reached
        if len(current_route.path) == len(
                Config.get('entry_point')) and not entry_point_reached:
            log.debug('Entry point ({}) reached'.format(
                Config.get('entry_point')))
            entry_point_reached = True

        # Hock sys.argv
        with mock.patch('sys.argv', current_route.get_fake_sys_argv()):

            if Config.get('autoreload_addon'):
                # We need to reload the addon module in order to be able
                # to modify the source code of the addon on the fly without restarting
                # the simulator
                # (usefull during dev)
                for k, v in sys.modules.items():
                    # print(str(k) + ' :: ' + str(v))
                    if 'plugin.video.catchuptvandmore' in str(v) and \
                            'plugin.video.catchuptvandmore/addon.py' not in str(v):
                        # print('\tRELOAD')
                        reload(v)
                reload(addon)

            # We need to clean this var
            RuntimeErrorCQ.last_error_message = ""

            # Simulate the addon execution
            addon.main()

            # We have to know the next item to epxlore
            # If next_item = -2 we just reload the addon we the same route
            next_item = -2

            # If an error was trigger
            if RuntimeErrorCQ.last_menu_triggered_error:

                log.warn('')
                log.warn(
                    WARNING +
                    ' The last selection triggered an error (see log above) ' +
                    WARNING)
                log.warn('')

                error = RuntimeErrorCQ(path=Route.pretty_exploring_routes())
                print(error)
                RuntimeErrorCQ.reset_error_trigger()

                if len(RuntimeErrorCQ.all_errors) >= Config.get(
                        'exit_after_x_errors'):
                    log.info(
                        'Max number of error reached ({}) --> Exit'.format(
                            Config.get('exit_after_x_errors')))
                    next_item = -1
                else:
                    log.info(
                        '[DEBUG] Max number of error not reached --> Go back')
                    next_item = 0

            # Else if the current directory is a playable item
            elif Directory.is_current_directory_playable():
                item = Directory.current_directory.items[1]
                log.info('Playable URL: {}'.format(item.url))
                next_item = 0
                if not Config.get('disable_video_player'):
                    player = Player(item.url)
                    player.play()

            # Else if succeeded is False (Happen when "No video found" notif is trigger)
            elif Directory.current_directory.succeeded is False:
                log.info(
                    'endOfDirectory was called with succeeded=False --> Go back'
                )
                next_item = 0

            # Else print the current directory
            else:
                print(Directory.current_directory)
                print(Route.pretty_exploring_routes() + '\n')

                # If the entry_point was not reached we follow the entry point path
                if not entry_point_reached:
                    next_item = Config.get('entry_point')[len(
                        current_route.path)]
                    if next_item == 'R':
                        next_item = randint(
                            1, len(Directory.current_directory.items))
                        log.info(
                            'Entry point not yet reached --> random next item: {}'
                            .format(next_item))
                    else:
                        next_item = int(next_item)
                        log.info(
                            'Entry point not yet reached --> next item: {}'.
                            format(next_item))

                # Else if we are in auto exploration
                elif Config.get('auto_exploration'):
                    log.debug('Auto exploration mode')
                    # If needed, add items of the current menu to explore later
                    AutoExploration.add_items_current_menu(
                        current_route.path, Directory.current_directory)

                    # We wait a fake time
                    sys.stdout.flush()
                    time.sleep(Config.get('wait_time'))

                    # We ask for the next item to epxlore
                    next_item = AutoExploration.next_item_to_explore(
                        current_route.path, Directory.current_directory)
                    log.info(
                        'next_item selected by auto exploration: {}'.format(
                            next_item))

                # Else we ask the user to choose the next item number
                else:
                    # We wait the user input
                    try:
                        sys.stdout.flush()
                        next_item = int(
                            input(
                                'Next item to select? (-1 to exit, <enter> to reload same directory)\n'
                            ))
                        log.info('Choosen next_item: {}'.format(next_item))

                    except Exception:
                        pass
                    print('')

            # Check for timeout
            delta_time = time.time() - start_time
            if Config.get('timeout') != -1 and delta_time >= Config.get(
                    'timeout'):
                log.warn('AUTO EXPLORATION TIMEOUT --> Exit exploration')
                next_item = -1

            # Else if the user wants to exit the simulator, let's break the loop
            if next_item == -1:
                break

            if Directory.current_directory is None:
                next_item = -2

            else:
                # If there is no item for this value, reload the same menu to prevent error
                if next_item > len(Directory.current_directory.items) or (
                        next_item == 0 and len(current_route.path) <= 1):
                    next_item = -2

            # If next_item has the default value just reload the same menu
            if next_item == -2:
                pass

            # Else if the user want to go back in the previous menu
            elif next_item == 0:
                Route.previous_route()

            # Else if the user want an item
            else:
                selected_item = Directory.current_directory.items[next_item]
                Route.add_item_to_explore(selected_item)
    def test_root(self, mock_print):
        expected_result = [
            {
                "label": "Фильмы",
                "path": "/list_movies/?category=movies&"
                "content_type_id=1&genre_black_list=12",
                "is_folder": True,
            },
            {
                "label": "Фильмы (премьеры)",
                "path": "/list_movies/?category=movies&"
                "content_type_id=1&genre_black_list=12&sort_type=1",
                "is_folder": True,
            },
            {
                "label": "Сериалы",
                "path": "/list_movies/?category=tv-series&"
                "content_type_id=2&genre_black_list=12",
                "is_folder": True,
            },
            {
                "label": "Сериалы (премьеры)",
                "path": "/list_movies/?category=tv-series&"
                "content_type_id=2&genre_black_list=12&sort_type=1",
                "is_folder": True,
            },
            {
                "label": "Мультфильмы",
                "path": "/list_movies/?category=cartoons&"
                "content_type_id=0&genre_list=12",
                "is_folder": True,
            },
            {
                "label": "Мультфильмы (премьеры)",
                "path": "/list_movies/?category=cartoons&"
                "content_type_id=0&genre_list=12&sort_type=1",
                "is_folder": True,
            },
            {
                "label": "ТВ-программы",
                "path": "/list_movies/?category=tv-shows&"
                "content_type_id=3&genre_black_list=12",
                "is_folder": True,
            },
            {
                "label": "ТВ-программы (премьеры)",
                "path": "/list_movies/?category=tv-shows&"
                "content_type_id=3&genre_black_list=12&sort_type=1",
                "is_folder": True,
            },
            {
                "label": "Видеоблоги",
                "path": "/list_movies/?category=vlogs&"
                "content_type_id=4&genre_black_list=12",
                "is_folder": True,
            },
            {
                "label": "Видеоблоги (премьеры)",
                "path": "/list_movies/?category=vlogs&"
                "content_type_id=4&genre_black_list=12&sort_type=1",
                "is_folder": True,
            },
            {
                "label": "Избранное",
                "path": "/list_movies/?category=favorite&content_type_id=0&favorite=1"
                "&title=%D0%B8%D0%B7%D0%B1%D1%80%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5",
                "is_folder": True,
            },
            {
                "label": "Поиск по фильтру",
                "path": "/search_filter/",
                "video_data": {"art": {"icon": "DefaultAddonsSearch.png"}},
                "is_folder": True,
            },
            {
                "label": "Поиск",
                "path": "/search/",
                "video_data": {"art": {"icon": "DefaultAddonsSearch.png"}},
                "is_folder": True,
            },
        ]

        with mock.patch("sys.argv", ["plugin://test.plugin", "1", "/"]):
            addon.main()

        mock_print.assert_called_once_with(expected_result, cache=False)