412 lines
13 KiB
Perl
412 lines
13 KiB
Perl
|
|
# t/esn-journalnewcomment.t
|
||
|
|
#
|
||
|
|
# Test notifications for new journal comments.
|
||
|
|
#
|
||
|
|
# This code was forked from the LiveJournal project owned and operated
|
||
|
|
# by Live Journal, Inc. The code has been modified and expanded by
|
||
|
|
# Dreamwidth Studios, LLC. These files were originally licensed under
|
||
|
|
# the terms of the license supplied by Live Journal, Inc, which can
|
||
|
|
# currently be found at:
|
||
|
|
#
|
||
|
|
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
|
||
|
|
#
|
||
|
|
# In accordance with the original license, this code and all its
|
||
|
|
# modifications are provided under the GNU General Public License.
|
||
|
|
# A copy of that license can be found in the LICENSE file included as
|
||
|
|
# part of this distribution.
|
||
|
|
|
||
|
|
use strict;
|
||
|
|
use warnings;
|
||
|
|
|
||
|
|
use Test::More tests => 50;
|
||
|
|
|
||
|
|
BEGIN { $LJ::_T_CONFIG = 1; require "$ENV{LJHOME}/cgi-bin/ljlib.pl"; }
|
||
|
|
use LJ::Protocol;
|
||
|
|
|
||
|
|
use LJ::Event;
|
||
|
|
use LJ::Talk;
|
||
|
|
use LJ::Test qw(memcache_stress temp_user);
|
||
|
|
use FindBin qw($Bin);
|
||
|
|
|
||
|
|
# we want to test eight major cases here, matching and not matching for
|
||
|
|
# four types of subscriptions, all of subscr etypeid = JournalNewComment
|
||
|
|
#
|
||
|
|
# jid sarg1 sarg2 meaning
|
||
|
|
# S1: n 0 0 all new comments in journal 'n' (subject to security)
|
||
|
|
# S2: n ditemid 0 all new comments on post (n,ditemid)
|
||
|
|
# S3: n ditemid jtalkid all new comments UNDER comment n/jtalkid (in ditemid)
|
||
|
|
# S4: 0 0 0 all new comments from any journal you watch
|
||
|
|
# -- NOTE: This test is disabled unless JournalNewComment allows it
|
||
|
|
|
||
|
|
# we also want to test for matching and not matching cases for JournalNewComment::TopLevel
|
||
|
|
# a subclass of JournalNewComment
|
||
|
|
|
||
|
|
my %got_email = (); # userid -> received email
|
||
|
|
|
||
|
|
local $LJ::_T_EMAIL_NOTIFICATION = sub {
|
||
|
|
my ( $u, $body ) = @_;
|
||
|
|
$got_email{ $u->userid }++;
|
||
|
|
return 1;
|
||
|
|
};
|
||
|
|
|
||
|
|
my $proc_events = sub {
|
||
|
|
%got_email = ();
|
||
|
|
LJ::Event->process_fired_events;
|
||
|
|
};
|
||
|
|
|
||
|
|
my $got_notified = sub {
|
||
|
|
my $u = shift;
|
||
|
|
$proc_events->();
|
||
|
|
return $got_email{ $u->{userid} };
|
||
|
|
};
|
||
|
|
|
||
|
|
# testing case S1 above:
|
||
|
|
test_esn_flow(
|
||
|
|
sub {
|
||
|
|
my ( $u1, $u2 ) = @_;
|
||
|
|
my $email;
|
||
|
|
my $comment;
|
||
|
|
my $othercomment;
|
||
|
|
|
||
|
|
# clear subs
|
||
|
|
$_->delete foreach $u1->subscriptions;
|
||
|
|
$_->delete foreach $u2->subscriptions;
|
||
|
|
|
||
|
|
# subscribe $u1 to all posts on $u2
|
||
|
|
my $subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
);
|
||
|
|
ok( $subsc, "made S1 subscription" );
|
||
|
|
|
||
|
|
# post an entry in $u2
|
||
|
|
my $u2e1 = eval { $u2->t_post_fake_entry };
|
||
|
|
ok( $u2e1, "made a post" );
|
||
|
|
is( $@, "", "no errors" );
|
||
|
|
|
||
|
|
# $u1 leave a comment on $u2
|
||
|
|
$comment = $u2e1->t_enter_comment;
|
||
|
|
ok( $comment, "left a comment" );
|
||
|
|
|
||
|
|
# make sure we got notification
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( $email, "got the email" );
|
||
|
|
|
||
|
|
# S1 failing case:
|
||
|
|
# post an entry on $u1, where nobody's subscribed
|
||
|
|
my $u1e1 = eval { $u1->t_post_fake_entry };
|
||
|
|
ok( $u1e1, "did a post" );
|
||
|
|
|
||
|
|
# post a comment on it
|
||
|
|
$comment = $u1e1->t_enter_comment;
|
||
|
|
ok( $comment, "left comment" );
|
||
|
|
|
||
|
|
# make sure we didn't get notification
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "got no email" );
|
||
|
|
|
||
|
|
# S1 failing case, posting to u2, due to security
|
||
|
|
my $u2e2f = eval { $u2->t_post_fake_entry( security => "friends" ) };
|
||
|
|
ok( $u2e2f, "did a post" );
|
||
|
|
is( $u2e2f->security, "usemask", "is actually friends only" );
|
||
|
|
|
||
|
|
# post a comment on it
|
||
|
|
$comment = $u2e2f->t_enter_comment;
|
||
|
|
ok( $comment, "got jtalkid" );
|
||
|
|
|
||
|
|
# make sure we didn't get notification
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "got no email, due to security (u2 doesn't trust u1)" );
|
||
|
|
|
||
|
|
ok( $subsc->delete, "Deleted subscription" );
|
||
|
|
|
||
|
|
###### S2:
|
||
|
|
# subscribe $u1 to all comments on u2e1
|
||
|
|
$subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
arg1 => $u2e1->ditemid,
|
||
|
|
);
|
||
|
|
ok( $subsc, "made S2 subscription" );
|
||
|
|
|
||
|
|
# post a comment on u2e1
|
||
|
|
$comment = $u2e1->t_enter_comment;
|
||
|
|
ok( $comment, "got jtalkid" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( $email, "Got comment notification" );
|
||
|
|
|
||
|
|
# post another entry on u2
|
||
|
|
my $u2e3 = eval { $u2->t_post_fake_entry };
|
||
|
|
ok( $u2e3, "did a post" );
|
||
|
|
|
||
|
|
# post a comment that $subsc won't match
|
||
|
|
$comment = $u2e3->t_enter_comment( u => $u2 );
|
||
|
|
ok( $comment, "Posted comment" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "didn't get comment notification on unrelated post" );
|
||
|
|
|
||
|
|
# entry gets locked
|
||
|
|
$u2e1->{security} = "friends";
|
||
|
|
ok( $u2e1, "first entry locked" );
|
||
|
|
|
||
|
|
# u2 comments on their own entry
|
||
|
|
$othercomment = $u2e1->t_enter_comment;
|
||
|
|
ok( $othercomment, "comment added to locked entry" );
|
||
|
|
|
||
|
|
# u1 can't see and doesn't get notified
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "didn't get comment notification on locked post" );
|
||
|
|
|
||
|
|
$u2e1->{security} = "public";
|
||
|
|
|
||
|
|
$subsc->delete;
|
||
|
|
|
||
|
|
######## S3 (watching a thread)
|
||
|
|
|
||
|
|
# make sure we can track threads
|
||
|
|
$LJ::CAP{$_}->{track_thread} = 1 foreach ( 0 .. 15 );
|
||
|
|
|
||
|
|
# subscribe to replies to a thread
|
||
|
|
$subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
arg1 => $u2e3->ditemid,
|
||
|
|
arg2 => $comment->jtalkid,
|
||
|
|
);
|
||
|
|
ok( $subsc, "Subscribed" );
|
||
|
|
|
||
|
|
# post a reply to the comment from the earlier test
|
||
|
|
my $reply = $comment->t_reply( u => $u2 );
|
||
|
|
ok( $reply, "Got reply" );
|
||
|
|
|
||
|
|
$proc_events->();
|
||
|
|
|
||
|
|
$email = $got_email{ $u1->{userid} };
|
||
|
|
ok( $email, "Got notified" );
|
||
|
|
|
||
|
|
$email = $got_email{ $u2->{userid} };
|
||
|
|
ok( !$email, "Unsubscribed watcher not notified" );
|
||
|
|
|
||
|
|
# post a new comment on this entry, make sure not notified
|
||
|
|
my $comment2 = $u2e3->t_enter_comment;
|
||
|
|
ok( $comment2, "Posted comment" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "didn't get notified" );
|
||
|
|
|
||
|
|
# post a reply to a different thread and make sure not notified
|
||
|
|
my $reply2 = $comment2->t_reply;
|
||
|
|
ok( $reply2, "Posted reply" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "didn't get notified" );
|
||
|
|
|
||
|
|
$LJ::CAP{$_}->{track_thread} = 0 foreach ( 0 .. 15 );
|
||
|
|
$subsc->delete;
|
||
|
|
|
||
|
|
if ( ( LJ::Event::JournalNewComment->zero_journalid_subs_means // "" ) eq "friends" ) {
|
||
|
|
####### S4 (watching new comments on all friends' journals)
|
||
|
|
|
||
|
|
$subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
);
|
||
|
|
ok( $subsc, "made S4 wildcard subscription" );
|
||
|
|
|
||
|
|
my $u2e4 = eval { $u2->t_post_fake_entry };
|
||
|
|
ok( $u2e4, "Got entry" );
|
||
|
|
|
||
|
|
for my $pass ( 1 .. 2 ) {
|
||
|
|
my $u2c1 = eval { $u2e4->t_enter_comment };
|
||
|
|
ok( $u2c1, "Posted comment" );
|
||
|
|
|
||
|
|
$proc_events->();
|
||
|
|
|
||
|
|
if ( $pass == 1 ) {
|
||
|
|
$email = $got_email{ $u1->{userid} };
|
||
|
|
ok( $email, "Got wildcard notification" );
|
||
|
|
|
||
|
|
$email = $got_email{ $u2->{userid} };
|
||
|
|
ok( !$email, "Non-subscribed user did not get notification" );
|
||
|
|
|
||
|
|
# remove the friend
|
||
|
|
$u1->remove_edge( $u2, watch => { nonotify => 1 } );
|
||
|
|
|
||
|
|
}
|
||
|
|
elsif ( $pass == 2 ) {
|
||
|
|
$email = $got_email{ $u1->{userid} };
|
||
|
|
ok( !$email, "didn't get wildcard notification" );
|
||
|
|
|
||
|
|
# add the friend back
|
||
|
|
$u1->add_edge( $u2, watch => { nonotify => 1 } ); # make u1 watch u2
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# leave some comment on u1, make sure no notification received
|
||
|
|
my $u1e2 = eval { $u1->t_post_fake_entry };
|
||
|
|
ok( $u1e2, "Posted entry" );
|
||
|
|
|
||
|
|
my $u1c1 = eval { $u1e2->t_enter_comment };
|
||
|
|
ok( $u1c1, "Got comment" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "Did not receive notification" );
|
||
|
|
$subsc->delete;
|
||
|
|
}
|
||
|
|
|
||
|
|
# LJ::Event::JournalNewComment::TopLevel
|
||
|
|
my $u2e5 = eval { $u2->t_post_fake_entry };
|
||
|
|
|
||
|
|
# subscribe to replies to a thread
|
||
|
|
$subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment::TopLevel",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
arg1 => $u2e5->ditemid,
|
||
|
|
);
|
||
|
|
ok( $subsc, "Subscribed" );
|
||
|
|
|
||
|
|
# post a top-level comment
|
||
|
|
$comment = $u2e5->t_enter_comment;
|
||
|
|
ok( $comment, "Posted comment" );
|
||
|
|
|
||
|
|
$proc_events->();
|
||
|
|
|
||
|
|
$email = $got_email{ $u1->{userid} };
|
||
|
|
ok( $email, "Got notified" );
|
||
|
|
|
||
|
|
$email = $got_email{ $u2->{userid} };
|
||
|
|
ok( !$email, "Unsubscribed watcher not notified" );
|
||
|
|
|
||
|
|
# reply to a comment on this entry, make sure we're not notified
|
||
|
|
$reply = $comment->t_reply;
|
||
|
|
ok( $reply, "Posted reply" );
|
||
|
|
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "didn't get notified" );
|
||
|
|
|
||
|
|
$subsc->delete;
|
||
|
|
|
||
|
|
my $u2e6 = eval { $u2->t_post_fake_entry };
|
||
|
|
$subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
arg1 => $u2e6->ditemid,
|
||
|
|
);
|
||
|
|
|
||
|
|
my $subsc2 = $u1->subscribe(
|
||
|
|
event => "JournalNewComment::TopLevel",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
arg1 => $u2e6->ditemid,
|
||
|
|
);
|
||
|
|
ok( $subsc2, "Subscribed to new top-level comments on this journal" );
|
||
|
|
|
||
|
|
$comment = $u2e6->t_enter_comment( u => $u2 );
|
||
|
|
ok( $comment, "Posted comment" );
|
||
|
|
|
||
|
|
$proc_events->();
|
||
|
|
is( $got_email{ $u1->userid }, 1, "No duplicate emails" );
|
||
|
|
|
||
|
|
$subsc->delete;
|
||
|
|
$subsc2->delete;
|
||
|
|
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
######## Unscreen notification tests (issue #3487)
|
||
|
|
# When a screened comment is unscreened, users who couldn't see it
|
||
|
|
# while screened should be notified. Users who could already see it
|
||
|
|
# (journal owner, entry poster) should NOT get a duplicate.
|
||
|
|
|
||
|
|
test_esn_flow(
|
||
|
|
sub {
|
||
|
|
my ( $u1, $u2 ) = @_;
|
||
|
|
my $u3 = temp_user();
|
||
|
|
|
||
|
|
# clear subs
|
||
|
|
$_->delete foreach $u1->subscriptions;
|
||
|
|
$_->delete foreach $u2->subscriptions;
|
||
|
|
|
||
|
|
# u1 subscribes to all comments on u2's journal
|
||
|
|
my $subsc = $u1->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
);
|
||
|
|
ok( $subsc, "Unscreen: u1 subscribed to u2's journal comments" );
|
||
|
|
|
||
|
|
# u2 posts an entry
|
||
|
|
my $entry = eval { $u2->t_post_fake_entry };
|
||
|
|
ok( $entry, "Unscreen: u2 posted entry" );
|
||
|
|
|
||
|
|
# u3 posts a top-level comment (active)
|
||
|
|
my $comment = $entry->t_enter_comment( u => $u3 );
|
||
|
|
ok( $comment, "Unscreen: u3 posted comment" );
|
||
|
|
|
||
|
|
# u1 should be notified of the active comment
|
||
|
|
my $email = $got_notified->($u1);
|
||
|
|
ok( $email, "Unscreen: u1 notified of active comment" );
|
||
|
|
|
||
|
|
# u3 posts a SCREENED reply to the first comment
|
||
|
|
my $screened_reply = $comment->t_reply( u => $u3, state => 'S' );
|
||
|
|
ok( $screened_reply, "Unscreen: u3 posted screened reply" );
|
||
|
|
|
||
|
|
# u1 should NOT be notified (can't see screened comments)
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( !$email, "Unscreen: u1 not notified of screened reply" );
|
||
|
|
|
||
|
|
# unscreen the reply
|
||
|
|
LJ::Talk::unscreen_comment( $u2, $entry->jitemid, $screened_reply->jtalkid );
|
||
|
|
|
||
|
|
# u1 SHOULD now be notified
|
||
|
|
$email = $got_notified->($u1);
|
||
|
|
ok( $email, "Unscreen: u1 notified after reply unscreened" );
|
||
|
|
|
||
|
|
$subsc->delete;
|
||
|
|
|
||
|
|
# Now test that journal owner doesn't get duplicate notifications
|
||
|
|
my $subsc_owner = $u2->subscribe(
|
||
|
|
event => "JournalNewComment",
|
||
|
|
method => "Email",
|
||
|
|
journal => $u2,
|
||
|
|
);
|
||
|
|
ok( $subsc_owner, "Unscreen: u2 subscribed to own journal comments" );
|
||
|
|
|
||
|
|
# post a screened comment on the entry
|
||
|
|
my $screened2 = $entry->t_enter_comment( u => $u3, state => 'S' );
|
||
|
|
ok( $screened2, "Unscreen: u3 posted another screened comment" );
|
||
|
|
|
||
|
|
# u2 (journal owner) SHOULD be notified of screened comment
|
||
|
|
$proc_events->();
|
||
|
|
ok( $got_email{ $u2->userid }, "Unscreen: journal owner notified of screened comment" );
|
||
|
|
|
||
|
|
# unscreen it
|
||
|
|
LJ::Talk::unscreen_comment( $u2, $entry->jitemid, $screened2->jtalkid );
|
||
|
|
|
||
|
|
# u2 should NOT get a duplicate notification
|
||
|
|
$proc_events->();
|
||
|
|
ok( !$got_email{ $u2->userid },
|
||
|
|
"Unscreen: journal owner not notified again after unscreen" );
|
||
|
|
|
||
|
|
$subsc_owner->delete;
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
sub test_esn_flow {
|
||
|
|
my $cv = shift;
|
||
|
|
my $u1 = temp_user();
|
||
|
|
my $u2 = temp_user();
|
||
|
|
$u1->add_edge( $u2, watch => { nonotify => 1 } ); # make u1 watch u2
|
||
|
|
$cv->( $u1, $u2 );
|
||
|
|
}
|
||
|
|
|
||
|
|
1;
|
||
|
|
|