# Copyright (c) 2013 - 2021 <NAME>
# See the file license.txt for copying permission.

import sublime  # type: ignore
from unittesting import DeferrableTestCase  # type: ignore
from os import path
from typing import List, Tuple, Dict, Generator
try:
    from lib import settings, entities
except ImportError:
    # If we're running these tests in UnitTesting, then we need to use
    # The package name - Tab Filter - so let's grab import lib and try again.
    from importlib import import_module
    settings = import_module(".lib.settings", "Tab Filter")
    entities = import_module(".lib.entities", "Tab Filter")

TabSetting = settings.TabSetting
ShowCaptionsTabSetting = settings.ShowCaptionsTabSetting
IncludePathTabSetting = settings.IncludePathTabSetting
ShowGroupCaptionTabSetting = settings.ShowGroupCaptionTabSetting
Tab = entities.Tab

DEFAULT_SETINGS = settings.DEFAULT_SETINGS


class BaseSettingsTestCase(DeferrableTestCase):
    """Base settings test case to set up boiler plate methods."""
    settings: sublime.Settings
    layout: Dict[str, List]

    def setUp(self) -> None:
        self.settings = sublime.load_settings("tabfilter.sublime-settings")
        self.layout = sublime.active_window().layout()
        for setting in DEFAULT_SETINGS:
            self.settings.set(setting, DEFAULT_SETINGS[setting])

        # Close any existing views so as to avoid polluting the results.
        for view in sublime.active_window().views():
            view.window().focus_view(view)
            view.window().run_command("close_file")

    def tearDown(self) -> None:
        # Restore the original layout
        sublime.active_window().set_layout(self.layout)

        for view in sublime.active_window().views():
            view.window().focus_view(view)
            view.set_scratch(True)
            view.window().run_command("close_file")


class DefaultSettingsTestCase(BaseSettingsTestCase):
    def test_defaults(self) -> None:
        """Tests that the default settings are honoured."""

        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        data_set: Tuple[Tuple[TabSetting, bool, str], ...] = (
            (
                ShowCaptionsTabSetting,
                DEFAULT_SETINGS["show_captions"],
                "show_captions"
            ),
            (
                IncludePathTabSetting,
                DEFAULT_SETINGS["include_path"],
                "include_path"
            ),
            (
                ShowGroupCaptionTabSetting,
                DEFAULT_SETINGS["show_group_caption"],
                "show_group_caption"
            )
        )

        for (cls, enabled, caption) in data_set:
            with self.subTest(cls=cls, enabled=enabled, caption=caption):
                inst = cls(
                    self.settings,
                    sublime.active_window()
                )  # type: ignore
                self.assertEqual(enabled, inst.is_enabled())
                self.assertListEqual(tabs, inst.apply(tabs))


class ShowCaptionsTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Show Captions Tab Settings."""

    def test_setting_disabled(self) -> None:
        """Tests with the setting disabled."""
        self.settings.set("show_captions", False)
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_current_file(self) -> Generator[int, None, None]:
        """Tests detecting current file."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )
        bar_fixture: str = path.normpath(
            path.join(dir, "./fixtures/bar.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        bar_view: sublime.View = sublime.active_window().open_file(bar_fixture)

        data_set: Tuple[Tuple[List[Tab], List[List[str]], sublime.View], ...]

        data_set = (
            ([Tab(foo_view), Tab(bar_view)], [['Current File'], []], foo_view),
            ([Tab(foo_view), Tab(bar_view)], [[], ['Current File']], bar_view),
        )

        yield 100

        for (tabs, captions, view) in data_set:
            with self.subTest(tabs=tabs, captions=view, view=view):
                view.window().focus_view(view)
                self.assertTrue(setting.is_enabled())
                self.assertListEqual(tabs, setting.apply(tabs))
                actual = []
                for tab in tabs:
                    actual.append(tab.get_captions())
                self.assertListEqual(captions, actual)

    def test_unsaved_file(self) -> None:
        """Tests detecting unsaved files."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved File"],
            tabs[0].get_captions()
        )

    def test_unsaved_changes(self) -> Generator[int, None, None]:
        """Tests detecting unsaved changes."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)

        sublime.set_timeout(
            lambda: foo_view.run_command("insert", {"characters": "foo"}),
            100
        )

        yield 100

        tabs: List[Tab] = [Tab(foo_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved Changes"],
            tabs[0].get_captions()
        )

    def test_read_only(self) -> None:
        """Tests detecting read only views."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        scratch_view.set_read_only(True)
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved File", "Read Only"],
            tabs[0].get_captions()
        )


class IncludePathTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Include path Tab Settings."""

    def test_setting_disabled(self) -> Generator[int, None, None]:
        """Tests with the setting disabled."""
        self.settings.set("include_path", False)
        setting: IncludePathTabSetting = IncludePathTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        expected = path.basename(foo_fixture)

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        tabs: List[Tab] = [Tab(foo_view)]

        yield 100

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertEqual(expected, tabs[0].get_title())
        self.assertEqual(foo_fixture, tabs[0].get_subtitle())

    def test_with_file_view(self) -> Generator[int, None, None]:
        """Tests with the setting disabled."""
        self.settings.set("include_path", True)
        setting: IncludePathTabSetting = IncludePathTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        tabs: List[Tab] = [Tab(foo_view)]

        yield 100

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertEqual(foo_fixture, tabs[0].get_title())
        self.assertEqual(foo_fixture, tabs[0].get_subtitle())


class ShowGroupCaptionsTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Show Group Captions Tab Settings."""

    def test_setting_disabled(self) -> None:
        """Tests with the setting disabled."""
        self.settings.set("show_group_caption", False)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_single_group(self) -> None:
        """Tests applying to a single group (no caption expected)."""
        self.settings.set("show_group_caption", True)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        # single column layout
        layout: Dict[str, List] = {
            "cells": [[0, 0, 1, 1]],
            "cols": [0.0, 1.0],
            "rows": [0.0, 1.0]
        }

        sublime.active_window().set_layout(layout)

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_multiple_groups(self) -> None:
        """Tests applying to multiple groups."""
        self.settings.set("show_group_caption", True)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        second_view: sublime.View = sublime.active_window().new_file()

        # 2 column layout
        layout: Dict[str, List] = {
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]],
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0]
        }

        sublime.active_window().set_layout(layout)
        sublime.active_window().set_view_index(second_view, group=1, idx=0)

        tabs: List[Tab] = [Tab(scratch_view), Tab(second_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        captions: List[List[str]] = [tab.get_captions() for tab in tabs]
        self.assertListEqual([["Group: 1"], ["Group: 2"]], captions)

# Copyright (c) 2013 - 2021 <NAME>
# See the file license.txt for copying permission.

import sublime  # type: ignore
from unittesting import DeferrableTestCase  # type: ignore
from os import path
from typing import List, Tuple, Dict, Generator
try:
    from lib import settings, entities
except ImportError:
    # If we're running these tests in UnitTesting, then we need to use
    # The package name - Tab Filter - so let's grab import lib and try again.
    from importlib import import_module
    settings = import_module(".lib.settings", "Tab Filter")
    entities = import_module(".lib.entities", "Tab Filter")

TabSetting = settings.TabSetting
ShowCaptionsTabSetting = settings.ShowCaptionsTabSetting
IncludePathTabSetting = settings.IncludePathTabSetting
ShowGroupCaptionTabSetting = settings.ShowGroupCaptionTabSetting
Tab = entities.Tab

DEFAULT_SETINGS = settings.DEFAULT_SETINGS


class BaseSettingsTestCase(DeferrableTestCase):
    """Base settings test case to set up boiler plate methods."""
    settings: sublime.Settings
    layout: Dict[str, List]

    def setUp(self) -> None:
        self.settings = sublime.load_settings("tabfilter.sublime-settings")
        self.layout = sublime.active_window().layout()
        for setting in DEFAULT_SETINGS:
            self.settings.set(setting, DEFAULT_SETINGS[setting])

        # Close any existing views so as to avoid polluting the results.
        for view in sublime.active_window().views():
            view.window().focus_view(view)
            view.window().run_command("close_file")

    def tearDown(self) -> None:
        # Restore the original layout
        sublime.active_window().set_layout(self.layout)

        for view in sublime.active_window().views():
            view.window().focus_view(view)
            view.set_scratch(True)
            view.window().run_command("close_file")


class DefaultSettingsTestCase(BaseSettingsTestCase):
    def test_defaults(self) -> None:
        """Tests that the default settings are honoured."""

        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        data_set: Tuple[Tuple[TabSetting, bool, str], ...] = (
            (
                ShowCaptionsTabSetting,
                DEFAULT_SETINGS["show_captions"],
                "show_captions"
            ),
            (
                IncludePathTabSetting,
                DEFAULT_SETINGS["include_path"],
                "include_path"
            ),
            (
                ShowGroupCaptionTabSetting,
                DEFAULT_SETINGS["show_group_caption"],
                "show_group_caption"
            )
        )

        for (cls, enabled, caption) in data_set:
            with self.subTest(cls=cls, enabled=enabled, caption=caption):
                inst = cls(
                    self.settings,
                    sublime.active_window()
                )  # type: ignore
                self.assertEqual(enabled, inst.is_enabled())
                self.assertListEqual(tabs, inst.apply(tabs))


class ShowCaptionsTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Show Captions Tab Settings."""

    def test_setting_disabled(self) -> None:
        """Tests with the setting disabled."""
        self.settings.set("show_captions", False)
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_current_file(self) -> Generator[int, None, None]:
        """Tests detecting current file."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )
        bar_fixture: str = path.normpath(
            path.join(dir, "./fixtures/bar.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        bar_view: sublime.View = sublime.active_window().open_file(bar_fixture)

        data_set: Tuple[Tuple[List[Tab], List[List[str]], sublime.View], ...]

        data_set = (
            ([Tab(foo_view), Tab(bar_view)], [['Current File'], []], foo_view),
            ([Tab(foo_view), Tab(bar_view)], [[], ['Current File']], bar_view),
        )

        yield 100

        for (tabs, captions, view) in data_set:
            with self.subTest(tabs=tabs, captions=view, view=view):
                view.window().focus_view(view)
                self.assertTrue(setting.is_enabled())
                self.assertListEqual(tabs, setting.apply(tabs))
                actual = []
                for tab in tabs:
                    actual.append(tab.get_captions())
                self.assertListEqual(captions, actual)

    def test_unsaved_file(self) -> None:
        """Tests detecting unsaved files."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved File"],
            tabs[0].get_captions()
        )

    def test_unsaved_changes(self) -> Generator[int, None, None]:
        """Tests detecting unsaved changes."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)

        sublime.set_timeout(
            lambda: foo_view.run_command("insert", {"characters": "foo"}),
            100
        )

        yield 100

        tabs: List[Tab] = [Tab(foo_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved Changes"],
            tabs[0].get_captions()
        )

    def test_read_only(self) -> None:
        """Tests detecting read only views."""
        setting: ShowCaptionsTabSetting = ShowCaptionsTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        scratch_view.set_read_only(True)
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual(
            ["Current File", "Unsaved File", "Read Only"],
            tabs[0].get_captions()
        )


class IncludePathTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Include path Tab Settings."""

    def test_setting_disabled(self) -> Generator[int, None, None]:
        """Tests with the setting disabled."""
        self.settings.set("include_path", False)
        setting: IncludePathTabSetting = IncludePathTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        expected = path.basename(foo_fixture)

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        tabs: List[Tab] = [Tab(foo_view)]

        yield 100

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertEqual(expected, tabs[0].get_title())
        self.assertEqual(foo_fixture, tabs[0].get_subtitle())

    def test_with_file_view(self) -> Generator[int, None, None]:
        """Tests with the setting disabled."""
        self.settings.set("include_path", True)
        setting: IncludePathTabSetting = IncludePathTabSetting(
            self.settings,
            sublime.active_window()
        )

        dir: str = path.dirname(__file__)

        foo_fixture: str = path.normpath(
            path.join(dir, "./fixtures/foo.txt")
        )

        foo_view: sublime.View = sublime.active_window().open_file(foo_fixture)
        tabs: List[Tab] = [Tab(foo_view)]

        yield 100

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertEqual(foo_fixture, tabs[0].get_title())
        self.assertEqual(foo_fixture, tabs[0].get_subtitle())


class ShowGroupCaptionsTabSettingTestCase(BaseSettingsTestCase):
    """Tests the Show Group Captions Tab Settings."""

    def test_setting_disabled(self) -> None:
        """Tests with the setting disabled."""
        self.settings.set("show_group_caption", False)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_single_group(self) -> None:
        """Tests applying to a single group (no caption expected)."""
        self.settings.set("show_group_caption", True)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        tabs: List[Tab] = [Tab(scratch_view)]

        # single column layout
        layout: Dict[str, List] = {
            "cells": [[0, 0, 1, 1]],
            "cols": [0.0, 1.0],
            "rows": [0.0, 1.0]
        }

        sublime.active_window().set_layout(layout)

        self.assertFalse(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        self.assertListEqual([], tabs[0].get_captions())

    def test_multiple_groups(self) -> None:
        """Tests applying to multiple groups."""
        self.settings.set("show_group_caption", True)
        setting: ShowGroupCaptionTabSetting = ShowGroupCaptionTabSetting(
            self.settings,
            sublime.active_window()
        )
        scratch_view: sublime.View = sublime.active_window().new_file()
        second_view: sublime.View = sublime.active_window().new_file()

        # 2 column layout
        layout: Dict[str, List] = {
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]],
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0]
        }

        sublime.active_window().set_layout(layout)
        sublime.active_window().set_view_index(second_view, group=1, idx=0)

        tabs: List[Tab] = [Tab(scratch_view), Tab(second_view)]

        self.assertTrue(setting.is_enabled())
        self.assertListEqual(tabs, setting.apply(tabs))
        captions: List[List[str]] = [tab.get_captions() for tab in tabs]
        self.assertListEqual([["Group: 1"], ["Group: 2"]], captions)

# Copyright (c) 2013 - 2021 <NAME> # See the file license.txt for copying permission. # type: ignore # type: ignore # If we're running these tests in UnitTesting, then we need to use # The package name - Tab Filter - so let's grab import lib and try again. Base settings test case to set up boiler plate methods. # Close any existing views so as to avoid polluting the results. # Restore the original layout Tests that the default settings are honoured. # type: ignore Tests the Show Captions Tab Settings. Tests with the setting disabled. Tests detecting current file. Tests detecting unsaved files. Tests detecting unsaved changes. Tests detecting read only views. Tests the Include path Tab Settings. Tests with the setting disabled. Tests with the setting disabled. Tests the Show Group Captions Tab Settings. Tests with the setting disabled. Tests applying to a single group (no caption expected). # single column layout Tests applying to multiple groups. # 2 column layout