def test_user_filter_filter_combos(email, social_auth_provider, moira_list): """Verify that UserFilter works for combinations of filters""" if social_auth_provider is None and email is None: pytest.skip("Invalid combination") matching_user = UserFactory.create(email=f"*****@*****.**") nonmatching_user = UserFactory.create() params = {} if moira_list: moira_list = MoiraListFactory.create(name=moira_list) moira_list.users.add(matching_user) params["moira_lists"] = [moira_list] if email: params["email__endswith"] = email if social_auth_provider: params["social_auth_provider"] = social_auth_provider # for each provider create a matching user for provider in social_auth_provider: UserSocialAuthFactory.create(user=matching_user, provider=provider, uid=matching_user.email) query = UserFilter(params, queryset=User.objects.all()).qs assert matching_user in query assert nonmatching_user not in query
def test_moderator_create_email(): """Adds a moderator by email address""" user = UserFactory.create() moderator_user = UserFactory.create() moderator_redditor = Mock(spec=Redditor) moderator_redditor.name = moderator_user.username add_moderator_mock = Mock(return_value=None) list_moderators_mock = Mock(return_value=[moderator_redditor]) api_mock = Mock(add_moderator=add_moderator_mock, _list_moderators=list_moderators_mock) channel_name = "foo_channel" # Make sure that we're testing case insensitivity of email assert moderator_user.email != moderator_user.email.upper() moderator = ModeratorPrivateSerializer( context={ "channel_api": api_mock, "request": Mock(user=user), "view": Mock(kwargs={"channel_name": channel_name}), }).create({"email": moderator_user.email.upper()}) assert moderator is moderator_redditor add_moderator_mock.assert_called_once_with(moderator_user.username, channel_name) list_moderators_mock.assert_called_once_with( channel_name=channel_name, moderator_name=moderator_user.username)
def test_send_comment_notifications(post_id, comment_id): """Tests that send_comment_notifications works correctly""" comment_users = UserFactory.create_batch(5) for user in comment_users: NotificationSettingsFactory.create(user=user, comments_type=True) # create both so we cover the notifiication deduplication SubscriptionFactory.create(user=user, post_id=post_id, comment_id=comment_id) SubscriptionFactory.create(user=user, post_id=post_id, comment_id=None) post_users = UserFactory.create_batch(5) for user in post_users: NotificationSettingsFactory.create(user=user, comments_type=True) SubscriptionFactory.create(user=user, post_id=post_id, comment_id=None) # create just a subscription for a user so we can test no settings scenario SubscriptionFactory.create(post_id=post_id, comment_id=comment_id) # create a bunch on other subscriptions SubscriptionFactory.create_batch(10) api.send_comment_notifications(post_id, comment_id, "abc") users = post_users + comment_users assert CommentEvent.objects.count() == len(users) for event in CommentEvent.objects.all(): assert event.post_id == post_id assert event.comment_id == "abc" assert event.user in users
def test_safe_format_recipients(): """Test that we get a list of emailable recipients""" user = UserFactory.create() user_no_email = UserFactory.create(email="") user_no_name = UserFactory.create(profile__name="") assert safe_format_recipients([user, user_no_email, user_no_name]) == [ (formataddr((user.profile.name, user.email)), user), (formataddr((None, user_no_name.email)), user_no_name), ]
def test_user_filter_email_endswith(): """Verify that UserFilter's email__endswith filter works""" matching_user = UserFactory.create(email="*****@*****.**") nonmatching_user = UserFactory.create(email="*****@*****.**") params = {"email__endswith": "@matching.email"} query = UserFilter(params, queryset=User.objects.all()).qs assert matching_user in query assert nonmatching_user not in query
def test_user_filter_moira_lists(): """Verify that UserFilter's moira_lists filter works""" matching_user = UserFactory.create() nonmatching_user = UserFactory.create() moira_list = MoiraListFactory.create() moira_list.users.add(matching_user) query = UserFilter({ "moira_lists": [moira_list.name] }, queryset=User.objects.all()).qs assert matching_user in query assert nonmatching_user not in query
def test_update_memberships_for_managed_channel_empty_queries(mocker): """Verifies that update_memberships_for_managed_channel() bails if the queries would return all users""" mock_api = mocker.patch("channels.api.Api", autospec=True).return_value channel = ChannelFactory.create(membership_is_managed=True) channel.channel_membership_configs.add( ChannelMembershipConfigFactory.create( query={} # an empty query should match all users )) UserFactory.create( is_active=True) # this user will match the `active_users` query update_memberships_for_managed_channel(channel) mock_api.add_subscriber.assert_not_called() mock_api.add_contributor.assert_not_called()
def test_user_list_items_endpoint_delete_items(client, user, is_author, mock_user_list_index): """Test userlistitems endpoint for deleting UserListItems""" author = UserFactory.create() userlist = UserListFactory.create(author=author, privacy_level=PrivacyLevel.public.value) list_items = sorted( UserListItemFactory.create_batch(2, user_list=userlist), key=lambda item: item.id, ) client.force_login(author if is_author else user) resp = client.delete( reverse("userlistitems-detail", args=[userlist.id, list_items[0].id]), format="json", ) assert resp.status_code == (204 if is_author else 403) if resp.status_code == 204: mock_user_list_index.upsert_user_list_view.assert_called_with( userlist.id) client.delete( reverse("userlistitems-detail", args=[userlist.id, list_items[1].id]), format="json", ) mock_user_list_index.delete_user_list.assert_called_with(userlist)
def test_list_comments_anonymous(client, public_channel, reddit_factories): """List comments as an anonymous user""" user = UserFactory.create(username="******") post = reddit_factories.text_post("a post with comments", user, channel=public_channel) comment = reddit_factories.comment("comment", user, post_id=post.id) url = reverse("comment-list", kwargs={"post_id": post.id}) resp = client.get(url) assert resp.status_code == status.HTTP_200_OK assert resp.json() == [{ "id": comment.id, "parent_id": None, "post_id": post.id, "text": comment.text, "author_id": user.username, "score": 1, "upvoted": False, "downvoted": False, "removed": False, "deleted": False, "subscribed": False, "created": comment.created, "profile_image": image_uri(user.profile), "author_name": user.profile.name, "author_headline": user.profile.headline, "edited": False, "comment_type": "comment", "num_reports": None, }]
def test_contributor_validate_name(): """validate the input""" user = UserFactory.create() serializer = ContributorSerializer( data={"contributor_name": user.username}) serializer.is_valid() assert "contributor_name" not in serializer.errors
def test_contributor_create_username(): """Adds a contributor by username""" user = UserFactory.create() contributor_user = UserFactory.create() contributor_redditor = Mock(spec=Redditor) contributor_redditor.name = contributor_user.username api_mock = Mock(add_contributor=Mock(return_value=contributor_redditor)) contributor = ContributorSerializer( context={ "channel_api": api_mock, "request": Mock(user=user), "view": Mock(kwargs={"channel_name": "foo_channel"}), }).create({"contributor_name": contributor_user.username}) assert contributor is contributor_redditor api_mock.add_contributor.assert_called_once_with(contributor_user.username, "foo_channel")
def test_favorites_serializer(): """ Test that the favorite serializer generic foreign key works and also rejects unexpected classes """ user = UserFactory.create() course = CourseFactory.create() bootcamp = BootcampFactory.create() user_list = UserListFactory.create(author=user) program = ProgramFactory.create() course_topic = CourseTopicFactory.create() favorite_item = FavoriteItem(user=user, item=course) serializer = FavoriteItemSerializer(favorite_item) assert serializer.data.get("content_data") == CourseSerializer(course).data favorite_item = FavoriteItem(user=user, item=bootcamp) serializer = FavoriteItemSerializer(favorite_item) assert serializer.data.get("content_data") == BootcampSerializer( bootcamp).data favorite_item = FavoriteItem(user=user, item=user_list) serializer = FavoriteItemSerializer(favorite_item) assert serializer.data.get("content_data") == UserListSerializer( user_list).data favorite_item = FavoriteItem(user=user, item=program) serializer = FavoriteItemSerializer(favorite_item) assert serializer.data.get("content_data") == ProgramSerializer( program).data favorite_item = FavoriteItem(user=user, item=course_topic) serializer = FavoriteItemSerializer(favorite_item) with pytest.raises(Exception): assert serializer.data.get("content_data").get("id") == course_topic.id
def test_moderator_validate_name(): """validate the input""" user = UserFactory.create() serializer = ModeratorPrivateSerializer( data={"moderator_name": user.username}) serializer.is_valid() assert "moderator_name" not in serializer.errors
class Params: type_text = factory.Trait(widget_type="Text", title="Text Widget", configuration={"body": "example"}) type_url = factory.Trait( widget_type="URL", title="URL Widget", configuration={"url": "http://example.com"}, ) type_markdown = factory.Trait( widget_type="Markdown", title="Markdown Widget", configuration={"source": "*Here's some basic markdown*"}, ) type_rss = factory.Trait( widget_type="RSS Feed", title="RSS Widget", configuration={ "url": "http://example.com", "feed_display_limit": 10 }, ) type_people = factory.Trait( widget_type="People", title="People Widget", configuration=factory.LazyAttribute( lambda _: { "title": "", "people": [UserFactory.create().username for _ in range(10)], "show_all_members_link": False, }), )
def test_update_user_moira_lists(mock_moira_client): """Test that update_user_moira_lists updates the user's related moira lists """ moira_user = UserFactory.create() user_lists = ["test.list.1", "test.list.2", "", None] mock_moira_client.return_value.user_list_membership.return_value = [{ "listName": list_name } for list_name in user_lists] valid_user_lists = user_lists[0:2] moira_list_3 = MoiraListFactory.create(name="test.list.3", users=[moira_user]) assert list(moira_list_3.users.all()) == [moira_user] assert list(moira_user.moira_lists.all()) == [moira_list_3] update_user_moira_lists(moira_user) assert (list( User.objects.get( id=moira_user.id).moira_lists.order_by("name").values_list( "name", flat=True)) == valid_user_lists) for name in valid_user_lists: assert list( MoiraList.objects.get(name=name).users.all()) == [moira_user] assert list( MoiraList.objects.get(name=moira_list_3.name).users.all()) == [] assert (list( moira_user.moira_lists.order_by("name").all().values_list( "name", flat=True)) == valid_user_lists) assert MoiraList.objects.filter(name="").count() == 0
def test_user_list_items_endpoint_update_item(client, user, is_author, mock_user_list_index): """Test userlistitems endpoint for updating UserListItem positions""" author = UserFactory.create() topics = CourseTopicFactory.create_batch(3) userlist = UserListFactory.create(author=author, privacy_level=PrivacyLevel.public.value, topics=topics) list_item_1 = UserListItemFactory.create(user_list=userlist, position=0) list_item_2 = UserListItemFactory.create(user_list=userlist, position=1) list_item_3 = UserListItemFactory.create(user_list=userlist, position=2) client.force_login(author if is_author else user) data = {"position": 0} resp = client.patch( reverse("userlistitems-detail", args=[userlist.id, list_item_3.id]), data=data, format="json", ) assert resp.status_code == (200 if is_author else 403) if resp.status_code == 200: assert resp.json()["position"] == 0 mock_user_list_index.upsert_user_list.assert_called_once_with( userlist.id) for idx, item in enumerate([list_item_3, list_item_1, list_item_2]): item.refresh_from_db() assert item.position == idx
def test_subscriber(): """Serialize of a redditor-like object""" redditor_name = "fooo_username" redditor_user = UserFactory.create(username=redditor_name) assert SubscriberSerializer(redditor_user).data == { "subscriber_name": redditor_name }
def test_query_moira_lists_no_lists(mock_moira_client): """ Test that an empty list is returned if Moira throws a java NPE """ mock_moira_client.return_value.user_list_membership.side_effect = Fault( "java.lang.NullPointerException") other_user = UserFactory(email="*****@*****.**") assert query_moira_lists(other_user) == []
def test_query_moira_lists_error(mock_moira_client): """ Test that a Moira exception is raised if moira client call fails with anything other than a java NPE """ mock_moira_client.return_value.user_list_membership.side_effect = Fault( "Not a java NPE") with pytest.raises(MoiraException): query_moira_lists(UserFactory())
def test_can_edit_other_profile(mocker, method, result, user, is_super): """ Test that non-staff users are not allowed to edit another user's profile """ request = mocker.Mock(user=user, method=method) profile = UserFactory.create(is_superuser=is_super).profile assert (HasEditPermission().has_object_permission( request, mocker.Mock(), profile) is result or is_super)
def test_contributor_create_neither(): """The user must specify an email address or a username""" user = UserFactory.create() contributor_user = UserFactory.create() contributor_redditor = Mock(spec=Redditor) contributor_redditor.name = contributor_user.username api_mock = Mock(add_contributor=Mock(return_value=contributor_redditor)) with pytest.raises(ValueError) as ex: ContributorSerializer( context={ "channel_api": api_mock, "request": Mock(user=user), "view": Mock(kwargs={"channel_name": "foo_channel"}), }).create({}) assert ex.value.args[0] == "Missing contributor_name or email"
def test_list_comments_forbidden(client, private_channel_and_contributor, reddit_factories): """List all comments in the comment tree for a post the user doesn't have access to""" channel, user = private_channel_and_contributor post = reddit_factories.text_post("one post", user, channel=channel) url = reverse("comment-list", kwargs={"post_id": post.id}) client.force_login(UserFactory.create()) resp = client.get(url) assert resp.status_code == status.HTTP_403_FORBIDDEN
def test_moderator_create_neither(): """The user must specify an email address or a username""" user = UserFactory.create() moderator_user = UserFactory.create() moderator_redditor = Mock(spec=Redditor) moderator_redditor.name = moderator_user.username api_mock = Mock(add_moderator=Mock(return_value=moderator_redditor)) # Make sure that we're testing case insensitivity of email assert moderator_user.email != moderator_user.email.upper() with pytest.raises(ValueError) as ex: ModeratorPrivateSerializer( context={ "channel_api": api_mock, "request": Mock(user=user), "view": Mock(kwargs={"channel_name": "foo_channel"}), }).create({}) assert ex.value.args[0] == "Missing moderator_name or email"
def channels_and_users(): """Channels and users for testing""" return ( [ ChannelFactory.create(name=channel_name) for channel_name in ["a", "b", "c"] ], UserFactory.create_batch(4), )
def test_contributor_create_email(): """Adds a contributor by email address""" user = UserFactory.create() contributor_user = UserFactory.create() contributor_redditor = Mock(spec=Redditor) contributor_redditor.name = contributor_user.username api_mock = Mock(add_contributor=Mock(return_value=contributor_redditor)) # Make sure that we're testing case insensitivity of email assert contributor_user.email != contributor_user.email.upper() contributor = ContributorSerializer( context={ "channel_api": api_mock, "request": Mock(user=user), "view": Mock(kwargs={"channel_name": "foo_channel"}), }).create({"email": contributor_user.email.upper()}) assert contributor is contributor_redditor api_mock.add_contributor.assert_called_once_with(contributor_user.username, "foo_channel")
def test_profile_img_url_micromaster_image(): """ Test that the correct profile image URL is returned for a profile with a micromasters profile URL """ profile = UserFactory.create().profile profile.image_file = profile.image_medium_file = profile.image_small_file = None profile.image_medium = "http://testserver/profiles/image.jpg" profile.save() assert image_uri(profile, "image_medium").endswith(profile.image_medium)
def test_prefetched_iterator(chunk_size): """ prefetched_iterator should yield all items in the record set across chunk boundaries """ users = UserFactory.create_batch(10) fetched_users = list( prefetched_iterator(User.objects.all(), chunk_size=chunk_size)) assert len(users) == len(fetched_users) for user in users: assert user in fetched_users
def test_user_list_endpoint_get(client, is_public, is_author, user): """Test learning path endpoint""" author = UserFactory.create() user_list = UserListFactory.create( author=author, privacy_level=PrivacyLevel.public.value if is_public else PrivacyLevel.private.value, ) another_user_list = UserListFactory.create( author=UserFactory.create(), privacy_level=PrivacyLevel.public.value if is_public else PrivacyLevel.private.value, ) UserListItemFactory.create(user_list=user_list, position=1, is_bootcamp=True) UserListItemFactory.create(user_list=user_list, position=2) # Anonymous users should get no results resp = client.get(reverse("userlists-list")) assert resp.data.get("count") == 0 # Logged in user should get own lists client.force_login(author if is_author else user) resp = client.get(reverse("userlists-list")) assert resp.data.get("count") == (1 if is_author else 0) if is_author: assert "content_data" not in resp.data.get("results")[0] resp = client.get(reverse("userlists-detail", args=[user_list.id])) assert resp.status_code == (403 if not (is_public or is_author) else 200) if resp.status_code == 200: assert resp.data.get("title") == user_list.title assert len(resp.data.get("lists")) == 0 assert resp.data.get("item_count") == 2 # Logged in user should see other person's public list resp = client.get(reverse("userlists-detail", args=[another_user_list.id])) assert resp.status_code == (403 if not is_public else 200) if resp.status_code == 200: assert resp.data.get("title") == another_user_list.title
def test_profile_img_url_uploaded_image(): """ Test that the correct profile image URL is returned for a profile with an uploaded image """ profile = UserFactory.create().profile image = Image.new("RGBA", size=(50, 50), color=(155, 0, 0)) profile.image_small_file.save("/profiles/realimage.jpg", BytesIO(image.tobytes()), True) profile.save() assert image_uri(profile, "image_small") == profile.image_small_file.url
def test_contributor(): """Serialize of a redditor-like object""" redditor = Mock(spec=Redditor) # the `name` attribute cannot be configured during the mock object creation redditor.name = "fooo_username" user = UserFactory.create(username=redditor.name) assert ContributorSerializer(redditor).data == { "contributor_name": "fooo_username", "full_name": user.profile.name, "email": user.email, }