def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for('update_comments_timestamp') payload = {'page': 'node', 'rootId': project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content='edited', save=True) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1)
def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for("update_comments_timestamp") payload = {"page": "node", "rootId": project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content="edited", save=True) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 1)
class TestCommentFiltering(ApiTestCase): def setUp(self): super(TestCommentFiltering, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.comment = CommentFactory(node=self.project, user=self.user) self.deleted_comment = CommentFactory(node=self.project, user=self.user, is_deleted=True) self.base_url = "/{}nodes/{}/comments/".format(API_BASE, self.project._id) self.formatted_date_created = self.comment.date_created.strftime("%Y-%m-%dT%H:%M:%S.%f") self.comment.edit("Edited comment", auth=core.Auth(self.user), save=True) self.formatted_date_modified = self.comment.date_modified.strftime("%Y-%m-%dT%H:%M:%S.%f") def test_node_comments_with_no_filter_returns_all_comments(self): res = self.app.get(self.base_url, auth=self.user.auth) assert_equal(len(res.json["data"]), 2) def test_filtering_for_deleted_comments(self): url = self.base_url + "?filter[deleted]=True" res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) assert_true(res.json["data"][0]["attributes"]["deleted"]) def test_filtering_for_non_deleted_comments(self): url = self.base_url + "?filter[deleted]=False" res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) assert_false(res.json["data"][0]["attributes"]["deleted"]) def test_filtering_comments_created_before_date(self): url = self.base_url + "?filter[date_created][lt]={}".format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 0) def test_filtering_comments_created_on_date(self): url = self.base_url + "?filter[date_created][eq]={}".format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) def test_filtering_comments_created_on_or_before_date(self): url = self.base_url + "?filter[date_created][lte]={}".format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) def test_filtering_comments_created_after_date(self): url = self.base_url + "?filter[date_created][gt]={}".format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) def test_filtering_comments_created_on_or_after_date(self): url = self.base_url + "?filter[date_created][gte]={}".format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 2) def test_filtering_comments_modified_before_date(self): url = self.base_url + "?filter[date_modified][lt]={}".format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) def test_filtering_comments_modified_on_date(self): url = self.base_url + "?filter[date_modified][eq]={}".format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 1) def test_filtering_comments_modified_after_date(self): url = self.base_url + "?filter[date_modified][gt]={}".format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json["data"]), 0)
class TestCommentRepliesFiltering(ApiTestCase): def setUp(self): super(TestCommentRepliesFiltering, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.comment = CommentFactory(node=self.project, user=self.user) self.reply = CommentFactory(node=self.project, target=self.comment, user=self.user) self.deleted_reply = CommentFactory(node=self.project, target=self.comment, user=self.user, is_deleted=True) self.base_url = '/{}comments/{}/replies/'.format( API_BASE, self.comment._id) self.formatted_date_created = self.reply.date_created.strftime( '%Y-%m-%dT%H:%M:%S.%f') self.reply.edit('Edited comment', auth=core.Auth(self.user), save=True) self.formatted_date_modified = self.reply.date_modified.strftime( '%Y-%m-%dT%H:%M:%S.%f') def test_node_comments_replies_with_no_filter_returns_all(self): res = self.app.get(self.base_url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_for_deleted_comment_replies(self): url = self.base_url + '?filter[deleted]=True' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_true(res.json['data'][0]['attributes']['deleted']) def test_filtering_for_non_deleted_comment_replies(self): url = self.base_url + '?filter[deleted]=False' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_false(res.json['data'][0]['attributes']['deleted']) def test_filtering_comments_replies_created_before_date(self): url = self.base_url + '?filter[date_created][lt]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_comment_replies_created_on_datetime(self): url = self.base_url + '?filter[date_created][eq]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_created_on_date(self): url = self.base_url + '?filter[date_created][eq]={}'.format( self.reply.date_created.strftime('%Y-%m-%d')) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_comment_replies_created_after_date(self): url = self.base_url + '?filter[date_created][gt]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_before_date(self): url = self.base_url + '?filter[date_modified][lt]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_on_date(self): url = self.base_url + '?filter[date_modified][eq]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_after_date(self): url = self.base_url + '?filter[date_modified][gt]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0)
class TestCommentModel(OsfTestCase): def setUp(self): super(TestCommentModel, self).setUp() self.comment = CommentFactory() self.auth = Auth(user=self.comment.user) def test_create(self): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, page='node', is_public=True, content='This is a comment.' ) assert_equal(comment.user, self.comment.user) assert_equal(comment.node, self.comment.node) assert_equal(comment.target, self.comment.target) assert_equal(len(comment.node.logs), 2) assert_equal(comment.node.logs[-1].action, NodeLog.COMMENT_ADDED) def test_create_comment_content_cannot_exceed_max_length(self): with assert_raises(ValidationValueError): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=''.join(['c' for c in range(settings.COMMENT_MAXLENGTH + 1)]) ) def test_create_comment_content_cannot_be_none(self): with assert_raises(ValidationError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=None ) assert_equal(error.exception.message, 'Value <content> is required.') def test_create_comment_content_cannot_be_empty(self): with assert_raises(ValidationValueError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content='' ) assert_equal(error.exception.message, 'Value must not be empty.') def test_create_comment_content_cannot_be_whitespace(self): with assert_raises(ValidationValueError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=' ' ) assert_equal(error.exception.message, 'Value must not be empty.') def test_create_sends_comment_added_signal(self): with capture_signals() as mock_signals: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content='This is a comment.' ) assert_equal(mock_signals.signals_sent(), set([comment_added])) def test_edit(self): self.comment.edit( auth=self.auth, content='edited', save=True ) assert_equal(self.comment.content, 'edited') assert_true(self.comment.modified) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_UPDATED) def test_delete(self): self.comment.delete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, True) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_REMOVED) def test_undelete(self): self.comment.delete(auth=self.auth, save=True) self.comment.undelete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, False) assert_equal(len(self.comment.node.logs), 3) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_RESTORED) def test_read_permission_contributor_can_comment(self): project = ProjectFactory() user = UserFactory() project.set_privacy('private') project.add_contributor(user, permissions=[permissions.READ]) project.save() assert_true(project.can_comment(Auth(user=user))) def test_get_content_for_not_deleted_comment(self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_returns_deleted_content_to_commenter(self): comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_does_not_return_deleted_content_to_non_commenter(self): user = AuthUserFactory() comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(user)) assert_is_none(content) def test_get_content_public_project_does_not_return_deleted_content_to_logged_out_user(self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project, is_deleted=True) content = comment.get_content(auth=None) assert_is_none(content) def test_get_content_private_project_throws_permissions_error_for_logged_out_users(self): project = ProjectFactory(is_public=False) comment = CommentFactory(node=project, is_deleted=True) with assert_raises(PermissionsError): comment.get_content(auth=None) def test_find_unread_is_zero_when_no_comments(self): n_unread = Comment.find_n_unread(user=UserFactory(), node=ProjectFactory()) assert_equal(n_unread, 0) def test_find_unread_new_comments(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) def test_find_unread_includes_comment_replies(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=user) reply = CommentFactory(node=project, target=comment, user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) # Regression test for https://openscience.atlassian.net/browse/OSF-5193 def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for('update_comments_timestamp') payload = {'page': 'node', 'rootId': project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0) # Edit previously read comment comment.edit( auth=Auth(project.creator), content='edited', save=True ) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) def test_find_unread_does_not_include_deleted_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator, is_deleted=True) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0)
class TestCommentFiltering(ApiTestCase): def setUp(self): super(TestCommentFiltering, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.comment = CommentFactory(node=self.project, user=self.user) self.deleted_comment = CommentFactory(node=self.project, user=self.user, is_deleted=True) self.base_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project._id) self.formatted_date_created = self.comment.date_created.strftime( '%Y-%m-%dT%H:%M:%S.%f') self.comment.edit('Edited comment', auth=core.Auth(self.user), save=True) self.formatted_date_modified = self.comment.date_modified.strftime( '%Y-%m-%dT%H:%M:%S.%f') def test_node_comments_with_no_filter_returns_all_comments(self): res = self.app.get(self.base_url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_for_deleted_comments(self): url = self.base_url + '?filter[deleted]=True' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_true(res.json['data'][0]['attributes']['deleted']) def test_filtering_for_non_deleted_comments(self): url = self.base_url + '?filter[deleted]=False' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_false(res.json['data'][0]['attributes']['deleted']) def test_filtering_comments_created_before_date(self): url = self.base_url + '?filter[date_created][lt]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_comments_created_on_date(self): url = self.base_url + '?filter[date_created][eq]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_on_or_before_date(self): url = self.base_url + '?filter[date_created][lte]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_after_date(self): url = self.base_url + '?filter[date_created][gt]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_on_or_after_date(self): url = self.base_url + '?filter[date_created][gte]={}'.format( self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_comments_modified_before_date(self): url = self.base_url + '?filter[date_modified][lt]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_modified_on_date(self): url = self.base_url + '?filter[date_modified][eq]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_modified_after_date(self): url = self.base_url + '?filter[date_modified][gt]={}'.format( self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_by_target(self): url = self.base_url + '?filter[target]=' + str(self.project._id) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) assert_in( self.project._id, res.json['data'][0]['relationships']['target'] ['links']['related']['href']) def test_filtering_by_target_no_results(self): url = self.base_url + '?filter[target]=' + 'fakeid' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0)
class TestCommentModel(OsfTestCase): def setUp(self): super(TestCommentModel, self).setUp() self.comment = CommentFactory() self.auth = Auth(user=self.comment.user) def test_create(self): comment = Comment.create(auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, page='node', is_public=True, content='This is a comment.') assert_equal(comment.user, self.comment.user) assert_equal(comment.node, self.comment.node) assert_equal(comment.target, self.comment.target) assert_equal(len(comment.node.logs), 2) assert_equal(comment.node.logs[-1].action, NodeLog.COMMENT_ADDED) def test_create_comment_content_cannot_exceed_max_length(self): with assert_raises(ValidationValueError): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=''.join( ['c' for c in range(settings.COMMENT_MAXLENGTH + 1)])) def test_create_comment_content_cannot_be_none(self): with assert_raises(ValidationError) as error: comment = Comment.create(auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=None) assert_equal(error.exception.message, 'Value <content> is required.') def test_create_comment_content_cannot_be_empty(self): with assert_raises(ValidationValueError) as error: comment = Comment.create(auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content='') assert_equal(error.exception.message, 'Value must not be empty.') def test_create_comment_content_cannot_be_whitespace(self): with assert_raises(ValidationValueError) as error: comment = Comment.create(auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=' ') assert_equal(error.exception.message, 'Value must not be empty.') def test_create_sends_comment_added_signal(self): with capture_signals() as mock_signals: comment = Comment.create(auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content='This is a comment.') assert_equal(mock_signals.signals_sent(), set([comment_added])) def test_edit(self): self.comment.edit(auth=self.auth, content='edited', save=True) assert_equal(self.comment.content, 'edited') assert_true(self.comment.modified) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_UPDATED) def test_delete(self): self.comment.delete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, True) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_REMOVED) def test_undelete(self): self.comment.delete(auth=self.auth, save=True) self.comment.undelete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, False) assert_equal(len(self.comment.node.logs), 3) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_RESTORED) def test_read_permission_contributor_can_comment(self): project = ProjectFactory() user = UserFactory() project.set_privacy('private') project.add_contributor(user, permissions=[permissions.READ]) project.save() assert_true(project.can_comment(Auth(user=user))) def test_get_content_for_not_deleted_comment(self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_returns_deleted_content_to_commenter(self): comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_does_not_return_deleted_content_to_non_commenter( self): user = AuthUserFactory() comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(user)) assert_is_none(content) def test_get_content_public_project_does_not_return_deleted_content_to_logged_out_user( self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project, is_deleted=True) content = comment.get_content(auth=None) assert_is_none(content) def test_get_content_private_project_throws_permissions_error_for_logged_out_users( self): project = ProjectFactory(is_public=False) comment = CommentFactory(node=project, is_deleted=True) with assert_raises(PermissionsError): comment.get_content(auth=None) def test_find_unread_is_zero_when_no_comments(self): n_unread = Comment.find_n_unread(user=UserFactory(), node=ProjectFactory()) assert_equal(n_unread, 0) def test_find_unread_new_comments(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) def test_find_unread_includes_comment_replies(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=user) reply = CommentFactory(node=project, target=comment, user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) # Regression test for https://openscience.atlassian.net/browse/OSF-5193 def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for('update_comments_timestamp') payload = {'page': 'node', 'rootId': project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content='edited', save=True) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 1) def test_find_unread_does_not_include_deleted_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator, is_deleted=True) n_unread = Comment.find_n_unread(user=user, node=project) assert_equal(n_unread, 0)
class TestCommentFiltering(ApiTestCase): def setUp(self): super(TestCommentFiltering, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.comment = CommentFactory(node=self.project, user=self.user) self.deleted_comment = CommentFactory(node=self.project, user=self.user, is_deleted=True) self.base_url = '/{}nodes/{}/comments/'.format(API_BASE, self.project._id) self.formatted_date_created = self.comment.date_created.strftime('%Y-%m-%dT%H:%M:%S.%f') self.comment.edit('Edited comment', auth=core.Auth(self.user), save=True) self.formatted_date_modified = self.comment.date_modified.strftime('%Y-%m-%dT%H:%M:%S.%f') def test_node_comments_with_no_filter_returns_all_comments(self): res = self.app.get(self.base_url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_for_deleted_comments(self): url = self.base_url + '?filter[deleted]=True' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_true(res.json['data'][0]['attributes']['deleted']) def test_filtering_for_non_deleted_comments(self): url = self.base_url + '?filter[deleted]=False' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_false(res.json['data'][0]['attributes']['deleted']) def test_filtering_comments_created_before_date(self): url = self.base_url + '?filter[date_created][lt]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_comments_created_on_date(self): url = self.base_url + '?filter[date_created][eq]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_on_or_before_date(self): url = self.base_url + '?filter[date_created][lte]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_after_date(self): url = self.base_url + '?filter[date_created][gt]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_created_on_or_after_date(self): url = self.base_url + '?filter[date_created][gte]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_comments_modified_before_date(self): url = self.base_url + '?filter[date_modified][lt]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_modified_on_date(self): url = self.base_url + '?filter[date_modified][eq]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comments_modified_after_date(self): url = self.base_url + '?filter[date_modified][gt]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_by_target(self): url = self.base_url + '?filter[target]=' + str(self.project._id) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) assert_in(self.project._id, res.json['data'][0]['relationships']['target']['links']['related']['href']) def test_filtering_by_target_no_results(self): url = self.base_url + '?filter[target]=' + 'fakeid' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0)
class TestCommentModel(OsfTestCase): def setUp(self): super(TestCommentModel, self).setUp() self.comment = CommentFactory() self.auth = Auth(user=self.comment.user) def test_create(self): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, root_target=self.comment.root_target, page="node", is_public=True, content="This is a comment.", ) assert_equal(comment.user, self.comment.user) assert_equal(comment.node, self.comment.node) assert_equal(comment.target, self.comment.target) assert_equal(len(comment.node.logs), 2) assert_equal(comment.node.logs[-1].action, NodeLog.COMMENT_ADDED) assert_equal([], self.comment.ever_mentioned) def test_create_comment_content_cannot_exceed_max_length_simple(self): with assert_raises(ValidationValueError): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="".join(["c" for c in range(settings.COMMENT_MAXLENGTH + 3)]), ) def test_create_comment_content_cannot_exceed_max_length_complex(self): with assert_raises(ValidationValueError): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="".join(["c" for c in range(settings.COMMENT_MAXLENGTH - 8)]) + "[@George Ant](http://localhost:5000/" + self.comment.user._id + "/)", ) def test_create_comment_content_does_not_exceed_max_length_complex(self): comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="".join(["c" for c in range(settings.COMMENT_MAXLENGTH - 12)]) + "[@George Ant](http://localhost:5000/" + self.comment.user._id + "/)", ) def test_create_comment_content_cannot_be_none(self): with assert_raises(ValidationError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=None, ) assert_equal(error.exception.message, "Value <content> is required.") def test_create_comment_content_cannot_be_empty(self): with assert_raises(ValidationValueError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="", ) assert_equal(error.exception.message, "Value must not be empty.") def test_create_comment_content_cannot_be_whitespace(self): with assert_raises(ValidationValueError) as error: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content=" ", ) assert_equal(error.exception.message, "Value must not be empty.") def test_create_sends_comment_added_signal(self): with capture_signals() as mock_signals: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, root_target=self.comment.root_target, is_public=True, content="This is a comment.", ) assert_equal(mock_signals.signals_sent(), set([comment_added])) def test_create_sends_mention_added_signal_if_mentions(self): with capture_signals() as mock_signals: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="This is a comment with a bad mention [@Unconfirmed User](http://localhost:5000/" + self.comment.user._id + "/).", ) assert_equal(mock_signals.signals_sent(), set([comment_added, mention_added])) def test_create_does_not_send_mention_added_signal_if_unconfirmed_contributor_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: user = UserFactory() user.is_registered = False user.is_claimed = False user.save() self.comment.node.add_contributor(user, visible=False, permissions=[permissions.READ]) self.comment.node.save() comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="This is a comment with a bad mention [@Unconfirmed User](http://localhost:5000/" + user._id + "/).", ) assert_equal(mock_signals.signals_sent(), set([contributor_added])) assert_equal(error.exception.message, "User does not exist or is not active.") def test_create_does_not_send_mention_added_signal_if_noncontributor_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: user = UserFactory() comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="This is a comment with a bad mention [@Non-contributor User](http://localhost:5000/" + user._id + "/).", ) assert_equal(mock_signals.signals_sent(), set([])) assert_equal(error.exception.message, "Mentioned user is not a contributor.") def test_create_does_not_send_mention_added_signal_if_nonuser_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: comment = Comment.create( auth=self.auth, user=self.comment.user, node=self.comment.node, target=self.comment.target, is_public=True, content="This is a comment with a bad mention [@Not a User](http://localhost:5000/qwert/).", ) assert_equal(mock_signals.signals_sent(), set([])) assert_equal(error.exception.message, "User does not exist or is not active.") def test_edit(self): self.comment.edit(auth=self.auth, content="edited", save=True) assert_equal(self.comment.content, "edited") assert_true(self.comment.modified) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_UPDATED) def test_edit_sends_mention_added_signal_if_mentions(self): with capture_signals() as mock_signals: self.comment.edit( auth=self.auth, content="This is a comment with a bad mention [@Mentioned User](http://localhost:5000/" + self.comment.user._id + "/).", save=True, ) assert_equal(mock_signals.signals_sent(), set([mention_added])) def test_edit_does_not_send_mention_added_signal_if_nonuser_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: self.comment.edit( auth=self.auth, content="This is a comment with a bad mention [@Not a User](http://localhost:5000/qwert/).", save=True, ) assert_equal(mock_signals.signals_sent(), set([])) assert_equal(error.exception.message, "User does not exist or is not active.") def test_edit_does_not_send_mention_added_signal_if_noncontributor_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: user = UserFactory() self.comment.edit( auth=self.auth, content="This is a comment with a bad mention [@Non-contributor User](http://localhost:5000/" + user._id + "/).", save=True, ) assert_equal(mock_signals.signals_sent(), set([])) assert_equal(error.exception.message, "Mentioned user is not a contributor.") def test_edit_does_not_send_mention_added_signal_if_unconfirmed_contributor_mentioned(self): with assert_raises(ValidationValueError) as error: with capture_signals() as mock_signals: user = UserFactory() user.is_registered = False user.is_claimed = False user.save() self.comment.node.add_contributor(user, visible=False, permissions=[permissions.READ]) self.comment.node.save() self.comment.edit( auth=self.auth, content="This is a comment with a bad mention [@Unconfirmed User](http://localhost:5000/" + user._id + "/).", save=True, ) assert_equal(mock_signals.signals_sent(), set([contributor_added])) assert_equal(error.exception.message, "User does not exist or is not active.") def test_edit_does_not_send_mention_added_signal_if_already_mentioned(self): with capture_signals() as mock_signals: self.comment.ever_mentioned = [self.comment.user._id] self.comment.edit( auth=self.auth, content="This is a comment with a bad mention [@Already Mentioned User](http://localhost:5000/" + self.comment.user._id + "/).", save=True, ) assert_equal(mock_signals.signals_sent(), set([])) def test_delete(self): self.comment.delete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, True) assert_equal(len(self.comment.node.logs), 2) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_REMOVED) def test_undelete(self): self.comment.delete(auth=self.auth, save=True) self.comment.undelete(auth=self.auth, save=True) assert_equal(self.comment.is_deleted, False) assert_equal(len(self.comment.node.logs), 3) assert_equal(self.comment.node.logs[-1].action, NodeLog.COMMENT_RESTORED) def test_read_permission_contributor_can_comment(self): project = ProjectFactory() user = UserFactory() project.set_privacy("private") project.add_contributor(user, permissions=[permissions.READ]) project.save() assert_true(project.can_comment(Auth(user=user))) def test_get_content_for_not_deleted_comment(self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_returns_deleted_content_to_commenter(self): comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(comment.user)) assert_equal(content, comment.content) def test_get_content_does_not_return_deleted_content_to_non_commenter(self): user = AuthUserFactory() comment = CommentFactory(is_deleted=True) content = comment.get_content(auth=Auth(user)) assert_is_none(content) def test_get_content_public_project_does_not_return_deleted_content_to_logged_out_user(self): project = ProjectFactory(is_public=True) comment = CommentFactory(node=project, is_deleted=True) content = comment.get_content(auth=None) assert_is_none(content) def test_get_content_private_project_throws_permissions_error_for_logged_out_users(self): project = ProjectFactory(is_public=False) comment = CommentFactory(node=project, is_deleted=True) with assert_raises(PermissionsError): comment.get_content(auth=None) def test_find_unread_is_zero_when_no_comments(self): n_unread = Comment.find_n_unread(user=UserFactory(), node=ProjectFactory(), page="node") assert_equal(n_unread, 0) def test_find_unread_new_comments(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 1) def test_find_unread_includes_comment_replies(self): project = ProjectFactory() user = UserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=user) reply = CommentFactory(node=project, target=Guid.load(comment._id), user=project.creator) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 1) # Regression test for https://openscience.atlassian.net/browse/OSF-5193 def test_find_unread_includes_edited_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator) url = project.api_url_for("update_comments_timestamp") payload = {"page": "node", "rootId": project._id} res = self.app.put_json(url, payload, auth=user.auth) user.reload() n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 0) # Edit previously read comment comment.edit(auth=Auth(project.creator), content="edited", save=True) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 1) def test_find_unread_does_not_include_deleted_comments(self): project = ProjectFactory() user = AuthUserFactory() project.add_contributor(user) project.save() comment = CommentFactory(node=project, user=project.creator, is_deleted=True) n_unread = Comment.find_n_unread(user=user, node=project, page="node") assert_equal(n_unread, 0)
class TestCommentRepliesFiltering(ApiTestCase): def setUp(self): super(TestCommentRepliesFiltering, self).setUp() self.user = AuthUserFactory() self.project = ProjectFactory(creator=self.user) self.comment = CommentFactory(node=self.project, user=self.user) self.reply = CommentFactory(node=self.project, target=self.comment, user=self.user) self.deleted_reply = CommentFactory(node=self.project, target=self.comment, user=self.user, is_deleted=True) self.base_url = '/{}comments/{}/replies/'.format(API_BASE, self.comment._id) self.formatted_date_created = self.reply.date_created.strftime('%Y-%m-%dT%H:%M:%S.%f') self.reply.edit('Edited comment', auth=core.Auth(self.user), save=True) self.formatted_date_modified = self.reply.date_modified.strftime('%Y-%m-%dT%H:%M:%S.%f') def test_node_comments_replies_with_no_filter_returns_all(self): res = self.app.get(self.base_url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_for_deleted_comment_replies(self): url = self.base_url + '?filter[deleted]=True' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_true(res.json['data'][0]['attributes']['deleted']) def test_filtering_for_non_deleted_comment_replies(self): url = self.base_url + '?filter[deleted]=False' res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) assert_false(res.json['data'][0]['attributes']['deleted']) def test_filtering_comments_replies_created_before_date(self): url = self.base_url + '?filter[date_created][lt]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0) def test_filtering_comment_replies_created_on_datetime(self): url = self.base_url + '?filter[date_created][eq]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_created_on_date(self): url = self.base_url + '?filter[date_created][eq]={}'.format(self.reply.date_created.strftime('%Y-%m-%d')) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 2) def test_filtering_comment_replies_created_after_date(self): url = self.base_url + '?filter[date_created][gt]={}'.format(self.formatted_date_created) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_before_date(self): url = self.base_url + '?filter[date_modified][lt]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_on_date(self): url = self.base_url + '?filter[date_modified][eq]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 1) def test_filtering_comment_replies_modified_after_date(self): url = self.base_url + '?filter[date_modified][gt]={}'.format(self.formatted_date_modified) res = self.app.get(url, auth=self.user.auth) assert_equal(len(res.json['data']), 0)