def test_author_checks(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'author': {'post_karma': '> 5'}, 'action': 'remove'}) assert mod.moderate(rule), "basic author checks are failing" rule = Rule({'author': {'post_karma': '> 15'}, 'action': 'remove'}) self.assertFalse(mod.moderate(rule), "basic author checks are throwing false positive")
def test_multiple_values(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'id': ['abcde', 'fghij'], 'action': 'remove'}) assert mod.moderate(rule), "Matches fail with multiple values" rule = Rule({'id': ['fghij', 'abcde'], 'action': 'remove'}) assert mod.moderate( rule ), "Matches fail with multiple values, when correct value is not first"
def test_include(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'body (includes)': 'Ell', 'action': 'remove'}) assert mod.moderate(rule), "include match failing to match" rule = Rule({'body (includes)': 'lo, ', 'action': 'remove'}) assert mod.moderate( rule), "include match failing to match with word boundaries" comment.body = "Hello world" self.assertFalse(mod.moderate(rule), "include match matching as a false positive")
def test_lowercase_checks(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'id (full-text)': 'AbCdE', 'action': 'remove'}) assert mod.moderate( rule), "full-text doesn't match when some letters are uppercase" rule = Rule({ 'id (full-text, case-sensitive)': 'AbCdE', 'action': 'remove' }) self.assertFalse( mod.moderate(rule), "full-text matches even when some letters are uppercase and case-sensitive is on" )
def crosspost_subreddit(self, value, rule, options): if not hasattr(self.item, 'crosspost_parent'): return None sub_checks = ModeratorCrosspostSubredditChecks(self.moderator) sub_rule = Rule(value) return self.moderator.check(sub_rule, checks=sub_checks)
def test_report_reasons_only(self): rule = Rule({ 'report_reasons (only)': 'abcde', 'action': 'approve' }) comment = helpers.comment() comment.user_reports = [ ['abcde', 1], ] mod = ModqueueModerator(comment) assert mod.moderate(rule), "User reports (only) not passing when only a match exists" comment = helpers.comment() comment.user_reports = [ ['abcde', 1], ['edcba', 1] ] comment.mod_reports = [] mod = ModqueueModerator(comment) self.assertFalse(mod.moderate(rule), "User reports (only) passing when a match exists alongside a non-match") comment = helpers.comment() comment.user_reports = [ ['fghij', 1], ['edcba', 1] ] comment.mod_reports = [] mod = ModqueueModerator(comment) self.assertFalse(mod.moderate(rule), "User reports (only) are passing when the list does not contain the value")
def test_poll_option_text_check(self): rule = Rule({ 'poll_option_text (full-exact)': 'Is this a test?', 'action': 'approve' }) class PollData: def __init__(self): self.options = [ 'Is this a test?', 'Or is this just fantasy?' ] poll_data = PollData() post = helpers.post() type(post).poll_data = PropertyMock(return_value=poll_data) mod = PostModerator(post) assert mod.moderate(rule), "Post poll_option_text not matching first option correctly" poll_data.options = ["Is this real life?", "Is this a test?"] assert mod.moderate(rule), "Post poll_option_text not matching first option correctly" poll_data.options = ["Is this real life?", "Or is this just fantasy?"] self.assertFalse(mod.moderate(rule), "Post poll_option_text matching as a false positive") type(post).poll_data = None
def test_set_locked(self): post = helpers.post() mod = Moderator(post) lock_mock = MagicMock() unlock_mock = MagicMock() post.mod.lock = lock_mock post.mod.unlock = unlock_mock mod.moderate(Rule({'id': post.id, 'set_locked': True})) lock_mock.assert_called() unlock_mock.assert_not_called() lock_mock.reset_mock() mod.moderate(Rule({'id': post.id, 'set_locked': False})) lock_mock.assert_not_called() unlock_mock.assert_called()
def test_multiple_checks(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'id+body (full-exact)': 'abcde', 'action': 'remove'}) assert mod.moderate(rule), "Matches fail when checks are combined" rule = Rule({ 'id+body (full-exact)': 'Hello, world!', 'action': 'remove' }) assert mod.moderate(rule), "Matches fail when checks are combined" rule = Rule({'id+body (full-exact)': 'not there', 'action': 'remove'}) self.assertFalse(mod.moderate(rule), "Matches when checks are combined")
def test_author_flair_template_id(self): post = helpers.post() rule = Rule({ 'author': { 'flair_template_id': 'test' }, 'action': 'remove' }) mod = Moderator(post) flair_mock = MagicMock( return_value={'current': { 'flair_template_id': 'test' }}) old_post = reddit.post reddit.post = flair_mock assert mod.moderate(rule), "Author flair_template_id not matching" flair_mock.return_value = {'current': {'flair_template_id': 'nomatch'}} self.assertFalse( mod.moderate(rule), "Author flair_template_id matching as a false positive") reddit.post = old_post
def crosspost_author(self, value, rule, options): if not hasattr(self.item, 'crosspost_parent'): return None author_checks = ModeratorAuthorChecks(self.moderator) author_checks.item = reddit.submission(self.item.crosspost_parent.split('_')[1]) author_rule = Rule(value) return self.moderator.check(author_rule, checks=author_checks)
def crosspost_author(self, rule, value): if not hasattr(self.item, 'crosspost_parent'): return None author_actions = ModeratorAuthorActions(self.moderator) author_actions.item = reddit.submission(self.item.crosspost_parent.split('_')[1]) author_rule = Rule(value) return self.moderator.action(author_rule, actions=author_actions)
def test_set_suggested_sort(self): post = helpers.post() mod = PostModerator(post) suggested_sort_mock = MagicMock() post.mod.suggested_sort = suggested_sort_mock mod.moderate(Rule({ 'id': post.id, 'set_suggested_sort': 'hot' })) suggested_sort_mock.assert_called_with('hot') mod.moderate(Rule({ 'id': post.id, 'set_suggested_sort': 'new' })) suggested_sort_mock.assert_called_with('new')
def parent_comment(self, rule, value): if comment_depth(self.item) == 0: return None comment_actions = CommentModeratorActions(self.moderator) comment_actions.item = self.item.parent() comment_rule = Rule(value) return self.moderator.action(comment_rule, actions=comment_actions)
def test_set_sticky(self): post = helpers.post() mod = Moderator(post) sticky_mock = MagicMock() post.mod.distinguish = sticky_mock # Sets text mod.moderate(Rule({'id': post.id, 'set_sticky': True})) sticky_mock.assert_called_with('yes', sticky=True) sticky_mock.reset_mock() mod.moderate(Rule({'id': post.id, 'set_sticky': 1})) sticky_mock.assert_called_with('yes', sticky=True) sticky_mock.reset_mock() mod.moderate(Rule({'id': post.id, 'set_sticky': False})) sticky_mock.assert_called_with('no', sticky=False)
def parent_comment(self, value, rule, options): if comment_depth(self.item) == 0: return None comment_checks = CommentModeratorChecks(self.moderator) comment_checks.item = self.item.parent() comment_rule = Rule(value) return self.moderator.check(comment_rule, checks=comment_checks)
def test_report(self): post = helpers.post() rule = Rule({'id': post.id, 'action': 'report'}) mod = Moderator(post) post.report.reset_mock() mod.moderate(rule) post.report.assert_called_with(None) rule = Rule({ 'id': post.id, 'action': 'report', 'action_reason': 'Just cuz' }) post.report.reset_mock() mod.moderate(rule) post.report.assert_called_with('Just cuz')
def test_set_contest_mode(self): post = helpers.post() mod = PostModerator(post) contest_mode_mock = MagicMock() post.mod.contest_mode = contest_mode_mock mod.moderate(Rule({ 'id': post.id, 'set_contest_mode': True })) contest_mode_mock.assert_called_with(True) mod.moderate(Rule({ 'id': post.id, 'set_contest_mode': False })) contest_mode_mock.assert_called_with(False)
def test_spam(self): post = helpers.post() rule = Rule({'id': post.id, 'action': 'spam'}) mod = Moderator(post) post.mod.remove.reset_mock() mod.moderate(rule) post.mod.remove.assert_called_with(spam=True)
def test_negation(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'id': 'abcde', 'action': 'remove'}) assert mod.moderate(rule), "Doesn't match when validity is default" rule = Rule({'id': ['abcde', 'fghij'], 'action': 'remove'}) assert mod.moderate( rule), "Doesn't match lists when validity is default" rule = Rule({'~id': 'abcde', 'action': 'remove'}) self.assertFalse(mod.moderate(rule), "Matches when validity is false") rule = Rule({'id': 'test', 'action': 'remove'}) self.assertFalse( mod.moderate(rule), "Matches when validity is default and there's no actual match") rule = Rule({'~id': 'test', 'action': 'remove'}) assert mod.moderate( rule ), "Doesn't match when validity is false, but there's no actual match" rule = Rule({'~id': ['fghij', 'klmno'], 'action': 'remove'}) assert mod.moderate( rule), "Matches when a list of values is given but none match" rule = Rule({'~id': ['abcde', 'fghij'], 'action': 'remove'}) self.assertFalse( mod.moderate(rule), "Matches when a list of values is given and one matches")
def test_full_exact_regex(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({ 'body (full-exact, regex)': 'Hello,? world!?', 'action': 'remove' }) assert mod.moderate( rule), "full_exact match with regex failing to match"
def test_starts_with(self): comment = helpers.comment() mod = Moderator(comment) rule = Rule({'body (starts-with)': 'Hello', 'action': 'remove'}) assert mod.moderate(rule), "starts-with match failing to match" comment.body = 'Wassup, buddy?' self.assertFalse(mod.moderate(rule), "starts-with match matching as false positive")
def test_satisfy_any_threshold(self): comment = helpers.comment() type(comment.author).comment_karma = PropertyMock(return_value=150) type(comment.author).link_karma = PropertyMock(return_value=100) mod = Moderator(comment) rule = Rule({ 'author': { 'comment_karma': '> 50', 'post_karma': '< 50' }, 'action': 'approve' }) self.assertFalse( mod.moderate(rule), 'Karma rules are passing when false, regardless of satisfy_any_threshold' ) rule = Rule({ 'author': { 'comment_karma': '> 50', 'post_karma': '< 50', 'satisfy_any_threshold': True }, 'action': 'approve' }) assert mod.moderate( rule ), 'Karma rules are not passing when satisfy_any_threshold is True' rule = Rule({ 'author': { 'comment_karma': '< 50', 'post_karma': '< 50', 'satisfy_any_threshold': True }, 'action': 'approve' }) self.assertFalse( mod.moderate(rule), 'Karma rules matching as false positive when satisfy_any_threshold is True' )
def test_is_edited(self): comment = helpers.comment() rule = Rule({'is_edited': True, 'action': 'approve'}) comment.edited = 1595932445.0 mod = Moderator(comment) assert mod.moderate(rule), "is_edited not matching" comment.edited = False self.assertFalse(mod.moderate(rule), "is_edited matching as false positive")
def test_domain_textpost_check(self): post = helpers.post() rule = Rule({ 'domain': "self.%s" % post.subreddit.name, 'action': 'approve' }) mod = PostModerator(post) assert mod.moderate(rule), "Post domains not matching textposts correctly" post.domain = "foobar" self.assertFalse(mod.moderate(rule), "Post domains matching textposts as a false positive")
def test_title_check(self): rule = Rule({ 'title': 'Post', 'action': 'approve' }) post = helpers.post() mod = PostModerator(post) assert mod.moderate(rule), "Post titles not matching correctly" post.title = "Foobar" self.assertFalse(mod.moderate(rule), "Post titles matching as a false positive")
def test_placeholders(self): comment = helpers.comment() comment.body = "Hello, %s" % comment.author.name mod = Moderator(comment) rule = Rule({ 'body (full-exact)': 'Hello, {{author}}', 'action': 'remove' }) assert mod.moderate(rule), "Author placeholder is not replaced" comment.body = "Hello, %s, how are you %s?" % (comment.author.name, comment.author.name) rule = Rule({ 'body (full-exact)': 'Hello, {{author}}, how are you {{author}}?', 'action': 'remove' }) assert mod.moderate( rule ), "Author placeholder is not replaced when there are multiple matches"
def test_flair_template_id_check(self): rule = Rule({ 'flair_template_id': 'test', 'action': 'approve' }) post = helpers.post() post.link_flair_template_id = 'test' mod = PostModerator(post) assert mod.moderate(rule), "Post flair_template_id not matching correctly" post.link_flair_template_id = "foobar" self.assertFalse(mod.moderate(rule), "Post flair_template_id matching as a false positive")
def test_is_top_level(self): rule = Rule({ 'is_top_level': True, 'action': 'approve' }) comment = helpers.comment() comment.depth = 0 mod = CommentModerator(comment) assert mod.moderate(rule), "is_top_level not matching correctly" comment.depth = 1 self.assertFalse(mod.moderate(rule), "is_top_level matching as a false positive")
def test_author_flair_text(self): post = helpers.post() rule = Rule({'author': {'flair_text': 'test'}, 'action': 'remove'}) mod = Moderator(post) flair_mock = MagicMock(return_value=iter([{'flair_text': 'test'}])) post.subreddit.flair = flair_mock assert mod.moderate(rule), "Author flair_text not matching" flair_mock.return_value = iter([{'flair_text': 'nomatch'}]) self.assertFalse(mod.moderate(rule), "Author flair_text matching as a false positive")