Test Failed
Push — main ( e3918a...309543 )
by Jochen
04:24
created

assert_email()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nop 5
dl 11
loc 11
rs 9.95
c 0
b 0
f 0
1
"""
2
:Copyright: 2006-2021 Jochen Kupperschmidt
3
:License: Revised BSD (see `LICENSE` file for details)
4
"""
5
6
from unittest.mock import patch
7
8
import pytest
9
10
from byceps.database import db
11
from byceps.services.authentication.password.dbmodels import (
12
    Credential as DbCredential,
13
)
14
from byceps.services.authentication.session import service as session_service
15
from byceps.services.authorization import service as authorization_service
16
from byceps.services.brand import settings_service as brand_settings_service
17
from byceps.services.consent import (
18
    consent_service,
19
    subject_service as consent_subject_service,
20
)
21
from byceps.services.newsletter import (
22
    command_service as newsletter_command_service,
23
    service as newsletter_service,
24
)
25
from byceps.services.user.dbmodels.user import User as DbUser
26
from byceps.services.user import event_service, service as user_service
27
from byceps.services.verification_token.dbmodels import Token as DbToken
28
from byceps.services.verification_token.transfer.models import (
29
    Purpose as TokenPurpose,
30
)
31
32
from tests.helpers import http_client
33
34
35
@pytest.fixture(scope='module')
36
def terms_consent_subject_id(brand):
37
    consent_subject = consent_subject_service.create_subject(
38
        f'{brand.id}_terms-of-service_v1',
39
        f'Terms of service for {brand.title} / v1',
40
        'Ich akzeptiere die <a href="{url}" target="_blank">Allgemeinen Geschäftsbedingungen</a>.',
41
        '/terms/',
42
    )
43
44
    consent_subject_service.create_brand_requirement(
45
        brand.id, consent_subject.id
46
    )
47
48
    yield consent_subject.id
49
50
    consent_subject_service.delete_brand_requirement(
51
        brand.id, consent_subject.id
52
    )
53
54
55
@pytest.fixture(scope='module')
56
def privacy_policy_consent_subject_id(brand):
57
    consent_subject = consent_subject_service.create_subject(
58
        f'{brand.id}_privacy_policy_v1',
59
        f'Privacy policy for {brand.title} / v1',
60
        'Ich akzeptiere die <a href="{url}" target="_blank">Datenschutzbestimmungen</a>.',
61
        '/privacy',
62
    )
63
64
    consent_subject_service.create_brand_requirement(
65
        brand.id, consent_subject.id
66
    )
67
68
    yield consent_subject.id
69
70
    consent_subject_service.delete_brand_requirement(
71
        brand.id, consent_subject.id
72
    )
73
74
75
@pytest.fixture(scope='module')
76
def newsletter_list(brand):
77
    list_ = newsletter_command_service.create_list(brand.id, brand.title)
78
79
    name = 'newsletter_list_id'
80
    value = str(list_.id)
81
82
    brand_settings_service.create_setting(brand.id, name, value)
83
84
    yield
85
86
    brand_settings_service.remove_setting(brand.id, name)
87
88
89
@patch('byceps.email.send')
90
def test_create(
91
    send_email_mock,
92
    site_app,
93
    brand,
94
    site,
95
    terms_consent_subject_id,
96
    privacy_policy_consent_subject_id,
97
    newsletter_list,
98
):
99
    screen_name = 'Hiro'
100
101
    user_count_before = get_user_count()
102
    assert find_user(screen_name) is None
103
104
    form_data = {
105
        'screen_name': screen_name,
106
        'first_names': 'Hiroaki',
107
        'last_name': 'Protagonist',
108
        'email_address': '[email protected]',
109
        'password': 'Snow_Crash',
110
        f'consent_to_subject_{terms_consent_subject_id.hex}': 'y',
111
        f'consent_to_subject_{privacy_policy_consent_subject_id.hex}': 'y',
112
        'subscribe_to_newsletter': 'y',
113
    }
114
115
    response = send_request(site_app, form_data)
116
    assert response.status_code == 302
117
118
    user_count_afterwards = get_user_count()
119
    assert user_count_afterwards == user_count_before + 1
120
121
    user = find_user(screen_name)
122
    assert user is not None
123
124
    assert user.created_at is not None
125
    assert user.screen_name == 'Hiro'
126
    assert user.email_address == '[email protected]'
127
    assert not user.initialized
128
    assert not user.deleted
129
130
    # events
131
    assert_creation_event_created(user.id, site.id)
132
133
    # password
134
    assert_password_credentials_created(user.id)
