"""Test the utils functions in .utils."""

from django.test import TestCase

from .exceptions import CircularRelationshipException
from .utils import compute_dependencies_order


class DependencyUtilsTestCase(TestCase):
    """Test the utils functions in .utils."""

    def test_compute_no_dependencies_order(self):
        """
        Check a simple case with no dependencies.
        """
        dependencies = [
            ('A', []),
            ('B', []),
            ('C', []),
        ]
        expected_order = ['A', 'B', 'C']
        computed_order = compute_dependencies_order(dependencies)
        self.assertListEqual(computed_order, expected_order)

    def test_compute_no_cross_dependencies_order(self):
        """
        Check a simple case with no cross dependencies.
        """
        dependencies = [
            ('A', ['B', 'C']),
            ('D', ['E', 'F']),
            ('G', []),
        ]
        expected_order = ['B', 'C', 'A', 'E', 'F', 'D', 'G']
        computed_order = compute_dependencies_order(dependencies)
        self.assertListEqual(computed_order, expected_order)

    def test_compute_simple_dependencies_order(self):
        """
        Check a simple case with cross dependencies.
        """
        dependencies = [
            ('A', ['B', 'C']),
            ('B', ['C', 'D']),
            ('D', ['E']),
        ]
        expected_order = ['C', 'E', 'D', 'B', 'A']
        computed_order = compute_dependencies_order(dependencies)
        self.assertListEqual(computed_order, expected_order)

    def test_compute_complex_dependencies_order(self):
        """
        Check a more complex case.
        """
        dependencies = [
            ('F', ['H', 'I']),
            ('B', ['D', 'E']),
            ('C', ['F', 'G', 'I']),
            ('Z', ['A', 'D']),
            ('D', ['J', 'K']),
            ('A', ['B', 'C']),
        ]
        expected_order = ['J', 'K', 'D', 'E', 'B', 'H', 'I', 'F', 'G', 'C', 'A', 'Z']
        computed_order = compute_dependencies_order(dependencies)
        self.assertListEqual(computed_order, expected_order)

    def test_compute_disjointed_dependencies_order(self):
        """
        Check a case of multiple disjoined dependency trees.
        """
        dependencies = [
            ('A', ['B', 'C']),
            ('D', ['E', 'F']),
            ('G', ['H', 'I', 'A']),
        ]
        expected_order = ['B', 'C', 'A', 'E', 'F', 'D', 'H', 'I', 'G']
        computed_order = compute_dependencies_order(dependencies)
        self.assertListEqual(computed_order, expected_order)

    def test_circular_relationships_raise_exception(self):
        """
        Check that circular relationships raise the proper exception.
        """
        dependencies = [
            ('A', ['B', 'C']),
            ('B', ['C', 'D']),
            ('D', ['E', 'A']),
        ]
        with self.assertRaises(CircularRelationshipException):
            compute_dependencies_order(dependencies)
