# Path: tidings/models.py
# class Watch(ModelBase):
#     """The registration of a user's interest in a certain event
# 
#     At minimum, specifies an event_type and thereby an
#     :class:`~tidings.events.Event` subclass. May also specify a content type
#     and/or object ID and, indirectly, any number of
#     :class:`WatchFilters <WatchFilter>`.
# 
#     """
#     #: Key used by an Event to find watches it manages:
#     event_type = models.CharField(max_length=30, db_index=True)
# 
#     #: Optional reference to a content type:
#     content_type = models.ForeignKey(ContentType, null=True, blank=True,
#                                      on_delete=models.CASCADE)
#     object_id = models.PositiveIntegerField(db_index=True, null=True)
#     content_object = GenericForeignKey('content_type', 'object_id')
# 
#     user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True,
#                              on_delete=models.CASCADE)
# 
#     #: Email stored only in the case of anonymous users:
#     email = models.EmailField(db_index=True, null=True, blank=True)
# 
#     #: Secret for activating anonymous watch email addresses.
#     secret = models.CharField(max_length=10, null=True, blank=True)
#     #: Active watches receive notifications, inactive watches don't.
#     is_active = models.BooleanField(default=False, db_index=True)
# 
#     def __unicode__(self):
#         # TODO: Trace event_type back to find the Event subclass, and ask it
#         # how to describe me in English.
#         rest = self.content_object or self.content_type or self.object_id
#         return u'id=%s, type=%s, content_object=%s' % (self.pk,
#                                                        self.event_type,
#                                                        text_type(rest))
# 
#     def activate(self):
#         """Enable this watch so it actually fires.
# 
#         Return ``self`` to support method chaining.
# 
#         """
#         self.is_active = True
#         return self
# 
#     def unsubscribe_url(self):
#         """Return the absolute URL to visit to delete me."""
#         server_relative = ('%s?s=%s' % (reverse('tidings.unsubscribe',
#                                                 args=[self.pk]),
#                                         self.secret))
#         return 'https://%s%s' % (Site.objects.get_current().domain,
#                                  server_relative)
# 
# Path: tidings/utils.py
# def collate(*iterables, **kwargs):
#     def gather_next_value(row, index):
# def hash_to_unsigned(data):
# def emails_with_users_and_watches(
#         subject, template_path, vars, users_and_watches,
#         from_email=settings.TIDINGS_FROM_ADDRESS, **extra_kwargs):
# def import_from_setting(setting_name, fallback):
# 
# Path: tests/base.py
# def watch(save=False, **kwargs):
#     # TODO: better defaults, when there are events available.
#     defaults = {'user': kwargs.get('user') or user(save=True),
#                 'is_active': True,
#                 'secret': 'abcdefghjk'}
#     defaults.update(kwargs)
#     w = Watch.objects.create(**defaults)
#     if save:
#         w.save()
#     return w


from django.test import TestCase
from tidings.models import Watch
from tidings.utils import reverse
from .base import watch
        self.assertContains(response, 'Are you sure you want to unsubscribe?')

    def test_no_such_watch(self):
        """Assert it complains when asked for a nonexistent Watch."""
        for method in [self.client.get, self.client.post]:
            response = method(reverse('tidings.unsubscribe', args=[33]))
            self.assertContains(response, FAILURE_STRING)

    def test_no_secret(self):
        """Assert it complains when no secret is given."""
        w = watch(save=True)
        for method in [self.client.get, self.client.post]:
            response = method(reverse('tidings.unsubscribe',
                                      args=[w.pk]))
            self.assertContains(response, FAILURE_STRING)

    def test_wrong_secret(self):
        """Assert it complains when an incorrect secret is given."""
        w = watch(save=True)
        for method in [self.client.get, self.client.post]:
            response = method(
                reverse('tidings.unsubscribe', args=[w.pk]) + '?s=WRONGwrong')
            self.assertContains(response, FAILURE_STRING)

    def test_success(self):
        """Ensure the watch deletes and view says "yay" when all goes well."""
        w = watch(save=True)
        response = self.client.post(
            reverse('tidings.unsubscribe', args=[w.pk]) + '?s=' + w.secret)
        self.assertContains(response, '<h1>Unsubscribed</h1>')

