Files
zulip/zerver/tests/test_custom_profile_data.py
Tim Abbott 594451707d check_capped_string: Clean up corner case.
We were rejecting strings of length equal to the max.

While we're at it, fix the unnecessary period in the error message,
which doesn't align with similar validators.
2018-05-03 14:30:03 -07:00

423 lines
18 KiB
Python

# -*- coding: utf-8 -*-
from typing import Union, List, Dict, Text, Any
from mock import patch
from zerver.lib.actions import get_realm, try_add_realm_custom_profile_field, \
do_update_user_custom_profile_data, do_remove_realm_custom_profile_field, \
try_reorder_realm_custom_profile_fields
from zerver.lib.test_classes import ZulipTestCase
from zerver.models import CustomProfileField, \
custom_profile_fields_for_realm, get_realm
import ujson
class CustomProfileFieldTest(ZulipTestCase):
def setUp(self) -> None:
self.original_count = len(custom_profile_fields_for_realm(get_realm("zulip").id))
def test_list(self) -> None:
self.login(self.example_email("iago"))
result = self.client_get("/json/realm/profile_fields")
self.assert_json_success(result)
self.assertEqual(200, result.status_code)
content = result.json()
self.assertEqual(len(content["custom_fields"]), self.original_count)
def test_list_order(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
order = (
CustomProfileField.objects.filter(realm=realm)
.order_by('-order')
.values_list('order', flat=True)
)
try_reorder_realm_custom_profile_fields(realm, order)
result = self.client_get("/json/realm/profile_fields")
content = result.json()
self.assertListEqual(content["custom_fields"],
sorted(content["custom_fields"], key=lambda x: -x["id"]))
def test_create(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
data = {"name": u"Phone", "field_type": "text id"} # type: Dict[str, Any]
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, u'Argument "field_type" is not valid JSON.')
data["name"] = ""
data["field_type"] = 100
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, u'Name cannot be blank.')
data["name"] = "Phone"
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, u'Invalid field type.')
data["name"] = "Phone"
data["hint"] = "*" * 81
data["field_type"] = CustomProfileField.SHORT_TEXT
result = self.client_post("/json/realm/profile_fields", info=data)
msg = "hint is too long (limit: 80 characters)"
self.assert_json_error(result, msg)
data["name"] = "Phone"
data["hint"] = "Contact number"
data["field_type"] = CustomProfileField.SHORT_TEXT
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_success(result)
field = CustomProfileField.objects.get(name="Phone", realm=realm)
self.assertEqual(field.id, field.order)
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result,
u'A field with that name already exists.')
def test_create_choice_field(self) -> None:
self.login(self.example_email("iago"))
data = {} # type: Dict[str, Union[str, int]]
data["name"] = "Favorite programming language"
data["field_type"] = CustomProfileField.CHOICE
data['field_data'] = 'invalid'
result = self.client_post("/json/realm/profile_fields", info=data)
error_msg = "Bad value for 'field_data': invalid"
self.assert_json_error(result, error_msg)
data["field_data"] = ujson.dumps({
'python': ['1'],
'java': ['2'],
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, 'field_data is not a dict')
data["field_data"] = ujson.dumps({
'python': {'text': 'Python'},
'java': {'text': 'Java'},
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, "order key is missing from field_data")
data["field_data"] = ujson.dumps({
'python': {'text': 'Python', 'order': ''},
'java': {'text': 'Java', 'order': '2'},
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, 'field_data["order"] cannot be blank.')
data["field_data"] = ujson.dumps({
'': {'text': 'Python', 'order': '1'},
'java': {'text': 'Java', 'order': '2'},
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, "'value' cannot be blank.")
data["field_data"] = ujson.dumps({
'python': {'text': 'Python', 'order': 1},
'java': {'text': 'Java', 'order': '2'},
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_error(result, 'field_data["order"] is not a string')
data["field_data"] = ujson.dumps({
'python': {'text': 'Python', 'order': '1'},
'java': {'text': 'Java', 'order': '2'},
})
result = self.client_post("/json/realm/profile_fields", info=data)
self.assert_json_success(result)
def test_not_realm_admin(self) -> None:
self.login(self.example_email("hamlet"))
result = self.client_post("/json/realm/profile_fields")
self.assert_json_error(result, u'Must be an organization administrator')
result = self.client_delete("/json/realm/profile_fields/1")
self.assert_json_error(result, 'Must be an organization administrator')
def test_delete(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
field = CustomProfileField.objects.get(name="Phone number", realm=realm)
result = self.client_delete("/json/realm/profile_fields/100")
self.assert_json_error(result, 'Field id 100 not found.')
self.assertEqual(CustomProfileField.objects.count(), self.original_count)
result = self.client_delete(
"/json/realm/profile_fields/{}".format(field.id))
self.assert_json_success(result)
self.assertEqual(CustomProfileField.objects.count(), self.original_count - 1)
def test_update(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
result = self.client_patch(
"/json/realm/profile_fields/100",
info={'name': '',
'field_type': CustomProfileField.SHORT_TEXT}
)
self.assert_json_error(result, u'Name cannot be blank.')
result = self.client_patch(
"/json/realm/profile_fields/100",
info={'name': 'Phone Number',
'field_type': CustomProfileField.SHORT_TEXT}
)
self.assert_json_error(result, u'Field id 100 not found.')
field = CustomProfileField.objects.get(name="Phone number", realm=realm)
self.assertEqual(CustomProfileField.objects.count(), self.original_count)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'New phone number',
'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_success(result)
field = CustomProfileField.objects.get(id=field.id, realm=realm)
self.assertEqual(CustomProfileField.objects.count(), self.original_count)
self.assertEqual(field.name, 'New phone number')
self.assertIs(field.hint, '')
self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'New phone number',
'hint': '*' * 81,
'field_type': CustomProfileField.SHORT_TEXT})
msg = "hint is too long (limit: 80 characters)"
self.assert_json_error(result, msg)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'New phone number',
'hint': 'New contact number',
'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_success(result)
field = CustomProfileField.objects.get(id=field.id, realm=realm)
self.assertEqual(CustomProfileField.objects.count(), self.original_count)
self.assertEqual(field.name, 'New phone number')
self.assertEqual(field.hint, 'New contact number')
self.assertEqual(field.field_type, CustomProfileField.SHORT_TEXT)
field = CustomProfileField.objects.get(name="Favorite editor", realm=realm)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'Favorite editor',
'field_data': 'invalid'})
self.assert_json_error(result, "Bad value for 'field_data': invalid")
field_data = ujson.dumps({
'vim': 'Vim',
'emacs': {'order': '2', 'text': 'Emacs'},
})
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'Favorite editor',
'field_data': field_data})
self.assert_json_error(result, "field_data is not a dict")
field_data = ujson.dumps({
'vim': {'order': '1', 'text': 'Vim'},
'emacs': {'order': '2', 'text': 'Emacs'},
'notepad': {'order': '3', 'text': 'Notepad'},
})
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'Favorite editor',
'field_data': field_data})
self.assert_json_success(result)
def test_update_is_aware_of_uniqueness(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
try_add_realm_custom_profile_field(realm, u"Phone",
CustomProfileField.SHORT_TEXT)
field = try_add_realm_custom_profile_field(
realm,
u"Phone 1",
CustomProfileField.SHORT_TEXT
)
self.assertEqual(CustomProfileField.objects.count(), self.original_count + 2)
result = self.client_patch(
"/json/realm/profile_fields/{}".format(field.id),
info={'name': 'Phone', 'field_type': CustomProfileField.SHORT_TEXT})
self.assert_json_error(
result, u'A field with that name already exists.')
def assert_error_update_invalid_value(self, field_name: str, new_value: object, error_msg: str) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
field = CustomProfileField.objects.get(name=field_name, realm=realm)
# Update value of field
result = self.client_patch("/json/users/me/profile_data",
{'data': ujson.dumps([{"id": field.id, "value": new_value}])})
self.assert_json_error(result, error_msg)
def test_reorder(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
order = (
CustomProfileField.objects.filter(realm=realm)
.order_by('-order')
.values_list('order', flat=True)
)
result = self.client_patch("/json/realm/profile_fields",
info={'order': ujson.dumps(order)})
self.assert_json_success(result)
fields = CustomProfileField.objects.filter(realm=realm).order_by('order')
for field in fields:
self.assertEqual(field.id, order[field.order])
def test_reorder_duplicates(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
order = (
CustomProfileField.objects.filter(realm=realm)
.order_by('-order')
.values_list('order', flat=True)
)
order = list(order)
order.append(4)
result = self.client_patch("/json/realm/profile_fields",
info={'order': ujson.dumps(order)})
self.assert_json_success(result)
fields = CustomProfileField.objects.filter(realm=realm).order_by('order')
for field in fields:
self.assertEqual(field.id, order[field.order])
def test_reorder_unauthorized(self) -> None:
self.login(self.example_email("hamlet"))
realm = get_realm('zulip')
order = (
CustomProfileField.objects.filter(realm=realm)
.order_by('-order')
.values_list('order', flat=True)
)
result = self.client_patch("/json/realm/profile_fields",
info={'order': ujson.dumps(order)})
self.assert_json_error(result, "Must be an organization administrator")
def test_reorder_invalid(self) -> None:
self.login(self.example_email("iago"))
order = [100, 200, 300]
result = self.client_patch("/json/realm/profile_fields",
info={'order': ujson.dumps(order)})
self.assert_json_error(
result, u'Invalid order mapping.')
order = [1, 2]
result = self.client_patch("/json/realm/profile_fields",
info={'order': ujson.dumps(order)})
self.assert_json_error(
result, u'Invalid order mapping.')
def test_update_invalid_field(self) -> None:
self.login(self.example_email("iago"))
data = [{'id': 1234, 'value': '12'}]
result = self.client_patch("/json/users/me/profile_data", {
'data': ujson.dumps(data)
})
self.assert_json_error(result,
u"Field id 1234 not found.")
def test_update_invalid_short_text(self) -> None:
field_name = "Phone number"
self.assert_error_update_invalid_value(field_name, 't' * 201,
u"{} is too long (limit: 50 characters)".format(field_name))
def test_update_invalid_date(self) -> None:
field_name = "Birthday"
self.assert_error_update_invalid_value(field_name, u"a-b-c",
u"{} is not a date".format(field_name))
self.assert_error_update_invalid_value(field_name, 123,
u"{} is not a string".format(field_name))
def test_update_invalid_url(self) -> None:
field_name = "GitHub profile"
self.assert_error_update_invalid_value(field_name, u"not URL",
u"{} is not a URL".format(field_name))
def test_update_profile_data_successfully(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
fields = [
('Phone number', 'short text data'),
('Biography', 'long text data'),
('Favorite food', 'short text data'),
('Favorite editor', 'vim'),
('Birthday', '1909-3-5'),
('GitHub profile', 'https://github.com/ABC'),
]
data = []
for i, field_value in enumerate(fields):
name, value = field_value
field = CustomProfileField.objects.get(name=name, realm=realm)
data.append({
'id': field.id,
'value': value,
})
# Update value of field
result = self.client_patch("/json/users/me/profile_data",
{'data': ujson.dumps(data)})
self.assert_json_success(result)
iago = self.example_user('iago')
expected_value = {f['id']: f['value'] for f in data}
for field_dict in iago.profile_data:
self.assertEqual(field_dict['value'], expected_value[field_dict['id']])
for k in ['id', 'type', 'name', 'field_data']:
self.assertIn(k, field_dict)
self.assertEqual(len(iago.profile_data), self.original_count)
# Update value of one field.
field = CustomProfileField.objects.get(name='Biography', realm=realm)
data = [{
'id': field.id,
'value': 'foobar',
}]
result = self.client_patch("/json/users/me/profile_data",
{'data': ujson.dumps(data)})
self.assert_json_success(result)
for f in iago.profile_data:
if f['id'] == field.id:
self.assertEqual(f['value'], 'foobar')
def test_update_invalid_choice_field(self) -> None:
field_name = "Favorite editor"
self.assert_error_update_invalid_value(field_name, "foobar",
"'foobar' is not a valid choice for '{}'.".format(field_name))
def test_update_choice_field_successfully(self) -> None:
self.login(self.example_email("iago"))
realm = get_realm('zulip')
field = CustomProfileField.objects.get(name='Favorite editor', realm=realm)
data = [{
'id': field.id,
'value': 'emacs',
}]
result = self.client_patch("/json/users/me/profile_data",
{'data': ujson.dumps(data)})
self.assert_json_success(result)
def test_delete_internals(self) -> None:
user_profile = self.example_user('iago')
realm = user_profile.realm
field = CustomProfileField.objects.get(name="Phone number", realm=realm)
data = [{'id': field.id, 'value': u'123456'}] # type: List[Dict[str, Union[int, Text]]]
do_update_user_custom_profile_data(user_profile, data)
self.assertEqual(len(custom_profile_fields_for_realm(realm.id)), self.original_count)
self.assertEqual(user_profile.customprofilefieldvalue_set.count(), self.original_count)
do_remove_realm_custom_profile_field(realm, field)
self.assertEqual(len(custom_profile_fields_for_realm(realm.id)), self.original_count - 1)
self.assertEqual(user_profile.customprofilefieldvalue_set.count(), self.original_count - 1)