Passed
Push — master ( 69ad40...f1cd88 )
by Jochen
02:35
created

NewsletterAdminTestCase.get_as_admin()   A

Complexity

Conditions 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
"""
2
:Copyright: 2006-2019 Jochen Kupperschmidt
3
:License: Modified BSD, see LICENSE for details.
4
"""
5
6
from datetime import datetime
7
8
from byceps.services.newsletter.models import (
9
    SubscriptionUpdate as DbSubscriptionUpdate,
10
)
11
from byceps.services.newsletter import command_service
12
from byceps.services.newsletter.types import SubscriptionState
13
14
from tests.base import AbstractAppTestCase, CONFIG_FILENAME_TEST_ADMIN
15
from tests.helpers import (
16
    assign_permissions_to_user,
17
    create_user,
18
    http_client,
19
    login_user,
20
)
21
22
23
class NewsletterAdminTestCase(AbstractAppTestCase):
24
25
    def setUp(self):
26
        super().setUp(config_filename=CONFIG_FILENAME_TEST_ADMIN)
27
28
        self.admin = self.create_admin()
29
30
        self.list_id = command_service.create_list('example', 'Example').id
31
32
        self.setup_subscribers()
33
34
    def create_admin(self):
35
        admin = create_user('Admin')
36
37
        permission_ids = {'admin.access', 'newsletter.export_subscribers'}
38
        assign_permissions_to_user(admin.id, 'admin', permission_ids)
39
40
        login_user(admin.id)
41
42
        return admin
43
44
    def setup_subscribers(self):
45
        for number, initialized, suspended, deleted, states in [
46
            (1, True,  False, False, [SubscriptionState.requested                             ]),
47
            (2, True,  False, False, [SubscriptionState.declined                              ]),
48
            (3, False, False, False, [SubscriptionState.requested                             ]),
49
            (4, True,  False, False, [SubscriptionState.declined,  SubscriptionState.requested]),
50
            (5, True,  False, False, [SubscriptionState.requested, SubscriptionState.declined ]),
51
            (6, True,  False, False, [SubscriptionState.requested                             ]),
52
            (7, True,  True , False, [SubscriptionState.requested                             ]),
53
            (8, True,  False, True , [SubscriptionState.requested                             ]),
54
        ]:
55
            user = create_user(
56
                screen_name=f'User-{number:d}',
57
                email_address=f'user{number:03d}@example.com',
58
                initialized=initialized,
59
            )
60
61
            if suspended:
62
                user.suspended = True
63
                self.db.session.commit()
64
65
            if deleted:
66
                user.deleted = True
67
                self.db.session.commit()
68
69
            self.add_subscriptions(user, states)
70
71
    def test_export_subscribers(self):
72
        expected_data = {
73
            'subscribers': [
74
                {
75
                    'screen_name': 'User-1',
76
                    'email_address': '[email protected]',
77
                },
78
79
                # User #2 has declined a subscription, and thus should be
80
                # excluded.
81
82
                # User #3 is not initialized, and thus should be excluded.
83
84
                # User #4 has initially declined, but later requested a
85
                # subscription, so it should be included.
86
                {
87
                    'screen_name': 'User-4',
88
                    'email_address': '[email protected]',
89
                },
90
91
                # User #5 has initially requested, but later declined a
92
                # subscription, so it should be excluded.
93
94
                {
95
                    'screen_name': 'User-6',
96
                    'email_address': '[email protected]',
97
                },
98
99
                # User #7 has been suspended and should be excluded, regardless
100
                # of subscription state.
101
102
                # User #8 has been deleted and should be excluded, regardless
103
                # of subscription state.
104
            ],
105
        }
106
107
        url = f'/admin/newsletter/lists/{self.list_id}/subscriptions/export'
108
        response = self.get_as_admin(url)
109
110
        assert response.status_code == 200
111
        assert response.content_type == 'application/json'
112
        assert response.json == expected_data
113
114
    def test_export_subscriber_email_addresses(self):
115
        expected_data = '\n'.join([
116
            '[email protected]',
117
            # User #2 has declined a subscription.
118
            # User #3 is not initialized.
119
            # User #4 has initially declined, but later requested a subscription.
120
            '[email protected]',
121
            # User #5 has initially requested, but later declined a subscription.
122
            '[email protected]',
123
            # User #7 has been suspended, and thus should be excluded.
124
            # User #8 has been deleted, and thus should be excluded.
125
        ]).encode('utf-8')
126
127
        url = f'/admin/newsletter/lists/{self.list_id}/subscriptions/email_addresses/export'
128
        response = self.get_as_admin(url)
129
130
        assert response.status_code == 200
131
        assert response.content_type == 'text/plain; charset=utf-8'
132
        assert response.mimetype == 'text/plain'
133
        assert response.get_data() == expected_data
134
135
    def add_subscriptions(self, user, states):
136
        for state in states:
137
            self.add_subscription(user, state)
138
139
        self.db.session.commit()
140
141
    def add_subscription(self, user, state):
142
        expressed_at = datetime.utcnow()
143
        subscription_update = DbSubscriptionUpdate(
144
            user.id, self.list_id, expressed_at, state
145
        )
146
        self.db.session.add(subscription_update)
147
148
    def get_as_admin(self, url):
149
        """Make a GET request as the admin and return the response."""
150
        with http_client(self.app, user_id=self.admin.id) as client:
151
            return client.get(url)
152