# Path: tidings/models.py
# class Watch(ModelBase):
#     """The registration of a user's interest in a certain event
# 
#     At minimum, specifies an event_type and thereby an
#     :class:`~tidings.events.Event` subclass. May also specify a content type
#     and/or object ID and, indirectly, any number of
#     :class:`WatchFilters <WatchFilter>`.
# 
#     """
#     #: Key used by an Event to find watches it manages:
#     event_type = models.CharField(max_length=30, db_index=True)
# 
#     #: Optional reference to a content type:
#     content_type = models.ForeignKey(ContentType, null=True, blank=True,
#                                      on_delete=models.CASCADE)
#     object_id = models.PositiveIntegerField(db_index=True, null=True)
#     content_object = GenericForeignKey('content_type', 'object_id')
# 
#     user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True,
#                              on_delete=models.CASCADE)
# 
#     #: Email stored only in the case of anonymous users:
#     email = models.EmailField(db_index=True, null=True, blank=True)
# 
#     #: Secret for activating anonymous watch email addresses.
#     secret = models.CharField(max_length=10, null=True, blank=True)
#     #: Active watches receive notifications, inactive watches don't.
#     is_active = models.BooleanField(default=False, db_index=True)
# 
#     def __unicode__(self):
#         # TODO: Trace event_type back to find the Event subclass, and ask it
#         # how to describe me in English.
#         rest = self.content_object or self.content_type or self.object_id
#         return u'id=%s, type=%s, content_object=%s' % (self.pk,
#                                                        self.event_type,
#                                                        text_type(rest))
# 
#     def activate(self):
#         """Enable this watch so it actually fires.
# 
#         Return ``self`` to support method chaining.
# 
#         """
#         self.is_active = True
#         return self
# 
#     def unsubscribe_url(self):
#         """Return the absolute URL to visit to delete me."""
#         server_relative = ('%s?s=%s' % (reverse('tidings.unsubscribe',
#                                                 args=[self.pk]),
#                                         self.secret))
#         return 'https://%s%s' % (Site.objects.get_current().domain,
#                                  server_relative)
# 
# Path: tidings/utils.py
# def collate(*iterables, **kwargs):
#     def gather_next_value(row, index):
# def hash_to_unsigned(data):
# def emails_with_users_and_watches(
#         subject, template_path, vars, users_and_watches,
#         from_email=settings.TIDINGS_FROM_ADDRESS, **extra_kwargs):
# def import_from_setting(setting_name, fallback):
# 
# Path: tests/base.py
# def watch(save=False, **kwargs):
#     # TODO: better defaults, when there are events available.
#     defaults = {'user': kwargs.get('user') or user(save=True),
#                 'is_active': True,
#                 'secret': 'abcdefghjk'}
#     defaults.update(kwargs)
#     w = Watch.objects.create(**defaults)
#     if save:
#         w.save()
#     return w


# Path: tests/test_templates.py
from django.test import TestCase
from tidings.models import Watch
from tidings.utils import reverse
from .base import watch

        self.assertContains(response, 'Are you sure you want to unsubscribe?')

    def test_no_such_watch(self):
        """Assert it complains when asked for a nonexistent Watch."""
        for method in [self.client.get, self.client.post]:
            response = method(reverse('tidings.unsubscribe', args=[33]))
            self.assertContains(response, FAILURE_STRING)

    def test_no_secret(self):
        """Assert it complains when no secret is given."""
        w = watch(save=True)
        for method in [self.client.get, self.client.post]:
            response = method(reverse('tidings.unsubscribe',
                                      args=[w.pk]))
            self.assertContains(response, FAILURE_STRING)

    def test_wrong_secret(self):
        """Assert it complains when an incorrect secret is given."""
        w = watch(save=True)
        for method in [self.client.get, self.client.post]:
            response = method(
                reverse('tidings.unsubscribe', args=[w.pk]) + '?s=WRONGwrong')
            self.assertContains(response, FAILURE_STRING)

    def test_success(self):
        """Ensure the watch deletes and view says "yay" when all goes well."""
        w = watch(save=True)
        response = self.client.post(
            reverse('tidings.unsubscribe', args=[w.pk]) + '?s=' + w.secret)
        self.assertContains(response, '<h1>Unsubscribed</h1>')

        self.assertEqual(0, Watch.objects.count())