add ability to get detailed signup error from create_account

pull/268/head
halcy 2022-11-19 02:34:01 +02:00
rodzic f26bf0db1d
commit 853cd82ecb
6 zmienionych plików z 331 dodań i 168 usunięć

Wyświetl plik

@ -8,6 +8,7 @@ v1.6.3
* Add confirmation email resend API (`email_resend_confirmation`)
* Add account lookup API (`account_lookup`)
* Add `policy` param to control notification sources for `push_subscription_set`
* Add ability to get detailed signup error to `create_account`
v1.6.2
------

Wyświetl plik

@ -33,7 +33,7 @@ Refer to mastodon changelog and API docs for details when implementing, add or m
* [x] Add POST /api/v1/emails/confirmations to REST API
* [x] Add GET /api/v1/accounts/lookup to REST API
* [x] Add policy param to POST /api/v1/push/subscriptions in REST API
* [ ] Add details to error response for POST /api/v1/accounts in REST API
* [x] Add details to error response for POST /api/v1/accounts in REST API
3.4.2
-----

Wyświetl plik

@ -605,8 +605,7 @@ class Mastodon:
params['scope'] = " ".join(scopes)
try:
response = self.__api_request(
'POST', '/oauth/token', params, do_ratelimiting=False)
response = self.__api_request('POST', '/oauth/token', params, do_ratelimiting=False)
self.access_token = response['access_token']
self.__set_refresh_token(response.get('refresh_token'))
self.__set_token_expired(int(response.get('expires_in', 0)))
@ -658,8 +657,8 @@ class Mastodon:
self.access_token = None
self.__logged_in_id = None
@api_version("2.7.0", "2.7.0", "2.7.0")
def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=__DEFAULT_SCOPES, to_file=None):
@api_version("2.7.0", "2.7.0", "3.4.0")
def create_account(self, username, password, email, agreement=False, reason=None, locale="en", scopes=__DEFAULT_SCOPES, to_file=None, return_detailed_error=False):
"""
Creates a new user account with the given username, password and email. "agreement"
must be set to true (after showing the user the instance's user agreement and having
@ -674,6 +673,26 @@ class Mastodon:
Returns an access token (just like log_in), which it can also persist to to_file,
and sets it internally so that the user is now logged in. Note that this token
can only be used after the user has confirmed their email.
By default, the function will throw if the account could not be created. Alternately,
when `return_detailed_error` is passed, Mastodon.py will return the detailed error
response that the API provides (Starting from version 3.4.0 - not checked here) as an dict with
error details as the second return value and the token returned as `None` in case of error.
The dict will contain a text `error` values as well as a `details` value which is a dict with
one optional key for each potential field (`username`, `password`, `email` and `agreement`),
each if present containing a dict with an `error` category and free text `description`.
Valid error categories are:
* ERR_BLOCKED - When e-mail provider is not allowed
* ERR_UNREACHABLE - When e-mail address does not resolve to any IP via DNS (MX, A, AAAA)
* ERR_TAKEN - When username or e-mail are already taken
* ERR_RESERVED - When a username is reserved, e.g. "webmaster" or "admin"
* ERR_ACCEPTED - When agreement has not been accepted
* ERR_BLANK - When a required attribute is blank
* ERR_INVALID - When an attribute is malformed, e.g. wrong characters or invalid e-mail address
* ERR_TOO_LONG - When an attribute is over the character limit
* ERR_TOO_SHORT - When an attribute is under the character requirement
* ERR_INCLUSION - When an attribute is not one of the allowed values, e.g. unsupported locale
"""
params = self.__generate_params(locals(), ['to_file', 'scopes'])
params['client_id'] = self.client_id
@ -690,8 +709,7 @@ class Mastodon:
oauth_params['client_secret'] = self.client_secret
oauth_params['grant_type'] = 'client_credentials'
response = self.__api_request(
'POST', '/oauth/token', oauth_params, do_ratelimiting=False)
response = self.__api_request('POST', '/oauth/token', oauth_params, do_ratelimiting=False)
temp_access_token = response['access_token']
except Exception as e:
raise MastodonIllegalArgumentError(
@ -699,13 +717,16 @@ class Mastodon:
# Step 2: Use that to create a user
try:
response = self.__api_request('POST', '/api/v1/accounts', params, do_ratelimiting=False,
access_token_override=temp_access_token)
response = self.__api_request('POST', '/api/v1/accounts', params, do_ratelimiting=False, access_token_override=temp_access_token, skip_error_check=True)
if "error" in response:
if return_detailed_error:
return None, response
raise MastodonIllegalArgumentError('Invalid request: %s' % e)
self.access_token = response['access_token']
self.__set_refresh_token(response.get('refresh_token'))
self.__set_token_expired(int(response.get('expires_in', 0)))
self.__set_token_expired(int(response.get('expires_in', 0)))
except Exception as e:
raise MastodonIllegalArgumentError('Invalid request: %s' % e)
raise MastodonIllegalArgumentError('Invalid request')
# Step 3: Check scopes, persist, et cetera
received_scopes = response["scope"].split(" ")
@ -714,8 +735,7 @@ class Mastodon:
received_scopes += self.__SCOPE_SETS[scope_set]
if not set(scopes) <= set(received_scopes):
raise MastodonAPIError(
'Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".')
raise MastodonAPIError('Granted scopes "' + " ".join(received_scopes) + '" do not contain all of the requested scopes "' + " ".join(scopes) + '".')
if to_file is not None:
with open(to_file, 'w') as token_file:
@ -724,7 +744,10 @@ class Mastodon:
self.__logged_in_id = None
return response['access_token']
if return_detailed_error:
return response['access_token'], {}
else:
return response['access_token']
@api_version("3.4.0", "3.4.0", "3.4.0")
def email_resend_confirmation(self):
@ -2775,7 +2798,7 @@ class Mastodon:
"""
if not policy in ['all', 'none', 'follower', 'followed']:
raise MastodonIllegalArgumentError("Valid values for policy are 'all', 'none', 'follower' or 'followed'.")
endpoint = Mastodon.__protocolize(endpoint)
push_pubkey_b64 = base64.b64encode(encrypt_params['pubkey'])
@ -3506,7 +3529,7 @@ class Mastodon:
isotime = isotime[:-2] + ":" + isotime[-2:]
return isotime
def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False):
def __api_request(self, method, endpoint, params={}, files={}, headers={}, access_token_override=None, base_url_override=None, do_ratelimiting=True, use_json=False, parse=True, return_response_object=False, skip_error_check=False):
"""
Internal API request helper.
"""
@ -3657,35 +3680,32 @@ class Mastodon:
time.sleep(to_next)
request_complete = False
continue
if skip_error_check == False:
if response_object.status_code == 404:
ex_type = MastodonNotFoundError
if not error_msg:
error_msg = 'Endpoint not found.'
# this is for compatibility with older versions
# which raised MastodonAPIError('Endpoint not found.')
# on any 404
elif response_object.status_code == 401:
ex_type = MastodonUnauthorizedError
elif response_object.status_code == 500:
ex_type = MastodonInternalServerError
elif response_object.status_code == 502:
ex_type = MastodonBadGatewayError
elif response_object.status_code == 503:
ex_type = MastodonServiceUnavailableError
elif response_object.status_code == 504:
ex_type = MastodonGatewayTimeoutError
elif response_object.status_code >= 500 and \
response_object.status_code <= 511:
ex_type = MastodonServerError
else:
ex_type = MastodonAPIError
if response_object.status_code == 404:
ex_type = MastodonNotFoundError
if not error_msg:
error_msg = 'Endpoint not found.'
# this is for compatibility with older versions
# which raised MastodonAPIError('Endpoint not found.')
# on any 404
elif response_object.status_code == 401:
ex_type = MastodonUnauthorizedError
elif response_object.status_code == 500:
ex_type = MastodonInternalServerError
elif response_object.status_code == 502:
ex_type = MastodonBadGatewayError
elif response_object.status_code == 503:
ex_type = MastodonServiceUnavailableError
elif response_object.status_code == 504:
ex_type = MastodonGatewayTimeoutError
elif response_object.status_code >= 500 and \
response_object.status_code <= 511:
ex_type = MastodonServerError
else:
ex_type = MastodonAPIError
raise ex_type(
'Mastodon API returned error',
response_object.status_code,
response_object.reason,
error_msg)
raise ex_type('Mastodon API returned error', response_object.status_code, response_object.reason, error_msg)
if return_response_object:
return response_object

Wyświetl plik

@ -0,0 +1,245 @@
interactions:
- request:
body: client_name=mastodon.py+generated+test+app&scopes=read+write+follow+push&redirect_uris=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '122'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- python-requests/2.28.1
method: POST
uri: http://localhost:3000/api/v1/apps
response:
body:
string: '{"id":"4","name":"mastodon.py generated test app","website":null,"redirect_uri":"urn:ietf:wg:oauth:2.0:oob","client_id":"OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE","client_secret":"i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA","vapid_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-eWGkzakxkoJqETI+J7AOfA=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"e57c57d0ecbadb4122581beb6057bf7b"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- c5d33842-2156-4850-ac91-154f71f72d2e
X-Runtime:
- '0.017495'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- mastodonpy
method: GET
uri: http://localhost:3000/api/v1/instance/
response:
body:
string: '{"uri":"localhost:3000","title":"Mastodon","short_description":"","description":"","email":"","version":"4.0.0rc2","urls":{"streaming_api":"ws://localhost:4000"},"stats":{"user_count":4,"status_count":5,"domain_count":0},"thumbnail":"http://localhost:3000/packs/media/images/preview-6399aebd96ccf025654e2977454f168f.png","languages":["en"],"registrations":true,"approval_required":false,"invites_enabled":true,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":null,"rules":[]}'
headers:
Cache-Control:
- max-age=180, public
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-pTVYgmBqNUhkaog/3BIWrg=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
Date:
- Sat, 19 Nov 2022 00:05:11 GMT
ETag:
- W/"58e74f5c697f043d86089eae87509b84"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 3f3580e9-a01c-4cb3-a8ff-e933a5b0a878
X-Runtime:
- '0.038202'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: scope=read+write+follow+push&client_id=OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE&client_secret=i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA&grant_type=client_credentials
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
Content-Length:
- '170'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- mastodonpy
method: POST
uri: http://localhost:3000/oauth/token
response:
body:
string: '{"access_token":"dDfMnIWbtYShiuOouwPaH1j8ZzGRdcg39Ns0nV5jXpo","token_type":"Bearer","scope":"read
write follow push","created_at":1668816311}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-2oP2TTFLzbSaiZa7hgho0w=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"d29d21f6cdf89562d22826c8794a7259"
Pragma:
- no-cache
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 10f9efb8-85eb-4b30-ad16-9656fe53fd44
X-Runtime:
- '0.022478'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: username=coolguy73878&password=&email=email%40localhost73878&locale=en&client_id=OueO_7-PGuI_wJwqr3gJCO3Mfp-CnB7ntLm2BDNgwoE&client_secret=i74hCQQyscpk-AoXt8gL1lBYLlgsQw7r-vP_cuKWquA
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer dDfMnIWbtYShiuOouwPaH1j8ZzGRdcg39Ns0nV5jXpo
Connection:
- keep-alive
Content-Length:
- '182'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- mastodonpy
method: POST
uri: http://localhost:3000/api/v1/accounts
response:
body:
string: '{"error":"Validation failed: Password can''t be blank, Service agreement
must be accepted","details":{"password":[{"error":"ERR_BLANK","description":"can''t
be blank"}],"agreement":[{"error":"ERR_ACCEPTED","description":"must be accepted"}]}}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-OtVYUk9hlx5v/TcbXUduUA=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- 48f3d7ec-0b4f-48ce-bf0c-acbec7479c71
X-Runtime:
- '0.561200'
X-XSS-Protection:
- 1; mode=block
status:
code: 422
message: Unprocessable Entity
version: 1

Wyświetl plik

@ -1,122 +0,0 @@
interactions:
- request:
body: subscription%5Bendpoint%5D=https%3A%2F%2Fexample.com&subscription%5Bkeys%5D%5Bp256dh%5D=BKFO5w6Uf%2B%2F2wo89ovbphk5Zrb0mcAKjZrIyrX66f2IAijRtuXx4yK6J9hR%2FemKnF2DyQcyx7%2F4IGhKHBk0OTEk%3D&subscription%5Bkeys%5D%5Bauth%5D=6T8gVmd01DhQUbejRj%2Bxmg%3D%3D&policy=none&data%5Balerts%5D%5Bfollow%5D=1&data%5Balerts%5D%5Bfavourite%5D=1&data%5Balerts%5D%5Breblog%5D=1&data%5Balerts%5D%5Bmention%5D=1&data%5Balerts%5D%5Bpoll%5D=1&data%5Balerts%5D%5Bfollow_request%5D=1&data%5Balerts%5D%5Bstatus%5D=1
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
Content-Length:
- '489'
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- tests/v311
method: POST
uri: http://localhost:3000/api/v1/push/subscription
response:
body:
string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-bz+9uelNbajqElylgkM2Gg=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"083c3b807a4d145ec452ffd03c768d76"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- abb4aec7-a93a-4a99-ba4c-5a290bbbf782
X-Runtime:
- '0.027761'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Authorization:
- Bearer __MASTODON_PY_TEST_ACCESS_TOKEN
Connection:
- keep-alive
User-Agent:
- tests/v311
method: GET
uri: http://localhost:3000/api/v1/push/subscription
response:
body:
string: '{"id":5,"endpoint":"https://example.com","alerts":{"mention":true,"status":true,"reblog":true,"follow":true,"follow_request":true,"favourite":true,"poll":true},"server_key":"BFu6DBpfcm8_h8gm3rHUkfaOLg7azvYN_auFI4KcNuh5SLBVMhTkKKvUaLENtA_c6v5Hmrucvh0WwsN1o9NFQRU="}'
headers:
Cache-Control:
- no-store
Content-Security-Policy:
- 'base-uri ''none''; default-src ''none''; frame-ancestors ''none''; font-src
''self'' http://localhost:3000; img-src ''self'' https: data: blob: http://localhost:3000;
style-src ''self'' http://localhost:3000 ''nonce-4kBQ0XWCASsxXi+/Z0W5jA=='';
media-src ''self'' https: data: http://localhost:3000; frame-src ''self''
https:; manifest-src ''self'' http://localhost:3000; connect-src ''self''
data: blob: http://localhost:3000 http://localhost:3000 ws://localhost:4000
ws://localhost:3035 http://localhost:3035; script-src ''self'' ''unsafe-inline''
''unsafe-eval'' http://localhost:3000; child-src ''self'' blob: http://localhost:3000;
worker-src ''self'' blob: http://localhost:3000'
Content-Type:
- application/json; charset=utf-8
ETag:
- W/"083c3b807a4d145ec452ffd03c768d76"
Referrer-Policy:
- strict-origin-when-cross-origin
Transfer-Encoding:
- chunked
Vary:
- Accept, Origin
X-Content-Type-Options:
- nosniff
X-Download-Options:
- noopen
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Request-Id:
- eeb007da-a24b-4e31-b962-30ef0ba3bc16
X-Runtime:
- '0.008203'
X-XSS-Protection:
- 1; mode=block
status:
code: 200
message: OK
version: 1

Wyświetl plik

@ -70,5 +70,24 @@ def test_app_account_create():
# We can also test resending (marginally)
test_app_api.email_resend_confirmation()
@pytest.mark.vcr(match_on=['path'])
def test_app_account_create_invalid():
suffix = str(time.time()).replace(".", "")[-5:]
test_app = test_app = Mastodon.create_app(
"mastodon.py generated test app",
api_base_url="http://localhost:3000/"
)
test_app_api = Mastodon(
test_app[0],
test_app[1],
api_base_url="http://localhost:3000/"
)
test_token, error = test_app_api.create_account("coolguy" + suffix, "", "email@localhost" + suffix, agreement=False, return_detailed_error=True)
assert test_token is None
assert "details" in error
assert "password" in error.details
assert "password" in error.details
assert not "username" in error.details