135
136
    # Session token should not have been created at this point.
137
    session_token = session_service.find_session_token_for_user(user.id)
138
    assert session_token is None
139
140
    # avatar
141
    assert user.avatar is None
142
143
    # details
144
    assert user.detail.first_names == 'Hiroaki'
145
    assert user.detail.last_name == 'Protagonist'
146
147
    # authorization
148
    role_ids = authorization_service.find_role_ids_for_user(user.id)
149
    assert role_ids == set()
150
151
    # consents
152
    assert_consent(user.id, terms_consent_subject_id)
153
    assert_consent(user.id, privacy_policy_consent_subject_id)
154
155
    # newsletter subscription
156
    assert is_subscribed_to_newsletter(user.id, brand.id)
157
158
    # confirmation e-mail
159
160
    verification_token = find_verification_token(user.id)
161
    assert verification_token is not None
162
163
    expected_sender = 'ACME Entertainment Convention <[email protected]>'
164
    expected_recipients = ['[email protected]']
165
    expected_subject = 'Hiro, bitte bestätige deine E-Mail-Adresse'
166
    expected_body = f'''
167
Hallo Hiro,
168
169
bitte bestätige deine E-Mail-Adresse indem du diese URL aufrufst: https://www.acmecon.test/users/email_address/confirmation/{verification_token.token}
170
    '''.strip()
171
172
    assert_email(
173
        send_email_mock,
174
        expected_sender,
175
        expected_recipients,
176
        expected_subject,
177
        expected_body,
178
    )
179
180
181
@patch('byceps.email.send')
182
def test_create_without_newsletter_subscription(
183
    send_email_mock,
184
    site_app,
185
    brand,
186
    site,
187
    terms_consent_subject_id,
188
    privacy_policy_consent_subject_id,
189
    newsletter_list,
190
):
191
    screen_name = 'Hiro2'
192
193
    form_data = {
194
        'screen_name': screen_name,
195
        'first_names': 'Hiroaki',
196
        'last_name': 'Protagonist',
197
        'email_address': '[email protected]',
198
        'password': 'Snow_Crash',
199
        f'consent_to_subject_{terms_consent_subject_id.hex}': 'y',
200
        f'consent_to_subject_{privacy_policy_consent_subject_id.hex}': 'y',
201
        'subscribe_to_newsletter': '',
202
    }
203
204
    response = send_request(site_app, form_data)
205
    assert response.status_code == 302
206
207
    user = find_user(screen_name)
208
    assert user is not None
209
210
    # newsletter subscription
211
    assert not is_subscribed_to_newsletter(user.id, brand.id)
212
213
214
# helpers
215
216
217
def send_request(app, form_data):
218
    url = '/users/'
219
220
    with http_client(app) as client:
221
        return client.post(url, data=form_data)
222
223
224
def find_user(screen_name):
225
    return user_service.find_db_user_by_screen_name(screen_name)
226
227
228
def get_user_count():
229
    return db.session.query(DbUser).count()
230
231
232
def find_verification_token(user_id):
233
    return db.session \
234
        .query(DbToken) \
235
        .filter_by(user_id=user_id) \
236
        .filter_by(_purpose=TokenPurpose.email_address_confirmation.name) \
237
        .first()
238
239
240
def is_subscribed_to_newsletter(user_id, brand_id):
241
    return newsletter_service.is_subscribed(user_id, brand_id)
242
243
244
def assert_creation_event_created(user_id, site_id):
245
    events = event_service.get_events_of_type_for_user(user_id, 'user-created')
246
    assert len(events) == 1
247
248
    first_event = events[0]
249
    assert first_event.event_type == 'user-created'
250
    assert first_event.data == {'site_id': site_id}
251
252
253
def assert_password_credentials_created(user_id):
254
    credential = db.session.query(DbCredential).get(user_id)
255
256
    assert credential is not None
257
    assert credential.password_hash.startswith('pbkdf2:sha256:250000$')
258
    assert credential.updated_at is not None
259
260
261
def assert_consent(user_id, subject_id):
262
    assert consent_service.has_user_consented_to_subject(user_id, subject_id)
263
264
265 View Code Duplication
def assert_email(
1 ignored issue
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
266
    mock, expected_sender, expected_recipients, expected_subject, expected_body
267
):
268
    calls = mock.call_args_list
269
    assert len(calls) == 1
270
271
    args = calls[0].args
272
    assert args[0] == expected_sender
273
    assert args[1] == expected_recipients
274
    assert args[2] == expected_subject
275
    assert args[3] == expected_body
276